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