1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 10 * 11 * Openvision retains the copyright to derivative works of 12 * this source code. Do *NOT* create a derivative of this 13 * source code before consulting with your legal department. 14 * Do *NOT* integrate *ANY* of this source code into another 15 * product before consulting with your legal department. 16 * 17 * For further information, read the top-level Openvision 18 * copyright which is contained in the top-level MIT Kerberos 19 * copyright. 20 * 21 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 22 * 23 */ 24 25 26 /* 27 * admin/edit/dump.c 28 * 29 * Copyright 1990,1991 by the Massachusetts Institute of Technology. 30 * All Rights Reserved. 31 * 32 * Export of this software from the United States of America may 33 * require a specific license from the United States Government. 34 * It is the responsibility of any person or organization contemplating 35 * export to obtain such a license before exporting. 36 * 37 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 38 * distribute this software and its documentation for any purpose and 39 * without fee is hereby granted, provided that the above copyright 40 * notice appear in all copies and that both that copyright notice and 41 * this permission notice appear in supporting documentation, and that 42 * the name of M.I.T. not be used in advertising or publicity pertaining 43 * to distribution of the software without specific, written prior 44 * permission. Furthermore if you modify this software you must label 45 * your software as modified software and not distribute it in such a 46 * fashion that it might be confused with the original M.I.T. software. 47 * M.I.T. makes no representations about the suitability of 48 * this software for any purpose. It is provided "as is" without express 49 * or implied warranty. 50 * 51 * 52 * Dump a KDC database 53 */ 54 55 #include <stdio.h> 56 #include <k5-int.h> 57 #include <kadm5/admin.h> 58 #include <kadm5/server_internal.h> 59 #include <kdb.h> 60 #include <com_err.h> 61 #include <libintl.h> 62 #include "kdb5_util.h" 63 #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) 64 #include <regex.h> 65 #endif /* HAVE_REGEX_H */ 66 67 /* 68 * Needed for master key conversion. 69 */ 70 extern krb5_keyblock master_key; 71 extern krb5_principal master_princ; 72 static int mkey_convert; 73 static krb5_keyblock new_master_key; 74 75 static int backwards; 76 static int recursive; 77 78 /* 79 * Use compile(3) if no regcomp present. 80 */ 81 #if !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H) 82 #define INIT char *sp = instring; 83 #define GETC() (*sp++) 84 #define PEEKC() (*sp) 85 #define UNGETC(c) (--sp) 86 #define RETURN(c) return(c) 87 #define ERROR(c) 88 #define RE_BUF_SIZE 1024 89 #include <regexp.h> 90 #endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */ 91 92 struct dump_args { 93 char *programname; 94 FILE *ofile; 95 krb5_context kcontext; 96 char **names; 97 int nnames; 98 int verbose; 99 }; 100 101 static krb5_error_code dump_k5beta_iterator (krb5_pointer, 102 krb5_db_entry *); 103 static krb5_error_code dump_k5beta6_iterator (krb5_pointer, 104 krb5_db_entry *); 105 static krb5_error_code dump_k5beta6_iterator_ext (krb5_pointer, 106 krb5_db_entry *, 107 int); 108 static krb5_error_code dump_iprop_iterator (krb5_pointer, 109 krb5_db_entry *); 110 static krb5_error_code dump_k5beta7_princ (krb5_pointer, 111 krb5_db_entry *); 112 static krb5_error_code dump_k5beta7_princ_ext (krb5_pointer, 113 krb5_db_entry *, 114 int); 115 static krb5_error_code dump_k5beta7_princ_withpolicy 116 (krb5_pointer, krb5_db_entry *); 117 static krb5_error_code dump_iprop_princ (krb5_pointer, 118 krb5_db_entry *); 119 static krb5_error_code dump_ov_princ (krb5_pointer, 120 krb5_db_entry *); 121 static void dump_k5beta7_policy (void *, osa_policy_ent_t); 122 123 typedef krb5_error_code (*dump_func)(krb5_pointer, 124 krb5_db_entry *); 125 126 static int process_k5beta_record (char *, krb5_context, 127 FILE *, int, int *); 128 static int process_k5beta6_record (char *, krb5_context, 129 FILE *, int, int *); 130 static int process_k5beta7_record (char *, krb5_context, 131 FILE *, int, int *); 132 static int process_ov_record (char *, krb5_context, 133 FILE *, int, int *); 134 typedef krb5_error_code (*load_func)(char *, krb5_context, 135 FILE *, int, int *); 136 137 typedef struct _dump_version { 138 char *name; 139 char *header; 140 int updateonly; 141 int create_kadm5; 142 dump_func dump_princ; 143 osa_adb_iter_policy_func dump_policy; 144 load_func load_record; 145 } dump_version; 146 147 dump_version old_version = { 148 "Kerberos version 5 old format", 149 "kdb5_edit load_dump version 2.0\n", 150 0, 151 1, 152 dump_k5beta_iterator, 153 NULL, 154 process_k5beta_record 155 }; 156 dump_version beta6_version = { 157 "Kerberos version 5 beta 6 format", 158 "kdb5_edit load_dump version 3.0\n", 159 0, 160 1, 161 dump_k5beta6_iterator, 162 NULL, 163 process_k5beta6_record 164 }; 165 dump_version beta7_version = { 166 "Kerberos version 5", 167 "kdb5_util load_dump version 4\n", 168 0, 169 0, 170 dump_k5beta7_princ, 171 dump_k5beta7_policy, 172 process_k5beta7_record 173 }; 174 dump_version iprop_version = { 175 "Kerberos iprop version", 176 "iprop", 177 0, 178 0, 179 dump_iprop_princ, 180 dump_k5beta7_policy, 181 process_k5beta7_record 182 }; 183 dump_version ov_version = { 184 "OpenV*Secure V1.0", 185 "OpenV*Secure V1.0\t", 186 1, 187 1, 188 dump_ov_princ, 189 dump_k5beta7_policy, 190 process_ov_record 191 }; 192 193 dump_version r1_3_version = { 194 "Kerberos version 5 release 1.3", 195 "kdb5_util load_dump version 5\n", 196 0, 197 0, 198 dump_k5beta7_princ_withpolicy, 199 dump_k5beta7_policy, 200 process_k5beta7_record, 201 }; 202 203 /* External data */ 204 extern char *current_dbname; 205 extern krb5_boolean dbactive; 206 extern int exit_status; 207 extern krb5_context util_context; 208 extern kadm5_config_params global_params; 209 210 /* Strings */ 211 212 #define k5beta_dump_header "kdb5_edit load_dump version 2.0\n" 213 214 static const char null_mprinc_name[] = "kdb5_dump@MISSING"; 215 216 /* 217 * We define gettext(s) to be s here, so that xgettext will extract the 218 * strings to the .po file. At the end of the message section we will 219 * undef gettext so that we can use it as a funtion. 220 */ 221 222 #define gettext(s) s 223 224 /* Message strings */ 225 static const char regex_err[] = 226 gettext("%s: regular expression error - %s\n"); 227 static const char regex_merr[] = 228 gettext("%s: regular expression match error - %s\n"); 229 static const char pname_unp_err[] = 230 gettext("%s: cannot unparse principal name (%s)\n"); 231 static const char mname_unp_err[] = 232 gettext("%s: cannot unparse modifier name (%s)\n"); 233 static const char nokeys_err[] = 234 gettext("%s: cannot find any standard key for %s\n"); 235 static const char sdump_tl_inc_err[] = 236 gettext("%s: tagged data list inconsistency for %s " 237 "(counted %d, stored %d)\n"); 238 static const char stand_fmt_name[] = 239 gettext("Kerberos version 5"); 240 static const char old_fmt_name[] = 241 gettext("Kerberos version 5 old format"); 242 static const char b6_fmt_name[] = 243 gettext("Kerberos version 5 beta 6 format"); 244 static const char ofopen_error[] = 245 gettext("%s: cannot open %s for writing (%s)\n"); 246 static const char oflock_error[] = 247 gettext("%s: cannot lock %s (%s)\n"); 248 static const char dumprec_err[] = 249 gettext("%s: error performing %s dump (%s)\n"); 250 static const char dumphdr_err[] = 251 gettext("%s: error dumping %s header (%s)\n"); 252 static const char trash_end_fmt[] = 253 gettext("%s(%d): ignoring trash at end of line: "); 254 static const char read_name_string[] = 255 gettext("name string"); 256 static const char read_key_type[] = 257 gettext("key type"); 258 static const char read_key_data[] = 259 gettext("key data"); 260 static const char read_pr_data1[] = 261 gettext("first set of principal attributes"); 262 static const char read_mod_name[] = 263 gettext("modifier name"); 264 static const char read_pr_data2[] = 265 gettext("second set of principal attributes"); 266 static const char read_salt_data[] = 267 gettext("salt data"); 268 static const char read_akey_type[] = 269 gettext("alternate key type"); 270 static const char read_akey_data[] = 271 gettext("alternate key data"); 272 static const char read_asalt_type[] = 273 gettext("alternate salt type"); 274 static const char read_asalt_data[] = 275 gettext("alternate salt data"); 276 static const char read_exp_data[] = 277 gettext("expansion data"); 278 static const char store_err_fmt[] = 279 gettext("%s(%d): cannot store %s(%s)\n"); 280 static const char add_princ_fmt[] = 281 gettext("%s\n"); 282 static const char parse_err_fmt[] = 283 gettext("%s(%d): cannot parse %s (%s)\n"); 284 static const char read_err_fmt[] = 285 gettext("%s(%d): cannot read %s\n"); 286 static const char no_mem_fmt[] = 287 gettext("%s(%d): no memory for buffers\n"); 288 static const char rhead_err_fmt[] = 289 gettext("%s(%d): cannot match size tokens\n"); 290 static const char err_line_fmt[] = 291 gettext("%s: error processing line %d of %s\n"); 292 static const char head_bad_fmt[] = 293 gettext("%s: dump header bad in %s\n"); 294 static const char read_bytecnt[] = 295 gettext("record byte count"); 296 static const char read_encdata[] = 297 gettext("encoded data"); 298 static const char n_name_unp_fmt[] = 299 gettext("%s(%s): cannot unparse name\n"); 300 static const char n_dec_cont_fmt[] = 301 gettext("%s(%s): cannot decode contents\n"); 302 static const char read_nint_data[] = 303 gettext("principal static attributes"); 304 static const char read_tcontents[] = 305 gettext("tagged data contents"); 306 static const char read_ttypelen[] = 307 gettext("tagged data type and length"); 308 static const char read_kcontents[] = 309 gettext("key data contents"); 310 static const char read_ktypelen[] = 311 gettext("key data type and length"); 312 static const char read_econtents[] = 313 gettext("extra data contents"); 314 static const char k5beta_fmt_name[] = 315 gettext("Kerberos version 5 old format"); 316 static const char standard_fmt_name[] = 317 gettext("Kerberos version 5 format"); 318 static const char no_name_mem_fmt[] = 319 gettext("%s: cannot get memory for temporary name\n"); 320 static const char ctx_err_fmt[] = 321 gettext("%s: cannot initialize Kerberos context\n"); 322 static const char stdin_name[] = 323 gettext("standard input"); 324 static const char remaster_err_fmt[] = 325 gettext("while re-encoding keys for principal %s with new master key"); 326 static const char restfail_fmt[] = 327 gettext("%s: %s restore failed\n"); 328 static const char close_err_fmt[] = 329 gettext("%s: cannot close database (%s)\n"); 330 static const char dbinit_err_fmt[] = 331 gettext("%s: cannot initialize database (%s)\n"); 332 static const char dblock_err_fmt[] = 333 gettext("%s: cannot initialize database lock (%s)\n"); 334 static const char dbname_err_fmt[] = 335 gettext("%s: cannot set database name to %s (%s)\n"); 336 static const char dbdelerr_fmt[] = 337 gettext("%s: cannot delete bad database %s (%s)\n"); 338 static const char dbunlockerr_fmt[] = 339 gettext("%s: cannot unlock database %s (%s)\n"); 340 static const char dbrenerr_fmt[] = 341 gettext("%s: cannot rename database %s to %s (%s)\n"); 342 static const char dbcreaterr_fmt[] = 343 gettext("%s: cannot create database %s (%s)\n"); 344 static const char dfile_err_fmt[] = 345 gettext("%s: cannot open %s (%s)\n"); 346 347 /* 348 * We now return you to your regularly scheduled program. 349 */ 350 #undef gettext 351 352 static const char oldoption[] = "-old"; 353 static const char b6option[] = "-b6"; 354 static const char b7option[] = "-b7"; 355 static const char ipropoption[] = "-i"; 356 static const char verboseoption[] = "-verbose"; 357 static const char updateoption[] = "-update"; 358 static const char hashoption[] = "-hash"; 359 static const char ovoption[] = "-ov"; 360 static const char dump_tmptrail[] = "~"; 361 362 /* 363 * Re-encrypt the key_data with the new master key... 364 */ 365 static krb5_error_code master_key_convert(context, db_entry) 366 krb5_context context; 367 krb5_db_entry * db_entry; 368 { 369 krb5_error_code retval; 370 krb5_keyblock v5plainkey, *key_ptr; 371 krb5_keysalt keysalt; 372 int i, j; 373 krb5_key_data new_key_data, *key_data; 374 krb5_boolean is_mkey; 375 376 is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ); 377 378 if (is_mkey && db_entry->n_key_data != 1) 379 fprintf(stderr, 380 gettext( 381 "Master key db entry has %d keys, expecting only 1!\n"), 382 db_entry->n_key_data); 383 for (i=0; i < db_entry->n_key_data; i++) { 384 key_data = &db_entry->key_data[i]; 385 if (key_data->key_data_length == 0) 386 continue; 387 retval = krb5_dbekd_decrypt_key_data(context, &master_key, 388 key_data, &v5plainkey, 389 &keysalt); 390 if (retval) 391 return retval; 392 393 memset(&new_key_data, 0, sizeof(new_key_data)); 394 key_ptr = is_mkey ? &new_master_key : &v5plainkey; 395 retval = krb5_dbekd_encrypt_key_data(context, &new_master_key, 396 key_ptr, &keysalt, 397 key_data->key_data_kvno, 398 &new_key_data); 399 if (retval) 400 return retval; 401 krb5_free_keyblock_contents(context, &v5plainkey); 402 for (j = 0; j < key_data->key_data_ver; j++) { 403 if (key_data->key_data_length[j]) { 404 free(key_data->key_data_contents[j]); 405 } 406 } 407 *key_data = new_key_data; 408 } 409 return 0; 410 } 411 412 /* 413 * Update the "ok" file. 414 */ 415 void update_ok_file (file_name) 416 char *file_name; 417 { 418 /* handle slave locking/failure stuff */ 419 char *file_ok; 420 int fd; 421 static char ok[]=".dump_ok"; 422 423 if ((file_ok = (char *)malloc(strlen(file_name) + strlen(ok) + 1)) 424 == NULL) { 425 com_err(progname, ENOMEM, 426 gettext("while allocating filename " 427 "for update_ok_file")); 428 exit_status++; 429 return; 430 } 431 strcpy(file_ok, file_name); 432 strcat(file_ok, ok); 433 if ((fd = open(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) { 434 com_err(progname, errno, 435 gettext("while creating 'ok' file, '%s'"), 436 file_ok); 437 exit_status++; 438 free(file_ok); 439 return; 440 } 441 if (write(fd, "", 1) != 1) { 442 com_err(progname, errno, 443 gettext("while writing to 'ok' file, '%s'"), 444 file_ok); 445 exit_status++; 446 free(file_ok); 447 return; 448 } 449 450 free(file_ok); 451 close(fd); 452 return; 453 } 454 455 /* 456 * name_matches() - See if a principal name matches a regular expression 457 * or string. 458 */ 459 static int 460 name_matches(name, arglist) 461 char *name; 462 struct dump_args *arglist; 463 { 464 #if HAVE_REGCOMP 465 regex_t match_exp; 466 regmatch_t match_match; 467 int match_error; 468 char match_errmsg[BUFSIZ]; 469 size_t errmsg_size; 470 #elif HAVE_REGEXP_H 471 char regexp_buffer[RE_BUF_SIZE]; 472 #elif HAVE_RE_COMP 473 extern char *re_comp(); 474 char *re_result; 475 #endif /* HAVE_RE_COMP */ 476 int i, match; 477 478 /* 479 * Plow, brute force, through the list of names/regular expressions. 480 */ 481 match = (arglist->nnames) ? 0 : 1; 482 for (i=0; i<arglist->nnames; i++) { 483 #if HAVE_REGCOMP 484 /* 485 * Compile the regular expression. 486 */ 487 match_error = regcomp(&match_exp, arglist->names[i], REG_EXTENDED); 488 if (match_error) { 489 errmsg_size = regerror(match_error, 490 &match_exp, 491 match_errmsg, 492 sizeof(match_errmsg)); 493 fprintf(stderr, gettext(regex_err), 494 arglist->programname, match_errmsg); 495 break; 496 } 497 /* 498 * See if we have a match. 499 */ 500 match_error = regexec(&match_exp, name, 1, &match_match, 0); 501 if (match_error) { 502 if (match_error != REG_NOMATCH) { 503 errmsg_size = regerror(match_error, 504 &match_exp, 505 match_errmsg, 506 sizeof(match_errmsg)); 507 fprintf(stderr, gettext(regex_merr), 508 arglist->programname, match_errmsg); 509 break; 510 } 511 } 512 else { 513 /* 514 * We have a match. See if it matches the whole 515 * name. 516 */ 517 if ((match_match.rm_so == 0) && 518 (match_match.rm_eo == strlen(name))) 519 match = 1; 520 } 521 regfree(&match_exp); 522 #elif HAVE_REGEXP_H 523 /* 524 * Compile the regular expression. 525 */ 526 compile(arglist->names[i], 527 regexp_buffer, 528 ®exp_buffer[RE_BUF_SIZE], 529 '\0'); 530 if (step(name, regexp_buffer)) { 531 if ((loc1 == name) && 532 (loc2 == &name[strlen(name)])) 533 match = 1; 534 } 535 #elif HAVE_RE_COMP 536 /* 537 * Compile the regular expression. 538 */ 539 if (re_result = re_comp(arglist->names[i])) { 540 fprintf(stderr, gettext(regex_err), arglist->programname, re_result); 541 break; 542 } 543 if (re_exec(name)) 544 match = 1; 545 #else /* HAVE_RE_COMP */ 546 /* 547 * If no regular expression support, then just compare the strings. 548 */ 549 if (!strcmp(arglist->names[i], name)) 550 match = 1; 551 #endif /* HAVE_REGCOMP */ 552 if (match) 553 break; 554 } 555 return(match); 556 } 557 558 static krb5_error_code 559 find_enctype(dbentp, enctype, salttype, kentp) 560 krb5_db_entry *dbentp; 561 krb5_enctype enctype; 562 krb5_int32 salttype; 563 krb5_key_data **kentp; 564 { 565 int i; 566 int maxkvno; 567 krb5_key_data *datap; 568 569 maxkvno = -1; 570 datap = (krb5_key_data *) NULL; 571 for (i=0; i<dbentp->n_key_data; i++) { 572 if (( (krb5_enctype)dbentp->key_data[i].key_data_type[0] == enctype) && 573 ((dbentp->key_data[i].key_data_type[1] == salttype) || 574 (salttype < 0))) { 575 maxkvno = dbentp->key_data[i].key_data_kvno; 576 datap = &dbentp->key_data[i]; 577 } 578 } 579 if (maxkvno >= 0) { 580 *kentp = datap; 581 return(0); 582 } 583 return(ENOENT); 584 } 585 586 #if 0 587 /* 588 * dump_k5beta_header() - Make a dump header that is recognizable by Kerberos 589 * Version 5 Beta 5 and previous releases. 590 */ 591 static krb5_error_code 592 dump_k5beta_header(arglist) 593 struct dump_args *arglist; 594 { 595 /* The old header consists of the leading string */ 596 fprintf(arglist->ofile, k5beta_dump_header); 597 return(0); 598 } 599 #endif 600 601 /* 602 * dump_k5beta_iterator() - Dump an entry in a format that is usable 603 * by Kerberos Version 5 Beta 5 and previous 604 * releases. 605 */ 606 static krb5_error_code 607 dump_k5beta_iterator(ptr, entry) 608 krb5_pointer ptr; 609 krb5_db_entry *entry; 610 { 611 krb5_error_code retval; 612 struct dump_args *arg; 613 char *name, *mod_name; 614 krb5_principal mod_princ; 615 krb5_key_data *pkey, *akey, nullkey; 616 krb5_timestamp mod_date, last_pwd_change; 617 int i; 618 619 /* Initialize */ 620 arg = (struct dump_args *) ptr; 621 name = (char *) NULL; 622 mod_name = (char *) NULL; 623 memset(&nullkey, 0, sizeof(nullkey)); 624 625 /* 626 * Flatten the principal name. 627 */ 628 if ((retval = krb5_unparse_name(arg->kcontext, 629 entry->princ, 630 &name))) { 631 fprintf(stderr, gettext(pname_unp_err), 632 arg->programname, error_message(retval)); 633 return(retval); 634 } 635 636 /* 637 * Re-encode the keys in the new master key, if necessary. 638 */ 639 if (mkey_convert) { 640 retval = master_key_convert(arg->kcontext, entry); 641 if (retval) { 642 com_err(arg->programname, retval, remaster_err_fmt, name); 643 return retval; 644 } 645 } 646 647 /* 648 * If we don't have any match strings, or if our name matches, then 649 * proceed with the dump, otherwise, just forget about it. 650 */ 651 if (!arg->nnames || name_matches(name, arg)) { 652 /* 653 * Deserialize the modifier record. 654 */ 655 mod_name = (char *) NULL; 656 mod_princ = NULL; 657 last_pwd_change = mod_date = 0; 658 pkey = akey = (krb5_key_data *) NULL; 659 if (!(retval = krb5_dbe_lookup_mod_princ_data(arg->kcontext, 660 entry, 661 &mod_date, 662 &mod_princ))) { 663 if (mod_princ) { 664 /* 665 * Flatten the modifier name. 666 */ 667 if ((retval = krb5_unparse_name(arg->kcontext, 668 mod_princ, 669 &mod_name))) 670 fprintf(stderr, gettext(mname_unp_err), 671 arg->programname, 672 error_message(retval)); 673 krb5_free_principal(arg->kcontext, mod_princ); 674 } 675 } 676 if (!mod_name) 677 mod_name = strdup(null_mprinc_name); 678 679 /* 680 * Find the last password change record and set it straight. 681 */ 682 if ((retval = 683 krb5_dbe_lookup_last_pwd_change(arg->kcontext, entry, 684 &last_pwd_change))) { 685 fprintf(stderr, gettext(nokeys_err), 686 arg->programname, name); 687 krb5_xfree(mod_name); 688 krb5_xfree(name); 689 return(retval); 690 } 691 692 /* 693 * Find the 'primary' key and the 'alternate' key. 694 */ 695 if ((retval = find_enctype(entry, 696 ENCTYPE_DES_CBC_CRC, 697 KRB5_KDB_SALTTYPE_NORMAL, 698 &pkey)) && 699 (retval = find_enctype(entry, 700 ENCTYPE_DES_CBC_CRC, 701 KRB5_KDB_SALTTYPE_V4, 702 &akey))) { 703 fprintf(stderr, gettext(nokeys_err), 704 arg->programname, name); 705 krb5_xfree(mod_name); 706 krb5_xfree(name); 707 return(retval); 708 } 709 710 /* If we only have one type, then ship it out as the primary. */ 711 if (!pkey && akey) { 712 pkey = akey; 713 akey = &nullkey; 714 } 715 else { 716 if (!akey) 717 akey = &nullkey; 718 } 719 720 /* 721 * First put out strings representing the length of the variable 722 * length data in this record, then the name and the primary key type. 723 */ 724 fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%s\t%d\t", strlen(name), 725 strlen(mod_name), 726 (krb5_int32) pkey->key_data_length[0], 727 (krb5_int32) akey->key_data_length[0], 728 (krb5_int32) pkey->key_data_length[1], 729 (krb5_int32) akey->key_data_length[1], 730 name, 731 (krb5_int32) pkey->key_data_type[0]); 732 for (i=0; i<pkey->key_data_length[0]; i++) { 733 fprintf(arg->ofile, "%02x", pkey->key_data_contents[0][i]); 734 } 735 /* 736 * Second, print out strings representing the standard integer 737 * data in this record. 738 */ 739 fprintf(arg->ofile, 740 "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%s\t%u\t%u\t%u\t", 741 (krb5_int32) pkey->key_data_kvno, 742 entry->max_life, entry->max_renewable_life, 743 1 /* Fake mkvno */, entry->expiration, entry->pw_expiration, 744 last_pwd_change, entry->last_success, entry->last_failed, 745 entry->fail_auth_count, mod_name, mod_date, 746 entry->attributes, pkey->key_data_type[1]); 747 748 /* Pound out the salt data, if present. */ 749 for (i=0; i<pkey->key_data_length[1]; i++) { 750 fprintf(arg->ofile, "%02x", pkey->key_data_contents[1][i]); 751 } 752 /* Pound out the alternate key type and contents */ 753 fprintf(arg->ofile, "\t%u\t", akey->key_data_type[0]); 754 for (i=0; i<akey->key_data_length[0]; i++) { 755 fprintf(arg->ofile, "%02x", akey->key_data_contents[0][i]); 756 } 757 /* Pound out the alternate salt type and contents */ 758 fprintf(arg->ofile, "\t%u\t", akey->key_data_type[1]); 759 for (i=0; i<akey->key_data_length[1]; i++) { 760 fprintf(arg->ofile, "%02x", akey->key_data_contents[1][i]); 761 } 762 /* Pound out the expansion data. (is null) */ 763 for (i=0; i < 8; i++) { 764 fprintf(arg->ofile, "\t%u", 0); 765 } 766 fprintf(arg->ofile, ";\n"); 767 /* If we're blabbing, do it */ 768 if (arg->verbose) 769 fprintf(stderr, "%s\n", name); 770 krb5_xfree(mod_name); 771 } 772 krb5_xfree(name); 773 return(0); 774 } 775 776 /* 777 * dump_k5beta6_iterator() - Output a dump record in krb5b6 format. 778 */ 779 static krb5_error_code 780 dump_k5beta6_iterator(ptr, entry) 781 krb5_pointer ptr; 782 krb5_db_entry *entry; 783 { 784 return dump_k5beta6_iterator_ext(ptr, entry, 0); 785 } 786 787 static krb5_error_code 788 dump_k5beta6_iterator_ext(ptr, entry, kadm) 789 krb5_pointer ptr; 790 krb5_db_entry *entry; 791 int kadm; 792 { 793 krb5_error_code retval; 794 struct dump_args *arg; 795 char *name; 796 krb5_tl_data *tlp; 797 krb5_key_data *kdata; 798 int counter, skip, i, j; 799 800 /* Initialize */ 801 arg = (struct dump_args *) ptr; 802 name = (char *) NULL; 803 804 /* 805 * Flatten the principal name. 806 */ 807 if ((retval = krb5_unparse_name(arg->kcontext, 808 entry->princ, 809 &name))) { 810 fprintf(stderr, gettext(pname_unp_err), 811 arg->programname, error_message(retval)); 812 return(retval); 813 } 814 815 /* 816 * Re-encode the keys in the new master key, if necessary. 817 */ 818 if (mkey_convert) { 819 retval = master_key_convert(arg->kcontext, entry); 820 if (retval) { 821 com_err(arg->programname, retval, remaster_err_fmt, name); 822 return retval; 823 } 824 } 825 826 /* 827 * If we don't have any match strings, or if our name matches, then 828 * proceed with the dump, otherwise, just forget about it. 829 */ 830 if (!arg->nnames || name_matches(name, arg)) { 831 /* 832 * We'd like to just blast out the contents as they would appear in 833 * the database so that we can just suck it back in, but it doesn't 834 * lend itself to easy editing. 835 */ 836 837 /* 838 * The dump format is as follows: 839 * len strlen(name) n_tl_data n_key_data e_length 840 * name 841 * attributes max_life max_renewable_life expiration 842 * pw_expiration last_success last_failed fail_auth_count 843 * n_tl_data*[type length <contents>] 844 * n_key_data*[ver kvno ver*(type length <contents>)] 845 * <e_data> 846 * Fields which are not encapsulated by angle-brackets are to appear 847 * verbatim. A bracketed field's absence is indicated by a -1 in its 848 * place 849 */ 850 851 /* 852 * Make sure that the tagged list is reasonably correct. 853 */ 854 counter = skip = 0; 855 for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) { 856 /* 857 * don't dump tl data types we know aren't understood by 858 * earlier revisions [krb5-admin/89] 859 */ 860 switch (tlp->tl_data_type) { 861 case KRB5_TL_KADM_DATA: 862 if (kadm) 863 counter++; 864 else 865 skip++; 866 break; 867 default: 868 counter++; 869 break; 870 } 871 } 872 873 if (counter + skip == entry->n_tl_data) { 874 /* Pound out header */ 875 fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%s\t", 876 (int) entry->len, 877 strlen(name), 878 counter, 879 (int) entry->n_key_data, 880 (int) entry->e_length, 881 name); 882 fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t", 883 entry->attributes, 884 entry->max_life, 885 entry->max_renewable_life, 886 entry->expiration, 887 entry->pw_expiration, 888 entry->last_success, 889 entry->last_failed, 890 entry->fail_auth_count); 891 /* Pound out tagged data. */ 892 for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) { 893 if (tlp->tl_data_type == KRB5_TL_KADM_DATA && !kadm) 894 continue; /* see above, [krb5-admin/89] */ 895 896 fprintf(arg->ofile, "%d\t%d\t", 897 (int) tlp->tl_data_type, 898 (int) tlp->tl_data_length); 899 if (tlp->tl_data_length) 900 for (i=0; i<tlp->tl_data_length; i++) 901 fprintf(arg->ofile, "%02x", tlp->tl_data_contents[i]); 902 else 903 fprintf(arg->ofile, "%d", -1); 904 fprintf(arg->ofile, "\t"); 905 } 906 907 /* Pound out key data */ 908 for (counter=0; counter<entry->n_key_data; counter++) { 909 kdata = &entry->key_data[counter]; 910 fprintf(arg->ofile, "%d\t%d\t", 911 (int) kdata->key_data_ver, 912 (int) kdata->key_data_kvno); 913 for (i=0; i<kdata->key_data_ver; i++) { 914 fprintf(arg->ofile, "%d\t%d\t", 915 kdata->key_data_type[i], 916 kdata->key_data_length[i]); 917 if (kdata->key_data_length[i]) 918 for (j=0; j<kdata->key_data_length[i]; j++) 919 fprintf(arg->ofile, "%02x", 920 kdata->key_data_contents[i][j]); 921 else 922 fprintf(arg->ofile, "%d", -1); 923 fprintf(arg->ofile, "\t"); 924 } 925 } 926 927 /* Pound out extra data */ 928 if (entry->e_length) 929 for (i=0; i<entry->e_length; i++) 930 fprintf(arg->ofile, "%02x", entry->e_data[i]); 931 else 932 fprintf(arg->ofile, "%d", -1); 933 934 /* Print trailer */ 935 fprintf(arg->ofile, ";\n"); 936 937 if (arg->verbose) 938 fprintf(stderr, "%s\n", name); 939 } 940 else { 941 fprintf(stderr, gettext(sdump_tl_inc_err), 942 arg->programname, name, counter+skip, 943 (int) entry->n_tl_data); 944 retval = EINVAL; 945 } 946 } 947 krb5_xfree(name); 948 return(retval); 949 } 950 951 /* 952 * dump_iprop_iterator() - Output a dump record in iprop format. 953 */ 954 static krb5_error_code 955 dump_iprop_iterator(ptr, entry) 956 krb5_pointer ptr; 957 krb5_db_entry *entry; 958 { 959 krb5_error_code retval; 960 struct dump_args *arg; 961 char *name; 962 krb5_tl_data *tlp; 963 krb5_key_data *kdata; 964 int counter, i, j; 965 966 /* Initialize */ 967 arg = (struct dump_args *) ptr; 968 name = (char *) NULL; 969 970 /* 971 * Flatten the principal name. 972 */ 973 if ((retval = krb5_unparse_name(arg->kcontext, 974 entry->princ, 975 &name))) { 976 fprintf(stderr, gettext(pname_unp_err), 977 arg->programname, error_message(retval)); 978 return(retval); 979 } 980 981 /* 982 * Re-encode the keys in the new master key, if necessary. 983 */ 984 if (mkey_convert) { 985 retval = master_key_convert(arg->kcontext, entry); 986 if (retval) { 987 com_err(arg->programname, retval, remaster_err_fmt, name); 988 return retval; 989 } 990 } 991 992 /* 993 * If we don't have any match strings, or if our name matches, then 994 * proceed with the dump, otherwise, just forget about it. 995 */ 996 if (!arg->nnames || name_matches(name, arg)) { 997 /* 998 * We'd like to just blast out the contents as they would 999 * appear in the database so that we can just suck it back 1000 * in, but it doesn't lend itself to easy editing. 1001 */ 1002 1003 /* 1004 * The dump format is as follows: len strlen(name) 1005 * n_tl_data n_key_data e_length name attributes max_life 1006 * max_renewable_life expiration pw_expiration last_success 1007 * last_failed fail_auth_count n_tl_data*[type length 1008 * <contents>] n_key_data*[ver kvno ver*(type length 1009 * <contents>)] <e_data> Fields which are not encapsulated 1010 * by angle-brackets are to appear verbatim. Bracketed 1011 * fields absence is indicated by a -1 in its place 1012 */ 1013 1014 /* 1015 * Make sure that the tagged list is reasonably correct. 1016 */ 1017 counter = 0; 1018 for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) 1019 counter++; 1020 1021 if (counter == entry->n_tl_data) { 1022 /* Pound out header */ 1023 fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%s\t", 1024 (int) entry->len, 1025 strlen(name), 1026 (int) entry->n_tl_data, 1027 (int) entry->n_key_data, 1028 (int) entry->e_length, 1029 name); 1030 fprintf(arg->ofile, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t", 1031 entry->attributes, 1032 entry->max_life, 1033 entry->max_renewable_life, 1034 entry->expiration, 1035 entry->pw_expiration, 1036 entry->last_success, 1037 entry->last_failed, 1038 entry->fail_auth_count); 1039 /* Pound out tagged data. */ 1040 for (tlp = entry->tl_data; tlp; 1041 tlp = tlp->tl_data_next) { 1042 fprintf(arg->ofile, "%d\t%d\t", 1043 (int) tlp->tl_data_type, 1044 (int) tlp->tl_data_length); 1045 if (tlp->tl_data_length) 1046 for (i = 0; 1047 i < tlp->tl_data_length; 1048 i++) 1049 fprintf(arg->ofile, "%02x", 1050 tlp-> 1051 tl_data_contents[i]); 1052 else 1053 fprintf(arg->ofile, "%d", -1); 1054 fprintf(arg->ofile, "\t"); 1055 } 1056 1057 /* Pound out key data */ 1058 for (counter = 0; 1059 counter < entry->n_key_data; counter++) { 1060 kdata = &entry->key_data[counter]; 1061 fprintf(arg->ofile, "%d\t%d\t", 1062 (int) kdata->key_data_ver, 1063 (int) kdata->key_data_kvno); 1064 for (i=0; i<kdata->key_data_ver; i++) { 1065 fprintf(arg->ofile, "%d\t%d\t", 1066 kdata->key_data_type[i], 1067 kdata->key_data_length[i]); 1068 if (kdata->key_data_length[i]) 1069 for (j = 0; 1070 j < kdata-> 1071 key_data_length[i]; 1072 j++) 1073 fprintf(arg->ofile, 1074 "%02x", 1075 kdata-> 1076 key_data_contents 1077 [i][j]); 1078 else 1079 fprintf(arg->ofile, "%d", -1); 1080 fprintf(arg->ofile, "\t"); 1081 } 1082 } 1083 1084 /* Pound out extra data */ 1085 if (entry->e_length) 1086 for (i=0; i<entry->e_length; i++) 1087 fprintf(arg->ofile, "%02x", 1088 entry->e_data[i]); 1089 else 1090 fprintf(arg->ofile, "%d", -1); 1091 1092 /* Print trailer */ 1093 fprintf(arg->ofile, ";\n"); 1094 1095 if (arg->verbose) 1096 fprintf(stderr, "%s\n", name); 1097 } else { 1098 fprintf(stderr, gettext(sdump_tl_inc_err), 1099 arg->programname, name, counter, 1100 (int) entry->n_tl_data); 1101 retval = EINVAL; 1102 } 1103 } 1104 krb5_xfree(name); 1105 return(retval); 1106 } 1107 1108 /* 1109 * dump_k5beta7_iterator() - Output a dump record in krb5b7 format. 1110 */ 1111 static krb5_error_code 1112 dump_k5beta7_princ(ptr, entry) 1113 krb5_pointer ptr; 1114 krb5_db_entry *entry; 1115 { 1116 return dump_k5beta7_princ_ext(ptr, entry, 0); 1117 } 1118 1119 static krb5_error_code 1120 dump_k5beta7_princ_ext(ptr, entry, kadm) 1121 krb5_pointer ptr; 1122 krb5_db_entry *entry; 1123 int kadm; 1124 { 1125 krb5_error_code retval; 1126 struct dump_args *arg; 1127 char *name; 1128 int tmp_nnames; 1129 1130 /* Initialize */ 1131 arg = (struct dump_args *) ptr; 1132 name = (char *) NULL; 1133 1134 /* 1135 * Flatten the principal name. 1136 */ 1137 if ((retval = krb5_unparse_name(arg->kcontext, 1138 entry->princ, 1139 &name))) { 1140 fprintf(stderr, gettext(pname_unp_err), 1141 arg->programname, error_message(retval)); 1142 return(retval); 1143 } 1144 /* 1145 * If we don't have any match strings, or if our name matches, then 1146 * proceed with the dump, otherwise, just forget about it. 1147 */ 1148 if (!arg->nnames || name_matches(name, arg)) { 1149 fprintf(arg->ofile, "princ\t"); 1150 1151 /* save the callee from matching the name again */ 1152 tmp_nnames = arg->nnames; 1153 arg->nnames = 0; 1154 retval = dump_k5beta6_iterator_ext(ptr, entry, kadm); 1155 arg->nnames = tmp_nnames; 1156 } 1157 1158 free(name); 1159 return retval; 1160 } 1161 1162 /* 1163 * dump_iprop_princ() - Output a dump record in iprop format. 1164 * This was created in order to dump more data, such as kadm5 tl 1165 */ 1166 static krb5_error_code 1167 dump_iprop_princ(ptr, entry) 1168 krb5_pointer ptr; 1169 krb5_db_entry *entry; 1170 { 1171 krb5_error_code retval; 1172 struct dump_args *arg; 1173 char *name; 1174 int tmp_nnames; 1175 1176 /* Initialize */ 1177 arg = (struct dump_args *) ptr; 1178 name = (char *) NULL; 1179 1180 /* 1181 * Flatten the principal name. 1182 */ 1183 if ((retval = krb5_unparse_name(arg->kcontext, 1184 entry->princ, 1185 &name))) { 1186 fprintf(stderr, gettext(pname_unp_err), 1187 arg->programname, error_message(retval)); 1188 return(retval); 1189 } 1190 /* 1191 * If we don't have any match strings, or if our name matches, then 1192 * proceed with the dump, otherwise, just forget about it. 1193 */ 1194 if (!arg->nnames || name_matches(name, arg)) { 1195 fprintf(arg->ofile, "princ\t"); 1196 1197 /* save the callee from matching the name again */ 1198 tmp_nnames = arg->nnames; 1199 arg->nnames = 0; 1200 retval = dump_iprop_iterator(ptr, entry); 1201 arg->nnames = tmp_nnames; 1202 } 1203 free(name); 1204 return (retval); 1205 } 1206 1207 static krb5_error_code 1208 dump_k5beta7_princ_withpolicy(ptr, entry) 1209 krb5_pointer ptr; 1210 krb5_db_entry *entry; 1211 { 1212 return dump_k5beta7_princ_ext(ptr, entry, 1); 1213 } 1214 1215 void dump_k5beta7_policy(void *data, osa_policy_ent_t entry) 1216 { 1217 struct dump_args *arg; 1218 1219 arg = (struct dump_args *) data; 1220 fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n", entry->name, 1221 entry->pw_min_life, entry->pw_max_life, entry->pw_min_length, 1222 entry->pw_min_classes, entry->pw_history_num, 1223 entry->policy_refcnt); 1224 } 1225 1226 static void print_key_data(FILE *f, krb5_key_data *key_data) 1227 { 1228 int c; 1229 1230 fprintf(f, "%d\t%d\t", key_data->key_data_type[0], 1231 key_data->key_data_length[0]); 1232 for(c = 0; c < key_data->key_data_length[0]; c++) 1233 fprintf(f, "%02x ", 1234 key_data->key_data_contents[0][c]); 1235 } 1236 1237 /* 1238 * Function: print_princ 1239 * 1240 * Purpose: output osa_adb_princ_ent data in a human 1241 * readable format (which is a format suitable for 1242 * ovsec_adm_import consumption) 1243 * 1244 * Arguments: 1245 * data (input) pointer to a structure containing a FILE * 1246 * and a record counter. 1247 * entry (input) entry to get dumped. 1248 * <return value> void 1249 * 1250 * Requires: 1251 * nuttin 1252 * 1253 * Effects: 1254 * writes data to the specified file pointerp. 1255 * 1256 * Modifies: 1257 * nuttin 1258 * 1259 */ 1260 static krb5_error_code dump_ov_princ(krb5_pointer ptr, krb5_db_entry *kdb) 1261 { 1262 char *princstr; 1263 int x, y, foundcrc; 1264 struct dump_args *arg; 1265 krb5_tl_data tl_data; 1266 osa_princ_ent_rec adb; 1267 XDR xdrs; 1268 1269 arg = (struct dump_args *) ptr; 1270 /* 1271 * XXX Currently, lookup_tl_data always returns zero; it sets 1272 * tl_data->tl_data_length to zero if the type isn't found. 1273 * This should be fixed... 1274 */ 1275 /* 1276 * XXX Should this function do nothing for a principal with no 1277 * admin data, or print a record of "default" values? See 1278 * comment in server_kdb.c to help decide. 1279 */ 1280 tl_data.tl_data_type = KRB5_TL_KADM_DATA; 1281 if (krb5_dbe_lookup_tl_data(arg->kcontext, kdb, &tl_data) 1282 || (tl_data.tl_data_length == 0)) 1283 return 0; 1284 1285 memset(&adb, 0, sizeof(adb)); 1286 xdrmem_create(&xdrs, (const caddr_t) tl_data.tl_data_contents, 1287 tl_data.tl_data_length, XDR_DECODE); 1288 if (! xdr_osa_princ_ent_rec(&xdrs, &adb)) { 1289 xdr_destroy(&xdrs); 1290 return(KADM5_XDR_FAILURE); 1291 } 1292 xdr_destroy(&xdrs); 1293 1294 krb5_unparse_name(arg->kcontext, kdb->princ, &princstr); 1295 fprintf(arg->ofile, "princ\t%s\t", princstr); 1296 if(adb.policy == NULL) 1297 fputc('\t', arg->ofile); 1298 else 1299 fprintf(arg->ofile, "%s\t", adb.policy); 1300 fprintf(arg->ofile, "%lx\t%d\t%d\t%d", adb.aux_attributes, 1301 adb.old_key_len,adb.old_key_next, adb.admin_history_kvno); 1302 1303 for (x = 0; x < adb.old_key_len; x++) { 1304 foundcrc = 0; 1305 for (y = 0; y < adb.old_keys[x].n_key_data; y++) { 1306 krb5_key_data *key_data = &adb.old_keys[x].key_data[y]; 1307 1308 if (key_data->key_data_type[0] != ENCTYPE_DES_CBC_CRC) 1309 continue; 1310 if (foundcrc) { 1311 fprintf(stderr, 1312 gettext("Warning! Multiple DES-CBC-CRC " 1313 "keys for principal %s; skipping " 1314 "duplicates.\n"), 1315 princstr); 1316 continue; 1317 } 1318 foundcrc++; 1319 1320 fputc('\t', arg->ofile); 1321 print_key_data(arg->ofile, key_data); 1322 } 1323 if (!foundcrc) 1324 fprintf(stderr, 1325 gettext("Warning! No DES-CBC-CRC key " 1326 "for principal %s, cannot generate " 1327 "OV-compatible record; skipping\n"), 1328 princstr); 1329 } 1330 1331 fputc('\n', arg->ofile); 1332 free(princstr); 1333 return 0; 1334 } 1335 1336 /* 1337 * usage is: 1338 * dump_db [-i] [-old] [-b6] [-b7] [-ov] [-verbose] [-mkey_convert] 1339 * [-new_mkey_file mkey_file] [-rev] [-recurse] 1340 * [filename [principals...]] 1341 */ 1342 void 1343 dump_db(argc, argv) 1344 int argc; 1345 char **argv; 1346 { 1347 FILE *f; 1348 struct dump_args arglist; 1349 char *programname; 1350 char *ofile; 1351 krb5_error_code kret, retval; 1352 dump_version *dump; 1353 int aindex; 1354 krb5_boolean locked; 1355 char *new_mkey_file = 0; 1356 bool_t dump_sno = FALSE; 1357 kdb_log_context *log_ctx; 1358 1359 /* 1360 * Parse the arguments. 1361 */ 1362 programname = argv[0]; 1363 if (strrchr(programname, (int) '/')) 1364 programname = strrchr(argv[0], (int) '/') + 1; 1365 ofile = (char *) NULL; 1366 dump = &r1_3_version; 1367 arglist.verbose = 0; 1368 new_mkey_file = 0; 1369 mkey_convert = 0; 1370 backwards = 0; 1371 recursive = 0; 1372 log_ctx = util_context->kdblog_context; 1373 1374 /* 1375 * Parse the qualifiers. 1376 */ 1377 for (aindex = 1; aindex < argc; aindex++) { 1378 if (!strcmp(argv[aindex], oldoption)) 1379 dump = &old_version; 1380 else if (!strcmp(argv[aindex], b6option)) 1381 dump = &beta6_version; 1382 else if (!strcmp(argv[aindex], b7option)) 1383 dump = &beta7_version; 1384 else if (!strcmp(argv[aindex], ovoption)) 1385 dump = &ov_version; 1386 else if (!strcmp(argv[aindex], ipropoption)) { 1387 if (log_ctx && log_ctx->iproprole) { 1388 dump = &iprop_version; 1389 /* 1390 * dump_sno is used to indicate if the serial 1391 * # should be populated in the output 1392 * file to be used later by iprop for updating 1393 * the slave's update log when loading 1394 */ 1395 dump_sno = TRUE; 1396 } else { 1397 fprintf(stderr, gettext("Iprop not enabled\n")); 1398 exit_status++; 1399 return; 1400 } 1401 } 1402 else if (!strcmp(argv[aindex], verboseoption)) 1403 arglist.verbose++; 1404 else if (!strcmp(argv[aindex], "-mkey_convert")) 1405 mkey_convert = 1; 1406 else if (!strcmp(argv[aindex], "-new_mkey_file")) { 1407 new_mkey_file = argv[++aindex]; 1408 mkey_convert = 1; 1409 } else if (!strcmp(argv[aindex], "-rev")) 1410 backwards = 1; 1411 else if (!strcmp(argv[aindex], "-recurse")) 1412 recursive = 1; 1413 else 1414 break; 1415 } 1416 1417 arglist.names = (char **) NULL; 1418 arglist.nnames = 0; 1419 if (aindex < argc) { 1420 ofile = argv[aindex]; 1421 aindex++; 1422 if (aindex < argc) { 1423 arglist.names = &argv[aindex]; 1424 arglist.nnames = argc - aindex; 1425 } 1426 } 1427 1428 /* 1429 * Make sure the database is open. The policy database only has 1430 * to be opened if we try a dump that uses it. 1431 */ 1432 if (!dbactive) { 1433 com_err(argv[0], 0, Err_no_database); 1434 exit_status++; 1435 return; 1436 } 1437 1438 /* 1439 * If we're doing a master key conversion, set up for it. 1440 */ 1441 if (mkey_convert) { 1442 if (!valid_master_key) { 1443 /* TRUE here means read the keyboard, but only once */ 1444 retval = krb5_db_fetch_mkey(util_context, 1445 master_princ, 1446 global_params.enctype, 1447 TRUE, FALSE, 1448 (char *) NULL, 0, 1449 &master_key); 1450 if (retval) { 1451 com_err(argv[0], retval, 1452 gettext("while reading master key")); 1453 exit(1); 1454 } 1455 retval = krb5_db_verify_master_key(util_context, 1456 master_princ, 1457 &master_key); 1458 if (retval) { 1459 com_err(argv[0], retval, 1460 gettext("while verifying master key")); 1461 exit(1); 1462 } 1463 } 1464 if (!new_mkey_file) 1465 printf(gettext("Please enter new master key....\n")); 1466 if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 1467 global_params.enctype, 1468 (new_mkey_file == 0) ? 1469 (krb5_boolean) 1 : 0, 1470 TRUE, 1471 new_mkey_file, 0, 1472 &new_master_key))) { 1473 com_err(argv[0], retval, 1474 gettext("while reading new master key")); 1475 exit(1); 1476 } 1477 } 1478 1479 kret = 0; 1480 locked = 0; 1481 if (ofile && strcmp(ofile, "-")) { 1482 /* 1483 * Discourage accidental dumping to filenames beginning with '-'. 1484 */ 1485 if (ofile[0] == '-') 1486 usage(); 1487 /* 1488 * Make sure that we don't open and truncate on the fopen, 1489 * since that may hose an on-going kprop process. 1490 * 1491 * We could also control this by opening for read and 1492 * write, doing an flock with LOCK_EX, and then 1493 * truncating the file once we have gotten the lock, 1494 * but that would involve more OS dependencies than I 1495 * want to get into. 1496 */ 1497 unlink(ofile); 1498 if (!(f = fopen(ofile, "w"))) { 1499 fprintf(stderr, gettext(ofopen_error), 1500 programname, ofile, error_message(errno)); 1501 exit_status++; 1502 return; 1503 } 1504 if ((kret = krb5_lock_file(util_context, 1505 fileno(f), 1506 KRB5_LOCKMODE_EXCLUSIVE))) { 1507 fprintf(stderr, gettext(oflock_error), 1508 programname, ofile, error_message(kret)); 1509 exit_status++; 1510 } 1511 else 1512 locked = 1; 1513 } else { 1514 f = stdout; 1515 } 1516 if (f && !(kret)) { 1517 arglist.programname = programname; 1518 arglist.ofile = f; 1519 arglist.kcontext = util_context; 1520 fprintf(arglist.ofile, "%s", dump->header); 1521 1522 if (dump_sno) { 1523 if (ulog_map(util_context, &global_params, FKCOMMAND)) { 1524 fprintf(stderr, 1525 gettext("%s: Could not map log\n"), programname); 1526 exit_status++; 1527 goto error; 1528 } 1529 1530 /* 1531 * We grab the lock twice (once again in the iterator call), 1532 * but that's ok since the lock func handles incr locks held. 1533 */ 1534 if (krb5_db_lock(util_context, KRB5_LOCKMODE_SHARED)) { 1535 fprintf(stderr, 1536 gettext("%s: Couldn't grab lock\n"), programname); 1537 exit_status++; 1538 goto error; 1539 } 1540 1541 fprintf(f, " %u", log_ctx->ulog->kdb_last_sno); 1542 fprintf(f, " %u", log_ctx->ulog->kdb_last_time.seconds); 1543 fprintf(f, " %u", log_ctx->ulog->kdb_last_time.useconds); 1544 } 1545 1546 if (dump->header[strlen(dump->header)-1] != '\n') 1547 fputc('\n', arglist.ofile); 1548 1549 if ((kret = krb5_db_iterate(util_context, 1550 NULL, 1551 dump->dump_princ, 1552 (krb5_pointer) &arglist))) { /* TBD: backwards and recursive not supported */ 1553 fprintf(stderr, dumprec_err, 1554 programname, dump->name, error_message(kret)); 1555 exit_status++; 1556 if (dump_sno) 1557 (void) krb5_db_unlock(util_context); 1558 } 1559 if (dump->dump_policy && 1560 (kret = krb5_db_iter_policy( util_context, "*", dump->dump_policy, 1561 &arglist))) { 1562 fprintf(stderr, gettext(dumprec_err), 1563 programname, dump->name, 1564 error_message(kret)); 1565 exit_status++; 1566 } 1567 1568 error: 1569 if (ofile && f != stdout && !exit_status) { 1570 if (locked) { 1571 (void) krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_UNLOCK); 1572 locked = 0; 1573 } 1574 fclose(f); 1575 update_ok_file(ofile); 1576 } 1577 } 1578 if (locked) 1579 (void) krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_UNLOCK); 1580 } 1581 1582 /* 1583 * Read a string of bytes while counting the number of lines passed. 1584 */ 1585 static int 1586 read_string(f, buf, len, lp) 1587 FILE *f; 1588 char *buf; 1589 int len; 1590 int *lp; 1591 { 1592 int c; 1593 int i, retval; 1594 1595 retval = 0; 1596 for (i=0; i<len; i++) { 1597 c = fgetc(f); 1598 if (c < 0) { 1599 retval = 1; 1600 break; 1601 } 1602 if (c == '\n') 1603 (*lp)++; 1604 buf[i] = (char) c; 1605 } 1606 buf[len] = '\0'; 1607 return(retval); 1608 } 1609 1610 /* 1611 * Read a string of two character representations of bytes. 1612 */ 1613 static int 1614 read_octet_string(f, buf, len) 1615 FILE *f; 1616 krb5_octet *buf; 1617 int len; 1618 { 1619 int c; 1620 int i, retval; 1621 1622 retval = 0; 1623 for (i=0; i<len; i++) { 1624 if (fscanf(f, "%02x", &c) != 1) { 1625 retval = 1; 1626 break; 1627 } 1628 buf[i] = (krb5_octet) c; 1629 } 1630 return(retval); 1631 } 1632 1633 /* 1634 * Find the end of an old format record. 1635 */ 1636 static void 1637 find_record_end(f, fn, lineno) 1638 FILE *f; 1639 char *fn; 1640 int lineno; 1641 { 1642 int ch; 1643 1644 if (((ch = fgetc(f)) != ';') || ((ch = fgetc(f)) != '\n')) { 1645 fprintf(stderr, gettext(trash_end_fmt), fn, lineno); 1646 while (ch != '\n') { 1647 putc(ch, stderr); 1648 ch = fgetc(f); 1649 } 1650 putc(ch, stderr); 1651 } 1652 } 1653 1654 #if 0 1655 /* 1656 * update_tl_data() - Generate the tl_data entries. 1657 */ 1658 static krb5_error_code 1659 update_tl_data(kcontext, dbentp, mod_name, mod_date, last_pwd_change) 1660 krb5_context kcontext; 1661 krb5_db_entry *dbentp; 1662 krb5_principal mod_name; 1663 krb5_timestamp mod_date; 1664 krb5_timestamp last_pwd_change; 1665 { 1666 krb5_error_code kret; 1667 1668 kret = 0 ; 1669 1670 /* 1671 * Handle modification principal. 1672 */ 1673 if (mod_name) { 1674 krb5_tl_mod_princ mprinc; 1675 1676 memset(&mprinc, 0, sizeof(mprinc)); 1677 if (!(kret = krb5_copy_principal(kcontext, 1678 mod_name, 1679 &mprinc.mod_princ))) { 1680 mprinc.mod_date = mod_date; 1681 kret = krb5_dbe_encode_mod_princ_data(kcontext, 1682 &mprinc, 1683 dbentp); 1684 } 1685 if (mprinc.mod_princ) 1686 krb5_free_principal(kcontext, mprinc.mod_princ); 1687 } 1688 1689 /* 1690 * Handle last password change. 1691 */ 1692 if (!kret) { 1693 krb5_tl_data *pwchg; 1694 krb5_boolean linked; 1695 1696 /* Find a previously existing entry */ 1697 for (pwchg = dbentp->tl_data; 1698 (pwchg) && (pwchg->tl_data_type != KRB5_TL_LAST_PWD_CHANGE); 1699 pwchg = pwchg->tl_data_next); 1700 1701 /* Check to see if we found one. */ 1702 linked = 0; 1703 if (!pwchg) { 1704 /* No, allocate a new one */ 1705 if ((pwchg = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) { 1706 memset(pwchg, 0, sizeof(krb5_tl_data)); 1707 if (!(pwchg->tl_data_contents = 1708 (krb5_octet *) malloc(sizeof(krb5_timestamp)))) { 1709 free(pwchg); 1710 pwchg = (krb5_tl_data *) NULL; 1711 } 1712 else { 1713 pwchg->tl_data_type = KRB5_TL_LAST_PWD_CHANGE; 1714 pwchg->tl_data_length = 1715 (krb5_int16) sizeof(krb5_timestamp); 1716 } 1717 } 1718 } 1719 else 1720 linked = 1; 1721 1722 /* Do we have an entry? */ 1723 if (pwchg && pwchg->tl_data_contents) { 1724 /* Encode it */ 1725 krb5_kdb_encode_int32(last_pwd_change, pwchg->tl_data_contents); 1726 /* Link it in if necessary */ 1727 if (!linked) { 1728 pwchg->tl_data_next = dbentp->tl_data; 1729 dbentp->tl_data = pwchg; 1730 dbentp->n_tl_data++; 1731 } 1732 } 1733 else 1734 kret = ENOMEM; 1735 } 1736 1737 return(kret); 1738 } 1739 #endif 1740 1741 /* 1742 * process_k5beta_record() - Handle a dump record in old format. 1743 * 1744 * Returns -1 for end of file, 0 for success and 1 for failure. 1745 */ 1746 static int 1747 process_k5beta_record(fname, kcontext, filep, verbose, linenop) 1748 char *fname; 1749 krb5_context kcontext; 1750 FILE *filep; 1751 int verbose; 1752 int *linenop; 1753 { 1754 int nmatched; 1755 int retval; 1756 krb5_db_entry dbent; 1757 int name_len, mod_name_len, key_len; 1758 int alt_key_len, salt_len, alt_salt_len; 1759 char *name; 1760 char *mod_name; 1761 int tmpint1, tmpint2, tmpint3; 1762 int error; 1763 const char *try2read; 1764 int i; 1765 krb5_key_data *pkey, *akey; 1766 krb5_timestamp last_pwd_change, mod_date; 1767 krb5_principal mod_princ; 1768 krb5_error_code kret; 1769 krb5_octet *shortcopy1 = NULL; /* SUNWresync121 memleak fix */ 1770 krb5_octet *shortcopy2 = NULL; 1771 1772 try2read = (char *) NULL; 1773 (*linenop)++; 1774 retval = 1; 1775 memset((char *)&dbent, 0, sizeof(dbent)); 1776 1777 /* Make sure we've got key_data entries */ 1778 if (krb5_dbe_create_key_data(kcontext, &dbent) || 1779 krb5_dbe_create_key_data(kcontext, &dbent)) { 1780 krb5_db_free_principal(kcontext, &dbent, 1); 1781 return(1); 1782 } 1783 pkey = &dbent.key_data[0]; 1784 akey = &dbent.key_data[1]; 1785 1786 /* 1787 * Match the sizes. 6 tokens to match. 1788 */ 1789 nmatched = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t", 1790 &name_len, &mod_name_len, &key_len, 1791 &alt_key_len, &salt_len, &alt_salt_len); 1792 if (nmatched == 6) { 1793 pkey->key_data_length[0] = key_len; 1794 akey->key_data_length[0] = alt_key_len; 1795 pkey->key_data_length[1] = salt_len; 1796 akey->key_data_length[1] = alt_salt_len; 1797 name = (char *) NULL; 1798 mod_name = (char *) NULL; 1799 /* 1800 * Get the memory for the variable length fields. 1801 */ 1802 if ((name = (char *) malloc((size_t) (name_len + 1))) && 1803 (mod_name = (char *) malloc((size_t) (mod_name_len + 1))) && 1804 (!key_len || 1805 (pkey->key_data_contents[0] = 1806 (krb5_octet *) malloc((size_t) (key_len + 1)))) && 1807 (!alt_key_len || 1808 (akey->key_data_contents[0] = 1809 (krb5_octet *) malloc((size_t) (alt_key_len + 1)))) && 1810 (!salt_len || 1811 (pkey->key_data_contents[1] = 1812 (krb5_octet *) malloc((size_t) (salt_len + 1)))) && 1813 (!alt_salt_len || 1814 (akey->key_data_contents[1] = 1815 (krb5_octet *) malloc((size_t) (alt_salt_len + 1)))) 1816 ) { 1817 error = 0; 1818 1819 /* Read the principal name */ 1820 if (read_string(filep, name, name_len, linenop)) { 1821 try2read = read_name_string; 1822 error++; 1823 } 1824 /* Read the key type */ 1825 if (!error && (fscanf(filep, "\t%d\t", &tmpint1) != 1)) { 1826 try2read = read_key_type; 1827 error++; 1828 } 1829 pkey->key_data_type[0] = tmpint1; 1830 /* Read the old format key */ 1831 if (!error && read_octet_string(filep, 1832 pkey->key_data_contents[0], 1833 pkey->key_data_length[0])) { 1834 try2read = read_key_data; 1835 error++; 1836 } 1837 /* convert to a new format key */ 1838 /* the encrypted version is stored as the unencrypted key length 1839 (4 bytes, MSB first) followed by the encrypted key. */ 1840 if ((pkey->key_data_length[0] > 4) 1841 && (pkey->key_data_contents[0][0] == 0) 1842 && (pkey->key_data_contents[0][1] == 0)) { 1843 /* this really does look like an old key, so drop and swap */ 1844 /* the *new* length is 2 bytes, LSB first, sigh. */ 1845 size_t shortlen = pkey->key_data_length[0]-4+2; 1846 krb5_octet *origdata = pkey->key_data_contents[0]; 1847 1848 shortcopy1 = (krb5_octet *) malloc(shortlen); 1849 if (shortcopy1) { 1850 shortcopy1[0] = origdata[3]; 1851 shortcopy1[1] = origdata[2]; 1852 memcpy(shortcopy1 + 2, origdata + 4, shortlen - 2); 1853 free(origdata); 1854 pkey->key_data_length[0] = shortlen; 1855 pkey->key_data_contents[0] = shortcopy1; 1856 } else { 1857 fprintf(stderr, gettext(no_mem_fmt), fname, *linenop); 1858 error++; 1859 } 1860 } 1861 1862 /* Read principal attributes */ 1863 if (!error && (fscanf(filep, 1864 "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t", 1865 &tmpint1, &dbent.max_life, 1866 &dbent.max_renewable_life, 1867 &tmpint2, &dbent.expiration, 1868 &dbent.pw_expiration, &last_pwd_change, 1869 &dbent.last_success, &dbent.last_failed, 1870 &tmpint3) != 10)) { 1871 try2read = read_pr_data1; 1872 error++; 1873 } 1874 pkey->key_data_kvno = tmpint1; 1875 dbent.fail_auth_count = tmpint3; 1876 /* Read modifier name */ 1877 if (!error && read_string(filep, 1878 mod_name, 1879 mod_name_len, 1880 linenop)) { 1881 try2read = read_mod_name; 1882 error++; 1883 } 1884 /* Read second set of attributes */ 1885 if (!error && (fscanf(filep, "\t%u\t%u\t%u\t", 1886 &mod_date, &dbent.attributes, 1887 &tmpint1) != 3)) { 1888 try2read = read_pr_data2; 1889 error++; 1890 } 1891 pkey->key_data_type[1] = tmpint1; 1892 /* Read salt data */ 1893 if (!error && read_octet_string(filep, 1894 pkey->key_data_contents[1], 1895 pkey->key_data_length[1])) { 1896 try2read = read_salt_data; 1897 error++; 1898 } 1899 /* Read alternate key type */ 1900 if (!error && (fscanf(filep, "\t%u\t", &tmpint1) != 1)) { 1901 try2read = read_akey_type; 1902 error++; 1903 } 1904 akey->key_data_type[0] = tmpint1; 1905 /* Read alternate key */ 1906 if (!error && read_octet_string(filep, 1907 akey->key_data_contents[0], 1908 akey->key_data_length[0])) { 1909 try2read = read_akey_data; 1910 error++; 1911 } 1912 1913 /* convert to a new format key */ 1914 /* the encrypted version is stored as the unencrypted key length 1915 (4 bytes, MSB first) followed by the encrypted key. */ 1916 if ((akey->key_data_length[0] > 4) 1917 && (akey->key_data_contents[0][0] == 0) 1918 && (akey->key_data_contents[0][1] == 0)) { 1919 /* this really does look like an old key, so drop and swap */ 1920 /* the *new* length is 2 bytes, LSB first, sigh. */ 1921 size_t shortlen = akey->key_data_length[0]-4+2; 1922 1923 krb5_octet *origdata = akey->key_data_contents[0]; 1924 1925 shortcopy2 = (krb5_octet *) malloc(shortlen); 1926 if (shortcopy2) { 1927 shortcopy2[0] = origdata[3]; 1928 shortcopy2[1] = origdata[2]; 1929 memcpy(shortcopy2 + 2, 1930 origdata + 4, shortlen - 2); 1931 free(origdata); 1932 akey->key_data_length[0] = shortlen; 1933 akey->key_data_contents[0] = shortcopy2; 1934 } else { 1935 fprintf(stderr, gettext(no_mem_fmt), fname, *linenop); 1936 error++; 1937 } 1938 } 1939 1940 /* Read alternate salt type */ 1941 if (!error && (fscanf(filep, "\t%u\t", &tmpint1) != 1)) { 1942 try2read = read_asalt_type; 1943 error++; 1944 } 1945 akey->key_data_type[1] = tmpint1; 1946 /* Read alternate salt data */ 1947 if (!error && read_octet_string(filep, 1948 akey->key_data_contents[1], 1949 akey->key_data_length[1])) { 1950 try2read = read_asalt_data; 1951 error++; 1952 } 1953 /* Read expansion data - discard it */ 1954 if (!error) { 1955 for (i=0; i<8; i++) { 1956 if (fscanf(filep, "\t%u", &tmpint1) != 1) { 1957 try2read = read_exp_data; 1958 error++; 1959 break; 1960 } 1961 } 1962 if (!error) 1963 find_record_end(filep, fname, *linenop); 1964 } 1965 1966 /* 1967 * If no error, then we're done reading. Now parse the names 1968 * and store the database dbent. 1969 */ 1970 if (!error) { 1971 if (!(kret = krb5_parse_name(kcontext, 1972 name, 1973 &dbent.princ))) { 1974 if (!(kret = krb5_parse_name(kcontext, 1975 mod_name, 1976 &mod_princ))) { 1977 if (!(kret = 1978 krb5_dbe_update_mod_princ_data(kcontext, 1979 &dbent, 1980 mod_date, 1981 mod_princ)) && 1982 !(kret = 1983 krb5_dbe_update_last_pwd_change(kcontext, 1984 &dbent, 1985 last_pwd_change))) { 1986 int one = 1; 1987 1988 dbent.len = KRB5_KDB_V1_BASE_LENGTH; 1989 pkey->key_data_ver = (pkey->key_data_type[1] || pkey->key_data_length[1]) ? 1990 2 : 1; 1991 akey->key_data_ver = (akey->key_data_type[1] || akey->key_data_length[1]) ? 1992 2 : 1; 1993 if ((pkey->key_data_type[0] == 1994 akey->key_data_type[0]) && 1995 (pkey->key_data_type[1] == 1996 akey->key_data_type[1])) 1997 dbent.n_key_data--; 1998 else if ((akey->key_data_type[0] == 0) 1999 && (akey->key_data_length[0] == 0) 2000 && (akey->key_data_type[1] == 0) 2001 && (akey->key_data_length[1] == 0)) 2002 dbent.n_key_data--; 2003 2004 dbent.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | 2005 KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_KEY_DATA | 2006 KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS | 2007 KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT; 2008 2009 if ((kret = krb5_db_put_principal(kcontext, 2010 &dbent, 2011 &one)) || 2012 (one != 1)) { 2013 fprintf(stderr, gettext(store_err_fmt), 2014 fname, *linenop, name, 2015 error_message(kret)); 2016 error++; 2017 } 2018 else { 2019 if (verbose) 2020 fprintf(stderr, 2021 gettext(add_princ_fmt), 2022 name); 2023 retval = 0; 2024 } 2025 dbent.n_key_data = 2; 2026 } 2027 krb5_free_principal(kcontext, mod_princ); 2028 } 2029 else { 2030 fprintf(stderr, 2031 gettext(parse_err_fmt), 2032 fname, *linenop, mod_name, 2033 error_message(kret)); 2034 error++; 2035 } 2036 } 2037 else { 2038 fprintf(stderr, gettext(parse_err_fmt), 2039 fname, *linenop, name, error_message(kret)); 2040 error++; 2041 } 2042 } 2043 else { 2044 fprintf(stderr, gettext(no_mem_fmt), fname, *linenop, try2read); 2045 } 2046 } 2047 else { 2048 fprintf(stderr, gettext(read_err_fmt), fname, *linenop); 2049 } 2050 2051 krb5_db_free_principal(kcontext, &dbent, 1); 2052 if (mod_name) 2053 free(mod_name); 2054 if (name) 2055 free(name); 2056 } 2057 else { 2058 if (nmatched != EOF) 2059 fprintf(stderr, gettext(rhead_err_fmt), 2060 fname, *linenop); 2061 else 2062 retval = -1; 2063 } 2064 2065 if (shortcopy1) 2066 free(shortcopy1); 2067 if (shortcopy2) 2068 free(shortcopy2); 2069 2070 return(retval); 2071 } 2072 2073 /* 2074 * process_k5beta6_record() - Handle a dump record in krb5b6 format. 2075 * 2076 * Returns -1 for end of file, 0 for success and 1 for failure. 2077 */ 2078 static int 2079 process_k5beta6_record(fname, kcontext, filep, verbose, linenop) 2080 char *fname; 2081 krb5_context kcontext; 2082 FILE *filep; 2083 int verbose; 2084 int *linenop; 2085 { 2086 int retval; 2087 krb5_db_entry dbentry; 2088 krb5_int32 t1, t2, t3, t4, t5, t6, t7, t8, t9; 2089 int nread; 2090 int error; 2091 int i, j, one; 2092 char *name; 2093 krb5_key_data *kp, *kdatap; 2094 krb5_tl_data **tlp, *tl; 2095 krb5_octet *op; 2096 krb5_error_code kret; 2097 const char *try2read; 2098 2099 try2read = (char *) NULL; 2100 memset((char *) &dbentry, 0, sizeof(dbentry)); 2101 (*linenop)++; 2102 retval = 1; 2103 name = (char *) NULL; 2104 kp = (krb5_key_data *) NULL; 2105 op = (krb5_octet *) NULL; 2106 error = 0; 2107 kret = 0; 2108 nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t", &t1, &t2, &t3, &t4, &t5); 2109 if (nread == 5) { 2110 /* Get memory for flattened principal name */ 2111 if (!(name = (char *) malloc((size_t) t2 + 1))) 2112 error++; 2113 2114 /* Get memory for and form tagged data linked list */ 2115 tlp = &dbentry.tl_data; 2116 for (i=0; i<t3; i++) { 2117 if ((*tlp = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) { 2118 memset(*tlp, 0, sizeof(krb5_tl_data)); 2119 tlp = &((*tlp)->tl_data_next); 2120 dbentry.n_tl_data++; 2121 } 2122 else { 2123 error++; 2124 break; 2125 } 2126 } 2127 2128 /* Get memory for key list */ 2129 if (t4 && !(kp = (krb5_key_data *) malloc((size_t) 2130 (t4*sizeof(krb5_key_data))))) 2131 error++; 2132 2133 /* Get memory for extra data */ 2134 if (t5 && !(op = (krb5_octet *) malloc((size_t) t5))) 2135 error++; 2136 2137 if (!error) { 2138 dbentry.len = t1; 2139 dbentry.n_key_data = t4; 2140 dbentry.e_length = t5; 2141 if (kp) { 2142 memset(kp, 0, (size_t) (t4*sizeof(krb5_key_data))); 2143 dbentry.key_data = kp; 2144 kp = (krb5_key_data *) NULL; 2145 } 2146 if (op) { 2147 memset(op, 0, (size_t) t5); 2148 dbentry.e_data = op; 2149 op = (krb5_octet *) NULL; 2150 } 2151 2152 /* Read in and parse the principal name */ 2153 if (!read_string(filep, name, t2, linenop) && 2154 !(kret = krb5_parse_name(kcontext, name, &dbentry.princ))) { 2155 2156 /* Get the fixed principal attributes */ 2157 nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t", 2158 &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9); 2159 if (nread == 8) { 2160 dbentry.attributes = (krb5_flags) t2; 2161 dbentry.max_life = (krb5_deltat) t3; 2162 dbentry.max_renewable_life = (krb5_deltat) t4; 2163 dbentry.expiration = (krb5_timestamp) t5; 2164 dbentry.pw_expiration = (krb5_timestamp) t6; 2165 dbentry.last_success = (krb5_timestamp) t7; 2166 dbentry.last_failed = (krb5_timestamp) t8; 2167 dbentry.fail_auth_count = (krb5_kvno) t9; 2168 dbentry.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | 2169 KADM5_MAX_LIFE | KADM5_MAX_RLIFE | 2170 KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS | 2171 KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT; 2172 } else { 2173 try2read = read_nint_data; 2174 error++; 2175 } 2176 2177 /* 2178 * Get the tagged data. 2179 * 2180 * Really, this code ought to discard tl data types 2181 * that it knows are special to the current version 2182 * and were not supported in the previous version. 2183 * But it's a pain to implement that here, and doing 2184 * it at dump time has almost as good an effect, so 2185 * that's what I did. [krb5-admin/89] 2186 */ 2187 if (!error && dbentry.n_tl_data) { 2188 for (tl = dbentry.tl_data; tl; tl = tl->tl_data_next) { 2189 nread = fscanf(filep, "%d\t%d\t", &t1, &t2); 2190 if (nread == 2) { 2191 tl->tl_data_type = (krb5_int16) t1; 2192 tl->tl_data_length = (krb5_int16) t2; 2193 if (tl->tl_data_length) { 2194 if (!(tl->tl_data_contents = 2195 (krb5_octet *) malloc((size_t) t2+1)) || 2196 read_octet_string(filep, 2197 tl->tl_data_contents, 2198 t2)) { 2199 try2read = read_tcontents; 2200 error++; 2201 break; 2202 } 2203 /* test to set mask fields */ 2204 if (t1 == KRB5_TL_KADM_DATA) { 2205 XDR xdrs; 2206 osa_princ_ent_rec osa_princ_ent; 2207 2208 /* 2209 * Assuming aux_attributes will always be 2210 * there 2211 */ 2212 dbentry.mask |= KADM5_AUX_ATTRIBUTES; 2213 2214 /* test for an actual policy reference */ 2215 memset(&osa_princ_ent, 0, sizeof(osa_princ_ent)); 2216 xdrmem_create(&xdrs, (char *)tl->tl_data_contents, 2217 tl->tl_data_length, XDR_DECODE); 2218 if (xdr_osa_princ_ent_rec(&xdrs, &osa_princ_ent) && 2219 (osa_princ_ent.aux_attributes & KADM5_POLICY) && 2220 osa_princ_ent.policy != NULL) { 2221 2222 dbentry.mask |= KADM5_POLICY; 2223 kdb_free_entry(NULL, NULL, &osa_princ_ent); 2224 } 2225 xdr_destroy(&xdrs); 2226 } 2227 } 2228 else { 2229 /* Should be a null field */ 2230 nread = fscanf(filep, "%d", &t9); 2231 if ((nread != 1) || (t9 != -1)) { 2232 error++; 2233 try2read = read_tcontents; 2234 break; 2235 } 2236 } 2237 } 2238 else { 2239 try2read = read_ttypelen; 2240 error++; 2241 break; 2242 } 2243 } 2244 if (!error) 2245 dbentry.mask |= KADM5_TL_DATA; 2246 } 2247 2248 /* Get the key data */ 2249 if (!error && dbentry.n_key_data) { 2250 for (i=0; !error && (i<dbentry.n_key_data); i++) { 2251 kdatap = &dbentry.key_data[i]; 2252 nread = fscanf(filep, "%d\t%d\t", &t1, &t2); 2253 if (nread == 2) { 2254 kdatap->key_data_ver = (krb5_int16) t1; 2255 kdatap->key_data_kvno = (krb5_int16) t2; 2256 2257 for (j=0; j<t1; j++) { 2258 nread = fscanf(filep, "%d\t%d\t", &t3, &t4); 2259 if (nread == 2) { 2260 kdatap->key_data_type[j] = t3; 2261 kdatap->key_data_length[j] = t4; 2262 if (t4) { 2263 if (!(kdatap->key_data_contents[j] = 2264 (krb5_octet *) 2265 malloc((size_t) t4+1)) || 2266 read_octet_string(filep, 2267 kdatap->key_data_contents[j], 2268 t4)) { 2269 try2read = read_kcontents; 2270 error++; 2271 break; 2272 } 2273 } 2274 else { 2275 /* Should be a null field */ 2276 nread = fscanf(filep, "%d", &t9); 2277 if ((nread != 1) || (t9 != -1)) { 2278 error++; 2279 try2read = read_kcontents; 2280 break; 2281 } 2282 } 2283 } 2284 else { 2285 try2read = read_ktypelen; 2286 error++; 2287 break; 2288 } 2289 } 2290 } 2291 } 2292 if (!error) 2293 dbentry.mask |= KADM5_KEY_DATA; 2294 } 2295 2296 /* Get the extra data */ 2297 if (!error && dbentry.e_length) { 2298 if (read_octet_string(filep, 2299 dbentry.e_data, 2300 (int) dbentry.e_length)) { 2301 try2read = read_econtents; 2302 error++; 2303 } 2304 } 2305 else { 2306 nread = fscanf(filep, "%d", &t9); 2307 if ((nread != 1) || (t9 != -1)) { 2308 error++; 2309 try2read = read_econtents; 2310 } 2311 } 2312 2313 /* Finally, find the end of the record. */ 2314 if (!error) 2315 find_record_end(filep, fname, *linenop); 2316 2317 /* 2318 * We have either read in all the data or choked. 2319 */ 2320 if (!error) { 2321 one = 1; 2322 if ((kret = krb5_db_put_principal(kcontext, 2323 &dbentry, 2324 &one))) { 2325 fprintf(stderr, 2326 gettext(store_err_fmt), 2327 fname, *linenop, 2328 name, error_message(kret)); 2329 } 2330 else { 2331 if (verbose) 2332 fprintf(stderr, 2333 gettext( 2334 add_princ_fmt), 2335 name); 2336 retval = 0; 2337 } 2338 } 2339 else { 2340 fprintf(stderr, gettext(read_err_fmt), 2341 fname, *linenop, try2read); 2342 } 2343 } 2344 else { 2345 if (kret) 2346 fprintf(stderr, gettext(parse_err_fmt), 2347 fname, *linenop, name, error_message(kret)); 2348 else 2349 fprintf(stderr, gettext(no_mem_fmt), 2350 fname, *linenop); 2351 } 2352 } 2353 else { 2354 fprintf(stderr, 2355 gettext(rhead_err_fmt), fname, *linenop); 2356 } 2357 2358 if (op) 2359 free(op); 2360 if (kp) 2361 free(kp); 2362 if (name) 2363 free(name); 2364 krb5_db_free_principal(kcontext, &dbentry, 1); 2365 } 2366 else { 2367 if (nread == EOF) 2368 retval = -1; 2369 } 2370 return(retval); 2371 } 2372 2373 static int 2374 process_k5beta7_policy(fname, kcontext, filep, verbose, linenop, pol_db) 2375 char *fname; 2376 krb5_context kcontext; 2377 FILE *filep; 2378 int verbose; 2379 int *linenop; 2380 void *pol_db; 2381 { 2382 osa_policy_ent_rec rec; 2383 char namebuf[1024]; 2384 int nread, ret; 2385 2386 (*linenop)++; 2387 rec.name = namebuf; 2388 2389 nread = fscanf(filep, "%1024s\t%d\t%d\t%d\t%d\t%d\t%d", rec.name, 2390 &rec.pw_min_life, &rec.pw_max_life, 2391 &rec.pw_min_length, &rec.pw_min_classes, 2392 &rec.pw_history_num, &rec.policy_refcnt); 2393 if (nread == EOF) 2394 return -1; 2395 else if (nread != 7) { 2396 fprintf(stderr, 2397 gettext("cannot parse policy on line %d (%d read)\n"), 2398 *linenop, nread); 2399 return 1; 2400 } 2401 2402 if ((ret = krb5_db_create_policy(kcontext, &rec))) { 2403 if (ret && 2404 ((ret = krb5_db_put_policy(kcontext, &rec)))) { 2405 fprintf(stderr, gettext("cannot create policy on line %d: %s\n"), 2406 *linenop, error_message(ret)); 2407 return 1; 2408 } 2409 } 2410 if (verbose) 2411 fprintf(stderr, gettext("created policy %s\n"), rec.name); 2412 2413 return 0; 2414 } 2415 2416 /* 2417 * process_k5beta7_record() - Handle a dump record in krb5b7 format. 2418 * 2419 * Returns -1 for end of file, 0 for success and 1 for failure. 2420 */ 2421 static int 2422 process_k5beta7_record(fname, kcontext, filep, verbose, linenop) 2423 char *fname; 2424 krb5_context kcontext; 2425 FILE *filep; 2426 int verbose; 2427 int *linenop; 2428 { 2429 int nread; 2430 char rectype[100]; 2431 2432 nread = fscanf(filep, "%100s\t", rectype); 2433 if (nread == EOF) 2434 return -1; 2435 else if (nread != 1) 2436 return 1; 2437 if (strcmp(rectype, "princ") == 0) 2438 process_k5beta6_record(fname, kcontext, filep, verbose, 2439 linenop); 2440 else if (strcmp(rectype, "policy") == 0) 2441 process_k5beta7_policy(fname, kcontext, filep, verbose, 2442 linenop); 2443 else { 2444 fprintf(stderr, 2445 gettext("unknown record type \"%s\" on line %d\n"), 2446 rectype, *linenop); 2447 return 1; 2448 } 2449 2450 return 0; 2451 } 2452 2453 /* 2454 * process_ov_record() - Handle a dump record in OpenV*Secure 1.0 format. 2455 * 2456 * Returns -1 for end of file, 0 for success and 1 for failure. 2457 */ 2458 static int 2459 process_ov_record(fname, kcontext, filep, verbose, linenop) 2460 char *fname; 2461 krb5_context kcontext; 2462 FILE *filep; 2463 int verbose; 2464 int *linenop; 2465 { 2466 int nread; 2467 char rectype[100]; 2468 2469 nread = fscanf(filep, "%100s\t", rectype); 2470 if (nread == EOF) 2471 return -1; 2472 else if (nread != 1) 2473 return 1; 2474 if (strcmp(rectype, "princ") == 0) 2475 process_ov_principal(fname, kcontext, filep, verbose, 2476 linenop); 2477 else if (strcmp(rectype, "policy") == 0) 2478 process_k5beta7_policy(fname, kcontext, filep, verbose, 2479 linenop); 2480 else if (strcmp(rectype, "End") == 0) 2481 return -1; 2482 else { 2483 fprintf(stderr, 2484 gettext("unknown record type \"%s\" on line %d\n"), 2485 rectype, *linenop); 2486 return 1; 2487 } 2488 2489 return 0; 2490 } 2491 2492 /* 2493 * restore_dump() - Restore the database from any version dump file. 2494 */ 2495 static int 2496 restore_dump(programname, kcontext, dumpfile, f, verbose, dump) 2497 char *programname; 2498 krb5_context kcontext; 2499 char *dumpfile; 2500 FILE *f; 2501 int verbose; 2502 dump_version *dump; 2503 { 2504 int error; 2505 int lineno; 2506 2507 error = 0; 2508 lineno = 1; 2509 2510 /* 2511 * Process the records. 2512 */ 2513 while (!(error = (*dump->load_record)(dumpfile, 2514 kcontext, 2515 f, 2516 verbose, 2517 &lineno))) 2518 ; 2519 if (error != -1) 2520 fprintf(stderr, gettext(err_line_fmt), 2521 programname, lineno, dumpfile); 2522 else 2523 error = 0; 2524 2525 return(error); 2526 } 2527 2528 /* 2529 * Usage: load_db [-i] [-old] [-ov] [-b6] [-b7] [-verbose] [-update] [-hash] 2530 * filename 2531 */ 2532 void 2533 load_db(argc, argv) 2534 int argc; 2535 char **argv; 2536 { 2537 kadm5_config_params newparams; 2538 krb5_error_code kret; 2539 krb5_context kcontext; 2540 FILE *f; 2541 extern char *optarg; 2542 extern int optind; 2543 char *programname; 2544 char *dumpfile; 2545 char *dbname; 2546 char *dbname_tmp; 2547 char buf[BUFSIZ]; 2548 dump_version *load; 2549 int update, verbose; 2550 krb5_int32 crflags; 2551 int aindex; 2552 bool_t add_update = TRUE; 2553 char iheader[MAX_HEADER]; 2554 uint32_t caller, last_sno, last_seconds, last_useconds; 2555 kdb_log_context *log_ctx; 2556 int db_locked = 0; 2557 2558 /* 2559 * Parse the arguments. 2560 */ 2561 programname = argv[0]; 2562 if (strrchr(programname, (int) '/')) 2563 programname = strrchr(argv[0], (int) '/') + 1; 2564 dumpfile = (char *) NULL; 2565 dbname = global_params.dbname; 2566 load = NULL; 2567 update = 0; 2568 verbose = 0; 2569 crflags = KRB5_KDB_CREATE_BTREE; 2570 exit_status = 0; 2571 dbname_tmp = (char *) NULL; 2572 log_ctx = util_context->kdblog_context; 2573 2574 for (aindex = 1; aindex < argc; aindex++) { 2575 if (!strcmp(argv[aindex], oldoption)) 2576 load = &old_version; 2577 else if (!strcmp(argv[aindex], b6option)) 2578 load = &beta6_version; 2579 else if (!strcmp(argv[aindex], b7option)) 2580 load = &beta7_version; 2581 else if (!strcmp(argv[aindex], ovoption)) 2582 load = &ov_version; 2583 else if (!strcmp(argv[aindex], ipropoption)) { 2584 if (log_ctx && log_ctx->iproprole) { 2585 load = &iprop_version; 2586 add_update = FALSE; 2587 } else { 2588 fprintf(stderr, gettext("Iprop not enabled\n")); 2589 exit_status++; 2590 return; 2591 } 2592 } 2593 else if (!strcmp(argv[aindex], verboseoption)) 2594 verbose = 1; 2595 else if (!strcmp(argv[aindex], updateoption)) 2596 update = 1; 2597 else if (!strcmp(argv[aindex], hashoption)) { 2598 if (!add_db_arg("hash=true")) { 2599 com_err(progname, ENOMEM, "while parsing command arguments\n"); 2600 exit(1); 2601 } 2602 } else 2603 break; 2604 } 2605 if ((argc - aindex) != 1) { 2606 usage(); 2607 return; 2608 } 2609 dumpfile = argv[aindex]; 2610 2611 if (!(dbname_tmp = (char *) malloc(strlen(dbname)+ 2612 strlen(dump_tmptrail)+1))) { 2613 fprintf(stderr, gettext(no_name_mem_fmt), argv[0]); 2614 exit_status++; 2615 return; 2616 } 2617 strcpy(dbname_tmp, dbname); 2618 strcat(dbname_tmp, dump_tmptrail); 2619 2620 /* 2621 * Initialize the Kerberos context and error tables. 2622 */ 2623 if ((kret = kadm5_init_krb5_context(&kcontext))) { 2624 fprintf(stderr, gettext(ctx_err_fmt), programname); 2625 free(dbname_tmp); 2626 exit_status++; 2627 return; 2628 } 2629 2630 if( (kret = krb5_set_default_realm(kcontext, util_context->default_realm)) ) 2631 { 2632 fprintf(stderr, gettext("%s: Unable to set the default realm\n"), programname); 2633 free(dbname_tmp); 2634 exit_status++; 2635 return; 2636 } 2637 if (log_ctx && log_ctx->iproprole) 2638 kcontext->kdblog_context = (void *)log_ctx; 2639 /* 2640 * Open the dumpfile 2641 */ 2642 if (dumpfile) { 2643 if ((f = fopen(dumpfile, "r")) == NULL) { 2644 fprintf(stderr, gettext(dfile_err_fmt), 2645 programname, dumpfile, 2646 error_message(errno)); 2647 exit_status++; 2648 return; 2649 } 2650 if ((kret = krb5_lock_file(kcontext, fileno(f), 2651 KRB5_LOCKMODE_SHARED))) { 2652 fprintf(stderr, gettext("%s: Cannot lock %s: %s\n"), programname, 2653 dumpfile, error_message(errno)); 2654 exit_status++; 2655 return; 2656 } 2657 } else 2658 f = stdin; 2659 2660 /* 2661 * Auto-detect dump version if we weren't told, verify if we 2662 * were told. 2663 */ 2664 fgets(buf, sizeof(buf), f); 2665 if (load) { 2666 /* only check what we know; some headers only contain a prefix */ 2667 if (strncmp(buf, load->header, strlen(load->header)) != 0) { 2668 fprintf(stderr, gettext(head_bad_fmt), programname, dumpfile); 2669 exit_status++; 2670 if (dumpfile) fclose(f); 2671 return; 2672 } 2673 } else { 2674 /* perhaps this should be in an array, but so what? */ 2675 if (strcmp(buf, old_version.header) == 0) 2676 load = &old_version; 2677 else if (strcmp(buf, beta6_version.header) == 0) 2678 load = &beta6_version; 2679 else if (strcmp(buf, beta7_version.header) == 0) 2680 load = &beta7_version; 2681 else if (strcmp(buf, r1_3_version.header) == 0) 2682 load = &r1_3_version; 2683 else if (strncmp(buf, ov_version.header, 2684 strlen(ov_version.header)) == 0) 2685 load = &ov_version; 2686 else { 2687 fprintf(stderr, gettext(head_bad_fmt), 2688 programname, dumpfile); 2689 exit_status++; 2690 if (dumpfile) fclose(f); 2691 return; 2692 } 2693 } 2694 if (load->updateonly && !update) { 2695 fprintf(stderr, 2696 gettext("%s: dump version %s can only " 2697 "be loaded with the -update flag\n"), 2698 programname, load->name); 2699 exit_status++; 2700 return; 2701 } 2702 2703 /* 2704 * Cons up params for the new databases. If we are not in update 2705 * mode, we create an alternate database and then promote it to 2706 * be the live db. 2707 */ 2708 newparams = global_params; 2709 if (! update) { 2710 newparams.mask |= KADM5_CONFIG_DBNAME; 2711 newparams.dbname = dbname_tmp; 2712 2713 /* Solaris kerberos: using older kadm5_get_config_params interface */ 2714 if ((kret = kadm5_get_config_params(kcontext, NULL, NULL, 2715 &newparams, &newparams))) { 2716 com_err(argv[0], kret, 2717 gettext("while retreiving new " 2718 "configuration parameters")); 2719 exit_status++; 2720 return; 2721 } 2722 2723 if (!add_db_arg("temporary")) { 2724 com_err(progname, ENOMEM, "computing parameters for database"); 2725 exit(1); 2726 } 2727 } 2728 2729 /* 2730 * If not an update restoration, create the database. otherwise open 2731 */ 2732 if (!update) { 2733 if((kret = krb5_db_create(kcontext, db5util_db_args))) { 2734 const char *emsg = krb5_get_error_message(kcontext, kret); 2735 /* 2736 * See if something (like DAL KDB plugin) has set a specific error 2737 * message and use that otherwise use default. 2738 */ 2739 2740 if (emsg != NULL) { 2741 fprintf(stderr, "%s: %s\n", programname, emsg); 2742 krb5_free_error_message (kcontext, emsg); 2743 } else { 2744 fprintf(stderr, dbcreaterr_fmt, 2745 programname, dbname, error_message(kret)); 2746 } 2747 exit_status++; 2748 kadm5_free_config_params(kcontext, &newparams); 2749 if (dumpfile) fclose(f); 2750 return; 2751 } 2752 } 2753 else { 2754 /* 2755 * Initialize the database. 2756 */ 2757 if ((kret = krb5_db_open(kcontext, db5util_db_args, 2758 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) { 2759 const char *emsg = krb5_get_error_message(kcontext, kret); 2760 /* 2761 * See if something (like DAL KDB plugin) has set a specific 2762 * error message and use that otherwise use default. 2763 */ 2764 2765 if (emsg != NULL) { 2766 fprintf(stderr, "%s: %s\n", programname, emsg); 2767 krb5_free_error_message (kcontext, emsg); 2768 } else { 2769 fprintf(stderr, dbinit_err_fmt, 2770 programname, error_message(kret)); 2771 } 2772 exit_status++; 2773 goto error; 2774 } 2775 } 2776 2777 2778 /* 2779 * If an update restoration, make sure the db is left unusable if 2780 * the update fails. 2781 */ 2782 if ((kret = krb5_db_lock(kcontext, update?KRB5_DB_LOCKMODE_PERMANENT: KRB5_DB_LOCKMODE_EXCLUSIVE))) { 2783 /* 2784 * Ignore a not supported error since there is nothing to do about it 2785 * anyway. 2786 */ 2787 if (kret != KRB5_PLUGIN_OP_NOTSUPP) { 2788 fprintf(stderr, gettext("%s: %s while permanently locking database\n"), 2789 programname, error_message(kret)); 2790 exit_status++; 2791 goto error; 2792 } 2793 } 2794 else 2795 db_locked = 1; 2796 2797 if (log_ctx && log_ctx->iproprole) { 2798 if (add_update) 2799 caller = FKCOMMAND; 2800 else 2801 caller = FKPROPD; 2802 2803 if (ulog_map(kcontext, &global_params, caller)) { 2804 fprintf(stderr, 2805 gettext("%s: Could not map log\n"), 2806 programname); 2807 exit_status++; 2808 goto error; 2809 } 2810 2811 /* 2812 * We don't want to take out the ulog out from underneath 2813 * kadmind so we reinit the header log. 2814 * 2815 * We also don't want to add to the update log since we 2816 * are doing a whole sale replace of the db, because: 2817 * we could easily exceed # of update entries 2818 * we could implicity delete db entries during a replace 2819 * no advantage in incr updates when entire db is replaced 2820 */ 2821 if (!update) { 2822 memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t)); 2823 2824 log_ctx->ulog->kdb_hmagic = KDB_HMAGIC; 2825 log_ctx->ulog->db_version_num = KDB_VERSION; 2826 log_ctx->ulog->kdb_state = KDB_STABLE; 2827 log_ctx->ulog->kdb_block = ULOG_BLOCK; 2828 2829 log_ctx->iproprole = IPROP_NULL; 2830 2831 if (!add_update) { 2832 sscanf(buf, "%s %u %u %u", iheader, &last_sno, 2833 &last_seconds, &last_useconds); 2834 2835 log_ctx->ulog->kdb_last_sno = last_sno; 2836 log_ctx->ulog->kdb_last_time.seconds = 2837 last_seconds; 2838 log_ctx->ulog->kdb_last_time.useconds = 2839 last_useconds; 2840 } 2841 } 2842 } 2843 2844 if (restore_dump(programname, kcontext, (dumpfile) ? dumpfile : stdin_name, 2845 f, verbose, load)) { 2846 fprintf(stderr, gettext(restfail_fmt), 2847 programname, load->name); 2848 exit_status++; 2849 } 2850 2851 if (!update && load->create_kadm5 && 2852 ((kret = kadm5_create_magic_princs(&newparams, kcontext)))) { 2853 /* error message printed by create_magic_princs */ 2854 exit_status++; 2855 } 2856 2857 if (db_locked && (kret = krb5_db_unlock(kcontext))) { 2858 /* change this error? */ 2859 fprintf(stderr, gettext(dbunlockerr_fmt), 2860 programname, dbname, error_message(kret)); 2861 exit_status++; 2862 } 2863 2864 #if 0 2865 if ((kret = krb5_db_fini(kcontext))) { 2866 fprintf(stderr, gettext(close_err_fmt), 2867 programname, error_message(kret)); 2868 exit_status++; 2869 } 2870 #endif 2871 2872 /* close policy db below */ 2873 2874 if (exit_status == 0 && !update) { 2875 kret = krb5_db_promote(kcontext, db5util_db_args); 2876 /* 2877 * Ignore a not supported error since there is nothing to do about it 2878 * anyway. 2879 */ 2880 if (kret != 0 && kret != KRB5_PLUGIN_OP_NOTSUPP) { 2881 fprintf(stderr, gettext("%s: cannot make newly loaded database live (%s)\n"), 2882 programname, error_message(kret)); 2883 exit_status++; 2884 } 2885 } 2886 2887 error: 2888 /* 2889 * If not an update: if there was an error, destroy the temp database, 2890 * otherwise rename it into place. 2891 * 2892 * If an update: if there was no error, unlock the database. 2893 */ 2894 if (!update) { 2895 if (exit_status) { 2896 kret = krb5_db_destroy(kcontext, db5util_db_args); 2897 /* 2898 * Ignore a not supported error since there is nothing to do about 2899 * it anyway. 2900 */ 2901 if (kret != 0 && kret != KRB5_PLUGIN_OP_NOTSUPP) { 2902 fprintf(stderr, gettext(dbdelerr_fmt), 2903 programname, dbname, error_message(kret)); 2904 exit_status++; 2905 } 2906 } 2907 } 2908 2909 if (dumpfile) { 2910 (void) krb5_lock_file(kcontext, fileno(f), KRB5_LOCKMODE_UNLOCK); 2911 fclose(f); 2912 } 2913 2914 if (dbname_tmp) 2915 free(dbname_tmp); 2916 krb5_free_context(kcontext); 2917 } 2918