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