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