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