1 /* 2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. 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 #define KRB5_KDB_DISALLOW_POSTDATED 0x00000001 37 #define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002 38 #define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004 39 #define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008 40 #define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010 41 #define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020 42 #define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040 43 #define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080 44 #define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100 45 #define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200 46 #define KRB5_KDB_DISALLOW_SVR 0x00001000 47 #define KRB5_KDB_PWCHANGE_SERVICE 0x00002000 48 #define KRB5_KDB_SUPPORT_DESMD5 0x00004000 49 #define KRB5_KDB_NEW_PRINC 0x00008000 50 51 /* 52 53 key: krb5_unparse_name + NUL 54 55 16: baselength 56 32: attributes 57 32: max time 58 32: max renewable time 59 32: client expire 60 32: passwd expire 61 32: last successful passwd 62 32: last failed attempt 63 32: num of failed attempts 64 16: num tl data 65 16: num data data 66 16: principal length 67 length: principal 68 for num tl data times 69 16: tl data type 70 16: tl data length 71 length: length 72 for num key data times 73 16: version (num keyblocks) 74 16: kvno 75 for version times: 76 16: type 77 16: length 78 length: keydata 79 80 81 key_data_contents[0] 82 83 int16: length 84 read-of-data: key-encrypted, key-usage 0, master-key 85 86 salt: 87 version2 = salt in key_data->key_data_contents[1] 88 else default salt. 89 90 */ 91 92 #include "hdb_locl.h" 93 94 static void 95 attr_to_flags(unsigned attr, HDBFlags *flags) 96 { 97 flags->postdate = !(attr & KRB5_KDB_DISALLOW_POSTDATED); 98 flags->forwardable = !(attr & KRB5_KDB_DISALLOW_FORWARDABLE); 99 flags->initial = !!(attr & KRB5_KDB_DISALLOW_TGT_BASED); 100 flags->renewable = !(attr & KRB5_KDB_DISALLOW_RENEWABLE); 101 flags->proxiable = !(attr & KRB5_KDB_DISALLOW_PROXIABLE); 102 /* DUP_SKEY */ 103 flags->invalid = !!(attr & KRB5_KDB_DISALLOW_ALL_TIX); 104 flags->require_preauth = !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH); 105 flags->require_hwauth = !!(attr & KRB5_KDB_REQUIRES_HW_AUTH); 106 flags->server = !(attr & KRB5_KDB_DISALLOW_SVR); 107 flags->change_pw = !!(attr & KRB5_KDB_PWCHANGE_SERVICE); 108 flags->client = 1; /* XXX */ 109 } 110 111 #define KDB_V1_BASE_LENGTH 38 112 113 #define CHECK(x) do { if ((x)) goto out; } while(0) 114 115 #ifdef HAVE_DB1 116 static krb5_error_code 117 mdb_principal2key(krb5_context context, 118 krb5_const_principal principal, 119 krb5_data *key) 120 { 121 krb5_error_code ret; 122 char *str; 123 124 ret = krb5_unparse_name(context, principal, &str); 125 if (ret) 126 return ret; 127 key->data = str; 128 key->length = strlen(str) + 1; 129 return 0; 130 } 131 #endif /* HAVE_DB1 */ 132 133 #define KRB5_KDB_SALTTYPE_NORMAL 0 134 #define KRB5_KDB_SALTTYPE_V4 1 135 #define KRB5_KDB_SALTTYPE_NOREALM 2 136 #define KRB5_KDB_SALTTYPE_ONLYREALM 3 137 #define KRB5_KDB_SALTTYPE_SPECIAL 4 138 #define KRB5_KDB_SALTTYPE_AFS3 5 139 #define KRB5_KDB_SALTTYPE_CERTHASH 6 140 141 static krb5_error_code 142 fix_salt(krb5_context context, hdb_entry *ent, int key_num) 143 { 144 krb5_error_code ret; 145 Salt *salt = ent->keys.val[key_num].salt; 146 /* fix salt type */ 147 switch((int)salt->type) { 148 case KRB5_KDB_SALTTYPE_NORMAL: 149 salt->type = KRB5_PADATA_PW_SALT; 150 break; 151 case KRB5_KDB_SALTTYPE_V4: 152 krb5_data_free(&salt->salt); 153 salt->type = KRB5_PADATA_PW_SALT; 154 break; 155 case KRB5_KDB_SALTTYPE_NOREALM: 156 { 157 size_t len; 158 size_t i; 159 char *p; 160 161 len = 0; 162 for (i = 0; i < ent->principal->name.name_string.len; ++i) 163 len += strlen(ent->principal->name.name_string.val[i]); 164 ret = krb5_data_alloc (&salt->salt, len); 165 if (ret) 166 return ret; 167 p = salt->salt.data; 168 for (i = 0; i < ent->principal->name.name_string.len; ++i) { 169 memcpy (p, 170 ent->principal->name.name_string.val[i], 171 strlen(ent->principal->name.name_string.val[i])); 172 p += strlen(ent->principal->name.name_string.val[i]); 173 } 174 175 salt->type = KRB5_PADATA_PW_SALT; 176 break; 177 } 178 case KRB5_KDB_SALTTYPE_ONLYREALM: 179 krb5_data_free(&salt->salt); 180 ret = krb5_data_copy(&salt->salt, 181 ent->principal->realm, 182 strlen(ent->principal->realm)); 183 if(ret) 184 return ret; 185 salt->type = KRB5_PADATA_PW_SALT; 186 break; 187 case KRB5_KDB_SALTTYPE_SPECIAL: 188 salt->type = KRB5_PADATA_PW_SALT; 189 break; 190 case KRB5_KDB_SALTTYPE_AFS3: 191 krb5_data_free(&salt->salt); 192 ret = krb5_data_copy(&salt->salt, 193 ent->principal->realm, 194 strlen(ent->principal->realm)); 195 if(ret) 196 return ret; 197 salt->type = KRB5_PADATA_AFS3_SALT; 198 break; 199 case KRB5_KDB_SALTTYPE_CERTHASH: 200 krb5_data_free(&salt->salt); 201 free(ent->keys.val[key_num].salt); 202 ent->keys.val[key_num].salt = NULL; 203 break; 204 default: 205 abort(); 206 } 207 return 0; 208 } 209 210 211 krb5_error_code 212 _hdb_mdb_value2entry(krb5_context context, krb5_data *data, 213 krb5_kvno kvno, hdb_entry *entry) 214 { 215 krb5_error_code ret; 216 krb5_storage *sp; 217 uint32_t u32; 218 uint16_t u16, num_keys, num_tl; 219 ssize_t sz; 220 size_t i, j; 221 char *p; 222 223 sp = krb5_storage_from_data(data); 224 if (sp == NULL) { 225 krb5_set_error_message(context, ENOMEM, "out of memory"); 226 return ENOMEM; 227 } 228 229 krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); 230 231 /* 232 * 16: baselength 233 * 234 * The story here is that these 16 bits have to be a constant: 235 * KDB_V1_BASE_LENGTH. Once upon a time a different value here 236 * would have been used to indicate the presence of "extra data" 237 * between the "base" contents and the {principal name, TL data, 238 * keys} that follow it. Nothing supports such "extra data" 239 * nowadays, so neither do we here. 240 * 241 * XXX But... surely we ought to log about this extra data, or skip 242 * it, or something, in case anyone has MIT KDBs with ancient 243 * entries in them... Logging would allow the admin to know which 244 * entries to dump with MIT krb5's kdb5_util. 245 */ 246 CHECK(ret = krb5_ret_uint16(sp, &u16)); 247 if (u16 != KDB_V1_BASE_LENGTH) { ret = EINVAL; goto out; } 248 /* 32: attributes */ 249 CHECK(ret = krb5_ret_uint32(sp, &u32)); 250 attr_to_flags(u32, &entry->flags); 251 252 /* 32: max time */ 253 CHECK(ret = krb5_ret_uint32(sp, &u32)); 254 if (u32) { 255 entry->max_life = malloc(sizeof(*entry->max_life)); 256 *entry->max_life = u32; 257 } 258 /* 32: max renewable time */ 259 CHECK(ret = krb5_ret_uint32(sp, &u32)); 260 if (u32) { 261 entry->max_renew = malloc(sizeof(*entry->max_renew)); 262 *entry->max_renew = u32; 263 } 264 /* 32: client expire */ 265 CHECK(ret = krb5_ret_uint32(sp, &u32)); 266 if (u32) { 267 entry->valid_end = malloc(sizeof(*entry->valid_end)); 268 *entry->valid_end = u32; 269 } 270 /* 32: passwd expire */ 271 CHECK(ret = krb5_ret_uint32(sp, &u32)); 272 if (u32) { 273 entry->pw_end = malloc(sizeof(*entry->pw_end)); 274 *entry->pw_end = u32; 275 } 276 /* 32: last successful passwd */ 277 CHECK(ret = krb5_ret_uint32(sp, &u32)); 278 /* 32: last failed attempt */ 279 CHECK(ret = krb5_ret_uint32(sp, &u32)); 280 /* 32: num of failed attempts */ 281 CHECK(ret = krb5_ret_uint32(sp, &u32)); 282 /* 16: num tl data */ 283 CHECK(ret = krb5_ret_uint16(sp, &u16)); 284 num_tl = u16; 285 /* 16: num key data */ 286 CHECK(ret = krb5_ret_uint16(sp, &u16)); 287 num_keys = u16; 288 /* 16: principal length */ 289 CHECK(ret = krb5_ret_uint16(sp, &u16)); 290 /* length: principal */ 291 { 292 /* 293 * Note that the principal name includes the NUL in the entry, 294 * but we don't want to take chances, so we add an extra NUL. 295 */ 296 p = malloc(u16 + 1); 297 if (p == NULL) { 298 ret = ENOMEM; 299 goto out; 300 } 301 sz = krb5_storage_read(sp, p, u16); 302 if (sz != u16) { 303 ret = EINVAL; /* XXX */ 304 goto out; 305 } 306 p[u16] = '\0'; 307 CHECK(ret = krb5_parse_name(context, p, &entry->principal)); 308 free(p); 309 } 310 /* for num tl data times 311 16: tl data type 312 16: tl data length 313 length: length */ 314 #define mit_KRB5_TL_LAST_PWD_CHANGE 1 315 #define mit_KRB5_TL_MOD_PRINC 2 316 for (i = 0; i < num_tl; i++) { 317 int tl_type; 318 krb5_principal modby; 319 /* 16: TL data type */ 320 CHECK(ret = krb5_ret_uint16(sp, &u16)); 321 tl_type = u16; 322 /* 16: TL data length */ 323 CHECK(ret = krb5_ret_uint16(sp, &u16)); 324 /* 325 * For rollback to MIT purposes we really must understand some 326 * TL data! 327 * 328 * XXX Move all this to separate functions, one per-TL type. 329 */ 330 switch (tl_type) { 331 case mit_KRB5_TL_LAST_PWD_CHANGE: 332 CHECK(ret = krb5_ret_uint32(sp, &u32)); 333 CHECK(ret = hdb_entry_set_pw_change_time(context, entry, u32)); 334 break; 335 case mit_KRB5_TL_MOD_PRINC: 336 if (u16 < 5) { 337 ret = EINVAL; /* XXX */ 338 goto out; 339 } 340 CHECK(ret = krb5_ret_uint32(sp, &u32)); /* mod time */ 341 p = malloc(u16 - 4 + 1); 342 if (!p) { 343 ret = ENOMEM; 344 goto out; 345 } 346 p[u16 - 4] = '\0'; 347 sz = krb5_storage_read(sp, p, u16 - 4); 348 if (sz != u16 - 4) { 349 ret = EINVAL; /* XXX */ 350 goto out; 351 } 352 CHECK(ret = krb5_parse_name(context, p, &modby)); 353 ret = hdb_set_last_modified_by(context, entry, modby, u32); 354 krb5_free_principal(context, modby); 355 free(p); 356 break; 357 default: 358 krb5_storage_seek(sp, u16, SEEK_CUR); 359 break; 360 } 361 } 362 /* 363 * for num key data times 364 * 16: "version" 365 * 16: kvno 366 * for version times: 367 * 16: type 368 * 16: length 369 * length: keydata 370 * 371 * "version" here is really 1 or 2, the first meaning there's only 372 * keys for this kvno, the second meaning there's keys and salt[s?]. 373 * That's right... hold that gag reflex, you can do it. 374 */ 375 for (i = 0; i < num_keys; i++) { 376 int keep = 0; 377 uint16_t version; 378 void *ptr; 379 380 CHECK(ret = krb5_ret_uint16(sp, &u16)); 381 version = u16; 382 CHECK(ret = krb5_ret_uint16(sp, &u16)); 383 384 /* 385 * First time through, and until we find one matching key, 386 * entry->kvno == 0. 387 */ 388 if ((entry->kvno < u16) && (kvno == 0 || kvno == u16)) { 389 keep = 1; 390 entry->kvno = u16; 391 /* 392 * Found a higher kvno than earlier, so free the old highest 393 * kvno keys. 394 * 395 * XXX Of course, we actually want to extract the old kvnos 396 * as well, for some of the kadm5 APIs. We shouldn't free 397 * these keys, but keep them elsewhere. 398 */ 399 for (j = 0; j < entry->keys.len; j++) 400 free_Key(&entry->keys.val[j]); 401 free(entry->keys.val); 402 entry->keys.len = 0; 403 entry->keys.val = NULL; 404 } else if (entry->kvno == u16) 405 /* Accumulate keys */ 406 keep = 1; 407 408 if (keep) { 409 Key *k; 410 411 ptr = realloc(entry->keys.val, sizeof(entry->keys.val[0]) * (entry->keys.len + 1)); 412 if (ptr == NULL) { 413 ret = ENOMEM; 414 goto out; 415 } 416 entry->keys.val = ptr; 417 418 /* k points to current Key */ 419 k = &entry->keys.val[entry->keys.len]; 420 421 memset(k, 0, sizeof(*k)); 422 entry->keys.len += 1; 423 424 k->mkvno = malloc(sizeof(*k->mkvno)); 425 if (k->mkvno == NULL) { 426 ret = ENOMEM; 427 goto out; 428 } 429 *k->mkvno = 1; 430 431 for (j = 0; j < version; j++) { 432 uint16_t type; 433 CHECK(ret = krb5_ret_uint16(sp, &type)); 434 CHECK(ret = krb5_ret_uint16(sp, &u16)); 435 if (j == 0) { 436 /* This "version" means we have a key */ 437 k->key.keytype = type; 438 if (u16 < 2) { 439 ret = EINVAL; 440 goto out; 441 } 442 /* 443 * MIT stores keys encrypted keys as {16-bit length 444 * of plaintext key, {encrypted key}}. The reason 445 * for this is that the Kerberos cryptosystem is not 446 * length-preserving. Heimdal's approach is to 447 * truncate the plaintext to the expected length of 448 * the key given its enctype, so we ignore this 449 * 16-bit length-of-plaintext-key field. 450 */ 451 krb5_storage_seek(sp, 2, SEEK_CUR); /* skip real length */ 452 k->key.keyvalue.length = u16 - 2; /* adjust cipher len */ 453 k->key.keyvalue.data = malloc(k->key.keyvalue.length); 454 krb5_storage_read(sp, k->key.keyvalue.data, 455 k->key.keyvalue.length); 456 } else if (j == 1) { 457 /* This "version" means we have a salt */ 458 k->salt = calloc(1, sizeof(*k->salt)); 459 if (k->salt == NULL) { 460 ret = ENOMEM; 461 goto out; 462 } 463 k->salt->type = type; 464 if (u16 != 0) { 465 k->salt->salt.data = malloc(u16); 466 if (k->salt->salt.data == NULL) { 467 ret = ENOMEM; 468 goto out; 469 } 470 k->salt->salt.length = u16; 471 krb5_storage_read(sp, k->salt->salt.data, k->salt->salt.length); 472 } 473 fix_salt(context, entry, entry->keys.len - 1); 474 } else { 475 /* 476 * Whatever this "version" might be, we skip it 477 * 478 * XXX A krb5.conf parameter requesting that we log 479 * about strangeness like this, or return an error 480 * from here, might be nice. 481 */ 482 krb5_storage_seek(sp, u16, SEEK_CUR); 483 } 484 } 485 } else { 486 /* 487 * XXX For now we skip older kvnos, but we should extract 488 * them... 489 */ 490 for (j = 0; j < version; j++) { 491 /* enctype */ 492 CHECK(ret = krb5_ret_uint16(sp, &u16)); 493 /* encrypted key (or plaintext salt) */ 494 CHECK(ret = krb5_ret_uint16(sp, &u16)); 495 krb5_storage_seek(sp, u16, SEEK_CUR); 496 } 497 } 498 } 499 500 if (entry->kvno == 0 && kvno != 0) { 501 ret = HDB_ERR_NOT_FOUND_HERE; 502 goto out; 503 } 504 505 return 0; 506 out: 507 if (ret == HEIM_ERR_EOF) 508 /* Better error code than "end of file" */ 509 ret = HEIM_ERR_BAD_HDBENT_ENCODING; 510 return ret; 511 } 512 513 #if 0 514 static krb5_error_code 515 mdb_entry2value(krb5_context context, hdb_entry *entry, krb5_data *data) 516 { 517 return EINVAL; 518 } 519 #endif 520 521 #if HAVE_DB1 522 523 #if defined(HAVE_DB_185_H) 524 #include <db_185.h> 525 #elif defined(HAVE_DB_H) 526 #include <db.h> 527 #endif 528 529 530 static krb5_error_code 531 mdb_close(krb5_context context, HDB *db) 532 { 533 DB *d = (DB*)db->hdb_db; 534 (*d->close)(d); 535 return 0; 536 } 537 538 static krb5_error_code 539 mdb_destroy(krb5_context context, HDB *db) 540 { 541 krb5_error_code ret; 542 543 ret = hdb_clear_master_key (context, db); 544 free(db->hdb_name); 545 free(db); 546 return ret; 547 } 548 549 static krb5_error_code 550 mdb_lock(krb5_context context, HDB *db, int operation) 551 { 552 DB *d = (DB*)db->hdb_db; 553 int fd = (*d->fd)(d); 554 if(fd < 0) { 555 krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB, 556 "Can't lock database: %s", db->hdb_name); 557 return HDB_ERR_CANT_LOCK_DB; 558 } 559 return hdb_lock(fd, operation); 560 } 561 562 static krb5_error_code 563 mdb_unlock(krb5_context context, HDB *db) 564 { 565 DB *d = (DB*)db->hdb_db; 566 int fd = (*d->fd)(d); 567 if(fd < 0) { 568 krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB, 569 "Can't unlock database: %s", db->hdb_name); 570 return HDB_ERR_CANT_LOCK_DB; 571 } 572 return hdb_unlock(fd); 573 } 574 575 576 static krb5_error_code 577 mdb_seq(krb5_context context, HDB *db, 578 unsigned flags, hdb_entry_ex *entry, int flag) 579 { 580 DB *d = (DB*)db->hdb_db; 581 DBT key, value; 582 krb5_data key_data, data; 583 int code; 584 585 code = db->hdb_lock(context, db, HDB_RLOCK); 586 if(code == -1) { 587 krb5_set_error_message(context, HDB_ERR_DB_INUSE, "Database %s in use", db->hdb_name); 588 return HDB_ERR_DB_INUSE; 589 } 590 code = (*d->seq)(d, &key, &value, flag); 591 db->hdb_unlock(context, db); /* XXX check value */ 592 if(code == -1) { 593 code = errno; 594 krb5_set_error_message(context, code, "Database %s seq error: %s", 595 db->hdb_name, strerror(code)); 596 return code; 597 } 598 if(code == 1) { 599 krb5_clear_error_message(context); 600 return HDB_ERR_NOENTRY; 601 } 602 603 key_data.data = key.data; 604 key_data.length = key.size; 605 data.data = value.data; 606 data.length = value.size; 607 memset(entry, 0, sizeof(*entry)); 608 609 if (_hdb_mdb_value2entry(context, &data, 0, &entry->entry)) 610 return mdb_seq(context, db, flags, entry, R_NEXT); 611 612 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 613 code = hdb_unseal_keys (context, db, &entry->entry); 614 if (code) 615 hdb_free_entry (context, entry); 616 } 617 618 return code; 619 } 620 621 622 static krb5_error_code 623 mdb_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 624 { 625 return mdb_seq(context, db, flags, entry, R_FIRST); 626 } 627 628 629 static krb5_error_code 630 mdb_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 631 { 632 return mdb_seq(context, db, flags, entry, R_NEXT); 633 } 634 635 static krb5_error_code 636 mdb_rename(krb5_context context, HDB *db, const char *new_name) 637 { 638 int ret; 639 char *old, *new; 640 641 asprintf(&old, "%s.db", db->hdb_name); 642 asprintf(&new, "%s.db", new_name); 643 ret = rename(old, new); 644 free(old); 645 free(new); 646 if(ret) 647 return errno; 648 649 free(db->hdb_name); 650 db->hdb_name = strdup(new_name); 651 return 0; 652 } 653 654 static krb5_error_code 655 mdb__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply) 656 { 657 DB *d = (DB*)db->hdb_db; 658 DBT k, v; 659 int code; 660 661 k.data = key.data; 662 k.size = key.length; 663 code = db->hdb_lock(context, db, HDB_RLOCK); 664 if(code) 665 return code; 666 code = (*d->get)(d, &k, &v, 0); 667 db->hdb_unlock(context, db); 668 if(code < 0) { 669 code = errno; 670 krb5_set_error_message(context, code, "Database %s get error: %s", 671 db->hdb_name, strerror(code)); 672 return code; 673 } 674 if(code == 1) { 675 krb5_clear_error_message(context); 676 return HDB_ERR_NOENTRY; 677 } 678 679 krb5_data_copy(reply, v.data, v.size); 680 return 0; 681 } 682 683 static krb5_error_code 684 mdb__put(krb5_context context, HDB *db, int replace, 685 krb5_data key, krb5_data value) 686 { 687 DB *d = (DB*)db->hdb_db; 688 DBT k, v; 689 int code; 690 691 k.data = key.data; 692 k.size = key.length; 693 v.data = value.data; 694 v.size = value.length; 695 code = db->hdb_lock(context, db, HDB_WLOCK); 696 if(code) 697 return code; 698 code = (*d->put)(d, &k, &v, replace ? 0 : R_NOOVERWRITE); 699 db->hdb_unlock(context, db); 700 if(code < 0) { 701 code = errno; 702 krb5_set_error_message(context, code, "Database %s put error: %s", 703 db->hdb_name, strerror(code)); 704 return code; 705 } 706 if(code == 1) { 707 krb5_clear_error_message(context); 708 return HDB_ERR_EXISTS; 709 } 710 return 0; 711 } 712 713 static krb5_error_code 714 mdb__del(krb5_context context, HDB *db, krb5_data key) 715 { 716 DB *d = (DB*)db->hdb_db; 717 DBT k; 718 krb5_error_code code; 719 k.data = key.data; 720 k.size = key.length; 721 code = db->hdb_lock(context, db, HDB_WLOCK); 722 if(code) 723 return code; 724 code = (*d->del)(d, &k, 0); 725 db->hdb_unlock(context, db); 726 if(code == 1) { 727 code = errno; 728 krb5_set_error_message(context, code, "Database %s put error: %s", 729 db->hdb_name, strerror(code)); 730 return code; 731 } 732 if(code < 0) 733 return errno; 734 return 0; 735 } 736 737 static krb5_error_code 738 mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, 739 unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) 740 { 741 krb5_data key, value; 742 krb5_error_code ret; 743 744 ret = mdb_principal2key(context, principal, &key); 745 if (ret) 746 return ret; 747 ret = db->hdb__get(context, db, key, &value); 748 krb5_data_free(&key); 749 if(ret) 750 return ret; 751 ret = _hdb_mdb_value2entry(context, &value, kvno, &entry->entry); 752 krb5_data_free(&value); 753 if (ret) 754 return ret; 755 756 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 757 ret = hdb_unseal_keys (context, db, &entry->entry); 758 if (ret) { 759 hdb_free_entry(context, entry); 760 return ret; 761 } 762 } 763 764 return 0; 765 } 766 767 static krb5_error_code 768 mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 769 { 770 krb5_error_code ret; 771 krb5_storage *sp = NULL; 772 krb5_storage *spent = NULL; 773 krb5_data line = { 0, 0 }; 774 krb5_data kdb_ent = { 0, 0 }; 775 krb5_data key = { 0, 0 }; 776 ssize_t sz; 777 778 sp = krb5_storage_emem(); 779 if (!sp) return ENOMEM; 780 ret = _hdb_set_master_key_usage(context, db, 0); /* MIT KDB uses KU 0 */ 781 ret = hdb_seal_keys(context, db, &entry->entry); 782 if (ret) return ret; 783 ret = entry2mit_string_int(context, sp, &entry->entry); 784 if (ret) goto out; 785 sz = krb5_storage_write(sp, "\n", 2); /* NUL-terminate */ 786 ret = ENOMEM; 787 if (sz == -1) goto out; 788 ret = krb5_storage_to_data(sp, &line); 789 if (ret) goto out; 790 791 ret = ENOMEM; 792 spent = krb5_storage_emem(); 793 if (!spent) goto out; 794 ret = _hdb_mit_dump2mitdb_entry(context, line.data, spent); 795 if (ret) goto out; 796 ret = krb5_storage_to_data(spent, &kdb_ent); 797 if (ret) goto out; 798 ret = mdb_principal2key(context, entry->entry.principal, &key); 799 if (ret) goto out; 800 ret = mdb__put(context, db, 1, key, kdb_ent); 801 802 out: 803 if (sp) 804 krb5_storage_free(sp); 805 if (spent) 806 krb5_storage_free(spent); 807 krb5_data_free(&line); 808 krb5_data_free(&kdb_ent); 809 krb5_data_free(&key); 810 811 return ret; 812 } 813 814 static krb5_error_code 815 mdb_remove(krb5_context context, HDB *db, krb5_const_principal principal) 816 { 817 krb5_error_code code; 818 krb5_data key; 819 820 code = db->hdb__del(context, db, key); 821 krb5_data_free(&key); 822 return code; 823 } 824 825 static krb5_error_code 826 mdb_open(krb5_context context, HDB *db, int flags, mode_t mode) 827 { 828 char *fn; 829 char *actual_fn; 830 krb5_error_code ret; 831 struct stat st; 832 833 asprintf(&fn, "%s.db", db->hdb_name); 834 if (fn == NULL) { 835 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 836 return ENOMEM; 837 } 838 839 if (stat(fn, &st) == 0) 840 actual_fn = fn; 841 else 842 actual_fn = db->hdb_name; 843 db->hdb_db = dbopen(actual_fn, flags, mode, DB_BTREE, NULL); 844 if (db->hdb_db == NULL) { 845 switch (errno) { 846 #ifdef EFTYPE 847 case EFTYPE: 848 #endif 849 case EINVAL: 850 db->hdb_db = dbopen(actual_fn, flags, mode, DB_BTREE, NULL); 851 } 852 } 853 free(fn); 854 855 /* try to open without .db extension */ 856 if(db->hdb_db == NULL && errno == ENOENT) 857 db->hdb_db = dbopen(db->hdb_name, flags, mode, DB_BTREE, NULL); 858 if(db->hdb_db == NULL) { 859 ret = errno; 860 krb5_set_error_message(context, ret, "dbopen (%s): %s", 861 db->hdb_name, strerror(ret)); 862 return ret; 863 } 864 #if 0 865 /* 866 * Don't do this -- MIT won't be able to handle the 867 * HDB_DB_FORMAT_ENTRY key. 868 */ 869 if ((flags & O_ACCMODE) != O_RDONLY) 870 ret = hdb_init_db(context, db); 871 #endif 872 ret = hdb_check_db_format(context, db); 873 if (ret == HDB_ERR_NOENTRY) { 874 krb5_clear_error_message(context); 875 return 0; 876 } 877 if (ret) { 878 mdb_close(context, db); 879 krb5_set_error_message(context, ret, "hdb_open: failed %s database %s", 880 (flags & O_ACCMODE) == O_RDONLY ? 881 "checking format of" : "initialize", 882 db->hdb_name); 883 } 884 return ret; 885 } 886 887 krb5_error_code 888 hdb_mdb_create(krb5_context context, HDB **db, 889 const char *filename) 890 { 891 *db = calloc(1, sizeof(**db)); 892 if (*db == NULL) { 893 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 894 return ENOMEM; 895 } 896 897 (*db)->hdb_db = NULL; 898 (*db)->hdb_name = strdup(filename); 899 if ((*db)->hdb_name == NULL) { 900 free(*db); 901 *db = NULL; 902 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 903 return ENOMEM; 904 } 905 (*db)->hdb_master_key_set = 0; 906 (*db)->hdb_openp = 0; 907 (*db)->hdb_capability_flags = 0; 908 (*db)->hdb_open = mdb_open; 909 (*db)->hdb_close = mdb_close; 910 (*db)->hdb_fetch_kvno = mdb_fetch_kvno; 911 (*db)->hdb_store = mdb_store; 912 (*db)->hdb_remove = mdb_remove; 913 (*db)->hdb_firstkey = mdb_firstkey; 914 (*db)->hdb_nextkey= mdb_nextkey; 915 (*db)->hdb_lock = mdb_lock; 916 (*db)->hdb_unlock = mdb_unlock; 917 (*db)->hdb_rename = mdb_rename; 918 (*db)->hdb__get = mdb__get; 919 (*db)->hdb__put = mdb__put; 920 (*db)->hdb__del = mdb__del; 921 (*db)->hdb_destroy = mdb_destroy; 922 return 0; 923 } 924 925 #endif /* HAVE_DB1 */ 926 927 /* 928 can have any number of princ stanzas. 929 format is as follows (only \n indicates newlines) 930 princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38) 931 %d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU) 932 %d\t (number of tl_data) 933 %d\t (number of key data, e.g. how many keys for this user) 934 %d\t (extra data length) 935 %s\t (principal name) 936 %d\t (attributes) 937 %d\t (max lifetime, seconds) 938 %d\t (max renewable life, seconds) 939 %d\t (expiration, seconds since epoch or 2145830400 for never) 940 %d\t (password expiration, seconds, 0 for never) 941 %d\t (last successful auth, seconds since epoch) 942 %d\t (last failed auth, per above) 943 %d\t (failed auth count) 944 foreach tl_data 0 to number of tl_data - 1 as above 945 %d\t%d\t (data type, data length) 946 foreach tl_data 0 to length-1 947 %02x (tl data contents[element n]) 948 except if tl_data length is 0 949 %d (always -1) 950 \t 951 foreach key 0 to number of keys - 1 as above 952 %d\t%d\t (key data version, kvno) 953 foreach version 0 to key data version - 1 (a key or a salt) 954 %d\t%d\t(data type for this key, data length for this key) 955 foreach key data length 0 to length-1 956 %02x (key data contents[element n]) 957 except if key_data length is 0 958 %d (always -1) 959 \t 960 foreach extra data length 0 to length - 1 961 %02x (extra data part) 962 unless no extra data 963 %d (always -1) 964 ;\n 965 966 */ 967 968 static char * 969 nexttoken(char **p) 970 { 971 char *q; 972 do { 973 q = strsep(p, " \t"); 974 } while(q && *q == '\0'); 975 return q; 976 } 977 978 static size_t 979 getdata(char **p, unsigned char *buf, size_t len) 980 { 981 size_t i; 982 int v; 983 char *q = nexttoken(p); 984 i = 0; 985 while(*q && i < len) { 986 if(sscanf(q, "%02x", &v) != 1) 987 break; 988 buf[i++] = v; 989 q += 2; 990 } 991 return i; 992 } 993 994 static int 995 getint(char **p) 996 { 997 int val; 998 char *q = nexttoken(p); 999 sscanf(q, "%d", &val); 1000 return val; 1001 } 1002 1003 static unsigned int 1004 getuint(char **p) 1005 { 1006 int val; 1007 char *q = nexttoken(p); 1008 sscanf(q, "%u", &val); 1009 return val; 1010 } 1011 1012 #define KRB5_KDB_SALTTYPE_NORMAL 0 1013 #define KRB5_KDB_SALTTYPE_V4 1 1014 #define KRB5_KDB_SALTTYPE_NOREALM 2 1015 #define KRB5_KDB_SALTTYPE_ONLYREALM 3 1016 #define KRB5_KDB_SALTTYPE_SPECIAL 4 1017 #define KRB5_KDB_SALTTYPE_AFS3 5 1018 1019 #define CHECK_UINT(num) \ 1020 if ((num) < 0 || (num) > INT_MAX) return EINVAL 1021 #define CHECK_UINT16(num) \ 1022 if ((num) < 0 || (num) > 1<<15) return EINVAL 1023 #define CHECK_NUM(num, maxv) \ 1024 if ((num) > (maxv)) return EINVAL 1025 1026 /* 1027 * This utility function converts an MIT dump entry to an MIT on-disk 1028 * encoded entry, which can then be decoded with _hdb_mdb_value2entry(). 1029 * This allows us to have a single decoding function (_hdb_mdb_value2entry), 1030 * which makes the code cleaner (less code duplication), if a bit less 1031 * efficient. It also will allow us to have a function to dump an HDB 1032 * entry in MIT format so we can dump HDB into MIT format for rollback 1033 * purposes. And that will allow us to write to MIT KDBs, again 1034 * somewhat inefficiently, also for migration/rollback purposes. 1035 */ 1036 int 1037 _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp) 1038 { 1039 krb5_error_code ret = EINVAL; 1040 char *p = line, *q; 1041 char *princ; 1042 ssize_t sz; 1043 size_t i; 1044 size_t princ_len; 1045 unsigned int num_tl_data; 1046 size_t num_key_data; 1047 unsigned int attributes; 1048 int tmp; 1049 1050 krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); 1051 1052 q = nexttoken(&p); 1053 if (strcmp(q, "kdb5_util") == 0 || strcmp(q, "policy") == 0 || 1054 strcmp(q, "princ") != 0) { 1055 return -1; 1056 } 1057 if (getint(&p) != 38) 1058 return EINVAL; 1059 #define KDB_V1_BASE_LENGTH 38 1060 ret = krb5_store_int16(sp, KDB_V1_BASE_LENGTH); 1061 if (ret) return ret; 1062 1063 nexttoken(&p); /* length of principal */ 1064 num_tl_data = getuint(&p); /* number of tl-data */ 1065 num_key_data = getuint(&p); /* number of key-data */ 1066 getint(&p); /* length of extra data */ 1067 princ = nexttoken(&p); /* principal name */ 1068 1069 attributes = getuint(&p); /* attributes */ 1070 ret = krb5_store_uint32(sp, attributes); 1071 if (ret) return ret; 1072 1073 tmp = getint(&p); /* max life */ 1074 CHECK_UINT(tmp); 1075 ret = krb5_store_uint32(sp, tmp); 1076 if (ret) return ret; 1077 1078 tmp = getint(&p); /* max renewable life */ 1079 CHECK_UINT(tmp); 1080 ret = krb5_store_uint32(sp, tmp); 1081 if (ret) return ret; 1082 1083 tmp = getint(&p); /* expiration */ 1084 CHECK_UINT(tmp); 1085 ret = krb5_store_uint32(sp, tmp); 1086 if (ret) return ret; 1087 1088 tmp = getint(&p); /* pw expiration */ 1089 CHECK_UINT(tmp); 1090 ret = krb5_store_uint32(sp, tmp); 1091 if (ret) return ret; 1092 1093 tmp = getint(&p); /* last auth */ 1094 CHECK_UINT(tmp); 1095 ret = krb5_store_uint32(sp, tmp); 1096 if (ret) return ret; 1097 1098 tmp = getint(&p); /* last failed auth */ 1099 CHECK_UINT(tmp); 1100 ret = krb5_store_uint32(sp, tmp); 1101 if (ret) return ret; 1102 1103 tmp = getint(&p); /* fail auth count */ 1104 CHECK_UINT(tmp); 1105 ret = krb5_store_uint32(sp, tmp); 1106 if (ret) return ret; 1107 1108 /* add TL data count */ 1109 CHECK_NUM(num_tl_data, 1023); 1110 ret = krb5_store_uint16(sp, num_tl_data); 1111 if (ret) return ret; 1112 1113 /* add key count */ 1114 CHECK_NUM(num_key_data, 1023); 1115 ret = krb5_store_uint16(sp, num_key_data); 1116 if (ret) return ret; 1117 1118 /* add principal unparsed name length and unparsed name */ 1119 princ_len = strlen(princ); 1120 if (princ_len > (1<<15) - 1) return EINVAL; 1121 princ_len++; /* must count and write the NUL in the on-disk encoding */ 1122 ret = krb5_store_uint16(sp, princ_len); 1123 if (ret) return ret; 1124 sz = krb5_storage_write(sp, princ, princ_len); 1125 if (sz == -1) return ENOMEM; 1126 1127 /* scan and write TL data */ 1128 for (i = 0; i < num_tl_data; i++) { 1129 int tl_type, tl_length; 1130 unsigned char *buf; 1131 1132 tl_type = getint(&p); /* data type */ 1133 tl_length = getint(&p); /* data length */ 1134 1135 CHECK_UINT16(tl_type); 1136 ret = krb5_store_uint16(sp, tl_type); 1137 if (ret) return ret; 1138 CHECK_UINT16(tl_length); 1139 ret = krb5_store_uint16(sp, tl_length); 1140 if (ret) return ret; 1141 1142 if (tl_length) { 1143 buf = malloc(tl_length); 1144 if (!buf) return ENOMEM; 1145 if (getdata(&p, buf, tl_length) != tl_length) return EINVAL; 1146 sz = krb5_storage_write(sp, buf, tl_length); 1147 free(buf); 1148 if (sz == -1) return ENOMEM; 1149 } else { 1150 if (strcmp(nexttoken(&p), "-1") != 0) return EINVAL; 1151 } 1152 } 1153 1154 for (i = 0; i < num_key_data; i++) { 1155 unsigned char *buf; 1156 int key_versions; 1157 int kvno; 1158 int keytype; 1159 int keylen; 1160 size_t k; 1161 1162 key_versions = getint(&p); /* key data version */ 1163 CHECK_UINT16(key_versions); 1164 ret = krb5_store_int16(sp, key_versions); 1165 if (ret) return ret; 1166 1167 kvno = getint(&p); 1168 CHECK_UINT16(kvno); 1169 ret = krb5_store_int16(sp, kvno); 1170 if (ret) return ret; 1171 1172 for (k = 0; k < key_versions; k++) { 1173 keytype = getint(&p); 1174 CHECK_UINT16(keytype); 1175 ret = krb5_store_int16(sp, keytype); 1176 if (ret) return ret; 1177 1178 keylen = getint(&p); 1179 CHECK_UINT16(keylen); 1180 ret = krb5_store_int16(sp, keylen); 1181 if (ret) return ret; 1182 1183 if (keylen) { 1184 buf = malloc(keylen); 1185 if (!buf) return ENOMEM; 1186 if (getdata(&p, buf, keylen) != keylen) return EINVAL; 1187 sz = krb5_storage_write(sp, buf, keylen); 1188 free(buf); 1189 if (sz == -1) return ENOMEM; 1190 } else { 1191 if (strcmp(nexttoken(&p), "-1") != 0) return EINVAL; 1192 } 1193 } 1194 } 1195 /* 1196 * The rest is "extra data", but there's never any and we wouldn't 1197 * know what to do with it. 1198 */ 1199 /* nexttoken(&p); */ 1200 return 0; 1201 } 1202 1203