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