1 /* $NetBSD: hdb-mitdb.c,v 1.2 2017/01/28 21:31:48 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * 3. Neither the name of the Institute nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #define KRB5_KDB_DISALLOW_POSTDATED 0x00000001 39 #define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002 40 #define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004 41 #define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008 42 #define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010 43 #define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020 44 #define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040 45 #define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080 46 #define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100 47 #define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200 48 #define KRB5_KDB_DISALLOW_SVR 0x00001000 49 #define KRB5_KDB_PWCHANGE_SERVICE 0x00002000 50 #define KRB5_KDB_SUPPORT_DESMD5 0x00004000 51 #define KRB5_KDB_NEW_PRINC 0x00008000 52 53 /* 54 55 key: krb5_unparse_name + NUL 56 57 16: baselength 58 32: attributes 59 32: max time 60 32: max renewable time 61 32: client expire 62 32: passwd expire 63 32: last successful passwd 64 32: last failed attempt 65 32: num of failed attempts 66 16: num tl data 67 16: num data data 68 16: principal length 69 length: principal 70 for num tl data times 71 16: tl data type 72 16: tl data length 73 length: length 74 for num key data times 75 16: version (num keyblocks) 76 16: kvno 77 for version times: 78 16: type 79 16: length 80 length: keydata 81 82 83 key_data_contents[0] 84 85 int16: length 86 read-of-data: key-encrypted, key-usage 0, master-key 87 88 salt: 89 version2 = salt in key_data->key_data_contents[1] 90 else default salt. 91 92 */ 93 94 #include "hdb_locl.h" 95 96 static void 97 attr_to_flags(unsigned attr, HDBFlags *flags) 98 { 99 flags->postdate = !(attr & KRB5_KDB_DISALLOW_POSTDATED); 100 flags->forwardable = !(attr & KRB5_KDB_DISALLOW_FORWARDABLE); 101 flags->initial = !!(attr & KRB5_KDB_DISALLOW_TGT_BASED); 102 flags->renewable = !(attr & KRB5_KDB_DISALLOW_RENEWABLE); 103 flags->proxiable = !(attr & KRB5_KDB_DISALLOW_PROXIABLE); 104 /* DUP_SKEY */ 105 flags->invalid = !!(attr & KRB5_KDB_DISALLOW_ALL_TIX); 106 flags->require_preauth = !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH); 107 flags->require_hwauth = !!(attr & KRB5_KDB_REQUIRES_HW_AUTH); 108 flags->server = !(attr & KRB5_KDB_DISALLOW_SVR); 109 flags->change_pw = !!(attr & KRB5_KDB_PWCHANGE_SERVICE); 110 flags->client = 1; /* XXX */ 111 } 112 113 #define KDB_V1_BASE_LENGTH 38 114 115 #define CHECK(x) do { if ((x)) goto out; } while(0) 116 117 #ifdef HAVE_DB1 118 static krb5_error_code 119 mdb_principal2key(krb5_context context, 120 krb5_const_principal principal, 121 krb5_data *key) 122 { 123 krb5_error_code ret; 124 char *str; 125 126 ret = krb5_unparse_name(context, principal, &str); 127 if (ret) 128 return ret; 129 key->data = str; 130 key->length = strlen(str) + 1; 131 return 0; 132 } 133 #endif /* HAVE_DB1 */ 134 135 #define KRB5_KDB_SALTTYPE_NORMAL 0 136 #define KRB5_KDB_SALTTYPE_V4 1 137 #define KRB5_KDB_SALTTYPE_NOREALM 2 138 #define KRB5_KDB_SALTTYPE_ONLYREALM 3 139 #define KRB5_KDB_SALTTYPE_SPECIAL 4 140 #define KRB5_KDB_SALTTYPE_AFS3 5 141 #define KRB5_KDB_SALTTYPE_CERTHASH 6 142 143 static krb5_error_code 144 fix_salt(krb5_context context, hdb_entry *ent, Key *k) 145 { 146 krb5_error_code ret; 147 Salt *salt = k->salt; 148 /* fix salt type */ 149 switch((int)salt->type) { 150 case KRB5_KDB_SALTTYPE_NORMAL: 151 salt->type = KRB5_PADATA_PW_SALT; 152 break; 153 case KRB5_KDB_SALTTYPE_V4: 154 krb5_data_free(&salt->salt); 155 salt->type = KRB5_PADATA_PW_SALT; 156 break; 157 case KRB5_KDB_SALTTYPE_NOREALM: 158 { 159 size_t len; 160 size_t i; 161 char *p; 162 163 len = 0; 164 for (i = 0; i < ent->principal->name.name_string.len; ++i) 165 len += strlen(ent->principal->name.name_string.val[i]); 166 ret = krb5_data_alloc (&salt->salt, len); 167 if (ret) 168 return ret; 169 p = salt->salt.data; 170 for (i = 0; i < ent->principal->name.name_string.len; ++i) { 171 memcpy (p, 172 ent->principal->name.name_string.val[i], 173 strlen(ent->principal->name.name_string.val[i])); 174 p += strlen(ent->principal->name.name_string.val[i]); 175 } 176 177 salt->type = KRB5_PADATA_PW_SALT; 178 break; 179 } 180 case KRB5_KDB_SALTTYPE_ONLYREALM: 181 krb5_data_free(&salt->salt); 182 ret = krb5_data_copy(&salt->salt, 183 ent->principal->realm, 184 strlen(ent->principal->realm)); 185 if(ret) 186 return ret; 187 salt->type = KRB5_PADATA_PW_SALT; 188 break; 189 case KRB5_KDB_SALTTYPE_SPECIAL: 190 salt->type = KRB5_PADATA_PW_SALT; 191 break; 192 case KRB5_KDB_SALTTYPE_AFS3: 193 krb5_data_free(&salt->salt); 194 ret = krb5_data_copy(&salt->salt, 195 ent->principal->realm, 196 strlen(ent->principal->realm)); 197 if(ret) 198 return ret; 199 salt->type = KRB5_PADATA_AFS3_SALT; 200 break; 201 case KRB5_KDB_SALTTYPE_CERTHASH: 202 krb5_data_free(&salt->salt); 203 free(k->salt); 204 k->salt = NULL; 205 break; 206 default: 207 abort(); 208 } 209 return 0; 210 } 211 212 213 /** 214 * This function takes a key from a krb5_storage from an MIT KDB encoded 215 * entry and places it in the given Key object. 216 * 217 * @param context Context 218 * @param entry HDB entry 219 * @param sp krb5_storage with current offset set to the beginning of a 220 * key 221 * @param version See comments in caller body for the backstory on this 222 * @param k Key * to load the key into 223 */ 224 static krb5_error_code 225 mdb_keyvalue2key(krb5_context context, hdb_entry *entry, krb5_storage *sp, uint16_t version, Key *k) 226 { 227 size_t i; 228 uint16_t u16, type; 229 krb5_error_code ret; 230 231 k->mkvno = malloc(sizeof(*k->mkvno)); 232 if (k->mkvno == NULL) { 233 ret = ENOMEM; 234 goto out; 235 } 236 *k->mkvno = 1; 237 238 for (i = 0; i < version; i++) { 239 CHECK(ret = krb5_ret_uint16(sp, &type)); 240 CHECK(ret = krb5_ret_uint16(sp, &u16)); 241 if (i == 0) { 242 /* This "version" means we have a key */ 243 k->key.keytype = type; 244 /* 245 * MIT stores keys encrypted keys as {16-bit length 246 * of plaintext key, {encrypted key}}. The reason 247 * for this is that the Kerberos cryptosystem is not 248 * length-preserving. Heimdal's approach is to 249 * truncate the plaintext to the expected length of 250 * the key given its enctype, so we ignore this 251 * 16-bit length-of-plaintext-key field. 252 */ 253 if (u16 > 2) { 254 krb5_storage_seek(sp, 2, SEEK_CUR); /* skip real length */ 255 k->key.keyvalue.length = u16 - 2; /* adjust cipher len */ 256 k->key.keyvalue.data = malloc(k->key.keyvalue.length); 257 krb5_storage_read(sp, k->key.keyvalue.data, 258 k->key.keyvalue.length); 259 } else { 260 /* We'll ignore this key; see our caller */ 261 k->key.keyvalue.length = 0; 262 k->key.keyvalue.data = NULL; 263 krb5_storage_seek(sp, u16, SEEK_CUR); /* skip real length */ 264 } 265 } else if (i == 1) { 266 /* This "version" means we have a salt */ 267 k->salt = calloc(1, sizeof(*k->salt)); 268 if (k->salt == NULL) { 269 ret = ENOMEM; 270 goto out; 271 } 272 k->salt->type = type; 273 if (u16 != 0) { 274 k->salt->salt.data = malloc(u16); 275 if (k->salt->salt.data == NULL) { 276 ret = ENOMEM; 277 goto out; 278 } 279 k->salt->salt.length = u16; 280 krb5_storage_read(sp, k->salt->salt.data, k->salt->salt.length); 281 } 282 fix_salt(context, entry, k); 283 } else { 284 /* 285 * Whatever this "version" might be, we skip it 286 * 287 * XXX A krb5.conf parameter requesting that we log 288 * about strangeness like this, or return an error 289 * from here, might be nice. 290 */ 291 krb5_storage_seek(sp, u16, SEEK_CUR); 292 } 293 } 294 295 return 0; 296 297 out: 298 free_Key(k); 299 return ret; 300 } 301 302 303 static krb5_error_code 304 add_1des_dup(krb5_context context, Keys *keys, Key *key, krb5_keytype keytype) 305 { 306 key->key.keytype = keytype; 307 return add_Keys(keys, key); 308 } 309 310 /* 311 * This monstrosity is here so we can avoid having to do enctype 312 * similarity checking in the KDC. This helper function dups 1DES keys 313 * in a keyset for all the similar 1DES enctypes for which keys are 314 * missing. And, of course, we do this only if there's any 1DES keys in 315 * the keyset to begin with. 316 */ 317 static krb5_error_code 318 dup_similar_keys_in_keyset(krb5_context context, Keys *keys) 319 { 320 krb5_error_code ret; 321 size_t i, k; 322 Key key; 323 int keyset_has_1des_crc = 0; 324 int keyset_has_1des_md4 = 0; 325 int keyset_has_1des_md5 = 0; 326 327 memset(&key, 0, sizeof (key)); 328 k = keys->len; 329 for (i = 0; i < keys->len; i++) { 330 if (keys->val[i].key.keytype == ETYPE_DES_CBC_CRC) { 331 keyset_has_1des_crc = 1; 332 if (k == keys->len) 333 k = i; 334 } else if (keys->val[i].key.keytype == ETYPE_DES_CBC_MD4) { 335 keyset_has_1des_crc = 1; 336 if (k == keys->len) 337 k = i; 338 } else if (keys->val[i].key.keytype == ETYPE_DES_CBC_MD5) { 339 keyset_has_1des_crc = 1; 340 if (k == keys->len) 341 k = i; 342 } 343 } 344 if (k == keys->len) 345 return 0; 346 347 ret = copy_Key(&keys->val[k], &key); 348 if (ret) 349 return ret; 350 if (!keyset_has_1des_crc) { 351 ret = add_1des_dup(context, keys, &key, ETYPE_DES_CBC_CRC); 352 if (ret) 353 goto out; 354 } 355 if (!keyset_has_1des_md4) { 356 ret = add_1des_dup(context, keys, &key, ETYPE_DES_CBC_MD4); 357 if (ret) 358 goto out; 359 } 360 if (!keyset_has_1des_md5) { 361 ret = add_1des_dup(context, keys, &key, ETYPE_DES_CBC_MD5); 362 if (ret) 363 goto out; 364 } 365 366 out: 367 free_Key(&key); 368 return ret; 369 } 370 371 372 static krb5_error_code 373 dup_similar_keys(krb5_context context, hdb_entry *entry) 374 { 375 krb5_error_code ret; 376 HDB_Ext_KeySet *hist_keys; 377 HDB_extension *extp; 378 size_t i; 379 380 ret = dup_similar_keys_in_keyset(context, &entry->keys); 381 if (ret) 382 return ret; 383 extp = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys); 384 if (extp == NULL) 385 return 0; 386 387 hist_keys = &extp->data.u.hist_keys; 388 for (i = 0; i < hist_keys->len; i++) { 389 ret = dup_similar_keys_in_keyset(context, &hist_keys->val[i].keys); 390 if (ret) 391 return ret; 392 } 393 return 0; 394 } 395 396 397 /** 398 * This function parses an MIT krb5 encoded KDB entry and fills in the 399 * given HDB entry with it. 400 * 401 * @param context krb5_context 402 * @param data Encoded MIT KDB entry 403 * @param target_kvno Desired kvno, or 0 for the entry's current kvno 404 * @param entry Desired kvno, or 0 for the entry's current kvno 405 */ 406 krb5_error_code 407 _hdb_mdb_value2entry(krb5_context context, krb5_data *data, 408 krb5_kvno target_kvno, hdb_entry *entry) 409 { 410 krb5_error_code ret; 411 krb5_storage *sp; 412 Key k; 413 krb5_kvno key_kvno; 414 uint32_t u32; 415 uint16_t u16, num_keys, num_tl; 416 ssize_t sz; 417 size_t i; 418 char *p; 419 420 memset(&k, 0, sizeof (k)); 421 memset(entry, 0, sizeof(*entry)); 422 423 sp = krb5_storage_from_data(data); 424 if (sp == NULL) { 425 krb5_set_error_message(context, ENOMEM, "out of memory"); 426 return ENOMEM; 427 } 428 429 krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); 430 431 /* 432 * 16: baselength 433 * 434 * The story here is that these 16 bits have to be a constant: 435 * KDB_V1_BASE_LENGTH. Once upon a time a different value here 436 * would have been used to indicate the presence of "extra data" 437 * between the "base" contents and the {principal name, TL data, 438 * keys} that follow it. Nothing supports such "extra data" 439 * nowadays, so neither do we here. 440 * 441 * XXX But... surely we ought to log about this extra data, or skip 442 * it, or something, in case anyone has MIT KDBs with ancient 443 * entries in them... Logging would allow the admin to know which 444 * entries to dump with MIT krb5's kdb5_util. But logging would be 445 * noisy. For now we do nothing. 446 */ 447 CHECK(ret = krb5_ret_uint16(sp, &u16)); 448 if (u16 != KDB_V1_BASE_LENGTH) { ret = EINVAL; goto out; } 449 /* 32: attributes */ 450 CHECK(ret = krb5_ret_uint32(sp, &u32)); 451 attr_to_flags(u32, &entry->flags); 452 453 /* 32: max time */ 454 CHECK(ret = krb5_ret_uint32(sp, &u32)); 455 if (u32) { 456 entry->max_life = malloc(sizeof(*entry->max_life)); 457 *entry->max_life = u32; 458 } 459 /* 32: max renewable time */ 460 CHECK(ret = krb5_ret_uint32(sp, &u32)); 461 if (u32) { 462 entry->max_renew = malloc(sizeof(*entry->max_renew)); 463 *entry->max_renew = u32; 464 } 465 /* 32: client expire */ 466 CHECK(ret = krb5_ret_uint32(sp, &u32)); 467 if (u32) { 468 entry->valid_end = malloc(sizeof(*entry->valid_end)); 469 *entry->valid_end = u32; 470 } 471 /* 32: passwd expire */ 472 CHECK(ret = krb5_ret_uint32(sp, &u32)); 473 if (u32) { 474 entry->pw_end = malloc(sizeof(*entry->pw_end)); 475 *entry->pw_end = u32; 476 } 477 /* 32: last successful passwd */ 478 CHECK(ret = krb5_ret_uint32(sp, &u32)); 479 /* 32: last failed attempt */ 480 CHECK(ret = krb5_ret_uint32(sp, &u32)); 481 /* 32: num of failed attempts */ 482 CHECK(ret = krb5_ret_uint32(sp, &u32)); 483 /* 16: num tl data */ 484 CHECK(ret = krb5_ret_uint16(sp, &u16)); 485 num_tl = u16; 486 /* 16: num key data */ 487 CHECK(ret = krb5_ret_uint16(sp, &u16)); 488 num_keys = u16; 489 /* 16: principal length */ 490 CHECK(ret = krb5_ret_uint16(sp, &u16)); 491 /* length: principal */ 492 { 493 /* 494 * Note that the principal name includes the NUL in the entry, 495 * but we don't want to take chances, so we add an extra NUL. 496 */ 497 p = malloc(u16 + 1); 498 if (p == NULL) { 499 ret = ENOMEM; 500 goto out; 501 } 502 sz = krb5_storage_read(sp, p, u16); 503 if (sz != u16) { 504 ret = EINVAL; /* XXX */ 505 goto out; 506 } 507 p[u16] = '\0'; 508 CHECK(ret = krb5_parse_name(context, p, &entry->principal)); 509 free(p); 510 } 511 /* for num tl data times 512 16: tl data type 513 16: tl data length 514 length: length */ 515 #define mit_KRB5_TL_LAST_PWD_CHANGE 1 516 #define mit_KRB5_TL_MOD_PRINC 2 517 for (i = 0; i < num_tl; i++) { 518 int tl_type; 519 krb5_principal modby; 520 /* 16: TL data type */ 521 CHECK(ret = krb5_ret_uint16(sp, &u16)); 522 tl_type = u16; 523 /* 16: TL data length */ 524 CHECK(ret = krb5_ret_uint16(sp, &u16)); 525 /* 526 * For rollback to MIT purposes we really must understand some 527 * TL data! 528 * 529 * XXX Move all this to separate functions, one per-TL type. 530 */ 531 switch (tl_type) { 532 case mit_KRB5_TL_LAST_PWD_CHANGE: 533 CHECK(ret = krb5_ret_uint32(sp, &u32)); 534 CHECK(ret = hdb_entry_set_pw_change_time(context, entry, u32)); 535 break; 536 case mit_KRB5_TL_MOD_PRINC: 537 if (u16 < 5) { 538 ret = EINVAL; /* XXX */ 539 goto out; 540 } 541 CHECK(ret = krb5_ret_uint32(sp, &u32)); /* mod time */ 542 p = malloc(u16 - 4 + 1); 543 if (!p) { 544 ret = ENOMEM; 545 goto out; 546 } 547 p[u16 - 4] = '\0'; 548 sz = krb5_storage_read(sp, p, u16 - 4); 549 if (sz != u16 - 4) { 550 ret = EINVAL; /* XXX */ 551 goto out; 552 } 553 CHECK(ret = krb5_parse_name(context, p, &modby)); 554 ret = hdb_set_last_modified_by(context, entry, modby, u32); 555 krb5_free_principal(context, modby); 556 free(p); 557 break; 558 default: 559 krb5_storage_seek(sp, u16, SEEK_CUR); 560 break; 561 } 562 } 563 /* 564 * for num key data times 565 * 16: "version" 566 * 16: kvno 567 * for version times: 568 * 16: type 569 * 16: length 570 * length: keydata 571 * 572 * "version" here is really 1 or 2, the first meaning there's only 573 * keys for this kvno, the second meaning there's keys and salt[s?]. 574 * That's right... hold that gag reflex, you can do it. 575 */ 576 for (i = 0; i < num_keys; i++) { 577 uint16_t version; 578 579 CHECK(ret = krb5_ret_uint16(sp, &u16)); 580 version = u16; 581 CHECK(ret = krb5_ret_uint16(sp, &u16)); 582 key_kvno = u16; 583 584 ret = mdb_keyvalue2key(context, entry, sp, version, &k); 585 if (ret) 586 goto out; 587 if (k.key.keytype == 0 || k.key.keyvalue.length == 0) { 588 /* 589 * Older MIT KDBs may have enctype 0 / length 0 keys. We 590 * ignore these. 591 */ 592 free_Key(&k); 593 continue; 594 } 595 596 if ((target_kvno == 0 && entry->kvno < key_kvno) || 597 (target_kvno == key_kvno && entry->kvno != target_kvno)) { 598 /* 599 * MIT's KDB doesn't keep track of kvno. The highest kvno 600 * is the current kvno, and we just found a new highest 601 * kvno or the desired kvno. 602 * 603 * Note that there's no guarantee of any key ordering, but 604 * generally MIT KDB entries have keys in strictly 605 * descending kvno order. 606 * 607 * XXX We do assume that keys are clustered by kvno. If 608 * not, then bad. It might be possible to construct 609 * non-clustered keys via the kadm5 API. It wouldn't be 610 * hard to cope with this, since if it happens the worst 611 * that will happen is that some of the current keys can be 612 * found in the history extension, and we could just pull 613 * them back out in that case. 614 */ 615 ret = hdb_add_current_keys_to_history(context, entry); 616 if (ret) 617 goto out; 618 free_Keys(&entry->keys); 619 ret = add_Keys(&entry->keys, &k); 620 free_Key(&k); 621 if (ret) 622 goto out; 623 entry->kvno = key_kvno; 624 continue; 625 } 626 627 if (entry->kvno == key_kvno) { 628 /* 629 * Note that if key_kvno == 0 and target_kvno == 0 then we 630 * end up adding those keys here. Yeah, kvno 0 is very 631 * special for us, but just in case, we keep such keys. 632 */ 633 ret = add_Keys(&entry->keys, &k); 634 free_Key(&k); 635 if (ret) 636 goto out; 637 entry->kvno = key_kvno; 638 } else { 639 ret = hdb_add_history_key(context, entry, key_kvno, &k); 640 if (ret) 641 goto out; 642 free_Key(&k); 643 } 644 } 645 646 if (target_kvno != 0 && entry->kvno != target_kvno) { 647 ret = HDB_ERR_KVNO_NOT_FOUND; 648 goto out; 649 } 650 651 krb5_storage_free(sp); 652 653 return dup_similar_keys(context, entry); 654 655 out: 656 krb5_storage_free(sp); 657 658 if (ret == HEIM_ERR_EOF) 659 /* Better error code than "end of file" */ 660 ret = HEIM_ERR_BAD_HDBENT_ENCODING; 661 free_hdb_entry(entry); 662 free_Key(&k); 663 return ret; 664 } 665 666 #if 0 667 static krb5_error_code 668 mdb_entry2value(krb5_context context, hdb_entry *entry, krb5_data *data) 669 { 670 return EINVAL; 671 } 672 #endif 673 674 #if HAVE_DB1 675 676 #if defined(HAVE_DB_185_H) 677 #include <db_185.h> 678 #elif defined(HAVE_DB_H) 679 #include <db.h> 680 #endif 681 682 683 static krb5_error_code 684 mdb_close(krb5_context context, HDB *db) 685 { 686 DB *d = (DB*)db->hdb_db; 687 (*d->close)(d); 688 return 0; 689 } 690 691 static krb5_error_code 692 mdb_destroy(krb5_context context, HDB *db) 693 { 694 krb5_error_code ret; 695 696 ret = hdb_clear_master_key (context, db); 697 free(db->hdb_name); 698 free(db); 699 return ret; 700 } 701 702 static krb5_error_code 703 mdb_lock(krb5_context context, HDB *db, int operation) 704 { 705 DB *d = (DB*)db->hdb_db; 706 int fd = (*d->fd)(d); 707 krb5_error_code ret; 708 709 if (db->lock_count > 1) { 710 db->lock_count++; 711 if (db->lock_type == HDB_WLOCK || db->lock_count == operation) 712 return 0; 713 } 714 715 if(fd < 0) { 716 krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB, 717 "Can't lock database: %s", db->hdb_name); 718 return HDB_ERR_CANT_LOCK_DB; 719 } 720 ret = hdb_lock(fd, operation); 721 if (ret) 722 return ret; 723 db->lock_count++; 724 return 0; 725 } 726 727 static krb5_error_code 728 mdb_unlock(krb5_context context, HDB *db) 729 { 730 DB *d = (DB*)db->hdb_db; 731 int fd = (*d->fd)(d); 732 733 if (db->lock_count > 1) { 734 db->lock_count--; 735 return 0; 736 } 737 heim_assert(db->lock_count == 1, "HDB lock/unlock sequence does not match"); 738 db->lock_count--; 739 740 if(fd < 0) { 741 krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB, 742 "Can't unlock database: %s", db->hdb_name); 743 return HDB_ERR_CANT_LOCK_DB; 744 } 745 return hdb_unlock(fd); 746 } 747 748 749 static krb5_error_code 750 mdb_seq(krb5_context context, HDB *db, 751 unsigned flags, hdb_entry_ex *entry, int flag) 752 { 753 DB *d = (DB*)db->hdb_db; 754 DBT key, value; 755 krb5_data key_data, data; 756 int code; 757 758 code = db->hdb_lock(context, db, HDB_RLOCK); 759 if(code == -1) { 760 krb5_set_error_message(context, HDB_ERR_DB_INUSE, "Database %s in use", db->hdb_name); 761 return HDB_ERR_DB_INUSE; 762 } 763 code = (*d->seq)(d, &key, &value, flag); 764 db->hdb_unlock(context, db); /* XXX check value */ 765 if(code == -1) { 766 code = errno; 767 krb5_set_error_message(context, code, "Database %s seq error: %s", 768 db->hdb_name, strerror(code)); 769 return code; 770 } 771 if(code == 1) { 772 krb5_clear_error_message(context); 773 return HDB_ERR_NOENTRY; 774 } 775 776 key_data.data = key.data; 777 key_data.length = key.size; 778 data.data = value.data; 779 data.length = value.size; 780 memset(entry, 0, sizeof(*entry)); 781 782 if (_hdb_mdb_value2entry(context, &data, 0, &entry->entry)) 783 return mdb_seq(context, db, flags, entry, R_NEXT); 784 785 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 786 code = hdb_unseal_keys (context, db, &entry->entry); 787 if (code) 788 hdb_free_entry (context, entry); 789 } 790 791 return code; 792 } 793 794 795 static krb5_error_code 796 mdb_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 797 { 798 return mdb_seq(context, db, flags, entry, R_FIRST); 799 } 800 801 802 static krb5_error_code 803 mdb_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 804 { 805 return mdb_seq(context, db, flags, entry, R_NEXT); 806 } 807 808 static krb5_error_code 809 mdb_rename(krb5_context context, HDB *db, const char *new_name) 810 { 811 int ret; 812 char *old = NULL; 813 char *new = NULL; 814 815 if (asprintf(&old, "%s.db", db->hdb_name) < 0) 816 goto out; 817 if (asprintf(&new, "%s.db", new_name) < 0) 818 goto out; 819 ret = rename(old, new); 820 if(ret) 821 goto out; 822 823 free(db->hdb_name); 824 db->hdb_name = strdup(new_name); 825 errno = 0; 826 827 out: 828 free(old); 829 free(new); 830 return errno; 831 } 832 833 static krb5_error_code 834 mdb__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply) 835 { 836 DB *d = (DB*)db->hdb_db; 837 DBT k, v; 838 int code; 839 840 k.data = key.data; 841 k.size = key.length; 842 code = db->hdb_lock(context, db, HDB_RLOCK); 843 if(code) 844 return code; 845 code = (*d->get)(d, &k, &v, 0); 846 db->hdb_unlock(context, db); 847 if(code < 0) { 848 code = errno; 849 krb5_set_error_message(context, code, "Database %s get error: %s", 850 db->hdb_name, strerror(code)); 851 return code; 852 } 853 if(code == 1) { 854 krb5_clear_error_message(context); 855 return HDB_ERR_NOENTRY; 856 } 857 858 krb5_data_copy(reply, v.data, v.size); 859 return 0; 860 } 861 862 static krb5_error_code 863 mdb__put(krb5_context context, HDB *db, int replace, 864 krb5_data key, krb5_data value) 865 { 866 DB *d = (DB*)db->hdb_db; 867 DBT k, v; 868 int code; 869 870 k.data = key.data; 871 k.size = key.length; 872 v.data = value.data; 873 v.size = value.length; 874 code = db->hdb_lock(context, db, HDB_WLOCK); 875 if(code) 876 return code; 877 code = (*d->put)(d, &k, &v, replace ? 0 : R_NOOVERWRITE); 878 db->hdb_unlock(context, db); 879 if(code < 0) { 880 code = errno; 881 krb5_set_error_message(context, code, "Database %s put error: %s", 882 db->hdb_name, strerror(code)); 883 return code; 884 } 885 if(code == 1) { 886 krb5_clear_error_message(context); 887 return HDB_ERR_EXISTS; 888 } 889 return 0; 890 } 891 892 static krb5_error_code 893 mdb__del(krb5_context context, HDB *db, krb5_data key) 894 { 895 DB *d = (DB*)db->hdb_db; 896 DBT k; 897 krb5_error_code code; 898 k.data = key.data; 899 k.size = key.length; 900 code = db->hdb_lock(context, db, HDB_WLOCK); 901 if(code) 902 return code; 903 code = (*d->del)(d, &k, 0); 904 db->hdb_unlock(context, db); 905 if(code == 1) { 906 code = errno; 907 krb5_set_error_message(context, code, "Database %s put error: %s", 908 db->hdb_name, strerror(code)); 909 return code; 910 } 911 if(code < 0) 912 return errno; 913 return 0; 914 } 915 916 static krb5_error_code 917 mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, 918 unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) 919 { 920 krb5_data key, value; 921 krb5_error_code ret; 922 923 ret = mdb_principal2key(context, principal, &key); 924 if (ret) 925 return ret; 926 ret = db->hdb__get(context, db, key, &value); 927 krb5_data_free(&key); 928 if(ret) 929 return ret; 930 ret = _hdb_mdb_value2entry(context, &value, kvno, &entry->entry); 931 krb5_data_free(&value); 932 if (ret) 933 return ret; 934 935 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 936 ret = hdb_unseal_keys (context, db, &entry->entry); 937 if (ret) { 938 hdb_free_entry(context, entry); 939 return ret; 940 } 941 } 942 943 return 0; 944 } 945 946 static krb5_error_code 947 mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 948 { 949 krb5_error_code ret; 950 krb5_storage *sp = NULL; 951 krb5_storage *spent = NULL; 952 krb5_data line = { 0, 0 }; 953 krb5_data kdb_ent = { 0, 0 }; 954 krb5_data key = { 0, 0 }; 955 krb5_data value = { 0, 0 }; 956 ssize_t sz; 957 958 if ((flags & HDB_F_PRECHECK) && (flags & HDB_F_REPLACE)) 959 return 0; 960 961 if ((flags & HDB_F_PRECHECK)) { 962 ret = mdb_principal2key(context, entry->entry.principal, &key); 963 if (ret) return ret; 964 ret = db->hdb__get(context, db, key, &value); 965 krb5_data_free(&key); 966 if (ret == 0) 967 krb5_data_free(&value); 968 if (ret == HDB_ERR_NOENTRY) 969 return 0; 970 return ret ? ret : HDB_ERR_EXISTS; 971 } 972 973 sp = krb5_storage_emem(); 974 if (!sp) return ENOMEM; 975 ret = _hdb_set_master_key_usage(context, db, 0); /* MIT KDB uses KU 0 */ 976 ret = hdb_seal_keys(context, db, &entry->entry); 977 if (ret) return ret; 978 ret = entry2mit_string_int(context, sp, &entry->entry); 979 if (ret) goto out; 980 sz = krb5_storage_write(sp, "\n", 2); /* NUL-terminate */ 981 ret = ENOMEM; 982 if (sz == -1) goto out; 983 ret = krb5_storage_to_data(sp, &line); 984 if (ret) goto out; 985 986 ret = ENOMEM; 987 spent = krb5_storage_emem(); 988 if (!spent) goto out; 989 ret = _hdb_mit_dump2mitdb_entry(context, line.data, spent); 990 if (ret) goto out; 991 ret = krb5_storage_to_data(spent, &kdb_ent); 992 if (ret) goto out; 993 ret = mdb_principal2key(context, entry->entry.principal, &key); 994 if (ret) goto out; 995 ret = mdb__put(context, db, 1, key, kdb_ent); 996 997 out: 998 if (sp) 999 krb5_storage_free(sp); 1000 if (spent) 1001 krb5_storage_free(spent); 1002 krb5_data_free(&line); 1003 krb5_data_free(&kdb_ent); 1004 krb5_data_free(&key); 1005 1006 return ret; 1007 } 1008 1009 static krb5_error_code 1010 mdb_remove(krb5_context context, HDB *db, 1011 unsigned flags, krb5_const_principal principal) 1012 { 1013 krb5_error_code code; 1014 krb5_data key; 1015 krb5_data value = { 0, 0 }; 1016 1017 if ((flags & HDB_F_PRECHECK)) { 1018 code = db->hdb__get(context, db, key, &value); 1019 krb5_data_free(&key); 1020 if (code == 0) { 1021 krb5_data_free(&value); 1022 return 0; 1023 } 1024 return code; 1025 } 1026 1027 mdb_principal2key(context, principal, &key); 1028 code = db->hdb__del(context, db, key); 1029 krb5_data_free(&key); 1030 return code; 1031 } 1032 1033 static krb5_error_code 1034 mdb_open(krb5_context context, HDB *db, int flags, mode_t mode) 1035 { 1036 char *fn; 1037 char *actual_fn; 1038 krb5_error_code ret; 1039 struct stat st; 1040 1041 if (asprintf(&fn, "%s.db", db->hdb_name) < 0) { 1042 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 1043 return ENOMEM; 1044 } 1045 1046 if (stat(fn, &st) == 0) 1047 actual_fn = fn; 1048 else 1049 actual_fn = db->hdb_name; 1050 db->hdb_db = dbopen(actual_fn, flags, mode, DB_BTREE, NULL); 1051 if (db->hdb_db == NULL) { 1052 switch (errno) { 1053 #ifdef EFTYPE 1054 case EFTYPE: 1055 #endif 1056 case EINVAL: 1057 db->hdb_db = dbopen(actual_fn, flags, mode, DB_HASH, NULL); 1058 } 1059 } 1060 free(fn); 1061 1062 if (db->hdb_db == NULL) { 1063 ret = errno; 1064 krb5_set_error_message(context, ret, "dbopen (%s): %s", 1065 db->hdb_name, strerror(ret)); 1066 return ret; 1067 } 1068 #if 0 1069 /* 1070 * Don't do this -- MIT won't be able to handle the 1071 * HDB_DB_FORMAT_ENTRY key. 1072 */ 1073 if ((flags & O_ACCMODE) != O_RDONLY) 1074 ret = hdb_init_db(context, db); 1075 #endif 1076 ret = hdb_check_db_format(context, db); 1077 if (ret == HDB_ERR_NOENTRY) { 1078 krb5_clear_error_message(context); 1079 return 0; 1080 } 1081 if (ret) { 1082 mdb_close(context, db); 1083 krb5_set_error_message(context, ret, "hdb_open: failed %s database %s", 1084 (flags & O_ACCMODE) == O_RDONLY ? 1085 "checking format of" : "initialize", 1086 db->hdb_name); 1087 } 1088 return ret; 1089 } 1090 1091 krb5_error_code 1092 hdb_mitdb_create(krb5_context context, HDB **db, 1093 const char *filename) 1094 { 1095 *db = calloc(1, sizeof(**db)); 1096 if (*db == NULL) { 1097 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 1098 return ENOMEM; 1099 } 1100 1101 (*db)->hdb_db = NULL; 1102 (*db)->hdb_name = strdup(filename); 1103 if ((*db)->hdb_name == NULL) { 1104 free(*db); 1105 *db = NULL; 1106 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 1107 return ENOMEM; 1108 } 1109 (*db)->hdb_master_key_set = 0; 1110 (*db)->hdb_openp = 0; 1111 (*db)->hdb_capability_flags = 0; 1112 (*db)->hdb_open = mdb_open; 1113 (*db)->hdb_close = mdb_close; 1114 (*db)->hdb_fetch_kvno = mdb_fetch_kvno; 1115 (*db)->hdb_store = mdb_store; 1116 (*db)->hdb_remove = mdb_remove; 1117 (*db)->hdb_firstkey = mdb_firstkey; 1118 (*db)->hdb_nextkey= mdb_nextkey; 1119 (*db)->hdb_lock = mdb_lock; 1120 (*db)->hdb_unlock = mdb_unlock; 1121 (*db)->hdb_rename = mdb_rename; 1122 (*db)->hdb__get = mdb__get; 1123 (*db)->hdb__put = mdb__put; 1124 (*db)->hdb__del = mdb__del; 1125 (*db)->hdb_destroy = mdb_destroy; 1126 return 0; 1127 } 1128 1129 #endif /* HAVE_DB1 */ 1130 1131 /* 1132 can have any number of princ stanzas. 1133 format is as follows (only \n indicates newlines) 1134 princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38) 1135 %d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU) 1136 %d\t (number of tl_data) 1137 %d\t (number of key data, e.g. how many keys for this user) 1138 %d\t (extra data length) 1139 %s\t (principal name) 1140 %d\t (attributes) 1141 %d\t (max lifetime, seconds) 1142 %d\t (max renewable life, seconds) 1143 %d\t (expiration, seconds since epoch or 2145830400 for never) 1144 %d\t (password expiration, seconds, 0 for never) 1145 %d\t (last successful auth, seconds since epoch) 1146 %d\t (last failed auth, per above) 1147 %d\t (failed auth count) 1148 foreach tl_data 0 to number of tl_data - 1 as above 1149 %d\t%d\t (data type, data length) 1150 foreach tl_data 0 to length-1 1151 %02x (tl data contents[element n]) 1152 except if tl_data length is 0 1153 %d (always -1) 1154 \t 1155 foreach key 0 to number of keys - 1 as above 1156 %d\t%d\t (key data version, kvno) 1157 foreach version 0 to key data version - 1 (a key or a salt) 1158 %d\t%d\t(data type for this key, data length for this key) 1159 foreach key data length 0 to length-1 1160 %02x (key data contents[element n]) 1161 except if key_data length is 0 1162 %d (always -1) 1163 \t 1164 foreach extra data length 0 to length - 1 1165 %02x (extra data part) 1166 unless no extra data 1167 %d (always -1) 1168 ;\n 1169 1170 */ 1171 1172 #if 0 1173 /* Why ever did we loop? */ 1174 static char * 1175 nexttoken(char **p) 1176 { 1177 char *q; 1178 do { 1179 q = strsep(p, " \t"); 1180 } while(q && *q == '\0'); 1181 return q; 1182 } 1183 #endif 1184 1185 static char * 1186 nexttoken(char **p, size_t len, const char *what) 1187 { 1188 char *q; 1189 1190 if (*p == NULL) 1191 return NULL; 1192 1193 q = *p; 1194 *p += len; 1195 /* Must be followed by a delimiter (right?) */ 1196 if (strsep(p, " \t") != q + len) { 1197 warnx("No tokens left in dump entry while looking for %s", what); 1198 return NULL; 1199 } 1200 if (*q == '\0') 1201 warnx("Empty last token in dump entry while looking for %s", what); 1202 return q; 1203 } 1204 1205 static size_t 1206 getdata(char **p, unsigned char *buf, size_t len, const char *what) 1207 { 1208 size_t i; 1209 int v; 1210 char *q = nexttoken(p, 0, what); 1211 if (q == NULL) { 1212 warnx("Failed to find hex-encoded binary data (%s) in dump", what); 1213 return 0; 1214 } 1215 i = 0; 1216 while (*q && i < len) { 1217 if (sscanf(q, "%02x", &v) != 1) 1218 break; 1219 buf[i++] = v; 1220 q += 2; 1221 } 1222 return i; 1223 } 1224 1225 static int 1226 getint(char **p, const char *what) 1227 { 1228 int val; 1229 char *q = nexttoken(p, 0, what); 1230 if (!q) { 1231 warnx("Failed to find a signed integer (%s) in dump", what); 1232 return -1; 1233 } 1234 if (sscanf(q, "%d", &val) != 1) 1235 return -1; 1236 return val; 1237 } 1238 1239 static unsigned int 1240 getuint(char **p, const char *what) 1241 { 1242 int val; 1243 char *q = nexttoken(p, 0, what); 1244 if (!q) { 1245 warnx("Failed to find an unsigned integer (%s) in dump", what); 1246 return 0; 1247 } 1248 if (sscanf(q, "%u", &val) != 1) 1249 return 0; 1250 return val; 1251 } 1252 1253 #define KRB5_KDB_SALTTYPE_NORMAL 0 1254 #define KRB5_KDB_SALTTYPE_V4 1 1255 #define KRB5_KDB_SALTTYPE_NOREALM 2 1256 #define KRB5_KDB_SALTTYPE_ONLYREALM 3 1257 #define KRB5_KDB_SALTTYPE_SPECIAL 4 1258 #define KRB5_KDB_SALTTYPE_AFS3 5 1259 1260 #define CHECK_UINT(num) \ 1261 if ((num) < 0 || (num) > INT_MAX) return EINVAL 1262 #define CHECK_UINT16(num) \ 1263 if ((num) < 0 || (num) > 1<<15) return EINVAL 1264 #define CHECK_NUM(num, maxv) \ 1265 if ((num) > (maxv)) return EINVAL 1266 1267 /* 1268 * This utility function converts an MIT dump entry to an MIT on-disk 1269 * encoded entry, which can then be decoded with _hdb_mdb_value2entry(). 1270 * This allows us to have a single decoding function (_hdb_mdb_value2entry), 1271 * which makes the code cleaner (less code duplication), if a bit less 1272 * efficient. It also will allow us to have a function to dump an HDB 1273 * entry in MIT format so we can dump HDB into MIT format for rollback 1274 * purposes. And that will allow us to write to MIT KDBs, again 1275 * somewhat inefficiently, also for migration/rollback purposes. 1276 */ 1277 int 1278 _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) 1279 { 1280 krb5_error_code ret = EINVAL; 1281 char *p = line, *q; 1282 char *princ; 1283 ssize_t sz; 1284 size_t i; 1285 size_t princ_len; 1286 unsigned int num_tl_data; 1287 size_t num_key_data; 1288 unsigned int attributes; 1289 int tmp; 1290 1291 krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); 1292 1293 q = nexttoken(&p, 0, "record type (princ or policy)"); 1294 if (strcmp(q, "kdb5_util") == 0 || strcmp(q, "policy") == 0 || 1295 strcmp(q, "princ") != 0) { 1296 warnx("Supposed MIT dump entry does not start with 'kdb5_util', " 1297 "'policy', nor 'princ'"); 1298 return -1; 1299 } 1300 if (getint(&p, "constant '38'") != 38) { 1301 warnx("Dump entry does not start with '38<TAB>'"); 1302 return EINVAL; 1303 } 1304 #define KDB_V1_BASE_LENGTH 38 1305 ret = krb5_store_int16(sp, KDB_V1_BASE_LENGTH); 1306 if (ret) return ret; 1307 1308 princ_len = getuint(&p, "principal name length"); 1309 if (princ_len > (1<<15) - 1) { 1310 warnx("Principal name in dump entry too long (%llu)", 1311 (unsigned long long)princ_len); 1312 return EINVAL; 1313 } 1314 num_tl_data = getuint(&p, "number of TL data"); 1315 num_key_data = getuint(&p, "number of key data"); 1316 getint(&p, "5th field, length of 'extra data'"); 1317 princ = nexttoken(&p, (int)princ_len, "principal name"); 1318 if (princ == NULL) { 1319 warnx("Failed to read principal name (expected length %llu)", 1320 (unsigned long long)princ_len); 1321 return -1; 1322 } 1323 1324 attributes = getuint(&p, "attributes"); 1325 ret = krb5_store_uint32(sp, attributes); 1326 if (ret) return ret; 1327 1328 tmp = getint(&p, "max life"); 1329 CHECK_UINT(tmp); 1330 ret = krb5_store_uint32(sp, tmp); 1331 if (ret) return ret; 1332 1333 tmp = getint(&p, "max renewable life"); 1334 CHECK_UINT(tmp); 1335 ret = krb5_store_uint32(sp, tmp); 1336 if (ret) return ret; 1337 1338 tmp = getint(&p, "expiration"); 1339 CHECK_UINT(tmp); 1340 ret = krb5_store_uint32(sp, tmp); 1341 if (ret) return ret; 1342 1343 tmp = getint(&p, "pw expiration"); 1344 CHECK_UINT(tmp); 1345 ret = krb5_store_uint32(sp, tmp); 1346 if (ret) return ret; 1347 1348 tmp = getint(&p, "last auth"); 1349 CHECK_UINT(tmp); 1350 ret = krb5_store_uint32(sp, tmp); 1351 if (ret) return ret; 1352 1353 tmp = getint(&p, "last failed auth"); 1354 CHECK_UINT(tmp); 1355 ret = krb5_store_uint32(sp, tmp); 1356 if (ret) return ret; 1357 1358 tmp = getint(&p,"fail auth count"); 1359 CHECK_UINT(tmp); 1360 ret = krb5_store_uint32(sp, tmp); 1361 if (ret) return ret; 1362 1363 /* add TL data count */ 1364 CHECK_NUM(num_tl_data, 1023); 1365 ret = krb5_store_uint16(sp, num_tl_data); 1366 if (ret) return ret; 1367 1368 /* add key count */ 1369 CHECK_NUM(num_key_data, 1023); 1370 ret = krb5_store_uint16(sp, num_key_data); 1371 if (ret) return ret; 1372 1373 /* add principal unparsed name length and unparsed name */ 1374 princ_len = strlen(princ); 1375 princ_len++; /* must count and write the NUL in the on-disk encoding */ 1376 ret = krb5_store_uint16(sp, princ_len); 1377 if (ret) return ret; 1378 sz = krb5_storage_write(sp, princ, princ_len); 1379 if (sz == -1) return ENOMEM; 1380 1381 /* scan and write TL data */ 1382 for (i = 0; i < num_tl_data; i++) { 1383 char *reading_what; 1384 int tl_type, tl_length; 1385 unsigned char *buf; 1386 1387 tl_type = getint(&p, "TL data type"); 1388 tl_length = getint(&p, "data length"); 1389 1390 if (asprintf(&reading_what, "TL data type %d (length %d)", 1391 tl_type, tl_length) < 0) 1392 return ENOMEM; 1393 1394 /* 1395 * XXX Leaking reading_what, but only on ENOMEM cases anyways, 1396 * so we don't care. 1397 */ 1398 CHECK_UINT16(tl_type); 1399 ret = krb5_store_uint16(sp, tl_type); 1400 if (ret) return ret; 1401 CHECK_UINT16(tl_length); 1402 ret = krb5_store_uint16(sp, tl_length); 1403 if (ret) return ret; 1404 1405 if (tl_length) { 1406 buf = malloc(tl_length); 1407 if (!buf) return ENOMEM; 1408 if (getdata(&p, buf, tl_length, reading_what) != tl_length) 1409 return EINVAL; 1410 sz = krb5_storage_write(sp, buf, tl_length); 1411 free(buf); 1412 if (sz == -1) return ENOMEM; 1413 } else { 1414 if (strcmp(nexttoken(&p, 0, "'-1' field"), "-1") != 0) return EINVAL; 1415 } 1416 free(reading_what); 1417 } 1418 1419 for (i = 0; i < num_key_data; i++) { 1420 unsigned char *buf; 1421 int key_versions; 1422 int kvno; 1423 int keytype; 1424 int keylen; 1425 size_t k; 1426 1427 key_versions = getint(&p, "key data 'version'"); 1428 CHECK_UINT16(key_versions); 1429 ret = krb5_store_int16(sp, key_versions); 1430 if (ret) return ret; 1431 1432 kvno = getint(&p, "kvno"); 1433 CHECK_UINT16(kvno); 1434 ret = krb5_store_int16(sp, kvno); 1435 if (ret) return ret; 1436 1437 for (k = 0; k < key_versions; k++) { 1438 keytype = getint(&p, "enctype"); 1439 CHECK_UINT16(keytype); 1440 ret = krb5_store_int16(sp, keytype); 1441 if (ret) return ret; 1442 1443 keylen = getint(&p, "encrypted key length"); 1444 CHECK_UINT16(keylen); 1445 ret = krb5_store_int16(sp, keylen); 1446 if (ret) return ret; 1447 1448 if (keylen) { 1449 buf = malloc(keylen); 1450 if (!buf) return ENOMEM; 1451 if (getdata(&p, buf, keylen, "key (or salt) data") != keylen) 1452 return EINVAL; 1453 sz = krb5_storage_write(sp, buf, keylen); 1454 free(buf); 1455 if (sz == -1) return ENOMEM; 1456 } else { 1457 if (strcmp(nexttoken(&p, 0, 1458 "'-1' zero-length key/salt field"), 1459 "-1") != 0) { 1460 warnx("Expected '-1' field because key/salt length is 0"); 1461 return -1; 1462 } 1463 } 1464 } 1465 } 1466 /* 1467 * The rest is "extra data", but there's never any and we wouldn't 1468 * know what to do with it. 1469 */ 1470 /* nexttoken(&p, 0, "extra data"); */ 1471 return 0; 1472 } 1473 1474