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