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