1 /* $NetBSD: common.c,v 1.1.1.1 2011/04/13 18:14:41 elric Exp $ */ 2 3 /* 4 * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "hdb_locl.h" 37 38 int 39 hdb_principal2key(krb5_context context, krb5_const_principal p, krb5_data *key) 40 { 41 Principal new; 42 size_t len; 43 int ret; 44 45 ret = copy_Principal(p, &new); 46 if(ret) 47 return ret; 48 new.name.name_type = 0; 49 50 ASN1_MALLOC_ENCODE(Principal, key->data, key->length, &new, &len, ret); 51 if (ret == 0 && key->length != len) 52 krb5_abortx(context, "internal asn.1 encoder error"); 53 free_Principal(&new); 54 return ret; 55 } 56 57 int 58 hdb_key2principal(krb5_context context, krb5_data *key, krb5_principal p) 59 { 60 return decode_Principal(key->data, key->length, p, NULL); 61 } 62 63 int 64 hdb_entry2value(krb5_context context, const hdb_entry *ent, krb5_data *value) 65 { 66 size_t len; 67 int ret; 68 69 ASN1_MALLOC_ENCODE(hdb_entry, value->data, value->length, ent, &len, ret); 70 if (ret == 0 && value->length != len) 71 krb5_abortx(context, "internal asn.1 encoder error"); 72 return ret; 73 } 74 75 int 76 hdb_value2entry(krb5_context context, krb5_data *value, hdb_entry *ent) 77 { 78 return decode_hdb_entry(value->data, value->length, ent, NULL); 79 } 80 81 int 82 hdb_entry_alias2value(krb5_context context, 83 const hdb_entry_alias *alias, 84 krb5_data *value) 85 { 86 size_t len; 87 int ret; 88 89 ASN1_MALLOC_ENCODE(hdb_entry_alias, value->data, value->length, 90 alias, &len, ret); 91 if (ret == 0 && value->length != len) 92 krb5_abortx(context, "internal asn.1 encoder error"); 93 return ret; 94 } 95 96 int 97 hdb_value2entry_alias(krb5_context context, krb5_data *value, 98 hdb_entry_alias *ent) 99 { 100 return decode_hdb_entry_alias(value->data, value->length, ent, NULL); 101 } 102 103 krb5_error_code 104 _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, 105 unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) 106 { 107 krb5_principal enterprise_principal = NULL; 108 krb5_data key, value; 109 krb5_error_code ret; 110 int code; 111 112 if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { 113 if (principal->name.name_string.len != 1) { 114 ret = KRB5_PARSE_MALFORMED; 115 krb5_set_error_message(context, ret, "malformed principal: " 116 "enterprise name with %d name components", 117 principal->name.name_string.len); 118 return ret; 119 } 120 ret = krb5_parse_name(context, principal->name.name_string.val[0], 121 &enterprise_principal); 122 if (ret) 123 return ret; 124 principal = enterprise_principal; 125 } 126 127 hdb_principal2key(context, principal, &key); 128 if (enterprise_principal) 129 krb5_free_principal(context, enterprise_principal); 130 code = db->hdb__get(context, db, key, &value); 131 krb5_data_free(&key); 132 if(code) 133 return code; 134 code = hdb_value2entry(context, &value, &entry->entry); 135 if (code == ASN1_BAD_ID && (flags & HDB_F_CANON) == 0) { 136 krb5_data_free(&value); 137 return HDB_ERR_NOENTRY; 138 } else if (code == ASN1_BAD_ID) { 139 hdb_entry_alias alias; 140 141 code = hdb_value2entry_alias(context, &value, &alias); 142 if (code) { 143 krb5_data_free(&value); 144 return code; 145 } 146 hdb_principal2key(context, alias.principal, &key); 147 krb5_data_free(&value); 148 free_hdb_entry_alias(&alias); 149 150 code = db->hdb__get(context, db, key, &value); 151 krb5_data_free(&key); 152 if (code) 153 return code; 154 code = hdb_value2entry(context, &value, &entry->entry); 155 if (code) { 156 krb5_data_free(&value); 157 return code; 158 } 159 } 160 krb5_data_free(&value); 161 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 162 code = hdb_unseal_keys (context, db, &entry->entry); 163 if (code) 164 hdb_free_entry(context, entry); 165 } 166 return code; 167 } 168 169 static krb5_error_code 170 hdb_remove_aliases(krb5_context context, HDB *db, krb5_data *key) 171 { 172 const HDB_Ext_Aliases *aliases; 173 krb5_error_code code; 174 hdb_entry oldentry; 175 krb5_data value; 176 int i; 177 178 code = db->hdb__get(context, db, *key, &value); 179 if (code == HDB_ERR_NOENTRY) 180 return 0; 181 else if (code) 182 return code; 183 184 code = hdb_value2entry(context, &value, &oldentry); 185 krb5_data_free(&value); 186 if (code) 187 return code; 188 189 code = hdb_entry_get_aliases(&oldentry, &aliases); 190 if (code || aliases == NULL) { 191 free_hdb_entry(&oldentry); 192 return code; 193 } 194 for (i = 0; i < aliases->aliases.len; i++) { 195 krb5_data akey; 196 197 hdb_principal2key(context, &aliases->aliases.val[i], &akey); 198 code = db->hdb__del(context, db, akey); 199 krb5_data_free(&akey); 200 if (code) { 201 free_hdb_entry(&oldentry); 202 return code; 203 } 204 } 205 free_hdb_entry(&oldentry); 206 return 0; 207 } 208 209 static krb5_error_code 210 hdb_add_aliases(krb5_context context, HDB *db, 211 unsigned flags, hdb_entry_ex *entry) 212 { 213 const HDB_Ext_Aliases *aliases; 214 krb5_error_code code; 215 krb5_data key, value; 216 int i; 217 218 code = hdb_entry_get_aliases(&entry->entry, &aliases); 219 if (code || aliases == NULL) 220 return code; 221 222 for (i = 0; i < aliases->aliases.len; i++) { 223 hdb_entry_alias entryalias; 224 entryalias.principal = entry->entry.principal; 225 226 hdb_principal2key(context, &aliases->aliases.val[i], &key); 227 code = hdb_entry_alias2value(context, &entryalias, &value); 228 if (code) { 229 krb5_data_free(&key); 230 return code; 231 } 232 code = db->hdb__put(context, db, flags, key, value); 233 krb5_data_free(&key); 234 krb5_data_free(&value); 235 if (code) 236 return code; 237 } 238 return 0; 239 } 240 241 static krb5_error_code 242 hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry) 243 { 244 const HDB_Ext_Aliases *aliases; 245 int code, i; 246 247 /* check if new aliases already is used */ 248 249 code = hdb_entry_get_aliases(&entry->entry, &aliases); 250 if (code) 251 return code; 252 253 for (i = 0; aliases && i < aliases->aliases.len; i++) { 254 hdb_entry_alias alias; 255 krb5_data akey, value; 256 257 hdb_principal2key(context, &aliases->aliases.val[i], &akey); 258 code = db->hdb__get(context, db, akey, &value); 259 krb5_data_free(&akey); 260 if (code == HDB_ERR_NOENTRY) 261 continue; 262 else if (code) 263 return code; 264 265 code = hdb_value2entry_alias(context, &value, &alias); 266 krb5_data_free(&value); 267 268 if (code == ASN1_BAD_ID) 269 return HDB_ERR_EXISTS; 270 else if (code) 271 return code; 272 273 code = krb5_principal_compare(context, alias.principal, 274 entry->entry.principal); 275 free_hdb_entry_alias(&alias); 276 if (code == 0) 277 return HDB_ERR_EXISTS; 278 } 279 return 0; 280 } 281 282 krb5_error_code 283 _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 284 { 285 krb5_data key, value; 286 int code; 287 288 /* check if new aliases already is used */ 289 code = hdb_check_aliases(context, db, entry); 290 if (code) 291 return code; 292 293 if(entry->entry.generation == NULL) { 294 struct timeval t; 295 entry->entry.generation = malloc(sizeof(*entry->entry.generation)); 296 if(entry->entry.generation == NULL) { 297 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 298 return ENOMEM; 299 } 300 gettimeofday(&t, NULL); 301 entry->entry.generation->time = t.tv_sec; 302 entry->entry.generation->usec = t.tv_usec; 303 entry->entry.generation->gen = 0; 304 } else 305 entry->entry.generation->gen++; 306 307 code = hdb_seal_keys(context, db, &entry->entry); 308 if (code) 309 return code; 310 311 hdb_principal2key(context, entry->entry.principal, &key); 312 313 /* remove aliases */ 314 code = hdb_remove_aliases(context, db, &key); 315 if (code) { 316 krb5_data_free(&key); 317 return code; 318 } 319 hdb_entry2value(context, &entry->entry, &value); 320 code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value); 321 krb5_data_free(&value); 322 krb5_data_free(&key); 323 if (code) 324 return code; 325 326 code = hdb_add_aliases(context, db, flags, entry); 327 328 return code; 329 } 330 331 krb5_error_code 332 _hdb_remove(krb5_context context, HDB *db, krb5_const_principal principal) 333 { 334 krb5_data key; 335 int code; 336 337 hdb_principal2key(context, principal, &key); 338 339 code = hdb_remove_aliases(context, db, &key); 340 if (code) { 341 krb5_data_free(&key); 342 return code; 343 } 344 code = db->hdb__del(context, db, key); 345 krb5_data_free(&key); 346 return code; 347 } 348 349