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