1 /* 2 * Copyright 2008 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 /* Solaris Kerberos: adding support for -rev/recurse flags */ 1359 int db_arg_index = 0; 1360 char *db_args[3] = {NULL, NULL, NULL}; 1361 1362 /* 1363 * Parse the arguments. 1364 */ 1365 programname = argv[0]; 1366 if (strrchr(programname, (int) '/')) 1367 programname = strrchr(argv[0], (int) '/') + 1; 1368 ofile = (char *) NULL; 1369 dump = &r1_3_version; 1370 arglist.verbose = 0; 1371 new_mkey_file = 0; 1372 mkey_convert = 0; 1373 backwards = 0; 1374 recursive = 0; 1375 log_ctx = util_context->kdblog_context; 1376 1377 /* 1378 * Parse the qualifiers. 1379 */ 1380 for (aindex = 1; aindex < argc; aindex++) { 1381 if (!strcmp(argv[aindex], oldoption)) 1382 dump = &old_version; 1383 else if (!strcmp(argv[aindex], b6option)) 1384 dump = &beta6_version; 1385 else if (!strcmp(argv[aindex], b7option)) 1386 dump = &beta7_version; 1387 else if (!strcmp(argv[aindex], ovoption)) 1388 dump = &ov_version; 1389 else if (!strcmp(argv[aindex], ipropoption)) { 1390 if (log_ctx && log_ctx->iproprole) { 1391 dump = &iprop_version; 1392 /* 1393 * dump_sno is used to indicate if the serial 1394 * # should be populated in the output 1395 * file to be used later by iprop for updating 1396 * the slave's update log when loading 1397 */ 1398 dump_sno = TRUE; 1399 } else { 1400 fprintf(stderr, gettext("Iprop not enabled\n")); 1401 exit_status++; 1402 return; 1403 } 1404 } 1405 else if (!strcmp(argv[aindex], verboseoption)) 1406 arglist.verbose++; 1407 else if (!strcmp(argv[aindex], "-mkey_convert")) 1408 mkey_convert = 1; 1409 else if (!strcmp(argv[aindex], "-new_mkey_file")) { 1410 new_mkey_file = argv[++aindex]; 1411 mkey_convert = 1; 1412 } else if (!strcmp(argv[aindex], "-rev")) { 1413 /* Solaris Kerberos: adding support for -rev/recurse flags */ 1414 /* hack to pass args to db specific plugin */ 1415 db_args[db_arg_index++] = "rev"; 1416 } else if (!strcmp(argv[aindex], "-recurse")) { 1417 /* hack to pass args to db specific plugin */ 1418 db_args[db_arg_index++] = "recurse"; 1419 } else 1420 break; 1421 } 1422 1423 arglist.names = (char **) NULL; 1424 arglist.nnames = 0; 1425 if (aindex < argc) { 1426 ofile = argv[aindex]; 1427 aindex++; 1428 if (aindex < argc) { 1429 arglist.names = &argv[aindex]; 1430 arglist.nnames = argc - aindex; 1431 } 1432 } 1433 1434 /* 1435 * Make sure the database is open. The policy database only has 1436 * to be opened if we try a dump that uses it. 1437 */ 1438 if (!dbactive) { 1439 com_err(argv[0], 0, Err_no_database); 1440 exit_status++; 1441 return; 1442 } 1443 1444 /* 1445 * If we're doing a master key conversion, set up for it. 1446 */ 1447 if (mkey_convert) { 1448 if (!valid_master_key) { 1449 /* TRUE here means read the keyboard, but only once */ 1450 retval = krb5_db_fetch_mkey(util_context, 1451 master_princ, 1452 global_params.enctype, 1453 TRUE, FALSE, 1454 (char *) NULL, 0, 1455 &master_key); 1456 if (retval) { 1457 com_err(argv[0], retval, 1458 gettext("while reading master key")); 1459 exit(1); 1460 } 1461 retval = krb5_db_verify_master_key(util_context, 1462 master_princ, 1463 &master_key); 1464 if (retval) { 1465 com_err(argv[0], retval, 1466 gettext("while verifying master key")); 1467 exit(1); 1468 } 1469 } 1470 if (!new_mkey_file) 1471 printf(gettext("Please enter new master key....\n")); 1472 if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 1473 global_params.enctype, 1474 (new_mkey_file == 0) ? 1475 (krb5_boolean) 1 : 0, 1476 TRUE, 1477 new_mkey_file, 0, 1478 &new_master_key))) { 1479 com_err(argv[0], retval, 1480 gettext("while reading new master key")); 1481 exit(1); 1482 } 1483 } 1484 1485 kret = 0; 1486 locked = 0; 1487 if (ofile && strcmp(ofile, "-")) { 1488 /* 1489 * Discourage accidental dumping to filenames beginning with '-'. 1490 */ 1491 if (ofile[0] == '-') 1492 usage(); 1493 /* 1494 * Make sure that we don't open and truncate on the fopen, 1495 * since that may hose an on-going kprop process. 1496 * 1497 * We could also control this by opening for read and 1498 * write, doing an flock with LOCK_EX, and then 1499 * truncating the file once we have gotten the lock, 1500 * but that would involve more OS dependencies than I 1501 * want to get into. 1502 */ 1503 unlink(ofile); 1504 if (!(f = fopen(ofile, "w"))) { 1505 fprintf(stderr, gettext(ofopen_error), 1506 programname, ofile, error_message(errno)); 1507 exit_status++; 1508 return; 1509 } 1510 if ((kret = krb5_lock_file(util_context, 1511 fileno(f), 1512 KRB5_LOCKMODE_EXCLUSIVE))) { 1513 fprintf(stderr, gettext(oflock_error), 1514 programname, ofile, error_message(kret)); 1515 exit_status++; 1516 } 1517 else 1518 locked = 1; 1519 } else { 1520 f = stdout; 1521 } 1522 if (f && !(kret)) { 1523 arglist.programname = programname; 1524 arglist.ofile = f; 1525 arglist.kcontext = util_context; 1526 fprintf(arglist.ofile, "%s", dump->header); 1527 1528 if (dump_sno) { 1529 if (ulog_map(util_context, &global_params, FKCOMMAND)) { 1530 fprintf(stderr, 1531 gettext("%s: Could not map log\n"), programname); 1532 exit_status++; 1533 goto error; 1534 } 1535 1536 /* 1537 * We grab the lock twice (once again in the iterator call), 1538 * but that's ok since the lock func handles incr locks held. 1539 */ 1540 if (krb5_db_lock(util_context, KRB5_LOCKMODE_SHARED)) { 1541 fprintf(stderr, 1542 gettext("%s: Couldn't grab lock\n"), programname); 1543 exit_status++; 1544 goto error; 1545 } 1546 1547 fprintf(f, " %u", log_ctx->ulog->kdb_last_sno); 1548 fprintf(f, " %u", log_ctx->ulog->kdb_last_time.seconds); 1549 fprintf(f, " %u", log_ctx->ulog->kdb_last_time.useconds); 1550 } 1551 1552 if (dump->header[strlen(dump->header)-1] != '\n') 1553 fputc('\n', arglist.ofile); 1554 1555 /* Solaris Kerberos: adding support for -rev/recurse flags */ 1556 /* don't pass in db_args if there aren't any */ 1557 if ((kret = krb5_db_iterate(util_context, 1558 NULL, 1559 dump->dump_princ, 1560 (krb5_pointer) &arglist, 1561 db_arg_index > 0 ? (char **)&db_args : NULL))) { 1562 fprintf(stderr, dumprec_err, 1563 programname, dump->name, error_message(kret)); 1564 exit_status++; 1565 if (dump_sno) 1566 (void) krb5_db_unlock(util_context); 1567 } 1568 if (dump->dump_policy && 1569 (kret = krb5_db_iter_policy( util_context, "*", dump->dump_policy, 1570 &arglist))) { 1571 fprintf(stderr, gettext(dumprec_err), 1572 programname, dump->name, 1573 error_message(kret)); 1574 exit_status++; 1575 } 1576 1577 error: 1578 if (ofile && f != stdout && !exit_status) { 1579 if (locked) { 1580 (void) krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_UNLOCK); 1581 locked = 0; 1582 } 1583 fclose(f); 1584 update_ok_file(ofile); 1585 } 1586 } 1587 if (locked) 1588 (void) krb5_lock_file(util_context, fileno(f), KRB5_LOCKMODE_UNLOCK); 1589 } 1590 1591 /* 1592 * Read a string of bytes while counting the number of lines passed. 1593 */ 1594 static int 1595 read_string(f, buf, len, lp) 1596 FILE *f; 1597 char *buf; 1598 int len; 1599 int *lp; 1600 { 1601 int c; 1602 int i, retval; 1603 1604 retval = 0; 1605 for (i=0; i<len; i++) { 1606 c = fgetc(f); 1607 if (c < 0) { 1608 retval = 1; 1609 break; 1610 } 1611 if (c == '\n') 1612 (*lp)++; 1613 buf[i] = (char) c; 1614 } 1615 buf[len] = '\0'; 1616 return(retval); 1617 } 1618 1619 /* 1620 * Read a string of two character representations of bytes. 1621 */ 1622 static int 1623 read_octet_string(f, buf, len) 1624 FILE *f; 1625 krb5_octet *buf; 1626 int len; 1627 { 1628 int c; 1629 int i, retval; 1630 1631 retval = 0; 1632 for (i=0; i<len; i++) { 1633 if (fscanf(f, "%02x", &c) != 1) { 1634 retval = 1; 1635 break; 1636 } 1637 buf[i] = (krb5_octet) c; 1638 } 1639 return(retval); 1640 } 1641 1642 /* 1643 * Find the end of an old format record. 1644 */ 1645 static void 1646 find_record_end(f, fn, lineno) 1647 FILE *f; 1648 char *fn; 1649 int lineno; 1650 { 1651 int ch; 1652 1653 if (((ch = fgetc(f)) != ';') || ((ch = fgetc(f)) != '\n')) { 1654 fprintf(stderr, gettext(trash_end_fmt), fn, lineno); 1655 while (ch != '\n') { 1656 putc(ch, stderr); 1657 ch = fgetc(f); 1658 } 1659 putc(ch, stderr); 1660 } 1661 } 1662 1663 #if 0 1664 /* 1665 * update_tl_data() - Generate the tl_data entries. 1666 */ 1667 static krb5_error_code 1668 update_tl_data(kcontext, dbentp, mod_name, mod_date, last_pwd_change) 1669 krb5_context kcontext; 1670 krb5_db_entry *dbentp; 1671 krb5_principal mod_name; 1672 krb5_timestamp mod_date; 1673 krb5_timestamp last_pwd_change; 1674 { 1675 krb5_error_code kret; 1676 1677 kret = 0 ; 1678 1679 /* 1680 * Handle modification principal. 1681 */ 1682 if (mod_name) { 1683 krb5_tl_mod_princ mprinc; 1684 1685 memset(&mprinc, 0, sizeof(mprinc)); 1686 if (!(kret = krb5_copy_principal(kcontext, 1687 mod_name, 1688 &mprinc.mod_princ))) { 1689 mprinc.mod_date = mod_date; 1690 kret = krb5_dbe_encode_mod_princ_data(kcontext, 1691 &mprinc, 1692 dbentp); 1693 } 1694 if (mprinc.mod_princ) 1695 krb5_free_principal(kcontext, mprinc.mod_princ); 1696 } 1697 1698 /* 1699 * Handle last password change. 1700 */ 1701 if (!kret) { 1702 krb5_tl_data *pwchg; 1703 krb5_boolean linked; 1704 1705 /* Find a previously existing entry */ 1706 for (pwchg = dbentp->tl_data; 1707 (pwchg) && (pwchg->tl_data_type != KRB5_TL_LAST_PWD_CHANGE); 1708 pwchg = pwchg->tl_data_next); 1709 1710 /* Check to see if we found one. */ 1711 linked = 0; 1712 if (!pwchg) { 1713 /* No, allocate a new one */ 1714 if ((pwchg = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) { 1715 memset(pwchg, 0, sizeof(krb5_tl_data)); 1716 if (!(pwchg->tl_data_contents = 1717 (krb5_octet *) malloc(sizeof(krb5_timestamp)))) { 1718 free(pwchg); 1719 pwchg = (krb5_tl_data *) NULL; 1720 } 1721 else { 1722 pwchg->tl_data_type = KRB5_TL_LAST_PWD_CHANGE; 1723 pwchg->tl_data_length = 1724 (krb5_int16) sizeof(krb5_timestamp); 1725 } 1726 } 1727 } 1728 else 1729 linked = 1; 1730 1731 /* Do we have an entry? */ 1732 if (pwchg && pwchg->tl_data_contents) { 1733 /* Encode it */ 1734 krb5_kdb_encode_int32(last_pwd_change, pwchg->tl_data_contents); 1735 /* Link it in if necessary */ 1736 if (!linked) { 1737 pwchg->tl_data_next = dbentp->tl_data; 1738 dbentp->tl_data = pwchg; 1739 dbentp->n_tl_data++; 1740 } 1741 } 1742 else 1743 kret = ENOMEM; 1744 } 1745 1746 return(kret); 1747 } 1748 #endif 1749 1750 /* 1751 * process_k5beta_record() - Handle a dump record in old format. 1752 * 1753 * Returns -1 for end of file, 0 for success and 1 for failure. 1754 */ 1755 static int 1756 process_k5beta_record(fname, kcontext, filep, verbose, linenop) 1757 char *fname; 1758 krb5_context kcontext; 1759 FILE *filep; 1760 int verbose; 1761 int *linenop; 1762 { 1763 int nmatched; 1764 int retval; 1765 krb5_db_entry dbent; 1766 int name_len, mod_name_len, key_len; 1767 int alt_key_len, salt_len, alt_salt_len; 1768 char *name; 1769 char *mod_name; 1770 int tmpint1, tmpint2, tmpint3; 1771 int error; 1772 const char *try2read; 1773 int i; 1774 krb5_key_data *pkey, *akey; 1775 krb5_timestamp last_pwd_change, mod_date; 1776 krb5_principal mod_princ; 1777 krb5_error_code kret; 1778 krb5_octet *shortcopy1 = NULL; /* SUNWresync121 memleak fix */ 1779 krb5_octet *shortcopy2 = NULL; 1780 1781 try2read = (char *) NULL; 1782 (*linenop)++; 1783 retval = 1; 1784 memset((char *)&dbent, 0, sizeof(dbent)); 1785 1786 /* Make sure we've got key_data entries */ 1787 if (krb5_dbe_create_key_data(kcontext, &dbent) || 1788 krb5_dbe_create_key_data(kcontext, &dbent)) { 1789 krb5_db_free_principal(kcontext, &dbent, 1); 1790 return(1); 1791 } 1792 pkey = &dbent.key_data[0]; 1793 akey = &dbent.key_data[1]; 1794 1795 /* 1796 * Match the sizes. 6 tokens to match. 1797 */ 1798 nmatched = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t", 1799 &name_len, &mod_name_len, &key_len, 1800 &alt_key_len, &salt_len, &alt_salt_len); 1801 if (nmatched == 6) { 1802 pkey->key_data_length[0] = key_len; 1803 akey->key_data_length[0] = alt_key_len; 1804 pkey->key_data_length[1] = salt_len; 1805 akey->key_data_length[1] = alt_salt_len; 1806 name = (char *) NULL; 1807 mod_name = (char *) NULL; 1808 /* 1809 * Get the memory for the variable length fields. 1810 */ 1811 if ((name = (char *) malloc((size_t) (name_len + 1))) && 1812 (mod_name = (char *) malloc((size_t) (mod_name_len + 1))) && 1813 (!key_len || 1814 (pkey->key_data_contents[0] = 1815 (krb5_octet *) malloc((size_t) (key_len + 1)))) && 1816 (!alt_key_len || 1817 (akey->key_data_contents[0] = 1818 (krb5_octet *) malloc((size_t) (alt_key_len + 1)))) && 1819 (!salt_len || 1820 (pkey->key_data_contents[1] = 1821 (krb5_octet *) malloc((size_t) (salt_len + 1)))) && 1822 (!alt_salt_len || 1823 (akey->key_data_contents[1] = 1824 (krb5_octet *) malloc((size_t) (alt_salt_len + 1)))) 1825 ) { 1826 error = 0; 1827 1828 /* Read the principal name */ 1829 if (read_string(filep, name, name_len, linenop)) { 1830 try2read = read_name_string; 1831 error++; 1832 } 1833 /* Read the key type */ 1834 if (!error && (fscanf(filep, "\t%d\t", &tmpint1) != 1)) { 1835 try2read = read_key_type; 1836 error++; 1837 } 1838 pkey->key_data_type[0] = tmpint1; 1839 /* Read the old format key */ 1840 if (!error && read_octet_string(filep, 1841 pkey->key_data_contents[0], 1842 pkey->key_data_length[0])) { 1843 try2read = read_key_data; 1844 error++; 1845 } 1846 /* convert to a new format key */ 1847 /* the encrypted version is stored as the unencrypted key length 1848 (4 bytes, MSB first) followed by the encrypted key. */ 1849 if ((pkey->key_data_length[0] > 4) 1850 && (pkey->key_data_contents[0][0] == 0) 1851 && (pkey->key_data_contents[0][1] == 0)) { 1852 /* this really does look like an old key, so drop and swap */ 1853 /* the *new* length is 2 bytes, LSB first, sigh. */ 1854 size_t shortlen = pkey->key_data_length[0]-4+2; 1855 krb5_octet *origdata = pkey->key_data_contents[0]; 1856 1857 shortcopy1 = (krb5_octet *) malloc(shortlen); 1858 if (shortcopy1) { 1859 shortcopy1[0] = origdata[3]; 1860 shortcopy1[1] = origdata[2]; 1861 memcpy(shortcopy1 + 2, origdata + 4, shortlen - 2); 1862 free(origdata); 1863 pkey->key_data_length[0] = shortlen; 1864 pkey->key_data_contents[0] = shortcopy1; 1865 } else { 1866 fprintf(stderr, gettext(no_mem_fmt), fname, *linenop); 1867 error++; 1868 } 1869 } 1870 1871 /* Read principal attributes */ 1872 if (!error && (fscanf(filep, 1873 "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t", 1874 &tmpint1, &dbent.max_life, 1875 &dbent.max_renewable_life, 1876 &tmpint2, &dbent.expiration, 1877 &dbent.pw_expiration, &last_pwd_change, 1878 &dbent.last_success, &dbent.last_failed, 1879 &tmpint3) != 10)) { 1880 try2read = read_pr_data1; 1881 error++; 1882 } 1883 pkey->key_data_kvno = tmpint1; 1884 dbent.fail_auth_count = tmpint3; 1885 /* Read modifier name */ 1886 if (!error && read_string(filep, 1887 mod_name, 1888 mod_name_len, 1889 linenop)) { 1890 try2read = read_mod_name; 1891 error++; 1892 } 1893 /* Read second set of attributes */ 1894 if (!error && (fscanf(filep, "\t%u\t%u\t%u\t", 1895 &mod_date, &dbent.attributes, 1896 &tmpint1) != 3)) { 1897 try2read = read_pr_data2; 1898 error++; 1899 } 1900 pkey->key_data_type[1] = tmpint1; 1901 /* Read salt data */ 1902 if (!error && read_octet_string(filep, 1903 pkey->key_data_contents[1], 1904 pkey->key_data_length[1])) { 1905 try2read = read_salt_data; 1906 error++; 1907 } 1908 /* Read alternate key type */ 1909 if (!error && (fscanf(filep, "\t%u\t", &tmpint1) != 1)) { 1910 try2read = read_akey_type; 1911 error++; 1912 } 1913 akey->key_data_type[0] = tmpint1; 1914 /* Read alternate key */ 1915 if (!error && read_octet_string(filep, 1916 akey->key_data_contents[0], 1917 akey->key_data_length[0])) { 1918 try2read = read_akey_data; 1919 error++; 1920 } 1921 1922 /* convert to a new format key */ 1923 /* the encrypted version is stored as the unencrypted key length 1924 (4 bytes, MSB first) followed by the encrypted key. */ 1925 if ((akey->key_data_length[0] > 4) 1926 && (akey->key_data_contents[0][0] == 0) 1927 && (akey->key_data_contents[0][1] == 0)) { 1928 /* this really does look like an old key, so drop and swap */ 1929 /* the *new* length is 2 bytes, LSB first, sigh. */ 1930 size_t shortlen = akey->key_data_length[0]-4+2; 1931 1932 krb5_octet *origdata = akey->key_data_contents[0]; 1933 1934 shortcopy2 = (krb5_octet *) malloc(shortlen); 1935 if (shortcopy2) { 1936 shortcopy2[0] = origdata[3]; 1937 shortcopy2[1] = origdata[2]; 1938 memcpy(shortcopy2 + 2, 1939 origdata + 4, shortlen - 2); 1940 free(origdata); 1941 akey->key_data_length[0] = shortlen; 1942 akey->key_data_contents[0] = shortcopy2; 1943 } else { 1944 fprintf(stderr, gettext(no_mem_fmt), fname, *linenop); 1945 error++; 1946 } 1947 } 1948 1949 /* Read alternate salt type */ 1950 if (!error && (fscanf(filep, "\t%u\t", &tmpint1) != 1)) { 1951 try2read = read_asalt_type; 1952 error++; 1953 } 1954 akey->key_data_type[1] = tmpint1; 1955 /* Read alternate salt data */ 1956 if (!error && read_octet_string(filep, 1957 akey->key_data_contents[1], 1958 akey->key_data_length[1])) { 1959 try2read = read_asalt_data; 1960 error++; 1961 } 1962 /* Read expansion data - discard it */ 1963 if (!error) { 1964 for (i=0; i<8; i++) { 1965 if (fscanf(filep, "\t%u", &tmpint1) != 1) { 1966 try2read = read_exp_data; 1967 error++; 1968 break; 1969 } 1970 } 1971 if (!error) 1972 find_record_end(filep, fname, *linenop); 1973 } 1974 1975 /* 1976 * If no error, then we're done reading. Now parse the names 1977 * and store the database dbent. 1978 */ 1979 if (!error) { 1980 if (!(kret = krb5_parse_name(kcontext, 1981 name, 1982 &dbent.princ))) { 1983 if (!(kret = krb5_parse_name(kcontext, 1984 mod_name, 1985 &mod_princ))) { 1986 if (!(kret = 1987 krb5_dbe_update_mod_princ_data(kcontext, 1988 &dbent, 1989 mod_date, 1990 mod_princ)) && 1991 !(kret = 1992 krb5_dbe_update_last_pwd_change(kcontext, 1993 &dbent, 1994 last_pwd_change))) { 1995 int one = 1; 1996 1997 dbent.len = KRB5_KDB_V1_BASE_LENGTH; 1998 pkey->key_data_ver = (pkey->key_data_type[1] || pkey->key_data_length[1]) ? 1999 2 : 1; 2000 akey->key_data_ver = (akey->key_data_type[1] || akey->key_data_length[1]) ? 2001 2 : 1; 2002 if ((pkey->key_data_type[0] == 2003 akey->key_data_type[0]) && 2004 (pkey->key_data_type[1] == 2005 akey->key_data_type[1])) 2006 dbent.n_key_data--; 2007 else if ((akey->key_data_type[0] == 0) 2008 && (akey->key_data_length[0] == 0) 2009 && (akey->key_data_type[1] == 0) 2010 && (akey->key_data_length[1] == 0)) 2011 dbent.n_key_data--; 2012 2013 dbent.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | 2014 KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_KEY_DATA | 2015 KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS | 2016 KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT; 2017 2018 if ((kret = krb5_db_put_principal(kcontext, 2019 &dbent, 2020 &one)) || 2021 (one != 1)) { 2022 fprintf(stderr, gettext(store_err_fmt), 2023 fname, *linenop, name, 2024 error_message(kret)); 2025 error++; 2026 } 2027 else { 2028 if (verbose) 2029 fprintf(stderr, 2030 gettext(add_princ_fmt), 2031 name); 2032 retval = 0; 2033 } 2034 dbent.n_key_data = 2; 2035 } 2036 krb5_free_principal(kcontext, mod_princ); 2037 } 2038 else { 2039 fprintf(stderr, 2040 gettext(parse_err_fmt), 2041 fname, *linenop, mod_name, 2042 error_message(kret)); 2043 error++; 2044 } 2045 } 2046 else { 2047 fprintf(stderr, gettext(parse_err_fmt), 2048 fname, *linenop, name, error_message(kret)); 2049 error++; 2050 } 2051 } 2052 else { 2053 fprintf(stderr, gettext(no_mem_fmt), fname, *linenop, try2read); 2054 } 2055 } 2056 else { 2057 fprintf(stderr, gettext(read_err_fmt), fname, *linenop); 2058 } 2059 2060 krb5_db_free_principal(kcontext, &dbent, 1); 2061 if (mod_name) 2062 free(mod_name); 2063 if (name) 2064 free(name); 2065 } 2066 else { 2067 if (nmatched != EOF) 2068 fprintf(stderr, gettext(rhead_err_fmt), 2069 fname, *linenop); 2070 else 2071 retval = -1; 2072 } 2073 2074 if (shortcopy1) 2075 free(shortcopy1); 2076 if (shortcopy2) 2077 free(shortcopy2); 2078 2079 return(retval); 2080 } 2081 2082 /* 2083 * process_k5beta6_record() - Handle a dump record in krb5b6 format. 2084 * 2085 * Returns -1 for end of file, 0 for success and 1 for failure. 2086 */ 2087 static int 2088 process_k5beta6_record(fname, kcontext, filep, verbose, linenop) 2089 char *fname; 2090 krb5_context kcontext; 2091 FILE *filep; 2092 int verbose; 2093 int *linenop; 2094 { 2095 int retval; 2096 krb5_db_entry dbentry; 2097 krb5_int32 t1, t2, t3, t4, t5, t6, t7, t8, t9; 2098 int nread; 2099 int error; 2100 int i, j, one; 2101 char *name; 2102 krb5_key_data *kp, *kdatap; 2103 krb5_tl_data **tlp, *tl; 2104 krb5_octet *op; 2105 krb5_error_code kret; 2106 const char *try2read; 2107 2108 try2read = (char *) NULL; 2109 memset((char *) &dbentry, 0, sizeof(dbentry)); 2110 (*linenop)++; 2111 retval = 1; 2112 name = (char *) NULL; 2113 kp = (krb5_key_data *) NULL; 2114 op = (krb5_octet *) NULL; 2115 error = 0; 2116 kret = 0; 2117 nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t", &t1, &t2, &t3, &t4, &t5); 2118 if (nread == 5) { 2119 /* Get memory for flattened principal name */ 2120 if (!(name = (char *) malloc((size_t) t2 + 1))) 2121 error++; 2122 2123 /* Get memory for and form tagged data linked list */ 2124 tlp = &dbentry.tl_data; 2125 for (i=0; i<t3; i++) { 2126 if ((*tlp = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) { 2127 memset(*tlp, 0, sizeof(krb5_tl_data)); 2128 tlp = &((*tlp)->tl_data_next); 2129 dbentry.n_tl_data++; 2130 } 2131 else { 2132 error++; 2133 break; 2134 } 2135 } 2136 2137 /* Get memory for key list */ 2138 if (t4 && !(kp = (krb5_key_data *) malloc((size_t) 2139 (t4*sizeof(krb5_key_data))))) 2140 error++; 2141 2142 /* Get memory for extra data */ 2143 if (t5 && !(op = (krb5_octet *) malloc((size_t) t5))) 2144 error++; 2145 2146 if (!error) { 2147 dbentry.len = t1; 2148 dbentry.n_key_data = t4; 2149 dbentry.e_length = t5; 2150 if (kp) { 2151 memset(kp, 0, (size_t) (t4*sizeof(krb5_key_data))); 2152 dbentry.key_data = kp; 2153 kp = (krb5_key_data *) NULL; 2154 } 2155 if (op) { 2156 memset(op, 0, (size_t) t5); 2157 dbentry.e_data = op; 2158 op = (krb5_octet *) NULL; 2159 } 2160 2161 /* Read in and parse the principal name */ 2162 if (!read_string(filep, name, t2, linenop) && 2163 !(kret = krb5_parse_name(kcontext, name, &dbentry.princ))) { 2164 2165 /* Get the fixed principal attributes */ 2166 nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t", 2167 &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9); 2168 if (nread == 8) { 2169 dbentry.attributes = (krb5_flags) t2; 2170 dbentry.max_life = (krb5_deltat) t3; 2171 dbentry.max_renewable_life = (krb5_deltat) t4; 2172 dbentry.expiration = (krb5_timestamp) t5; 2173 dbentry.pw_expiration = (krb5_timestamp) t6; 2174 dbentry.last_success = (krb5_timestamp) t7; 2175 dbentry.last_failed = (krb5_timestamp) t8; 2176 dbentry.fail_auth_count = (krb5_kvno) t9; 2177 dbentry.mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | 2178 KADM5_MAX_LIFE | KADM5_MAX_RLIFE | 2179 KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS | 2180 KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT; 2181 } else { 2182 try2read = read_nint_data; 2183 error++; 2184 } 2185 2186 /* 2187 * Get the tagged data. 2188 * 2189 * Really, this code ought to discard tl data types 2190 * that it knows are special to the current version 2191 * and were not supported in the previous version. 2192 * But it's a pain to implement that here, and doing 2193 * it at dump time has almost as good an effect, so 2194 * that's what I did. [krb5-admin/89] 2195 */ 2196 if (!error && dbentry.n_tl_data) { 2197 for (tl = dbentry.tl_data; tl; tl = tl->tl_data_next) { 2198 nread = fscanf(filep, "%d\t%d\t", &t1, &t2); 2199 if (nread == 2) { 2200 tl->tl_data_type = (krb5_int16) t1; 2201 tl->tl_data_length = (krb5_int16) t2; 2202 if (tl->tl_data_length) { 2203 if (!(tl->tl_data_contents = 2204 (krb5_octet *) malloc((size_t) t2+1)) || 2205 read_octet_string(filep, 2206 tl->tl_data_contents, 2207 t2)) { 2208 try2read = read_tcontents; 2209 error++; 2210 break; 2211 } 2212 /* test to set mask fields */ 2213 if (t1 == KRB5_TL_KADM_DATA) { 2214 XDR xdrs; 2215 osa_princ_ent_rec osa_princ_ent; 2216 2217 /* 2218 * Assuming aux_attributes will always be 2219 * there 2220 */ 2221 dbentry.mask |= KADM5_AUX_ATTRIBUTES; 2222 2223 /* test for an actual policy reference */ 2224 memset(&osa_princ_ent, 0, sizeof(osa_princ_ent)); 2225 xdrmem_create(&xdrs, (char *)tl->tl_data_contents, 2226 tl->tl_data_length, XDR_DECODE); 2227 if (xdr_osa_princ_ent_rec(&xdrs, &osa_princ_ent) && 2228 (osa_princ_ent.aux_attributes & KADM5_POLICY) && 2229 osa_princ_ent.policy != NULL) { 2230 2231 dbentry.mask |= KADM5_POLICY; 2232 kdb_free_entry(NULL, NULL, &osa_princ_ent); 2233 } 2234 xdr_destroy(&xdrs); 2235 } 2236 } 2237 else { 2238 /* Should be a null field */ 2239 nread = fscanf(filep, "%d", &t9); 2240 if ((nread != 1) || (t9 != -1)) { 2241 error++; 2242 try2read = read_tcontents; 2243 break; 2244 } 2245 } 2246 } 2247 else { 2248 try2read = read_ttypelen; 2249 error++; 2250 break; 2251 } 2252 } 2253 if (!error) 2254 dbentry.mask |= KADM5_TL_DATA; 2255 } 2256 2257 /* Get the key data */ 2258 if (!error && dbentry.n_key_data) { 2259 for (i=0; !error && (i<dbentry.n_key_data); i++) { 2260 kdatap = &dbentry.key_data[i]; 2261 nread = fscanf(filep, "%d\t%d\t", &t1, &t2); 2262 if (nread == 2) { 2263 kdatap->key_data_ver = (krb5_int16) t1; 2264 kdatap->key_data_kvno = (krb5_int16) t2; 2265 2266 for (j=0; j<t1; j++) { 2267 nread = fscanf(filep, "%d\t%d\t", &t3, &t4); 2268 if (nread == 2) { 2269 kdatap->key_data_type[j] = t3; 2270 kdatap->key_data_length[j] = t4; 2271 if (t4) { 2272 if (!(kdatap->key_data_contents[j] = 2273 (krb5_octet *) 2274 malloc((size_t) t4+1)) || 2275 read_octet_string(filep, 2276 kdatap->key_data_contents[j], 2277 t4)) { 2278 try2read = read_kcontents; 2279 error++; 2280 break; 2281 } 2282 } 2283 else { 2284 /* Should be a null field */ 2285 nread = fscanf(filep, "%d", &t9); 2286 if ((nread != 1) || (t9 != -1)) { 2287 error++; 2288 try2read = read_kcontents; 2289 break; 2290 } 2291 } 2292 } 2293 else { 2294 try2read = read_ktypelen; 2295 error++; 2296 break; 2297 } 2298 } 2299 } 2300 } 2301 if (!error) 2302 dbentry.mask |= KADM5_KEY_DATA; 2303 } 2304 2305 /* Get the extra data */ 2306 if (!error && dbentry.e_length) { 2307 if (read_octet_string(filep, 2308 dbentry.e_data, 2309 (int) dbentry.e_length)) { 2310 try2read = read_econtents; 2311 error++; 2312 } 2313 } 2314 else { 2315 nread = fscanf(filep, "%d", &t9); 2316 if ((nread != 1) || (t9 != -1)) { 2317 error++; 2318 try2read = read_econtents; 2319 } 2320 } 2321 2322 /* Finally, find the end of the record. */ 2323 if (!error) 2324 find_record_end(filep, fname, *linenop); 2325 2326 /* 2327 * We have either read in all the data or choked. 2328 */ 2329 if (!error) { 2330 one = 1; 2331 if ((kret = krb5_db_put_principal(kcontext, 2332 &dbentry, 2333 &one))) { 2334 fprintf(stderr, 2335 gettext(store_err_fmt), 2336 fname, *linenop, 2337 name, error_message(kret)); 2338 } 2339 else { 2340 if (verbose) 2341 fprintf(stderr, 2342 gettext( 2343 add_princ_fmt), 2344 name); 2345 retval = 0; 2346 } 2347 } 2348 else { 2349 fprintf(stderr, gettext(read_err_fmt), 2350 fname, *linenop, try2read); 2351 } 2352 } 2353 else { 2354 if (kret) 2355 fprintf(stderr, gettext(parse_err_fmt), 2356 fname, *linenop, name, error_message(kret)); 2357 else 2358 fprintf(stderr, gettext(no_mem_fmt), 2359 fname, *linenop); 2360 } 2361 } 2362 else { 2363 fprintf(stderr, 2364 gettext(rhead_err_fmt), fname, *linenop); 2365 } 2366 2367 if (op) 2368 free(op); 2369 if (kp) 2370 free(kp); 2371 if (name) 2372 free(name); 2373 krb5_db_free_principal(kcontext, &dbentry, 1); 2374 } 2375 else { 2376 if (nread == EOF) 2377 retval = -1; 2378 } 2379 return(retval); 2380 } 2381 2382 static int 2383 process_k5beta7_policy(fname, kcontext, filep, verbose, linenop, pol_db) 2384 char *fname; 2385 krb5_context kcontext; 2386 FILE *filep; 2387 int verbose; 2388 int *linenop; 2389 void *pol_db; 2390 { 2391 osa_policy_ent_rec rec; 2392 char namebuf[1024]; 2393 int nread, ret; 2394 2395 (*linenop)++; 2396 rec.name = namebuf; 2397 2398 nread = fscanf(filep, "%1024s\t%d\t%d\t%d\t%d\t%d\t%d", rec.name, 2399 &rec.pw_min_life, &rec.pw_max_life, 2400 &rec.pw_min_length, &rec.pw_min_classes, 2401 &rec.pw_history_num, &rec.policy_refcnt); 2402 if (nread == EOF) 2403 return -1; 2404 else if (nread != 7) { 2405 fprintf(stderr, 2406 gettext("cannot parse policy on line %d (%d read)\n"), 2407 *linenop, nread); 2408 return 1; 2409 } 2410 2411 if ((ret = krb5_db_create_policy(kcontext, &rec))) { 2412 if (ret && 2413 ((ret = krb5_db_put_policy(kcontext, &rec)))) { 2414 fprintf(stderr, gettext("cannot create policy on line %d: %s\n"), 2415 *linenop, error_message(ret)); 2416 return 1; 2417 } 2418 } 2419 if (verbose) 2420 fprintf(stderr, gettext("created policy %s\n"), rec.name); 2421 2422 return 0; 2423 } 2424 2425 /* 2426 * process_k5beta7_record() - Handle a dump record in krb5b7 format. 2427 * 2428 * Returns -1 for end of file, 0 for success and 1 for failure. 2429 */ 2430 static int 2431 process_k5beta7_record(fname, kcontext, filep, verbose, linenop) 2432 char *fname; 2433 krb5_context kcontext; 2434 FILE *filep; 2435 int verbose; 2436 int *linenop; 2437 { 2438 int nread; 2439 char rectype[100]; 2440 2441 nread = fscanf(filep, "%100s\t", rectype); 2442 if (nread == EOF) 2443 return -1; 2444 else if (nread != 1) 2445 return 1; 2446 if (strcmp(rectype, "princ") == 0) 2447 process_k5beta6_record(fname, kcontext, filep, verbose, 2448 linenop); 2449 else if (strcmp(rectype, "policy") == 0) 2450 process_k5beta7_policy(fname, kcontext, filep, verbose, 2451 linenop); 2452 else { 2453 fprintf(stderr, 2454 gettext("unknown record type \"%s\" on line %d\n"), 2455 rectype, *linenop); 2456 return 1; 2457 } 2458 2459 return 0; 2460 } 2461 2462 /* 2463 * process_ov_record() - Handle a dump record in OpenV*Secure 1.0 format. 2464 * 2465 * Returns -1 for end of file, 0 for success and 1 for failure. 2466 */ 2467 static int 2468 process_ov_record(fname, kcontext, filep, verbose, linenop) 2469 char *fname; 2470 krb5_context kcontext; 2471 FILE *filep; 2472 int verbose; 2473 int *linenop; 2474 { 2475 int nread; 2476 char rectype[100]; 2477 2478 nread = fscanf(filep, "%100s\t", rectype); 2479 if (nread == EOF) 2480 return -1; 2481 else if (nread != 1) 2482 return 1; 2483 if (strcmp(rectype, "princ") == 0) 2484 process_ov_principal(fname, kcontext, filep, verbose, 2485 linenop); 2486 else if (strcmp(rectype, "policy") == 0) 2487 process_k5beta7_policy(fname, kcontext, filep, verbose, 2488 linenop); 2489 else if (strcmp(rectype, "End") == 0) 2490 return -1; 2491 else { 2492 fprintf(stderr, 2493 gettext("unknown record type \"%s\" on line %d\n"), 2494 rectype, *linenop); 2495 return 1; 2496 } 2497 2498 return 0; 2499 } 2500 2501 /* 2502 * restore_dump() - Restore the database from any version dump file. 2503 */ 2504 static int 2505 restore_dump(programname, kcontext, dumpfile, f, verbose, dump) 2506 char *programname; 2507 krb5_context kcontext; 2508 char *dumpfile; 2509 FILE *f; 2510 int verbose; 2511 dump_version *dump; 2512 { 2513 int error; 2514 int lineno; 2515 2516 error = 0; 2517 lineno = 1; 2518 2519 /* 2520 * Process the records. 2521 */ 2522 while (!(error = (*dump->load_record)(dumpfile, 2523 kcontext, 2524 f, 2525 verbose, 2526 &lineno))) 2527 ; 2528 if (error != -1) 2529 fprintf(stderr, gettext(err_line_fmt), 2530 programname, lineno, dumpfile); 2531 else 2532 error = 0; 2533 2534 return(error); 2535 } 2536 2537 /* 2538 * Usage: load_db [-i] [-old] [-ov] [-b6] [-b7] [-verbose] [-update] [-hash] 2539 * filename 2540 */ 2541 void 2542 load_db(argc, argv) 2543 int argc; 2544 char **argv; 2545 { 2546 kadm5_config_params newparams; 2547 krb5_error_code kret; 2548 krb5_context kcontext; 2549 FILE *f; 2550 extern char *optarg; 2551 extern int optind; 2552 char *programname; 2553 char *dumpfile; 2554 char *dbname; 2555 char *dbname_tmp; 2556 char buf[BUFSIZ]; 2557 dump_version *load; 2558 int update, verbose; 2559 krb5_int32 crflags; 2560 int aindex; 2561 bool_t add_update = TRUE; 2562 char iheader[MAX_HEADER]; 2563 uint32_t caller, last_sno, last_seconds, last_useconds; 2564 kdb_log_context *log_ctx; 2565 int db_locked = 0; 2566 2567 /* 2568 * Parse the arguments. 2569 */ 2570 programname = argv[0]; 2571 if (strrchr(programname, (int) '/')) 2572 programname = strrchr(argv[0], (int) '/') + 1; 2573 dumpfile = (char *) NULL; 2574 dbname = global_params.dbname; 2575 load = NULL; 2576 update = 0; 2577 verbose = 0; 2578 crflags = KRB5_KDB_CREATE_BTREE; 2579 exit_status = 0; 2580 dbname_tmp = (char *) NULL; 2581 log_ctx = util_context->kdblog_context; 2582 2583 for (aindex = 1; aindex < argc; aindex++) { 2584 if (!strcmp(argv[aindex], oldoption)) 2585 load = &old_version; 2586 else if (!strcmp(argv[aindex], b6option)) 2587 load = &beta6_version; 2588 else if (!strcmp(argv[aindex], b7option)) 2589 load = &beta7_version; 2590 else if (!strcmp(argv[aindex], ovoption)) 2591 load = &ov_version; 2592 else if (!strcmp(argv[aindex], ipropoption)) { 2593 if (log_ctx && log_ctx->iproprole) { 2594 load = &iprop_version; 2595 add_update = FALSE; 2596 } else { 2597 fprintf(stderr, gettext("Iprop not enabled\n")); 2598 exit_status++; 2599 return; 2600 } 2601 } 2602 else if (!strcmp(argv[aindex], verboseoption)) 2603 verbose = 1; 2604 else if (!strcmp(argv[aindex], updateoption)) 2605 update = 1; 2606 else if (!strcmp(argv[aindex], hashoption)) { 2607 if (!add_db_arg("hash=true")) { 2608 com_err(progname, ENOMEM, "while parsing command arguments\n"); 2609 exit(1); 2610 } 2611 } else 2612 break; 2613 } 2614 if ((argc - aindex) != 1) { 2615 usage(); 2616 return; 2617 } 2618 dumpfile = argv[aindex]; 2619 2620 if (!(dbname_tmp = (char *) malloc(strlen(dbname)+ 2621 strlen(dump_tmptrail)+1))) { 2622 fprintf(stderr, gettext(no_name_mem_fmt), argv[0]); 2623 exit_status++; 2624 return; 2625 } 2626 strcpy(dbname_tmp, dbname); 2627 strcat(dbname_tmp, dump_tmptrail); 2628 2629 /* 2630 * Initialize the Kerberos context and error tables. 2631 */ 2632 if ((kret = kadm5_init_krb5_context(&kcontext))) { 2633 fprintf(stderr, gettext(ctx_err_fmt), programname); 2634 free(dbname_tmp); 2635 exit_status++; 2636 return; 2637 } 2638 2639 if( (kret = krb5_set_default_realm(kcontext, util_context->default_realm)) ) 2640 { 2641 fprintf(stderr, gettext("%s: Unable to set the default realm\n"), programname); 2642 free(dbname_tmp); 2643 exit_status++; 2644 return; 2645 } 2646 if (log_ctx && log_ctx->iproprole) 2647 kcontext->kdblog_context = (void *)log_ctx; 2648 /* 2649 * Open the dumpfile 2650 */ 2651 if (dumpfile) { 2652 if ((f = fopen(dumpfile, "r")) == NULL) { 2653 fprintf(stderr, gettext(dfile_err_fmt), 2654 programname, dumpfile, 2655 error_message(errno)); 2656 exit_status++; 2657 return; 2658 } 2659 if ((kret = krb5_lock_file(kcontext, fileno(f), 2660 KRB5_LOCKMODE_SHARED))) { 2661 fprintf(stderr, gettext("%s: Cannot lock %s: %s\n"), programname, 2662 dumpfile, error_message(errno)); 2663 exit_status++; 2664 return; 2665 } 2666 } else 2667 f = stdin; 2668 2669 /* 2670 * Auto-detect dump version if we weren't told, verify if we 2671 * were told. 2672 */ 2673 fgets(buf, sizeof(buf), f); 2674 if (load) { 2675 /* only check what we know; some headers only contain a prefix */ 2676 if (strncmp(buf, load->header, strlen(load->header)) != 0) { 2677 fprintf(stderr, gettext(head_bad_fmt), programname, dumpfile); 2678 exit_status++; 2679 if (dumpfile) fclose(f); 2680 return; 2681 } 2682 } else { 2683 /* perhaps this should be in an array, but so what? */ 2684 if (strcmp(buf, old_version.header) == 0) 2685 load = &old_version; 2686 else if (strcmp(buf, beta6_version.header) == 0) 2687 load = &beta6_version; 2688 else if (strcmp(buf, beta7_version.header) == 0) 2689 load = &beta7_version; 2690 else if (strcmp(buf, r1_3_version.header) == 0) 2691 load = &r1_3_version; 2692 else if (strncmp(buf, ov_version.header, 2693 strlen(ov_version.header)) == 0) 2694 load = &ov_version; 2695 else { 2696 fprintf(stderr, gettext(head_bad_fmt), 2697 programname, dumpfile); 2698 exit_status++; 2699 if (dumpfile) fclose(f); 2700 return; 2701 } 2702 } 2703 if (load->updateonly && !update) { 2704 fprintf(stderr, 2705 gettext("%s: dump version %s can only " 2706 "be loaded with the -update flag\n"), 2707 programname, load->name); 2708 exit_status++; 2709 return; 2710 } 2711 2712 /* 2713 * Cons up params for the new databases. If we are not in update 2714 * mode, we create an alternate database and then promote it to 2715 * be the live db. 2716 */ 2717 newparams = global_params; 2718 if (! update) { 2719 newparams.mask |= KADM5_CONFIG_DBNAME; 2720 newparams.dbname = dbname_tmp; 2721 2722 /* Solaris kerberos: using older kadm5_get_config_params interface */ 2723 if ((kret = kadm5_get_config_params(kcontext, NULL, NULL, 2724 &newparams, &newparams))) { 2725 com_err(argv[0], kret, 2726 gettext("while retreiving new " 2727 "configuration parameters")); 2728 exit_status++; 2729 return; 2730 } 2731 2732 if (!add_db_arg("temporary")) { 2733 com_err(progname, ENOMEM, "computing parameters for database"); 2734 exit(1); 2735 } 2736 } 2737 2738 /* 2739 * If not an update restoration, create the database. otherwise open 2740 */ 2741 if (!update) { 2742 if((kret = krb5_db_create(kcontext, db5util_db_args))) { 2743 const char *emsg = krb5_get_error_message(kcontext, kret); 2744 /* 2745 * See if something (like DAL KDB plugin) has set a specific error 2746 * message and use that otherwise use default. 2747 */ 2748 2749 if (emsg != NULL) { 2750 fprintf(stderr, "%s: %s\n", programname, emsg); 2751 krb5_free_error_message (kcontext, emsg); 2752 } else { 2753 fprintf(stderr, dbcreaterr_fmt, 2754 programname, dbname, error_message(kret)); 2755 } 2756 exit_status++; 2757 kadm5_free_config_params(kcontext, &newparams); 2758 if (dumpfile) fclose(f); 2759 return; 2760 } 2761 } 2762 else { 2763 /* 2764 * Initialize the database. 2765 */ 2766 if ((kret = krb5_db_open(kcontext, db5util_db_args, 2767 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) { 2768 const char *emsg = krb5_get_error_message(kcontext, kret); 2769 /* 2770 * See if something (like DAL KDB plugin) has set a specific 2771 * error message and use that otherwise use default. 2772 */ 2773 2774 if (emsg != NULL) { 2775 fprintf(stderr, "%s: %s\n", programname, emsg); 2776 krb5_free_error_message (kcontext, emsg); 2777 } else { 2778 fprintf(stderr, dbinit_err_fmt, 2779 programname, error_message(kret)); 2780 } 2781 exit_status++; 2782 goto error; 2783 } 2784 } 2785 2786 2787 /* 2788 * If an update restoration, make sure the db is left unusable if 2789 * the update fails. 2790 */ 2791 if ((kret = krb5_db_lock(kcontext, update?KRB5_DB_LOCKMODE_PERMANENT: KRB5_DB_LOCKMODE_EXCLUSIVE))) { 2792 /* 2793 * Ignore a not supported error since there is nothing to do about it 2794 * anyway. 2795 */ 2796 if (kret != KRB5_PLUGIN_OP_NOTSUPP) { 2797 fprintf(stderr, gettext("%s: %s while permanently locking database\n"), 2798 programname, error_message(kret)); 2799 exit_status++; 2800 goto error; 2801 } 2802 } 2803 else 2804 db_locked = 1; 2805 2806 if (log_ctx && log_ctx->iproprole) { 2807 if (add_update) 2808 caller = FKCOMMAND; 2809 else 2810 caller = FKPROPD; 2811 2812 if (ulog_map(kcontext, &global_params, caller)) { 2813 fprintf(stderr, 2814 gettext("%s: Could not map log\n"), 2815 programname); 2816 exit_status++; 2817 goto error; 2818 } 2819 2820 /* 2821 * We don't want to take out the ulog out from underneath 2822 * kadmind so we reinit the header log. 2823 * 2824 * We also don't want to add to the update log since we 2825 * are doing a whole sale replace of the db, because: 2826 * we could easily exceed # of update entries 2827 * we could implicity delete db entries during a replace 2828 * no advantage in incr updates when entire db is replaced 2829 */ 2830 if (!update) { 2831 memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t)); 2832 2833 log_ctx->ulog->kdb_hmagic = KDB_HMAGIC; 2834 log_ctx->ulog->db_version_num = KDB_VERSION; 2835 log_ctx->ulog->kdb_state = KDB_STABLE; 2836 log_ctx->ulog->kdb_block = ULOG_BLOCK; 2837 2838 log_ctx->iproprole = IPROP_NULL; 2839 2840 if (!add_update) { 2841 sscanf(buf, "%s %u %u %u", iheader, &last_sno, 2842 &last_seconds, &last_useconds); 2843 2844 log_ctx->ulog->kdb_last_sno = last_sno; 2845 log_ctx->ulog->kdb_last_time.seconds = 2846 last_seconds; 2847 log_ctx->ulog->kdb_last_time.useconds = 2848 last_useconds; 2849 } 2850 } 2851 } 2852 2853 if (restore_dump(programname, kcontext, (dumpfile) ? dumpfile : stdin_name, 2854 f, verbose, load)) { 2855 fprintf(stderr, gettext(restfail_fmt), 2856 programname, load->name); 2857 exit_status++; 2858 } 2859 2860 if (!update && load->create_kadm5 && 2861 ((kret = kadm5_create_magic_princs(&newparams, kcontext)))) { 2862 /* error message printed by create_magic_princs */ 2863 exit_status++; 2864 } 2865 2866 if (db_locked && (kret = krb5_db_unlock(kcontext))) { 2867 /* change this error? */ 2868 fprintf(stderr, gettext(dbunlockerr_fmt), 2869 programname, dbname, error_message(kret)); 2870 exit_status++; 2871 } 2872 2873 #if 0 2874 if ((kret = krb5_db_fini(kcontext))) { 2875 fprintf(stderr, gettext(close_err_fmt), 2876 programname, error_message(kret)); 2877 exit_status++; 2878 } 2879 #endif 2880 2881 /* close policy db below */ 2882 2883 if (exit_status == 0 && !update) { 2884 kret = krb5_db_promote(kcontext, db5util_db_args); 2885 /* 2886 * Ignore a not supported error since there is nothing to do about it 2887 * anyway. 2888 */ 2889 if (kret != 0 && kret != KRB5_PLUGIN_OP_NOTSUPP) { 2890 fprintf(stderr, gettext("%s: cannot make newly loaded database live (%s)\n"), 2891 programname, error_message(kret)); 2892 exit_status++; 2893 } 2894 } 2895 2896 error: 2897 /* 2898 * If not an update: if there was an error, destroy the temp database, 2899 * otherwise rename it into place. 2900 * 2901 * If an update: if there was no error, unlock the database. 2902 */ 2903 if (!update) { 2904 if (exit_status) { 2905 kret = krb5_db_destroy(kcontext, db5util_db_args); 2906 /* 2907 * Ignore a not supported error since there is nothing to do about 2908 * it anyway. 2909 */ 2910 if (kret != 0 && kret != KRB5_PLUGIN_OP_NOTSUPP) { 2911 fprintf(stderr, gettext(dbdelerr_fmt), 2912 programname, dbname, error_message(kret)); 2913 exit_status++; 2914 } 2915 } 2916 } 2917 2918 if (dumpfile) { 2919 (void) krb5_lock_file(kcontext, fileno(f), KRB5_LOCKMODE_UNLOCK); 2920 fclose(f); 2921 } 2922 2923 if (dbname_tmp) 2924 free(dbname_tmp); 2925 krb5_free_context(kcontext); 2926 } 2927