xref: /freebsd/crypto/krb5/src/kadmin/dbutil/dump.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* kadmin/dbutil/dump.c - Dump a KDC database */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * Copyright 1990,1991,2001,2006,2008,2009,2013 by the Massachusetts Institute
5*7f2fe78bSCy Schubert  * of Technology.  All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert /*
27*7f2fe78bSCy Schubert  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28*7f2fe78bSCy Schubert  * Use is subject to license terms.
29*7f2fe78bSCy Schubert  */
30*7f2fe78bSCy Schubert 
31*7f2fe78bSCy Schubert #include <k5-int.h>
32*7f2fe78bSCy Schubert #include <kadm5/admin.h>
33*7f2fe78bSCy Schubert #include <kadm5/server_internal.h>
34*7f2fe78bSCy Schubert #include <kdb.h>
35*7f2fe78bSCy Schubert #include <com_err.h>
36*7f2fe78bSCy Schubert #include "kdb5_util.h"
37*7f2fe78bSCy Schubert #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
38*7f2fe78bSCy Schubert #include <regex.h>
39*7f2fe78bSCy Schubert #endif  /* HAVE_REGEX_H */
40*7f2fe78bSCy Schubert 
41*7f2fe78bSCy Schubert /* Needed for master key conversion. */
42*7f2fe78bSCy Schubert static krb5_boolean mkey_convert;
43*7f2fe78bSCy Schubert krb5_keyblock new_master_keyblock;
44*7f2fe78bSCy Schubert krb5_kvno new_mkvno;
45*7f2fe78bSCy Schubert 
46*7f2fe78bSCy Schubert #define K5Q1(x) #x
47*7f2fe78bSCy Schubert #define K5Q(x) K5Q1(x)
48*7f2fe78bSCy Schubert #define K5CONST_WIDTH_SCANF_STR(x) "%" K5Q(x) "s"
49*7f2fe78bSCy Schubert 
50*7f2fe78bSCy Schubert /* Use compile(3) if no regcomp present. */
51*7f2fe78bSCy Schubert #if !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H)
52*7f2fe78bSCy Schubert #define INIT char *sp = instring;
53*7f2fe78bSCy Schubert #define GETC() (*sp++)
54*7f2fe78bSCy Schubert #define PEEKC() (*sp)
55*7f2fe78bSCy Schubert #define UNGETC(c) (--sp)
56*7f2fe78bSCy Schubert #define RETURN(c) return(c)
57*7f2fe78bSCy Schubert #define ERROR(c)
58*7f2fe78bSCy Schubert #define RE_BUF_SIZE 1024
59*7f2fe78bSCy Schubert #include <regexp.h>
60*7f2fe78bSCy Schubert #endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */
61*7f2fe78bSCy Schubert 
62*7f2fe78bSCy Schubert typedef krb5_error_code (*dump_func)(krb5_context context,
63*7f2fe78bSCy Schubert                                      krb5_db_entry *entry, const char *name,
64*7f2fe78bSCy Schubert                                      FILE *fp, krb5_boolean verbose,
65*7f2fe78bSCy Schubert                                      krb5_boolean omit_nra);
66*7f2fe78bSCy Schubert typedef int (*load_func)(krb5_context context, const char *dumpfile, FILE *fp,
67*7f2fe78bSCy Schubert                          krb5_boolean verbose, int *linenop);
68*7f2fe78bSCy Schubert 
69*7f2fe78bSCy Schubert typedef struct _dump_version {
70*7f2fe78bSCy Schubert     char *name;
71*7f2fe78bSCy Schubert     char *header;
72*7f2fe78bSCy Schubert     int updateonly;
73*7f2fe78bSCy Schubert     int iprop;
74*7f2fe78bSCy Schubert     int ipropx;
75*7f2fe78bSCy Schubert     dump_func dump_princ;
76*7f2fe78bSCy Schubert     osa_adb_iter_policy_func dump_policy;
77*7f2fe78bSCy Schubert     load_func load_record;
78*7f2fe78bSCy Schubert } dump_version;
79*7f2fe78bSCy Schubert 
80*7f2fe78bSCy Schubert struct dump_args {
81*7f2fe78bSCy Schubert     FILE *ofile;
82*7f2fe78bSCy Schubert     krb5_context context;
83*7f2fe78bSCy Schubert     char **names;
84*7f2fe78bSCy Schubert     int nnames;
85*7f2fe78bSCy Schubert     krb5_boolean verbose;
86*7f2fe78bSCy Schubert     krb5_boolean omit_nra;      /* omit non-replicated attributes */
87*7f2fe78bSCy Schubert     dump_version *dump;
88*7f2fe78bSCy Schubert };
89*7f2fe78bSCy Schubert 
90*7f2fe78bSCy Schubert /* External data */
91*7f2fe78bSCy Schubert extern krb5_db_entry *master_entry;
92*7f2fe78bSCy Schubert 
93*7f2fe78bSCy Schubert /*
94*7f2fe78bSCy Schubert  * Re-encrypt the key_data with the new master key...
95*7f2fe78bSCy Schubert  */
96*7f2fe78bSCy Schubert krb5_error_code
master_key_convert(krb5_context context,krb5_db_entry * db_entry)97*7f2fe78bSCy Schubert master_key_convert(krb5_context context, krb5_db_entry *db_entry)
98*7f2fe78bSCy Schubert {
99*7f2fe78bSCy Schubert     krb5_error_code retval;
100*7f2fe78bSCy Schubert     krb5_keyblock v5plainkey, *key_ptr, *tmp_mkey;
101*7f2fe78bSCy Schubert     krb5_keysalt keysalt;
102*7f2fe78bSCy Schubert     krb5_key_data new_key_data, *key_data;
103*7f2fe78bSCy Schubert     krb5_boolean is_mkey;
104*7f2fe78bSCy Schubert     krb5_kvno kvno;
105*7f2fe78bSCy Schubert     int i, j;
106*7f2fe78bSCy Schubert 
107*7f2fe78bSCy Schubert     is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ);
108*7f2fe78bSCy Schubert 
109*7f2fe78bSCy Schubert     if (is_mkey) {
110*7f2fe78bSCy Schubert         return add_new_mkey(context, db_entry, &new_master_keyblock,
111*7f2fe78bSCy Schubert                             new_mkvno);
112*7f2fe78bSCy Schubert     }
113*7f2fe78bSCy Schubert 
114*7f2fe78bSCy Schubert     for (i = 0; i < db_entry->n_key_data; i++) {
115*7f2fe78bSCy Schubert         key_data = &db_entry->key_data[i];
116*7f2fe78bSCy Schubert         retval = krb5_dbe_find_mkey(context, db_entry, &tmp_mkey);
117*7f2fe78bSCy Schubert         if (retval)
118*7f2fe78bSCy Schubert             return retval;
119*7f2fe78bSCy Schubert         retval = krb5_dbe_decrypt_key_data(context, tmp_mkey, key_data,
120*7f2fe78bSCy Schubert                                            &v5plainkey, &keysalt);
121*7f2fe78bSCy Schubert         if (retval)
122*7f2fe78bSCy Schubert             return retval;
123*7f2fe78bSCy Schubert 
124*7f2fe78bSCy Schubert         memset(&new_key_data, 0, sizeof(new_key_data));
125*7f2fe78bSCy Schubert 
126*7f2fe78bSCy Schubert         key_ptr = &v5plainkey;
127*7f2fe78bSCy Schubert         kvno = key_data->key_data_kvno;
128*7f2fe78bSCy Schubert 
129*7f2fe78bSCy Schubert         retval = krb5_dbe_encrypt_key_data(context, &new_master_keyblock,
130*7f2fe78bSCy Schubert                                            key_ptr, &keysalt, kvno,
131*7f2fe78bSCy Schubert                                            &new_key_data);
132*7f2fe78bSCy Schubert         if (retval)
133*7f2fe78bSCy Schubert             return retval;
134*7f2fe78bSCy Schubert         krb5_free_keyblock_contents(context, &v5plainkey);
135*7f2fe78bSCy Schubert         for (j = 0; j < key_data->key_data_ver; j++) {
136*7f2fe78bSCy Schubert             if (key_data->key_data_length[j])
137*7f2fe78bSCy Schubert                 free(key_data->key_data_contents[j]);
138*7f2fe78bSCy Schubert         }
139*7f2fe78bSCy Schubert         *key_data = new_key_data;
140*7f2fe78bSCy Schubert     }
141*7f2fe78bSCy Schubert     assert(new_mkvno > 0);
142*7f2fe78bSCy Schubert     return krb5_dbe_update_mkvno(context, db_entry, new_mkvno);
143*7f2fe78bSCy Schubert }
144*7f2fe78bSCy Schubert 
145*7f2fe78bSCy Schubert /* Create temp file for new dump to be named ofile. */
146*7f2fe78bSCy Schubert static FILE *
create_ofile(char * ofile,char ** tmpname)147*7f2fe78bSCy Schubert create_ofile(char *ofile, char **tmpname)
148*7f2fe78bSCy Schubert {
149*7f2fe78bSCy Schubert     int fd = -1;
150*7f2fe78bSCy Schubert     FILE *f;
151*7f2fe78bSCy Schubert 
152*7f2fe78bSCy Schubert     *tmpname = NULL;
153*7f2fe78bSCy Schubert     if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0)
154*7f2fe78bSCy Schubert         goto error;
155*7f2fe78bSCy Schubert 
156*7f2fe78bSCy Schubert     fd = mkstemp(*tmpname);
157*7f2fe78bSCy Schubert     if (fd == -1)
158*7f2fe78bSCy Schubert         goto error;
159*7f2fe78bSCy Schubert 
160*7f2fe78bSCy Schubert     f = fdopen(fd, "w+");
161*7f2fe78bSCy Schubert     if (f != NULL)
162*7f2fe78bSCy Schubert         return f;
163*7f2fe78bSCy Schubert 
164*7f2fe78bSCy Schubert error:
165*7f2fe78bSCy Schubert     com_err(progname, errno, _("while allocating temporary filename dump"));
166*7f2fe78bSCy Schubert     if (fd >= 0)
167*7f2fe78bSCy Schubert         unlink(*tmpname);
168*7f2fe78bSCy Schubert     exit(1);
169*7f2fe78bSCy Schubert }
170*7f2fe78bSCy Schubert 
171*7f2fe78bSCy Schubert /* Rename new dump file into place. */
172*7f2fe78bSCy Schubert static void
finish_ofile(char * ofile,char ** tmpname)173*7f2fe78bSCy Schubert finish_ofile(char *ofile, char **tmpname)
174*7f2fe78bSCy Schubert {
175*7f2fe78bSCy Schubert     if (rename(*tmpname, ofile) == -1) {
176*7f2fe78bSCy Schubert         com_err(progname, errno, _("while renaming dump file into place"));
177*7f2fe78bSCy Schubert         exit(1);
178*7f2fe78bSCy Schubert     }
179*7f2fe78bSCy Schubert     free(*tmpname);
180*7f2fe78bSCy Schubert     *tmpname = NULL;
181*7f2fe78bSCy Schubert }
182*7f2fe78bSCy Schubert 
183*7f2fe78bSCy Schubert /* Create the .dump_ok file. */
184*7f2fe78bSCy Schubert static krb5_boolean
prep_ok_file(krb5_context context,char * file_name,int * fd_out)185*7f2fe78bSCy Schubert prep_ok_file(krb5_context context, char *file_name, int *fd_out)
186*7f2fe78bSCy Schubert {
187*7f2fe78bSCy Schubert     static char ok[] = ".dump_ok";
188*7f2fe78bSCy Schubert     krb5_error_code retval;
189*7f2fe78bSCy Schubert     char *file_ok = NULL;
190*7f2fe78bSCy Schubert     int fd = -1;
191*7f2fe78bSCy Schubert     krb5_boolean success = FALSE;
192*7f2fe78bSCy Schubert 
193*7f2fe78bSCy Schubert     *fd_out = -1;
194*7f2fe78bSCy Schubert 
195*7f2fe78bSCy Schubert     if (asprintf(&file_ok, "%s%s", file_name, ok) < 0) {
196*7f2fe78bSCy Schubert         com_err(progname, ENOMEM, _("while allocating dump_ok filename"));
197*7f2fe78bSCy Schubert         goto cleanup;
198*7f2fe78bSCy Schubert     }
199*7f2fe78bSCy Schubert 
200*7f2fe78bSCy Schubert     fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
201*7f2fe78bSCy Schubert     if (fd == -1) {
202*7f2fe78bSCy Schubert         com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
203*7f2fe78bSCy Schubert         goto cleanup;
204*7f2fe78bSCy Schubert     }
205*7f2fe78bSCy Schubert     retval = krb5_lock_file(context, fd, KRB5_LOCKMODE_EXCLUSIVE);
206*7f2fe78bSCy Schubert     if (retval) {
207*7f2fe78bSCy Schubert         com_err(progname, retval, _("while locking 'ok' file, '%s'"), file_ok);
208*7f2fe78bSCy Schubert         goto cleanup;
209*7f2fe78bSCy Schubert     }
210*7f2fe78bSCy Schubert 
211*7f2fe78bSCy Schubert     *fd_out = fd;
212*7f2fe78bSCy Schubert     fd = -1;
213*7f2fe78bSCy Schubert     success = TRUE;
214*7f2fe78bSCy Schubert 
215*7f2fe78bSCy Schubert cleanup:
216*7f2fe78bSCy Schubert     free(file_ok);
217*7f2fe78bSCy Schubert     if (fd != -1)
218*7f2fe78bSCy Schubert         close(fd);
219*7f2fe78bSCy Schubert     if (!success)
220*7f2fe78bSCy Schubert         exit_status++;
221*7f2fe78bSCy Schubert     return success;
222*7f2fe78bSCy Schubert }
223*7f2fe78bSCy Schubert 
224*7f2fe78bSCy Schubert /*
225*7f2fe78bSCy Schubert  * Update the "ok" file.
226*7f2fe78bSCy Schubert  */
227*7f2fe78bSCy Schubert static void
update_ok_file(krb5_context context,int fd)228*7f2fe78bSCy Schubert update_ok_file(krb5_context context, int fd)
229*7f2fe78bSCy Schubert {
230*7f2fe78bSCy Schubert     write(fd, "", 1);
231*7f2fe78bSCy Schubert     krb5_lock_file(context, fd, KRB5_LOCKMODE_UNLOCK);
232*7f2fe78bSCy Schubert     close(fd);
233*7f2fe78bSCy Schubert }
234*7f2fe78bSCy Schubert 
235*7f2fe78bSCy Schubert /* Return true if a principal name matches a regular expression or string. */
236*7f2fe78bSCy Schubert static int
name_matches(char * name,struct dump_args * args)237*7f2fe78bSCy Schubert name_matches(char *name, struct dump_args *args)
238*7f2fe78bSCy Schubert {
239*7f2fe78bSCy Schubert #if HAVE_REGCOMP
240*7f2fe78bSCy Schubert     regex_t reg;
241*7f2fe78bSCy Schubert     regmatch_t rmatch;
242*7f2fe78bSCy Schubert     int st;
243*7f2fe78bSCy Schubert     char errmsg[BUFSIZ];
244*7f2fe78bSCy Schubert #elif   HAVE_REGEXP_H
245*7f2fe78bSCy Schubert     char regexp_buffer[RE_BUF_SIZE];
246*7f2fe78bSCy Schubert #elif   HAVE_RE_COMP
247*7f2fe78bSCy Schubert     extern char *re_comp();
248*7f2fe78bSCy Schubert     char *re_result;
249*7f2fe78bSCy Schubert #endif  /* HAVE_RE_COMP */
250*7f2fe78bSCy Schubert     int i, match;
251*7f2fe78bSCy Schubert 
252*7f2fe78bSCy Schubert     /* Check each regular expression in args. */
253*7f2fe78bSCy Schubert     match = args->nnames ? 0 : 1;
254*7f2fe78bSCy Schubert     for (i = 0; i < args->nnames && !match; i++) {
255*7f2fe78bSCy Schubert #if HAVE_REGCOMP
256*7f2fe78bSCy Schubert         /* Compile the regular expression. */
257*7f2fe78bSCy Schubert         st = regcomp(&reg, args->names[i], REG_EXTENDED);
258*7f2fe78bSCy Schubert         if (st) {
259*7f2fe78bSCy Schubert             regerror(st, &reg, errmsg, sizeof(errmsg));
260*7f2fe78bSCy Schubert             fprintf(stderr, _("%s: regular expression error: %s\n"), progname,
261*7f2fe78bSCy Schubert                     errmsg);
262*7f2fe78bSCy Schubert             break;
263*7f2fe78bSCy Schubert         }
264*7f2fe78bSCy Schubert         /* See if we have a match. */
265*7f2fe78bSCy Schubert         st = regexec(&reg, name, 1, &rmatch, 0);
266*7f2fe78bSCy Schubert         if (st == 0) {
267*7f2fe78bSCy Schubert             /* See if it matches the whole name. */
268*7f2fe78bSCy Schubert             if (rmatch.rm_so == 0 && (size_t)rmatch.rm_eo == strlen(name))
269*7f2fe78bSCy Schubert                 match = 1;
270*7f2fe78bSCy Schubert         } else if (st != REG_NOMATCH) {
271*7f2fe78bSCy Schubert             regerror(st, &reg, errmsg, sizeof(errmsg));
272*7f2fe78bSCy Schubert             fprintf(stderr, _("%s: regular expression match error: %s\n"),
273*7f2fe78bSCy Schubert                     progname, errmsg);
274*7f2fe78bSCy Schubert             break;
275*7f2fe78bSCy Schubert         }
276*7f2fe78bSCy Schubert         regfree(&reg);
277*7f2fe78bSCy Schubert #elif HAVE_REGEXP_H
278*7f2fe78bSCy Schubert         /* Compile the regular expression. */
279*7f2fe78bSCy Schubert         compile(args->names[i], regexp_buffer, &regexp_buffer[RE_BUF_SIZE],
280*7f2fe78bSCy Schubert                 '\0');
281*7f2fe78bSCy Schubert         if (step(name, regexp_buffer)) {
282*7f2fe78bSCy Schubert             if (loc1 == name && loc2 == &name[strlen(name)])
283*7f2fe78bSCy Schubert                 match = 1;
284*7f2fe78bSCy Schubert         }
285*7f2fe78bSCy Schubert #elif HAVE_RE_COMP
286*7f2fe78bSCy Schubert         /* Compile the regular expression. */
287*7f2fe78bSCy Schubert         re_result = re_comp(args->names[i]);
288*7f2fe78bSCy Schubert         if (re_result) {
289*7f2fe78bSCy Schubert             fprintf(stderr, _("%s: regular expression error: %s\n"), progname,
290*7f2fe78bSCy Schubert                     re_result);
291*7f2fe78bSCy Schubert             break;
292*7f2fe78bSCy Schubert         }
293*7f2fe78bSCy Schubert         if (re_exec(name))
294*7f2fe78bSCy Schubert             match = 1;
295*7f2fe78bSCy Schubert #else /* HAVE_RE_COMP */
296*7f2fe78bSCy Schubert         /* If no regular expression support, then just compare the strings. */
297*7f2fe78bSCy Schubert         if (!strcmp(args->names[i], name))
298*7f2fe78bSCy Schubert             match = 1;
299*7f2fe78bSCy Schubert #endif /* HAVE_REGCOMP */
300*7f2fe78bSCy Schubert     }
301*7f2fe78bSCy Schubert     return match;
302*7f2fe78bSCy Schubert }
303*7f2fe78bSCy Schubert 
304*7f2fe78bSCy Schubert /* Output "-1" if len is 0; otherwise output len bytes of data in hex. */
305*7f2fe78bSCy Schubert static void
dump_octets_or_minus1(FILE * fp,unsigned char * data,size_t len)306*7f2fe78bSCy Schubert dump_octets_or_minus1(FILE *fp, unsigned char *data, size_t len)
307*7f2fe78bSCy Schubert {
308*7f2fe78bSCy Schubert     if (len > 0) {
309*7f2fe78bSCy Schubert         for (; len > 0; len--)
310*7f2fe78bSCy Schubert             fprintf(fp, "%02x", *data++);
311*7f2fe78bSCy Schubert     } else {
312*7f2fe78bSCy Schubert         fprintf(fp, "-1");
313*7f2fe78bSCy Schubert     }
314*7f2fe78bSCy Schubert }
315*7f2fe78bSCy Schubert 
316*7f2fe78bSCy Schubert /*
317*7f2fe78bSCy Schubert  * Dump TL data; common to principals and policies.
318*7f2fe78bSCy Schubert  *
319*7f2fe78bSCy Schubert  * If filter_kadm then the KRB5_TL_KADM_DATA (where a principal's policy
320*7f2fe78bSCy Schubert  * name is stored) is filtered out.  This is for dump formats that don't
321*7f2fe78bSCy Schubert  * support policies.
322*7f2fe78bSCy Schubert  */
323*7f2fe78bSCy Schubert static void
dump_tl_data(FILE * ofile,krb5_tl_data * tlp,krb5_boolean filter_kadm)324*7f2fe78bSCy Schubert dump_tl_data(FILE *ofile, krb5_tl_data *tlp, krb5_boolean filter_kadm)
325*7f2fe78bSCy Schubert {
326*7f2fe78bSCy Schubert     for (; tlp != NULL; tlp = tlp->tl_data_next) {
327*7f2fe78bSCy Schubert         if (tlp->tl_data_type == KRB5_TL_KADM_DATA && filter_kadm)
328*7f2fe78bSCy Schubert             continue;
329*7f2fe78bSCy Schubert         fprintf(ofile, "\t%d\t%d\t", (int)tlp->tl_data_type,
330*7f2fe78bSCy Schubert                 (int)tlp->tl_data_length);
331*7f2fe78bSCy Schubert         dump_octets_or_minus1(ofile, tlp->tl_data_contents,
332*7f2fe78bSCy Schubert                               tlp->tl_data_length);
333*7f2fe78bSCy Schubert     }
334*7f2fe78bSCy Schubert }
335*7f2fe78bSCy Schubert 
336*7f2fe78bSCy Schubert /* Dump a principal entry in krb5 beta 7 format.  Omit kadmin tl-data if kadm
337*7f2fe78bSCy Schubert  * is false. */
338*7f2fe78bSCy Schubert static krb5_error_code
k5beta7_common(krb5_context context,krb5_db_entry * entry,const char * name,FILE * fp,krb5_boolean verbose,krb5_boolean omit_nra,krb5_boolean kadm)339*7f2fe78bSCy Schubert k5beta7_common(krb5_context context, krb5_db_entry *entry,
340*7f2fe78bSCy Schubert                const char *name, FILE *fp, krb5_boolean verbose,
341*7f2fe78bSCy Schubert                krb5_boolean omit_nra, krb5_boolean kadm)
342*7f2fe78bSCy Schubert {
343*7f2fe78bSCy Schubert     krb5_tl_data *tlp;
344*7f2fe78bSCy Schubert     krb5_key_data *kdata;
345*7f2fe78bSCy Schubert     int counter, skip, i;
346*7f2fe78bSCy Schubert 
347*7f2fe78bSCy Schubert     /*
348*7f2fe78bSCy Schubert      * The dump format is as follows:
349*7f2fe78bSCy Schubert      *      len strlen(name) n_tl_data n_key_data e_length
350*7f2fe78bSCy Schubert      *      name
351*7f2fe78bSCy Schubert      *      attributes max_life max_renewable_life expiration
352*7f2fe78bSCy Schubert      *      pw_expiration last_success last_failed fail_auth_count
353*7f2fe78bSCy Schubert      *      n_tl_data*[type length <contents>]
354*7f2fe78bSCy Schubert      *      n_key_data*[ver kvno ver*(type length <contents>)]
355*7f2fe78bSCy Schubert      *      <e_data>
356*7f2fe78bSCy Schubert      * Fields which are not encapsulated by angle-brackets are to appear
357*7f2fe78bSCy Schubert      * verbatim.  A bracketed field's absence is indicated by a -1 in its
358*7f2fe78bSCy Schubert      * place.
359*7f2fe78bSCy Schubert      */
360*7f2fe78bSCy Schubert 
361*7f2fe78bSCy Schubert     /* Make sure that the tagged list is reasonably correct. */
362*7f2fe78bSCy Schubert     counter = skip = 0;
363*7f2fe78bSCy Schubert     for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) {
364*7f2fe78bSCy Schubert         /* Don't dump tl data types we know aren't understood by earlier
365*7f2fe78bSCy Schubert          * versions. */
366*7f2fe78bSCy Schubert         if (tlp->tl_data_type == KRB5_TL_KADM_DATA && !kadm)
367*7f2fe78bSCy Schubert             skip++;
368*7f2fe78bSCy Schubert         else
369*7f2fe78bSCy Schubert             counter++;
370*7f2fe78bSCy Schubert     }
371*7f2fe78bSCy Schubert 
372*7f2fe78bSCy Schubert     if (counter + skip != entry->n_tl_data) {
373*7f2fe78bSCy Schubert         fprintf(stderr, _("%s: tagged data list inconsistency for %s "
374*7f2fe78bSCy Schubert                           "(counted %d, stored %d)\n"), progname, name,
375*7f2fe78bSCy Schubert                 counter + skip, (int)entry->n_tl_data);
376*7f2fe78bSCy Schubert         return EINVAL;
377*7f2fe78bSCy Schubert     }
378*7f2fe78bSCy Schubert 
379*7f2fe78bSCy Schubert     /* Write out header. */
380*7f2fe78bSCy Schubert     fprintf(fp, "princ\t%d\t%lu\t%d\t%d\t%d\t%s\t", (int)entry->len,
381*7f2fe78bSCy Schubert             (unsigned long)strlen(name), counter, (int)entry->n_key_data,
382*7f2fe78bSCy Schubert             (int)entry->e_length, name);
383*7f2fe78bSCy Schubert     fprintf(fp, "%d\t%d\t%d\t%u\t%u\t%u\t%u\t%d", entry->attributes,
384*7f2fe78bSCy Schubert             entry->max_life, entry->max_renewable_life,
385*7f2fe78bSCy Schubert             (unsigned int)entry->expiration,
386*7f2fe78bSCy Schubert             (unsigned int)entry->pw_expiration,
387*7f2fe78bSCy Schubert             (unsigned int)(omit_nra ? 0 : entry->last_success),
388*7f2fe78bSCy Schubert             (unsigned int)(omit_nra ? 0 : entry->last_failed),
389*7f2fe78bSCy Schubert             omit_nra ? 0 : entry->fail_auth_count);
390*7f2fe78bSCy Schubert 
391*7f2fe78bSCy Schubert     /* Write out tagged data. */
392*7f2fe78bSCy Schubert     dump_tl_data(fp, entry->tl_data, !kadm);
393*7f2fe78bSCy Schubert     fprintf(fp, "\t");
394*7f2fe78bSCy Schubert 
395*7f2fe78bSCy Schubert     /* Write out key data. */
396*7f2fe78bSCy Schubert     for (counter = 0; counter < entry->n_key_data; counter++) {
397*7f2fe78bSCy Schubert         kdata = &entry->key_data[counter];
398*7f2fe78bSCy Schubert         fprintf(fp, "%d\t%d\t", (int)kdata->key_data_ver,
399*7f2fe78bSCy Schubert                 (int)kdata->key_data_kvno);
400*7f2fe78bSCy Schubert         for (i = 0; i < kdata->key_data_ver; i++) {
401*7f2fe78bSCy Schubert             fprintf(fp, "%d\t%d\t", kdata->key_data_type[i],
402*7f2fe78bSCy Schubert                     kdata->key_data_length[i]);
403*7f2fe78bSCy Schubert             dump_octets_or_minus1(fp, kdata->key_data_contents[i],
404*7f2fe78bSCy Schubert                                   kdata->key_data_length[i]);
405*7f2fe78bSCy Schubert             fprintf(fp, "\t");
406*7f2fe78bSCy Schubert         }
407*7f2fe78bSCy Schubert     }
408*7f2fe78bSCy Schubert 
409*7f2fe78bSCy Schubert     /* Write out extra data. */
410*7f2fe78bSCy Schubert     dump_octets_or_minus1(fp, entry->e_data, entry->e_length);
411*7f2fe78bSCy Schubert 
412*7f2fe78bSCy Schubert     /* Write trailer. */
413*7f2fe78bSCy Schubert     fprintf(fp, ";\n");
414*7f2fe78bSCy Schubert 
415*7f2fe78bSCy Schubert     if (verbose)
416*7f2fe78bSCy Schubert         fprintf(stderr, "%s\n", name);
417*7f2fe78bSCy Schubert 
418*7f2fe78bSCy Schubert     return 0;
419*7f2fe78bSCy Schubert }
420*7f2fe78bSCy Schubert 
421*7f2fe78bSCy Schubert /* Output a dump record in krb5b7 format. */
422*7f2fe78bSCy Schubert static krb5_error_code
dump_k5beta7_princ(krb5_context context,krb5_db_entry * entry,const char * name,FILE * fp,krb5_boolean verbose,krb5_boolean omit_nra)423*7f2fe78bSCy Schubert dump_k5beta7_princ(krb5_context context, krb5_db_entry *entry,
424*7f2fe78bSCy Schubert                    const char *name, FILE *fp, krb5_boolean verbose,
425*7f2fe78bSCy Schubert                    krb5_boolean omit_nra)
426*7f2fe78bSCy Schubert {
427*7f2fe78bSCy Schubert     return k5beta7_common(context, entry, name, fp, verbose, omit_nra, FALSE);
428*7f2fe78bSCy Schubert }
429*7f2fe78bSCy Schubert 
430*7f2fe78bSCy Schubert static krb5_error_code
dump_k5beta7_princ_withpolicy(krb5_context context,krb5_db_entry * entry,const char * name,FILE * fp,krb5_boolean verbose,krb5_boolean omit_nra)431*7f2fe78bSCy Schubert dump_k5beta7_princ_withpolicy(krb5_context context, krb5_db_entry *entry,
432*7f2fe78bSCy Schubert                               const char *name, FILE *fp, krb5_boolean verbose,
433*7f2fe78bSCy Schubert                               krb5_boolean omit_nra)
434*7f2fe78bSCy Schubert {
435*7f2fe78bSCy Schubert     return k5beta7_common(context, entry, name, fp, verbose, omit_nra, TRUE);
436*7f2fe78bSCy Schubert }
437*7f2fe78bSCy Schubert 
438*7f2fe78bSCy Schubert static void
dump_k5beta7_policy(void * data,osa_policy_ent_t entry)439*7f2fe78bSCy Schubert dump_k5beta7_policy(void *data, osa_policy_ent_t entry)
440*7f2fe78bSCy Schubert {
441*7f2fe78bSCy Schubert     struct dump_args *arg = data;
442*7f2fe78bSCy Schubert 
443*7f2fe78bSCy Schubert     fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n", entry->name,
444*7f2fe78bSCy Schubert             entry->pw_min_life, entry->pw_max_life, entry->pw_min_length,
445*7f2fe78bSCy Schubert             entry->pw_min_classes, entry->pw_history_num, 0);
446*7f2fe78bSCy Schubert }
447*7f2fe78bSCy Schubert 
448*7f2fe78bSCy Schubert static void
dump_r1_8_policy(void * data,osa_policy_ent_t entry)449*7f2fe78bSCy Schubert dump_r1_8_policy(void *data, osa_policy_ent_t entry)
450*7f2fe78bSCy Schubert {
451*7f2fe78bSCy Schubert     struct dump_args *arg = data;
452*7f2fe78bSCy Schubert 
453*7f2fe78bSCy Schubert     fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
454*7f2fe78bSCy Schubert             entry->name, entry->pw_min_life, entry->pw_max_life,
455*7f2fe78bSCy Schubert             entry->pw_min_length, entry->pw_min_classes, entry->pw_history_num,
456*7f2fe78bSCy Schubert             0, entry->pw_max_fail, entry->pw_failcnt_interval,
457*7f2fe78bSCy Schubert             entry->pw_lockout_duration);
458*7f2fe78bSCy Schubert }
459*7f2fe78bSCy Schubert 
460*7f2fe78bSCy Schubert static void
dump_r1_11_policy(void * data,osa_policy_ent_t entry)461*7f2fe78bSCy Schubert dump_r1_11_policy(void *data, osa_policy_ent_t entry)
462*7f2fe78bSCy Schubert {
463*7f2fe78bSCy Schubert     struct dump_args *arg = data;
464*7f2fe78bSCy Schubert 
465*7f2fe78bSCy Schubert     fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t"
466*7f2fe78bSCy Schubert             "%d\t%d\t%d\t%s\t%d", entry->name, entry->pw_min_life,
467*7f2fe78bSCy Schubert             entry->pw_max_life, entry->pw_min_length, entry->pw_min_classes,
468*7f2fe78bSCy Schubert             entry->pw_history_num, 0, entry->pw_max_fail,
469*7f2fe78bSCy Schubert             entry->pw_failcnt_interval, entry->pw_lockout_duration,
470*7f2fe78bSCy Schubert             entry->attributes, entry->max_life, entry->max_renewable_life,
471*7f2fe78bSCy Schubert             entry->allowed_keysalts ? entry->allowed_keysalts : "-",
472*7f2fe78bSCy Schubert             entry->n_tl_data);
473*7f2fe78bSCy Schubert 
474*7f2fe78bSCy Schubert     dump_tl_data(arg->ofile, entry->tl_data, FALSE);
475*7f2fe78bSCy Schubert     fprintf(arg->ofile, "\n");
476*7f2fe78bSCy Schubert }
477*7f2fe78bSCy Schubert 
478*7f2fe78bSCy Schubert static krb5_error_code
dump_iterator(void * ptr,krb5_db_entry * entry)479*7f2fe78bSCy Schubert dump_iterator(void *ptr, krb5_db_entry *entry)
480*7f2fe78bSCy Schubert {
481*7f2fe78bSCy Schubert     krb5_error_code ret;
482*7f2fe78bSCy Schubert     struct dump_args *args = ptr;
483*7f2fe78bSCy Schubert     char *name;
484*7f2fe78bSCy Schubert 
485*7f2fe78bSCy Schubert     ret = krb5_unparse_name(args->context, entry->princ, &name);
486*7f2fe78bSCy Schubert     if (ret) {
487*7f2fe78bSCy Schubert         com_err(progname, ret, _("while unparsing principal name"));
488*7f2fe78bSCy Schubert         return ret;
489*7f2fe78bSCy Schubert     }
490*7f2fe78bSCy Schubert 
491*7f2fe78bSCy Schubert     /* Re-encode the keys in the new master key, if necessary. */
492*7f2fe78bSCy Schubert     if (mkey_convert) {
493*7f2fe78bSCy Schubert         ret = master_key_convert(args->context, entry);
494*7f2fe78bSCy Schubert         if (ret) {
495*7f2fe78bSCy Schubert             com_err(progname, ret, _("while converting %s to new master key"),
496*7f2fe78bSCy Schubert                     name);
497*7f2fe78bSCy Schubert             goto cleanup;
498*7f2fe78bSCy Schubert         }
499*7f2fe78bSCy Schubert     }
500*7f2fe78bSCy Schubert 
501*7f2fe78bSCy Schubert     /* Don't dump this entry if we have match strings and it doesn't match. */
502*7f2fe78bSCy Schubert     if (args->nnames > 0 && !name_matches(name, args))
503*7f2fe78bSCy Schubert         goto cleanup;
504*7f2fe78bSCy Schubert 
505*7f2fe78bSCy Schubert     ret = args->dump->dump_princ(args->context, entry, name, args->ofile,
506*7f2fe78bSCy Schubert                                  args->verbose, args->omit_nra);
507*7f2fe78bSCy Schubert 
508*7f2fe78bSCy Schubert cleanup:
509*7f2fe78bSCy Schubert     free(name);
510*7f2fe78bSCy Schubert     return ret;
511*7f2fe78bSCy Schubert }
512*7f2fe78bSCy Schubert 
513*7f2fe78bSCy Schubert static inline void
load_err(const char * fname,int lineno,const char * msg)514*7f2fe78bSCy Schubert load_err(const char *fname, int lineno, const char *msg)
515*7f2fe78bSCy Schubert {
516*7f2fe78bSCy Schubert     fprintf(stderr, _("%s(%d): %s\n"), fname, lineno, msg);
517*7f2fe78bSCy Schubert }
518*7f2fe78bSCy Schubert 
519*7f2fe78bSCy Schubert /* Read a string of bytes.  Increment *lp for each newline.  Return 0 on
520*7f2fe78bSCy Schubert  * success, 1 on failure. */
521*7f2fe78bSCy Schubert static int
read_string(FILE * f,char * buf,int len,int * lp)522*7f2fe78bSCy Schubert read_string(FILE *f, char *buf, int len, int *lp)
523*7f2fe78bSCy Schubert {
524*7f2fe78bSCy Schubert     int c, i;
525*7f2fe78bSCy Schubert 
526*7f2fe78bSCy Schubert     for (i = 0; i < len; i++) {
527*7f2fe78bSCy Schubert         c = fgetc(f);
528*7f2fe78bSCy Schubert         if (c < 0)
529*7f2fe78bSCy Schubert             return 1;
530*7f2fe78bSCy Schubert         if (c == '\n')
531*7f2fe78bSCy Schubert             (*lp)++;
532*7f2fe78bSCy Schubert         buf[i] = c;
533*7f2fe78bSCy Schubert     }
534*7f2fe78bSCy Schubert     buf[len] = '\0';
535*7f2fe78bSCy Schubert     return 0;
536*7f2fe78bSCy Schubert }
537*7f2fe78bSCy Schubert 
538*7f2fe78bSCy Schubert /* Read a string of two-character representations of bytes. */
539*7f2fe78bSCy Schubert static int
read_octet_string(FILE * f,unsigned char * buf,int len)540*7f2fe78bSCy Schubert read_octet_string(FILE *f, unsigned char *buf, int len)
541*7f2fe78bSCy Schubert {
542*7f2fe78bSCy Schubert     int c, i;
543*7f2fe78bSCy Schubert 
544*7f2fe78bSCy Schubert     for (i = 0; i < len; i++) {
545*7f2fe78bSCy Schubert         if (fscanf(f, "%02x", &c) != 1)
546*7f2fe78bSCy Schubert             return 1;
547*7f2fe78bSCy Schubert         buf[i] = c;
548*7f2fe78bSCy Schubert     }
549*7f2fe78bSCy Schubert     return 0;
550*7f2fe78bSCy Schubert }
551*7f2fe78bSCy Schubert 
552*7f2fe78bSCy Schubert /* Read the end of a dumpfile record. */
553*7f2fe78bSCy Schubert static void
read_record_end(FILE * f,const char * fn,int lineno)554*7f2fe78bSCy Schubert read_record_end(FILE *f, const char *fn, int lineno)
555*7f2fe78bSCy Schubert {
556*7f2fe78bSCy Schubert     int ch;
557*7f2fe78bSCy Schubert 
558*7f2fe78bSCy Schubert     if ((ch = fgetc(f)) != ';' || (ch = fgetc(f)) != '\n') {
559*7f2fe78bSCy Schubert         fprintf(stderr, _("%s(%d): ignoring trash at end of line: "), fn,
560*7f2fe78bSCy Schubert                 lineno);
561*7f2fe78bSCy Schubert         while (ch != '\n') {
562*7f2fe78bSCy Schubert             putc(ch, stderr);
563*7f2fe78bSCy Schubert             ch = fgetc(f);
564*7f2fe78bSCy Schubert         }
565*7f2fe78bSCy Schubert         putc(ch, stderr);
566*7f2fe78bSCy Schubert     }
567*7f2fe78bSCy Schubert }
568*7f2fe78bSCy Schubert 
569*7f2fe78bSCy Schubert /* Allocate and form a TL data list of a desired size. */
570*7f2fe78bSCy Schubert static int
alloc_tl_data(krb5_int16 n_tl_data,krb5_tl_data ** tldp)571*7f2fe78bSCy Schubert alloc_tl_data(krb5_int16 n_tl_data, krb5_tl_data **tldp)
572*7f2fe78bSCy Schubert {
573*7f2fe78bSCy Schubert     krb5_tl_data **tlp = tldp;
574*7f2fe78bSCy Schubert     int i;
575*7f2fe78bSCy Schubert 
576*7f2fe78bSCy Schubert     for (i = 0; i < n_tl_data; i++) {
577*7f2fe78bSCy Schubert         *tlp = calloc(1, sizeof(krb5_tl_data));
578*7f2fe78bSCy Schubert         if (*tlp == NULL)
579*7f2fe78bSCy Schubert             return ENOMEM; /* caller cleans up */
580*7f2fe78bSCy Schubert         tlp = &((*tlp)->tl_data_next);
581*7f2fe78bSCy Schubert     }
582*7f2fe78bSCy Schubert 
583*7f2fe78bSCy Schubert     return 0;
584*7f2fe78bSCy Schubert }
585*7f2fe78bSCy Schubert 
586*7f2fe78bSCy Schubert /* If len is zero, read the string "-1" from fp.  Otherwise allocate space and
587*7f2fe78bSCy Schubert  * read len octets.  Return 0 on success, 1 on failure. */
588*7f2fe78bSCy Schubert static int
read_octets_or_minus1(FILE * fp,size_t len,unsigned char ** out)589*7f2fe78bSCy Schubert read_octets_or_minus1(FILE *fp, size_t len, unsigned char **out)
590*7f2fe78bSCy Schubert {
591*7f2fe78bSCy Schubert     int ival;
592*7f2fe78bSCy Schubert     unsigned char *buf;
593*7f2fe78bSCy Schubert 
594*7f2fe78bSCy Schubert     *out = NULL;
595*7f2fe78bSCy Schubert     if (len == 0)
596*7f2fe78bSCy Schubert         return fscanf(fp, "%d", &ival) != 1 || ival != -1;
597*7f2fe78bSCy Schubert     buf = malloc(len);
598*7f2fe78bSCy Schubert     if (buf == NULL)
599*7f2fe78bSCy Schubert         return 1;
600*7f2fe78bSCy Schubert     if (read_octet_string(fp, buf, len)) {
601*7f2fe78bSCy Schubert         free(buf);
602*7f2fe78bSCy Schubert         return 1;
603*7f2fe78bSCy Schubert     }
604*7f2fe78bSCy Schubert     *out = buf;
605*7f2fe78bSCy Schubert     return 0;
606*7f2fe78bSCy Schubert }
607*7f2fe78bSCy Schubert 
608*7f2fe78bSCy Schubert /* Read TL data for a principal or policy.  Print an error and return -1 on
609*7f2fe78bSCy Schubert  * failure. */
610*7f2fe78bSCy Schubert static int
process_tl_data(const char * fname,FILE * filep,int lineno,krb5_tl_data * tl_data)611*7f2fe78bSCy Schubert process_tl_data(const char *fname, FILE *filep, int lineno,
612*7f2fe78bSCy Schubert                 krb5_tl_data *tl_data)
613*7f2fe78bSCy Schubert {
614*7f2fe78bSCy Schubert     krb5_tl_data *tl;
615*7f2fe78bSCy Schubert     int nread, i1;
616*7f2fe78bSCy Schubert     unsigned int u1;
617*7f2fe78bSCy Schubert 
618*7f2fe78bSCy Schubert     for (tl = tl_data; tl; tl = tl->tl_data_next) {
619*7f2fe78bSCy Schubert         nread = fscanf(filep, "%d\t%u\t", &i1, &u1);
620*7f2fe78bSCy Schubert         if (nread != 2) {
621*7f2fe78bSCy Schubert             load_err(fname, lineno,
622*7f2fe78bSCy Schubert                      _("cannot read tagged data type and length"));
623*7f2fe78bSCy Schubert             return EINVAL;
624*7f2fe78bSCy Schubert         }
625*7f2fe78bSCy Schubert         if (i1 < INT16_MIN || i1 > INT16_MAX || u1 > UINT16_MAX) {
626*7f2fe78bSCy Schubert             load_err(fname, lineno, _("data type or length overflowed"));
627*7f2fe78bSCy Schubert             return EINVAL;
628*7f2fe78bSCy Schubert         }
629*7f2fe78bSCy Schubert         tl->tl_data_type = i1;
630*7f2fe78bSCy Schubert         tl->tl_data_length = u1;
631*7f2fe78bSCy Schubert         if (read_octets_or_minus1(filep, tl->tl_data_length,
632*7f2fe78bSCy Schubert                                   &tl->tl_data_contents)) {
633*7f2fe78bSCy Schubert             load_err(fname, lineno, _("cannot read tagged data contents"));
634*7f2fe78bSCy Schubert             return EINVAL;
635*7f2fe78bSCy Schubert         }
636*7f2fe78bSCy Schubert     }
637*7f2fe78bSCy Schubert 
638*7f2fe78bSCy Schubert     return 0;
639*7f2fe78bSCy Schubert }
640*7f2fe78bSCy Schubert 
641*7f2fe78bSCy Schubert /* Read a beta 7 entry and add it to the database.  Return -1 for end of file,
642*7f2fe78bSCy Schubert  * 0 for success and 1 for failure. */
643*7f2fe78bSCy Schubert static int
process_k5beta7_princ(krb5_context context,const char * fname,FILE * filep,krb5_boolean verbose,int * linenop)644*7f2fe78bSCy Schubert process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep,
645*7f2fe78bSCy Schubert                       krb5_boolean verbose, int *linenop)
646*7f2fe78bSCy Schubert {
647*7f2fe78bSCy Schubert     int retval, nread, i, j;
648*7f2fe78bSCy Schubert     krb5_db_entry *dbentry;
649*7f2fe78bSCy Schubert     int t1, t2, t3, t4;
650*7f2fe78bSCy Schubert     unsigned int u1, u2, u3, u4, u5;
651*7f2fe78bSCy Schubert     char *name = NULL;
652*7f2fe78bSCy Schubert     krb5_key_data *kp = NULL, *kd;
653*7f2fe78bSCy Schubert     krb5_tl_data *tl;
654*7f2fe78bSCy Schubert     krb5_error_code ret;
655*7f2fe78bSCy Schubert 
656*7f2fe78bSCy Schubert     dbentry = calloc(1, sizeof(*dbentry));
657*7f2fe78bSCy Schubert     if (dbentry == NULL)
658*7f2fe78bSCy Schubert         return 1;
659*7f2fe78bSCy Schubert     (*linenop)++;
660*7f2fe78bSCy Schubert     nread = fscanf(filep, "%u\t%u\t%u\t%u\t%u\t", &u1, &u2, &u3, &u4, &u5);
661*7f2fe78bSCy Schubert     if (nread == EOF) {
662*7f2fe78bSCy Schubert         retval = -1;
663*7f2fe78bSCy Schubert         goto cleanup;
664*7f2fe78bSCy Schubert     }
665*7f2fe78bSCy Schubert     if (nread != 5) {
666*7f2fe78bSCy Schubert         load_err(fname, *linenop, _("cannot match size tokens"));
667*7f2fe78bSCy Schubert         goto fail;
668*7f2fe78bSCy Schubert     }
669*7f2fe78bSCy Schubert 
670*7f2fe78bSCy Schubert     /* Get memory for flattened principal name */
671*7f2fe78bSCy Schubert     if (u2 > UINT_MAX / 2) {
672*7f2fe78bSCy Schubert         load_err(fname, *linenop, _("cannot allocate principal (too large)"));
673*7f2fe78bSCy Schubert         goto fail;
674*7f2fe78bSCy Schubert     }
675*7f2fe78bSCy Schubert     name = malloc(u2 + 1);
676*7f2fe78bSCy Schubert     if (name == NULL)
677*7f2fe78bSCy Schubert         goto fail;
678*7f2fe78bSCy Schubert 
679*7f2fe78bSCy Schubert     /* Get memory for and form tagged data linked list */
680*7f2fe78bSCy Schubert     if (u3 > UINT16_MAX) {
681*7f2fe78bSCy Schubert         load_err(fname, *linenop, _("cannot allocate tl_data (too large)"));
682*7f2fe78bSCy Schubert         goto fail;
683*7f2fe78bSCy Schubert     }
684*7f2fe78bSCy Schubert     if (alloc_tl_data(u3, &dbentry->tl_data))
685*7f2fe78bSCy Schubert         goto fail;
686*7f2fe78bSCy Schubert     dbentry->n_tl_data = u3;
687*7f2fe78bSCy Schubert 
688*7f2fe78bSCy Schubert     /* Get memory for key list */
689*7f2fe78bSCy Schubert     if (u4 > INT16_MAX) {
690*7f2fe78bSCy Schubert         load_err(fname, *linenop, _("invalid key_data size"));
691*7f2fe78bSCy Schubert         goto fail;
692*7f2fe78bSCy Schubert     }
693*7f2fe78bSCy Schubert     if (u4 && (kp = calloc(u4, sizeof(krb5_key_data))) == NULL)
694*7f2fe78bSCy Schubert         goto fail;
695*7f2fe78bSCy Schubert 
696*7f2fe78bSCy Schubert     dbentry->len = u1;
697*7f2fe78bSCy Schubert     dbentry->n_key_data = u4;
698*7f2fe78bSCy Schubert     dbentry->e_length = u5;
699*7f2fe78bSCy Schubert 
700*7f2fe78bSCy Schubert     if (kp != NULL) {
701*7f2fe78bSCy Schubert         dbentry->key_data = kp;
702*7f2fe78bSCy Schubert         kp = NULL;
703*7f2fe78bSCy Schubert     }
704*7f2fe78bSCy Schubert 
705*7f2fe78bSCy Schubert     /* Read in and parse the principal name */
706*7f2fe78bSCy Schubert     if (read_string(filep, name, u2, linenop)) {
707*7f2fe78bSCy Schubert         load_err(fname, *linenop, _("cannot read name string"));
708*7f2fe78bSCy Schubert         goto fail;
709*7f2fe78bSCy Schubert     }
710*7f2fe78bSCy Schubert     ret = krb5_parse_name(context, name, &dbentry->princ);
711*7f2fe78bSCy Schubert     if (ret) {
712*7f2fe78bSCy Schubert         com_err(progname, ret, _("while parsing name %s"), name);
713*7f2fe78bSCy Schubert         goto fail;
714*7f2fe78bSCy Schubert     }
715*7f2fe78bSCy Schubert 
716*7f2fe78bSCy Schubert     /* Get the fixed principal attributes */
717*7f2fe78bSCy Schubert     nread = fscanf(filep, "%d\t%d\t%d\t%u\t%u\t%d\t%d\t%d\t",
718*7f2fe78bSCy Schubert                    &t1, &t2, &t3, &u1, &u2, &u3, &u4, &u5);
719*7f2fe78bSCy Schubert     if (nread != 8) {
720*7f2fe78bSCy Schubert         load_err(fname, *linenop, _("cannot read principal attributes"));
721*7f2fe78bSCy Schubert         goto fail;
722*7f2fe78bSCy Schubert     }
723*7f2fe78bSCy Schubert     dbentry->attributes = t1;
724*7f2fe78bSCy Schubert     dbentry->max_life = t2;
725*7f2fe78bSCy Schubert     dbentry->max_renewable_life = t3;
726*7f2fe78bSCy Schubert     dbentry->expiration = u1;
727*7f2fe78bSCy Schubert     dbentry->pw_expiration = u2;
728*7f2fe78bSCy Schubert     dbentry->last_success = u3;
729*7f2fe78bSCy Schubert     dbentry->last_failed = u4;
730*7f2fe78bSCy Schubert     dbentry->fail_auth_count = u5;
731*7f2fe78bSCy Schubert     dbentry->mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
732*7f2fe78bSCy Schubert         KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
733*7f2fe78bSCy Schubert         KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION | KADM5_LAST_SUCCESS |
734*7f2fe78bSCy Schubert         KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT;
735*7f2fe78bSCy Schubert 
736*7f2fe78bSCy Schubert     /* Read tagged data. */
737*7f2fe78bSCy Schubert     if (dbentry->n_tl_data) {
738*7f2fe78bSCy Schubert         if (process_tl_data(fname, filep, *linenop, dbentry->tl_data))
739*7f2fe78bSCy Schubert             goto fail;
740*7f2fe78bSCy Schubert         for (tl = dbentry->tl_data; tl; tl = tl->tl_data_next) {
741*7f2fe78bSCy Schubert             /* test to set mask fields */
742*7f2fe78bSCy Schubert             if (tl->tl_data_type == KRB5_TL_KADM_DATA) {
743*7f2fe78bSCy Schubert                 XDR xdrs;
744*7f2fe78bSCy Schubert                 osa_princ_ent_rec osa_princ_ent;
745*7f2fe78bSCy Schubert 
746*7f2fe78bSCy Schubert                 /*
747*7f2fe78bSCy Schubert                  * Assuming aux_attributes will always be
748*7f2fe78bSCy Schubert                  * there
749*7f2fe78bSCy Schubert                  */
750*7f2fe78bSCy Schubert                 dbentry->mask |= KADM5_AUX_ATTRIBUTES;
751*7f2fe78bSCy Schubert 
752*7f2fe78bSCy Schubert                 /* test for an actual policy reference */
753*7f2fe78bSCy Schubert                 memset(&osa_princ_ent, 0, sizeof(osa_princ_ent));
754*7f2fe78bSCy Schubert                 xdrmem_create(&xdrs, (char *)tl->tl_data_contents,
755*7f2fe78bSCy Schubert                               tl->tl_data_length, XDR_DECODE);
756*7f2fe78bSCy Schubert                 if (xdr_osa_princ_ent_rec(&xdrs, &osa_princ_ent)) {
757*7f2fe78bSCy Schubert                     if ((osa_princ_ent.aux_attributes & KADM5_POLICY) &&
758*7f2fe78bSCy Schubert                         osa_princ_ent.policy != NULL)
759*7f2fe78bSCy Schubert                         dbentry->mask |= KADM5_POLICY;
760*7f2fe78bSCy Schubert                     kdb_free_entry(NULL, NULL, &osa_princ_ent);
761*7f2fe78bSCy Schubert                 }
762*7f2fe78bSCy Schubert                 xdr_destroy(&xdrs);
763*7f2fe78bSCy Schubert             }
764*7f2fe78bSCy Schubert         }
765*7f2fe78bSCy Schubert         dbentry->mask |= KADM5_TL_DATA;
766*7f2fe78bSCy Schubert     }
767*7f2fe78bSCy Schubert 
768*7f2fe78bSCy Schubert     /* Get the key data. */
769*7f2fe78bSCy Schubert     for (i = 0; i < dbentry->n_key_data; i++) {
770*7f2fe78bSCy Schubert         kd = &dbentry->key_data[i];
771*7f2fe78bSCy Schubert         nread = fscanf(filep, "%d\t%d\t", &t1, &t2);
772*7f2fe78bSCy Schubert         if (nread != 2) {
773*7f2fe78bSCy Schubert             load_err(fname, *linenop, _("cannot read key size and version"));
774*7f2fe78bSCy Schubert             goto fail;
775*7f2fe78bSCy Schubert         }
776*7f2fe78bSCy Schubert         if (t1 > KRB5_KDB_V1_KEY_DATA_ARRAY) {
777*7f2fe78bSCy Schubert             load_err(fname, *linenop, _("unsupported key_data_ver version"));
778*7f2fe78bSCy Schubert             goto fail;
779*7f2fe78bSCy Schubert         }
780*7f2fe78bSCy Schubert         if (t2 < 0 || t2 > UINT16_MAX) {
781*7f2fe78bSCy Schubert             load_err(fname, *linenop, _("invalid kvno"));
782*7f2fe78bSCy Schubert             goto fail;
783*7f2fe78bSCy Schubert         }
784*7f2fe78bSCy Schubert 
785*7f2fe78bSCy Schubert         kd->key_data_ver = t1;
786*7f2fe78bSCy Schubert         kd->key_data_kvno = t2;
787*7f2fe78bSCy Schubert 
788*7f2fe78bSCy Schubert         for (j = 0; j < t1; j++) {
789*7f2fe78bSCy Schubert             nread = fscanf(filep, "%d\t%d\t", &t3, &t4);
790*7f2fe78bSCy Schubert             if (nread != 2 || t4 < 0 || t4 > UINT16_MAX) {
791*7f2fe78bSCy Schubert                 load_err(fname, *linenop,
792*7f2fe78bSCy Schubert                          _("cannot read key type and length"));
793*7f2fe78bSCy Schubert                 goto fail;
794*7f2fe78bSCy Schubert             }
795*7f2fe78bSCy Schubert             kd->key_data_type[j] = t3;
796*7f2fe78bSCy Schubert             kd->key_data_length[j] = t4;
797*7f2fe78bSCy Schubert             if (read_octets_or_minus1(filep, t4, &kd->key_data_contents[j])) {
798*7f2fe78bSCy Schubert                 load_err(fname, *linenop, _("cannot read key data"));
799*7f2fe78bSCy Schubert                 goto fail;
800*7f2fe78bSCy Schubert             }
801*7f2fe78bSCy Schubert         }
802*7f2fe78bSCy Schubert     }
803*7f2fe78bSCy Schubert     if (dbentry->n_key_data)
804*7f2fe78bSCy Schubert         dbentry->mask |= KADM5_KEY_DATA;
805*7f2fe78bSCy Schubert 
806*7f2fe78bSCy Schubert     /* Get the extra data */
807*7f2fe78bSCy Schubert     if (read_octets_or_minus1(filep, dbentry->e_length, &dbentry->e_data)) {
808*7f2fe78bSCy Schubert         load_err(fname, *linenop, _("cannot read extra data"));
809*7f2fe78bSCy Schubert         goto fail;
810*7f2fe78bSCy Schubert     }
811*7f2fe78bSCy Schubert 
812*7f2fe78bSCy Schubert     /* Finally, find the end of the record. */
813*7f2fe78bSCy Schubert     read_record_end(filep, fname, *linenop);
814*7f2fe78bSCy Schubert 
815*7f2fe78bSCy Schubert     ret = krb5_db_put_principal(context, dbentry);
816*7f2fe78bSCy Schubert     if (ret) {
817*7f2fe78bSCy Schubert         com_err(progname, ret, _("while storing %s"), name);
818*7f2fe78bSCy Schubert         goto fail;
819*7f2fe78bSCy Schubert     }
820*7f2fe78bSCy Schubert 
821*7f2fe78bSCy Schubert     if (verbose)
822*7f2fe78bSCy Schubert         fprintf(stderr, "%s\n", name);
823*7f2fe78bSCy Schubert     retval = 0;
824*7f2fe78bSCy Schubert 
825*7f2fe78bSCy Schubert cleanup:
826*7f2fe78bSCy Schubert     free(kp);
827*7f2fe78bSCy Schubert     free(name);
828*7f2fe78bSCy Schubert     krb5_db_free_principal(context, dbentry);
829*7f2fe78bSCy Schubert     return retval;
830*7f2fe78bSCy Schubert 
831*7f2fe78bSCy Schubert fail:
832*7f2fe78bSCy Schubert     retval = 1;
833*7f2fe78bSCy Schubert     goto cleanup;
834*7f2fe78bSCy Schubert }
835*7f2fe78bSCy Schubert 
836*7f2fe78bSCy Schubert static int
process_k5beta7_policy(krb5_context context,const char * fname,FILE * filep,krb5_boolean verbose,int * linenop)837*7f2fe78bSCy Schubert process_k5beta7_policy(krb5_context context, const char *fname, FILE *filep,
838*7f2fe78bSCy Schubert                        krb5_boolean verbose, int *linenop)
839*7f2fe78bSCy Schubert {
840*7f2fe78bSCy Schubert     osa_policy_ent_rec rec;
841*7f2fe78bSCy Schubert     char namebuf[1024];
842*7f2fe78bSCy Schubert     unsigned int refcnt;
843*7f2fe78bSCy Schubert     int nread, ret;
844*7f2fe78bSCy Schubert 
845*7f2fe78bSCy Schubert     memset(&rec, 0, sizeof(rec));
846*7f2fe78bSCy Schubert 
847*7f2fe78bSCy Schubert     (*linenop)++;
848*7f2fe78bSCy Schubert     rec.name = namebuf;
849*7f2fe78bSCy Schubert 
850*7f2fe78bSCy Schubert     nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u", rec.name,
851*7f2fe78bSCy Schubert                    &rec.pw_min_life, &rec.pw_max_life, &rec.pw_min_length,
852*7f2fe78bSCy Schubert                    &rec.pw_min_classes, &rec.pw_history_num, &refcnt);
853*7f2fe78bSCy Schubert     if (nread == EOF)
854*7f2fe78bSCy Schubert         return -1;
855*7f2fe78bSCy Schubert     if (nread != 7) {
856*7f2fe78bSCy Schubert         fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
857*7f2fe78bSCy Schubert         return 1;
858*7f2fe78bSCy Schubert     }
859*7f2fe78bSCy Schubert 
860*7f2fe78bSCy Schubert     ret = krb5_db_create_policy(context, &rec);
861*7f2fe78bSCy Schubert     if (ret)
862*7f2fe78bSCy Schubert         ret = krb5_db_put_policy(context, &rec);
863*7f2fe78bSCy Schubert     if (ret) {
864*7f2fe78bSCy Schubert         com_err(progname, ret, _("while creating policy"));
865*7f2fe78bSCy Schubert         return 1;
866*7f2fe78bSCy Schubert     }
867*7f2fe78bSCy Schubert     if (verbose)
868*7f2fe78bSCy Schubert         fprintf(stderr, _("created policy %s\n"), rec.name);
869*7f2fe78bSCy Schubert 
870*7f2fe78bSCy Schubert     return 0;
871*7f2fe78bSCy Schubert }
872*7f2fe78bSCy Schubert 
873*7f2fe78bSCy Schubert static int
process_r1_8_policy(krb5_context context,const char * fname,FILE * filep,krb5_boolean verbose,int * linenop)874*7f2fe78bSCy Schubert process_r1_8_policy(krb5_context context, const char *fname, FILE *filep,
875*7f2fe78bSCy Schubert                     krb5_boolean verbose, int *linenop)
876*7f2fe78bSCy Schubert {
877*7f2fe78bSCy Schubert     osa_policy_ent_rec rec;
878*7f2fe78bSCy Schubert     char namebuf[1024];
879*7f2fe78bSCy Schubert     unsigned int refcnt;
880*7f2fe78bSCy Schubert     int nread, ret;
881*7f2fe78bSCy Schubert 
882*7f2fe78bSCy Schubert     memset(&rec, 0, sizeof(rec));
883*7f2fe78bSCy Schubert 
884*7f2fe78bSCy Schubert     (*linenop)++;
885*7f2fe78bSCy Schubert     rec.name = namebuf;
886*7f2fe78bSCy Schubert 
887*7f2fe78bSCy Schubert     nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
888*7f2fe78bSCy Schubert                    rec.name, &rec.pw_min_life, &rec.pw_max_life,
889*7f2fe78bSCy Schubert                    &rec.pw_min_length, &rec.pw_min_classes,
890*7f2fe78bSCy Schubert                    &rec.pw_history_num, &refcnt, &rec.pw_max_fail,
891*7f2fe78bSCy Schubert                    &rec.pw_failcnt_interval, &rec.pw_lockout_duration);
892*7f2fe78bSCy Schubert     if (nread == EOF)
893*7f2fe78bSCy Schubert         return -1;
894*7f2fe78bSCy Schubert     if (nread != 10) {
895*7f2fe78bSCy Schubert         fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
896*7f2fe78bSCy Schubert         return 1;
897*7f2fe78bSCy Schubert     }
898*7f2fe78bSCy Schubert 
899*7f2fe78bSCy Schubert     ret = krb5_db_create_policy(context, &rec);
900*7f2fe78bSCy Schubert     if (ret)
901*7f2fe78bSCy Schubert         ret = krb5_db_put_policy(context, &rec);
902*7f2fe78bSCy Schubert     if (ret) {
903*7f2fe78bSCy Schubert         com_err(progname, ret, _("while creating policy"));
904*7f2fe78bSCy Schubert         return 1;
905*7f2fe78bSCy Schubert     }
906*7f2fe78bSCy Schubert     if (verbose)
907*7f2fe78bSCy Schubert         fprintf(stderr, "created policy %s\n", rec.name);
908*7f2fe78bSCy Schubert 
909*7f2fe78bSCy Schubert     return 0;
910*7f2fe78bSCy Schubert }
911*7f2fe78bSCy Schubert 
912*7f2fe78bSCy Schubert static int
process_r1_11_policy(krb5_context context,const char * fname,FILE * filep,krb5_boolean verbose,int * linenop)913*7f2fe78bSCy Schubert process_r1_11_policy(krb5_context context, const char *fname, FILE *filep,
914*7f2fe78bSCy Schubert                      krb5_boolean verbose, int *linenop)
915*7f2fe78bSCy Schubert {
916*7f2fe78bSCy Schubert     osa_policy_ent_rec rec;
917*7f2fe78bSCy Schubert     krb5_tl_data *tl, *tl_next;
918*7f2fe78bSCy Schubert     char namebuf[1024];
919*7f2fe78bSCy Schubert     char keysaltbuf[KRB5_KDB_MAX_ALLOWED_KS_LEN + 1];
920*7f2fe78bSCy Schubert     unsigned int refcnt;
921*7f2fe78bSCy Schubert     int nread, c, ret = 0;
922*7f2fe78bSCy Schubert 
923*7f2fe78bSCy Schubert     memset(&rec, 0, sizeof(rec));
924*7f2fe78bSCy Schubert 
925*7f2fe78bSCy Schubert     (*linenop)++;
926*7f2fe78bSCy Schubert     rec.name = namebuf;
927*7f2fe78bSCy Schubert 
928*7f2fe78bSCy Schubert     /*
929*7f2fe78bSCy Schubert      * Due to a historical error, iprop dumps use the same version before and
930*7f2fe78bSCy Schubert      * after the 1.11 policy extensions.  So we need to accept both 1.8-format
931*7f2fe78bSCy Schubert      * and 1.11-format policy entries.  Begin by reading the 1.8 fields.
932*7f2fe78bSCy Schubert      */
933*7f2fe78bSCy Schubert     nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
934*7f2fe78bSCy Schubert                    rec.name, &rec.pw_min_life, &rec.pw_max_life,
935*7f2fe78bSCy Schubert                    &rec.pw_min_length, &rec.pw_min_classes,
936*7f2fe78bSCy Schubert                    &rec.pw_history_num, &refcnt, &rec.pw_max_fail,
937*7f2fe78bSCy Schubert                    &rec.pw_failcnt_interval, &rec.pw_lockout_duration);
938*7f2fe78bSCy Schubert     if (nread == EOF)
939*7f2fe78bSCy Schubert         return -1;
940*7f2fe78bSCy Schubert     if (nread != 10) {
941*7f2fe78bSCy Schubert         fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
942*7f2fe78bSCy Schubert         return 1;
943*7f2fe78bSCy Schubert     }
944*7f2fe78bSCy Schubert 
945*7f2fe78bSCy Schubert     /* The next character should be a newline (1.8) or a tab (1.11). */
946*7f2fe78bSCy Schubert     c = getc(filep);
947*7f2fe78bSCy Schubert     if (c == EOF)
948*7f2fe78bSCy Schubert         return -1;
949*7f2fe78bSCy Schubert     if (c != '\n') {
950*7f2fe78bSCy Schubert         /* Read the additional 1.11-format fields. */
951*7f2fe78bSCy Schubert         rec.allowed_keysalts = keysaltbuf;
952*7f2fe78bSCy Schubert         nread = fscanf(filep, "%u\t%u\t%u\t"
953*7f2fe78bSCy Schubert                        K5CONST_WIDTH_SCANF_STR(KRB5_KDB_MAX_ALLOWED_KS_LEN)
954*7f2fe78bSCy Schubert                        "\t%hd", &rec.attributes, &rec.max_life,
955*7f2fe78bSCy Schubert                        &rec.max_renewable_life, rec.allowed_keysalts,
956*7f2fe78bSCy Schubert                        &rec.n_tl_data);
957*7f2fe78bSCy Schubert         if (nread == EOF)
958*7f2fe78bSCy Schubert             return -1;
959*7f2fe78bSCy Schubert         if (nread != 5) {
960*7f2fe78bSCy Schubert             fprintf(stderr, _("cannot parse policy (%d read)\n"), nread);
961*7f2fe78bSCy Schubert             return 1;
962*7f2fe78bSCy Schubert         }
963*7f2fe78bSCy Schubert 
964*7f2fe78bSCy Schubert         if (rec.allowed_keysalts && !strcmp(rec.allowed_keysalts, "-"))
965*7f2fe78bSCy Schubert             rec.allowed_keysalts = NULL;
966*7f2fe78bSCy Schubert 
967*7f2fe78bSCy Schubert         /* Get TL data */
968*7f2fe78bSCy Schubert         ret = alloc_tl_data(rec.n_tl_data, &rec.tl_data);
969*7f2fe78bSCy Schubert         if (ret)
970*7f2fe78bSCy Schubert             goto cleanup;
971*7f2fe78bSCy Schubert 
972*7f2fe78bSCy Schubert         ret = process_tl_data(fname, filep, *linenop, rec.tl_data);
973*7f2fe78bSCy Schubert         if (ret)
974*7f2fe78bSCy Schubert             goto cleanup;
975*7f2fe78bSCy Schubert     }
976*7f2fe78bSCy Schubert 
977*7f2fe78bSCy Schubert     ret = krb5_db_create_policy(context, &rec);
978*7f2fe78bSCy Schubert     if (ret)
979*7f2fe78bSCy Schubert         ret = krb5_db_put_policy(context, &rec);
980*7f2fe78bSCy Schubert     if (ret) {
981*7f2fe78bSCy Schubert         com_err(progname, ret, _("while creating policy"));
982*7f2fe78bSCy Schubert         goto cleanup;
983*7f2fe78bSCy Schubert     }
984*7f2fe78bSCy Schubert     if (verbose)
985*7f2fe78bSCy Schubert         fprintf(stderr, "created policy %s\n", rec.name);
986*7f2fe78bSCy Schubert 
987*7f2fe78bSCy Schubert cleanup:
988*7f2fe78bSCy Schubert     for (tl = rec.tl_data; tl; tl = tl_next) {
989*7f2fe78bSCy Schubert         tl_next = tl->tl_data_next;
990*7f2fe78bSCy Schubert         free(tl->tl_data_contents);
991*7f2fe78bSCy Schubert         free(tl);
992*7f2fe78bSCy Schubert     }
993*7f2fe78bSCy Schubert     return ret ? 1 : 0;
994*7f2fe78bSCy Schubert }
995*7f2fe78bSCy Schubert 
996*7f2fe78bSCy Schubert /* Read a record which is tagged with "princ" or "policy", calling princfn
997*7f2fe78bSCy Schubert  * or policyfn as appropriate. */
998*7f2fe78bSCy Schubert static int
process_tagged(krb5_context context,const char * fname,FILE * filep,krb5_boolean verbose,int * linenop,load_func princfn,load_func policyfn)999*7f2fe78bSCy Schubert process_tagged(krb5_context context, const char *fname, FILE *filep,
1000*7f2fe78bSCy Schubert                krb5_boolean verbose, int *linenop, load_func princfn,
1001*7f2fe78bSCy Schubert                load_func policyfn)
1002*7f2fe78bSCy Schubert {
1003*7f2fe78bSCy Schubert     int nread;
1004*7f2fe78bSCy Schubert     char rectype[100];
1005*7f2fe78bSCy Schubert 
1006*7f2fe78bSCy Schubert     nread = fscanf(filep, "%99s\t", rectype);
1007*7f2fe78bSCy Schubert     if (nread == EOF)
1008*7f2fe78bSCy Schubert         return -1;
1009*7f2fe78bSCy Schubert     if (nread != 1)
1010*7f2fe78bSCy Schubert         return 1;
1011*7f2fe78bSCy Schubert     if (strcmp(rectype, "princ") == 0)
1012*7f2fe78bSCy Schubert         return (*princfn)(context, fname, filep, verbose, linenop);
1013*7f2fe78bSCy Schubert     if (strcmp(rectype, "policy") == 0)
1014*7f2fe78bSCy Schubert         return (*policyfn)(context, fname, filep, verbose, linenop);
1015*7f2fe78bSCy Schubert     if (strcmp(rectype, "End") == 0)  /* Only expected for OV format */
1016*7f2fe78bSCy Schubert         return -1;
1017*7f2fe78bSCy Schubert 
1018*7f2fe78bSCy Schubert     fprintf(stderr, _("unknown record type \"%s\"\n"), rectype);
1019*7f2fe78bSCy Schubert     return 1;
1020*7f2fe78bSCy Schubert }
1021*7f2fe78bSCy Schubert 
1022*7f2fe78bSCy Schubert static int
process_k5beta7_record(krb5_context context,const char * fname,FILE * filep,krb5_boolean verbose,int * linenop)1023*7f2fe78bSCy Schubert process_k5beta7_record(krb5_context context, const char *fname, FILE *filep,
1024*7f2fe78bSCy Schubert                        krb5_boolean verbose, int *linenop)
1025*7f2fe78bSCy Schubert {
1026*7f2fe78bSCy Schubert     return process_tagged(context, fname, filep, verbose, linenop,
1027*7f2fe78bSCy Schubert                           process_k5beta7_princ, process_k5beta7_policy);
1028*7f2fe78bSCy Schubert }
1029*7f2fe78bSCy Schubert 
1030*7f2fe78bSCy Schubert static int
process_r1_8_record(krb5_context context,const char * fname,FILE * filep,krb5_boolean verbose,int * linenop)1031*7f2fe78bSCy Schubert process_r1_8_record(krb5_context context, const char *fname, FILE *filep,
1032*7f2fe78bSCy Schubert                     krb5_boolean verbose, int *linenop)
1033*7f2fe78bSCy Schubert {
1034*7f2fe78bSCy Schubert     return process_tagged(context, fname, filep, verbose, linenop,
1035*7f2fe78bSCy Schubert                           process_k5beta7_princ, process_r1_8_policy);
1036*7f2fe78bSCy Schubert }
1037*7f2fe78bSCy Schubert 
1038*7f2fe78bSCy Schubert static int
process_r1_11_record(krb5_context context,const char * fname,FILE * filep,krb5_boolean verbose,int * linenop)1039*7f2fe78bSCy Schubert process_r1_11_record(krb5_context context, const char *fname, FILE *filep,
1040*7f2fe78bSCy Schubert                      krb5_boolean verbose, int *linenop)
1041*7f2fe78bSCy Schubert {
1042*7f2fe78bSCy Schubert     return process_tagged(context, fname, filep, verbose, linenop,
1043*7f2fe78bSCy Schubert                           process_k5beta7_princ, process_r1_11_policy);
1044*7f2fe78bSCy Schubert }
1045*7f2fe78bSCy Schubert 
1046*7f2fe78bSCy Schubert dump_version beta7_version = {
1047*7f2fe78bSCy Schubert     "Kerberos version 5",
1048*7f2fe78bSCy Schubert     "kdb5_util load_dump version 4\n",
1049*7f2fe78bSCy Schubert     0,
1050*7f2fe78bSCy Schubert     0,
1051*7f2fe78bSCy Schubert     0,
1052*7f2fe78bSCy Schubert     dump_k5beta7_princ,
1053*7f2fe78bSCy Schubert     dump_k5beta7_policy,
1054*7f2fe78bSCy Schubert     process_k5beta7_record,
1055*7f2fe78bSCy Schubert };
1056*7f2fe78bSCy Schubert dump_version r1_3_version = {
1057*7f2fe78bSCy Schubert     "Kerberos version 5 release 1.3",
1058*7f2fe78bSCy Schubert     "kdb5_util load_dump version 5\n",
1059*7f2fe78bSCy Schubert     0,
1060*7f2fe78bSCy Schubert     0,
1061*7f2fe78bSCy Schubert     0,
1062*7f2fe78bSCy Schubert     dump_k5beta7_princ_withpolicy,
1063*7f2fe78bSCy Schubert     dump_k5beta7_policy,
1064*7f2fe78bSCy Schubert     process_k5beta7_record,
1065*7f2fe78bSCy Schubert };
1066*7f2fe78bSCy Schubert dump_version r1_8_version = {
1067*7f2fe78bSCy Schubert     "Kerberos version 5 release 1.8",
1068*7f2fe78bSCy Schubert     "kdb5_util load_dump version 6\n",
1069*7f2fe78bSCy Schubert     0,
1070*7f2fe78bSCy Schubert     0,
1071*7f2fe78bSCy Schubert     0,
1072*7f2fe78bSCy Schubert     dump_k5beta7_princ_withpolicy,
1073*7f2fe78bSCy Schubert     dump_r1_8_policy,
1074*7f2fe78bSCy Schubert     process_r1_8_record,
1075*7f2fe78bSCy Schubert };
1076*7f2fe78bSCy Schubert dump_version r1_11_version = {
1077*7f2fe78bSCy Schubert     "Kerberos version 5 release 1.11",
1078*7f2fe78bSCy Schubert     "kdb5_util load_dump version 7\n",
1079*7f2fe78bSCy Schubert     0,
1080*7f2fe78bSCy Schubert     0,
1081*7f2fe78bSCy Schubert     0,
1082*7f2fe78bSCy Schubert     dump_k5beta7_princ_withpolicy,
1083*7f2fe78bSCy Schubert     dump_r1_11_policy,
1084*7f2fe78bSCy Schubert     process_r1_11_record,
1085*7f2fe78bSCy Schubert };
1086*7f2fe78bSCy Schubert dump_version iprop_version = {
1087*7f2fe78bSCy Schubert     "Kerberos iprop version",
1088*7f2fe78bSCy Schubert     "iprop",
1089*7f2fe78bSCy Schubert     0,
1090*7f2fe78bSCy Schubert     1,
1091*7f2fe78bSCy Schubert     0,
1092*7f2fe78bSCy Schubert     dump_k5beta7_princ_withpolicy,
1093*7f2fe78bSCy Schubert     dump_k5beta7_policy,
1094*7f2fe78bSCy Schubert     process_k5beta7_record,
1095*7f2fe78bSCy Schubert };
1096*7f2fe78bSCy Schubert dump_version ipropx_1_version = {
1097*7f2fe78bSCy Schubert     "Kerberos iprop extensible version",
1098*7f2fe78bSCy Schubert     "ipropx",
1099*7f2fe78bSCy Schubert     0,
1100*7f2fe78bSCy Schubert     1,
1101*7f2fe78bSCy Schubert     1,
1102*7f2fe78bSCy Schubert     dump_k5beta7_princ_withpolicy,
1103*7f2fe78bSCy Schubert     dump_r1_11_policy,
1104*7f2fe78bSCy Schubert     process_r1_11_record,
1105*7f2fe78bSCy Schubert };
1106*7f2fe78bSCy Schubert 
1107*7f2fe78bSCy Schubert /* Read the dump header.  Return 1 on success, 0 if the file is not a
1108*7f2fe78bSCy Schubert  * recognized iprop dump format. */
1109*7f2fe78bSCy Schubert static int
parse_iprop_header(char * buf,dump_version ** dv,kdb_last_t * last)1110*7f2fe78bSCy Schubert parse_iprop_header(char *buf, dump_version **dv, kdb_last_t *last)
1111*7f2fe78bSCy Schubert {
1112*7f2fe78bSCy Schubert     char head[128];
1113*7f2fe78bSCy Schubert     int nread;
1114*7f2fe78bSCy Schubert     uint32_t u[4];
1115*7f2fe78bSCy Schubert     uint32_t *up = &u[0];
1116*7f2fe78bSCy Schubert 
1117*7f2fe78bSCy Schubert     nread = sscanf(buf, "%127s %u %u %u %u", head, &u[0], &u[1], &u[2], &u[3]);
1118*7f2fe78bSCy Schubert     if (nread < 1)
1119*7f2fe78bSCy Schubert         return 0;
1120*7f2fe78bSCy Schubert 
1121*7f2fe78bSCy Schubert     if (!strcmp(head, ipropx_1_version.header)) {
1122*7f2fe78bSCy Schubert         if (nread != 5)
1123*7f2fe78bSCy Schubert             return 0;
1124*7f2fe78bSCy Schubert         if (u[0] == IPROPX_VERSION_0) {
1125*7f2fe78bSCy Schubert             *dv = &iprop_version;
1126*7f2fe78bSCy Schubert         } else if (u[0] == IPROPX_VERSION_1) {
1127*7f2fe78bSCy Schubert             *dv = &ipropx_1_version;
1128*7f2fe78bSCy Schubert         } else {
1129*7f2fe78bSCy Schubert             fprintf(stderr, _("%s: Unknown iprop dump version %d\n"), progname,
1130*7f2fe78bSCy Schubert                     u[0]);
1131*7f2fe78bSCy Schubert             return 0;
1132*7f2fe78bSCy Schubert         }
1133*7f2fe78bSCy Schubert         up = &u[1];
1134*7f2fe78bSCy Schubert     } else if (!strcmp(head, iprop_version.header)) {
1135*7f2fe78bSCy Schubert         if (nread != 4)
1136*7f2fe78bSCy Schubert             return 0;
1137*7f2fe78bSCy Schubert         *dv = &iprop_version;
1138*7f2fe78bSCy Schubert     } else {
1139*7f2fe78bSCy Schubert         fprintf(stderr, "Invalid iprop header\n");
1140*7f2fe78bSCy Schubert         return 0;
1141*7f2fe78bSCy Schubert     }
1142*7f2fe78bSCy Schubert 
1143*7f2fe78bSCy Schubert     last->last_sno = *up++;
1144*7f2fe78bSCy Schubert     last->last_time.seconds = *up++;
1145*7f2fe78bSCy Schubert     last->last_time.useconds = *up++;
1146*7f2fe78bSCy Schubert     return 1;
1147*7f2fe78bSCy Schubert }
1148*7f2fe78bSCy Schubert 
1149*7f2fe78bSCy Schubert /* Return true if the serial number and timestamp in an existing dump file is
1150*7f2fe78bSCy Schubert  * in the ulog. */
1151*7f2fe78bSCy Schubert static krb5_boolean
current_dump_sno_in_ulog(krb5_context context,const char * ifile)1152*7f2fe78bSCy Schubert current_dump_sno_in_ulog(krb5_context context, const char *ifile)
1153*7f2fe78bSCy Schubert {
1154*7f2fe78bSCy Schubert     update_status_t status;
1155*7f2fe78bSCy Schubert     dump_version *junk;
1156*7f2fe78bSCy Schubert     kdb_last_t last;
1157*7f2fe78bSCy Schubert     char buf[BUFSIZ], *r;
1158*7f2fe78bSCy Schubert     FILE *f;
1159*7f2fe78bSCy Schubert 
1160*7f2fe78bSCy Schubert     f = fopen(ifile, "r");
1161*7f2fe78bSCy Schubert     if (f == NULL)
1162*7f2fe78bSCy Schubert         return 0;              /* aliasing other errors to ENOENT here is OK */
1163*7f2fe78bSCy Schubert 
1164*7f2fe78bSCy Schubert     r = fgets(buf, sizeof(buf), f);
1165*7f2fe78bSCy Schubert     fclose(f);
1166*7f2fe78bSCy Schubert     if (r == NULL)
1167*7f2fe78bSCy Schubert         return errno ? -1 : 0;
1168*7f2fe78bSCy Schubert 
1169*7f2fe78bSCy Schubert     if (!parse_iprop_header(buf, &junk, &last))
1170*7f2fe78bSCy Schubert         return 0;
1171*7f2fe78bSCy Schubert 
1172*7f2fe78bSCy Schubert     status = ulog_get_sno_status(context, &last);
1173*7f2fe78bSCy Schubert     return status == UPDATE_OK || status == UPDATE_NIL;
1174*7f2fe78bSCy Schubert }
1175*7f2fe78bSCy Schubert 
1176*7f2fe78bSCy Schubert void
dump_db(int argc,char ** argv)1177*7f2fe78bSCy Schubert dump_db(int argc, char **argv)
1178*7f2fe78bSCy Schubert {
1179*7f2fe78bSCy Schubert     FILE *f;
1180*7f2fe78bSCy Schubert     struct dump_args args;
1181*7f2fe78bSCy Schubert     char *ofile = NULL, *tmpofile = NULL, *new_mkey_file = NULL;
1182*7f2fe78bSCy Schubert     krb5_error_code ret, retval;
1183*7f2fe78bSCy Schubert     dump_version *dump;
1184*7f2fe78bSCy Schubert     int aindex, ok_fd = -1;
1185*7f2fe78bSCy Schubert     bool_t dump_sno = FALSE;
1186*7f2fe78bSCy Schubert     kdb_log_context *log_ctx;
1187*7f2fe78bSCy Schubert     unsigned int ipropx_version = IPROPX_VERSION_0;
1188*7f2fe78bSCy Schubert     krb5_kvno kt_kvno;
1189*7f2fe78bSCy Schubert     krb5_boolean conditional = FALSE;
1190*7f2fe78bSCy Schubert     kdb_last_t last;
1191*7f2fe78bSCy Schubert     krb5_flags iterflags = 0;
1192*7f2fe78bSCy Schubert 
1193*7f2fe78bSCy Schubert     /* Parse the arguments. */
1194*7f2fe78bSCy Schubert     dump = &r1_11_version;
1195*7f2fe78bSCy Schubert     args.verbose = FALSE;
1196*7f2fe78bSCy Schubert     args.omit_nra = FALSE;
1197*7f2fe78bSCy Schubert     mkey_convert = FALSE;
1198*7f2fe78bSCy Schubert     log_ctx = util_context->kdblog_context;
1199*7f2fe78bSCy Schubert 
1200*7f2fe78bSCy Schubert     /*
1201*7f2fe78bSCy Schubert      * Parse the qualifiers.
1202*7f2fe78bSCy Schubert      */
1203*7f2fe78bSCy Schubert     for (aindex = 1; aindex < argc; aindex++) {
1204*7f2fe78bSCy Schubert         if (!strcmp(argv[aindex], "-b7")) {
1205*7f2fe78bSCy Schubert             dump = &beta7_version;
1206*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-ov")) {
1207*7f2fe78bSCy Schubert             fprintf(stderr, _("OV dump format not supported\n"));
1208*7f2fe78bSCy Schubert             goto error;
1209*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-r13")) {
1210*7f2fe78bSCy Schubert             dump = &r1_3_version;
1211*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-r18")) {
1212*7f2fe78bSCy Schubert             dump = &r1_8_version;
1213*7f2fe78bSCy Schubert         } else if (!strncmp(argv[aindex], "-i", 2)) {
1214*7f2fe78bSCy Schubert             /* Intentionally undocumented - only used by kadmin. */
1215*7f2fe78bSCy Schubert             if (log_ctx && log_ctx->iproprole) {
1216*7f2fe78bSCy Schubert                 /* ipropx_version is the maximum version acceptable. */
1217*7f2fe78bSCy Schubert                 ipropx_version = atoi(argv[aindex] + 2);
1218*7f2fe78bSCy Schubert                 dump = ipropx_version ? &ipropx_1_version : &iprop_version;
1219*7f2fe78bSCy Schubert                 /*
1220*7f2fe78bSCy Schubert                  * dump_sno is used to indicate if the serial number should be
1221*7f2fe78bSCy Schubert                  * populated in the output file to be used later by iprop for
1222*7f2fe78bSCy Schubert                  * updating the replica's update log when loading.
1223*7f2fe78bSCy Schubert                  */
1224*7f2fe78bSCy Schubert                 dump_sno = TRUE;
1225*7f2fe78bSCy Schubert                 /* FLAG_OMIT_NRA is set to indicate that non-replicated
1226*7f2fe78bSCy Schubert                  * attributes should be omitted. */
1227*7f2fe78bSCy Schubert                 args.omit_nra = TRUE;
1228*7f2fe78bSCy Schubert             } else {
1229*7f2fe78bSCy Schubert                 fprintf(stderr, _("Iprop not enabled\n"));
1230*7f2fe78bSCy Schubert                 goto error;
1231*7f2fe78bSCy Schubert             }
1232*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-c")) {
1233*7f2fe78bSCy Schubert             conditional = 1;
1234*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-verbose")) {
1235*7f2fe78bSCy Schubert             args.verbose = TRUE;
1236*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-mkey_convert")) {
1237*7f2fe78bSCy Schubert             mkey_convert = 1;
1238*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-new_mkey_file")) {
1239*7f2fe78bSCy Schubert             new_mkey_file = argv[++aindex];
1240*7f2fe78bSCy Schubert             mkey_convert = 1;
1241*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-rev")) {
1242*7f2fe78bSCy Schubert             iterflags |= KRB5_DB_ITER_REV;
1243*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-recurse")) {
1244*7f2fe78bSCy Schubert             iterflags |= KRB5_DB_ITER_RECURSE;
1245*7f2fe78bSCy Schubert         } else {
1246*7f2fe78bSCy Schubert             break;
1247*7f2fe78bSCy Schubert         }
1248*7f2fe78bSCy Schubert     }
1249*7f2fe78bSCy Schubert 
1250*7f2fe78bSCy Schubert     args.names = NULL;
1251*7f2fe78bSCy Schubert     args.nnames = 0;
1252*7f2fe78bSCy Schubert     if (aindex < argc) {
1253*7f2fe78bSCy Schubert         ofile = argv[aindex];
1254*7f2fe78bSCy Schubert         aindex++;
1255*7f2fe78bSCy Schubert         if (aindex < argc) {
1256*7f2fe78bSCy Schubert             args.names = &argv[aindex];
1257*7f2fe78bSCy Schubert             args.nnames = argc - aindex;
1258*7f2fe78bSCy Schubert         }
1259*7f2fe78bSCy Schubert     }
1260*7f2fe78bSCy Schubert 
1261*7f2fe78bSCy Schubert     /* If a conditional ipropx dump we check if the existing dump is
1262*7f2fe78bSCy Schubert      * good enough. */
1263*7f2fe78bSCy Schubert     if (ofile != NULL && conditional) {
1264*7f2fe78bSCy Schubert         if (!dump->iprop) {
1265*7f2fe78bSCy Schubert             com_err(progname, 0,
1266*7f2fe78bSCy Schubert                     _("Conditional dump is an undocumented option for "
1267*7f2fe78bSCy Schubert                       "use only for iprop dumps"));
1268*7f2fe78bSCy Schubert             goto error;
1269*7f2fe78bSCy Schubert         }
1270*7f2fe78bSCy Schubert         if (current_dump_sno_in_ulog(util_context, ofile))
1271*7f2fe78bSCy Schubert             return;
1272*7f2fe78bSCy Schubert     }
1273*7f2fe78bSCy Schubert 
1274*7f2fe78bSCy Schubert     /*
1275*7f2fe78bSCy Schubert      * Make sure the database is open.  The policy database only has
1276*7f2fe78bSCy Schubert      * to be opened if we try a dump that uses it.
1277*7f2fe78bSCy Schubert      */
1278*7f2fe78bSCy Schubert     if (!dbactive) {
1279*7f2fe78bSCy Schubert         com_err(progname, 0, _("Database not currently opened!"));
1280*7f2fe78bSCy Schubert         goto error;
1281*7f2fe78bSCy Schubert     }
1282*7f2fe78bSCy Schubert 
1283*7f2fe78bSCy Schubert     /*
1284*7f2fe78bSCy Schubert      * If we're doing a master key conversion, set up for it.
1285*7f2fe78bSCy Schubert      */
1286*7f2fe78bSCy Schubert     if (mkey_convert) {
1287*7f2fe78bSCy Schubert         if (!valid_master_key) {
1288*7f2fe78bSCy Schubert             /* TRUE here means read the keyboard, but only once */
1289*7f2fe78bSCy Schubert             retval = krb5_db_fetch_mkey(util_context, master_princ,
1290*7f2fe78bSCy Schubert                                         master_keyblock.enctype, TRUE, FALSE,
1291*7f2fe78bSCy Schubert                                         NULL, NULL, NULL, &master_keyblock);
1292*7f2fe78bSCy Schubert             if (retval) {
1293*7f2fe78bSCy Schubert                 com_err(progname, retval, _("while reading master key"));
1294*7f2fe78bSCy Schubert                 exit(1);
1295*7f2fe78bSCy Schubert             }
1296*7f2fe78bSCy Schubert             retval = krb5_db_fetch_mkey_list(util_context, master_princ,
1297*7f2fe78bSCy Schubert                                              &master_keyblock);
1298*7f2fe78bSCy Schubert             if (retval) {
1299*7f2fe78bSCy Schubert                 com_err(progname, retval, _("while verifying master key"));
1300*7f2fe78bSCy Schubert                 exit(1);
1301*7f2fe78bSCy Schubert             }
1302*7f2fe78bSCy Schubert         }
1303*7f2fe78bSCy Schubert         new_master_keyblock.enctype = global_params.enctype;
1304*7f2fe78bSCy Schubert         if (new_master_keyblock.enctype == ENCTYPE_UNKNOWN)
1305*7f2fe78bSCy Schubert             new_master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
1306*7f2fe78bSCy Schubert 
1307*7f2fe78bSCy Schubert         if (new_mkey_file) {
1308*7f2fe78bSCy Schubert             if (global_params.mask & KADM5_CONFIG_KVNO)
1309*7f2fe78bSCy Schubert                 kt_kvno = global_params.kvno;
1310*7f2fe78bSCy Schubert             else
1311*7f2fe78bSCy Schubert                 kt_kvno = IGNORE_VNO;
1312*7f2fe78bSCy Schubert 
1313*7f2fe78bSCy Schubert             retval = krb5_db_fetch_mkey(util_context, master_princ,
1314*7f2fe78bSCy Schubert                                         new_master_keyblock.enctype, FALSE,
1315*7f2fe78bSCy Schubert                                         FALSE, new_mkey_file, &kt_kvno, NULL,
1316*7f2fe78bSCy Schubert                                         &new_master_keyblock);
1317*7f2fe78bSCy Schubert             if (retval) {
1318*7f2fe78bSCy Schubert                 com_err(progname, retval, _("while reading new master key"));
1319*7f2fe78bSCy Schubert                 exit(1);
1320*7f2fe78bSCy Schubert             }
1321*7f2fe78bSCy Schubert         } else {
1322*7f2fe78bSCy Schubert             printf(_("Please enter new master key....\n"));
1323*7f2fe78bSCy Schubert             retval = krb5_db_fetch_mkey(util_context, master_princ,
1324*7f2fe78bSCy Schubert                                         new_master_keyblock.enctype, TRUE,
1325*7f2fe78bSCy Schubert                                         TRUE, NULL, NULL, NULL,
1326*7f2fe78bSCy Schubert                                         &new_master_keyblock);
1327*7f2fe78bSCy Schubert             if (retval) {
1328*7f2fe78bSCy Schubert                 com_err(progname, retval, _("while reading new master key"));
1329*7f2fe78bSCy Schubert                 exit(1);
1330*7f2fe78bSCy Schubert             }
1331*7f2fe78bSCy Schubert         }
1332*7f2fe78bSCy Schubert         /* Get new master key vno that will be used to protect princs. */
1333*7f2fe78bSCy Schubert         new_mkvno = get_next_kvno(util_context, master_entry);
1334*7f2fe78bSCy Schubert     }
1335*7f2fe78bSCy Schubert 
1336*7f2fe78bSCy Schubert     ret = 0;
1337*7f2fe78bSCy Schubert 
1338*7f2fe78bSCy Schubert     if (ofile != NULL && strcmp(ofile, "-")) {
1339*7f2fe78bSCy Schubert         /* Discourage accidental dumping to filenames beginning with '-'. */
1340*7f2fe78bSCy Schubert         if (ofile[0] == '-')
1341*7f2fe78bSCy Schubert             usage();
1342*7f2fe78bSCy Schubert         if (!prep_ok_file(util_context, ofile, &ok_fd))
1343*7f2fe78bSCy Schubert             return;             /* prep_ok_file() bumps exit_status */
1344*7f2fe78bSCy Schubert         f = create_ofile(ofile, &tmpofile);
1345*7f2fe78bSCy Schubert         if (f == NULL) {
1346*7f2fe78bSCy Schubert             com_err(progname, errno, _("while opening %s for writing"), ofile);
1347*7f2fe78bSCy Schubert             goto error;
1348*7f2fe78bSCy Schubert         }
1349*7f2fe78bSCy Schubert     } else {
1350*7f2fe78bSCy Schubert         f = stdout;
1351*7f2fe78bSCy Schubert     }
1352*7f2fe78bSCy Schubert 
1353*7f2fe78bSCy Schubert     args.ofile = f;
1354*7f2fe78bSCy Schubert     args.context = util_context;
1355*7f2fe78bSCy Schubert     args.dump = dump;
1356*7f2fe78bSCy Schubert     fprintf(args.ofile, "%s", dump->header);
1357*7f2fe78bSCy Schubert 
1358*7f2fe78bSCy Schubert     if (dump_sno) {
1359*7f2fe78bSCy Schubert         ret = ulog_get_last(util_context, &last);
1360*7f2fe78bSCy Schubert         if (ret) {
1361*7f2fe78bSCy Schubert             com_err(progname, ret, _("while reading update log header"));
1362*7f2fe78bSCy Schubert             goto error;
1363*7f2fe78bSCy Schubert         }
1364*7f2fe78bSCy Schubert         if (ipropx_version)
1365*7f2fe78bSCy Schubert             fprintf(f, " %u", IPROPX_VERSION);
1366*7f2fe78bSCy Schubert         fprintf(f, " %u", last.last_sno);
1367*7f2fe78bSCy Schubert         fprintf(f, " %u", last.last_time.seconds);
1368*7f2fe78bSCy Schubert         fprintf(f, " %u", last.last_time.useconds);
1369*7f2fe78bSCy Schubert     }
1370*7f2fe78bSCy Schubert 
1371*7f2fe78bSCy Schubert     if (dump->header[strlen(dump->header)-1] != '\n')
1372*7f2fe78bSCy Schubert         fputc('\n', args.ofile);
1373*7f2fe78bSCy Schubert 
1374*7f2fe78bSCy Schubert     ret = krb5_db_iterate(util_context, NULL, dump_iterator, &args, iterflags);
1375*7f2fe78bSCy Schubert     if (ret) {
1376*7f2fe78bSCy Schubert         com_err(progname, ret, _("performing %s dump"), dump->name);
1377*7f2fe78bSCy Schubert         goto error;
1378*7f2fe78bSCy Schubert     }
1379*7f2fe78bSCy Schubert 
1380*7f2fe78bSCy Schubert     /* Don't dump policies if specific principal entries were requested. */
1381*7f2fe78bSCy Schubert     if (dump->dump_policy != NULL && args.nnames == 0) {
1382*7f2fe78bSCy Schubert         ret = krb5_db_iter_policy(util_context, "*", dump->dump_policy, &args);
1383*7f2fe78bSCy Schubert         if (ret) {
1384*7f2fe78bSCy Schubert             com_err(progname, ret, _("performing %s dump"), dump->name);
1385*7f2fe78bSCy Schubert             goto error;
1386*7f2fe78bSCy Schubert         }
1387*7f2fe78bSCy Schubert     }
1388*7f2fe78bSCy Schubert 
1389*7f2fe78bSCy Schubert     if (f != stdout) {
1390*7f2fe78bSCy Schubert         fclose(f);
1391*7f2fe78bSCy Schubert         finish_ofile(ofile, &tmpofile);
1392*7f2fe78bSCy Schubert         update_ok_file(util_context, ok_fd);
1393*7f2fe78bSCy Schubert     }
1394*7f2fe78bSCy Schubert     return;
1395*7f2fe78bSCy Schubert 
1396*7f2fe78bSCy Schubert error:
1397*7f2fe78bSCy Schubert     if (tmpofile != NULL)
1398*7f2fe78bSCy Schubert         unlink(tmpofile);
1399*7f2fe78bSCy Schubert     free(tmpofile);
1400*7f2fe78bSCy Schubert     exit_status++;
1401*7f2fe78bSCy Schubert }
1402*7f2fe78bSCy Schubert 
1403*7f2fe78bSCy Schubert /* Restore the database from any version dump file. */
1404*7f2fe78bSCy Schubert static int
restore_dump(krb5_context context,char * dumpfile,FILE * f,krb5_boolean verbose,dump_version * dump)1405*7f2fe78bSCy Schubert restore_dump(krb5_context context, char *dumpfile, FILE *f,
1406*7f2fe78bSCy Schubert              krb5_boolean verbose, dump_version *dump)
1407*7f2fe78bSCy Schubert {
1408*7f2fe78bSCy Schubert     int err = 0;
1409*7f2fe78bSCy Schubert     int lineno = 1;
1410*7f2fe78bSCy Schubert 
1411*7f2fe78bSCy Schubert     /* Process the records. */
1412*7f2fe78bSCy Schubert     while (!(err = dump->load_record(context, dumpfile, f, verbose, &lineno)));
1413*7f2fe78bSCy Schubert     if (err != -1) {
1414*7f2fe78bSCy Schubert         fprintf(stderr, _("%s: error processing line %d of %s\n"), progname,
1415*7f2fe78bSCy Schubert                 lineno, dumpfile);
1416*7f2fe78bSCy Schubert         return err;
1417*7f2fe78bSCy Schubert     }
1418*7f2fe78bSCy Schubert     return 0;
1419*7f2fe78bSCy Schubert }
1420*7f2fe78bSCy Schubert 
1421*7f2fe78bSCy Schubert void
load_db(int argc,char ** argv)1422*7f2fe78bSCy Schubert load_db(int argc, char **argv)
1423*7f2fe78bSCy Schubert {
1424*7f2fe78bSCy Schubert     krb5_error_code ret;
1425*7f2fe78bSCy Schubert     FILE *f = NULL;
1426*7f2fe78bSCy Schubert     char *dumpfile = NULL, *dbname, buf[BUFSIZ];
1427*7f2fe78bSCy Schubert     dump_version *load = NULL;
1428*7f2fe78bSCy Schubert     int aindex;
1429*7f2fe78bSCy Schubert     kdb_log_context *log_ctx;
1430*7f2fe78bSCy Schubert     kdb_last_t last;
1431*7f2fe78bSCy Schubert     krb5_boolean db_locked = FALSE, temp_db_created = FALSE;
1432*7f2fe78bSCy Schubert     krb5_boolean verbose = FALSE, update = FALSE, iprop_load = FALSE;
1433*7f2fe78bSCy Schubert 
1434*7f2fe78bSCy Schubert     /* Parse the arguments. */
1435*7f2fe78bSCy Schubert     dbname = global_params.dbname;
1436*7f2fe78bSCy Schubert     exit_status = 0;
1437*7f2fe78bSCy Schubert     log_ctx = util_context->kdblog_context;
1438*7f2fe78bSCy Schubert 
1439*7f2fe78bSCy Schubert     for (aindex = 1; aindex < argc; aindex++) {
1440*7f2fe78bSCy Schubert         if (!strcmp(argv[aindex], "-b7")){
1441*7f2fe78bSCy Schubert             load = &beta7_version;
1442*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-ov")) {
1443*7f2fe78bSCy Schubert             fprintf(stderr, _("OV dump format not supported\n"));
1444*7f2fe78bSCy Schubert             goto error;
1445*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-r13")) {
1446*7f2fe78bSCy Schubert             load = &r1_3_version;
1447*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-r18")){
1448*7f2fe78bSCy Schubert             load = &r1_8_version;
1449*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-i")) {
1450*7f2fe78bSCy Schubert             /* Intentionally undocumented - only used by kadmin. */
1451*7f2fe78bSCy Schubert             if (log_ctx && log_ctx->iproprole) {
1452*7f2fe78bSCy Schubert                 load = &iprop_version;
1453*7f2fe78bSCy Schubert                 iprop_load = TRUE;
1454*7f2fe78bSCy Schubert             } else {
1455*7f2fe78bSCy Schubert                 fprintf(stderr, _("Iprop not enabled\n"));
1456*7f2fe78bSCy Schubert                 goto error;
1457*7f2fe78bSCy Schubert             }
1458*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-verbose")) {
1459*7f2fe78bSCy Schubert             verbose = TRUE;
1460*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-update")){
1461*7f2fe78bSCy Schubert             update = TRUE;
1462*7f2fe78bSCy Schubert         } else if (!strcmp(argv[aindex], "-hash")) {
1463*7f2fe78bSCy Schubert             if (!add_db_arg("hash=true")) {
1464*7f2fe78bSCy Schubert                 com_err(progname, ENOMEM, _("while parsing options"));
1465*7f2fe78bSCy Schubert                 goto error;
1466*7f2fe78bSCy Schubert             }
1467*7f2fe78bSCy Schubert         } else {
1468*7f2fe78bSCy Schubert             break;
1469*7f2fe78bSCy Schubert         }
1470*7f2fe78bSCy Schubert     }
1471*7f2fe78bSCy Schubert     if (argc - aindex != 1)
1472*7f2fe78bSCy Schubert         usage();
1473*7f2fe78bSCy Schubert     dumpfile = argv[aindex];
1474*7f2fe78bSCy Schubert 
1475*7f2fe78bSCy Schubert     /* Open the dumpfile. */
1476*7f2fe78bSCy Schubert     if (dumpfile != NULL) {
1477*7f2fe78bSCy Schubert         f = fopen(dumpfile, "r");
1478*7f2fe78bSCy Schubert         if (f == NULL) {
1479*7f2fe78bSCy Schubert             com_err(progname, errno, _("while opening %s"), dumpfile);
1480*7f2fe78bSCy Schubert             goto error;
1481*7f2fe78bSCy Schubert         }
1482*7f2fe78bSCy Schubert     } else {
1483*7f2fe78bSCy Schubert         f = stdin;
1484*7f2fe78bSCy Schubert         dumpfile = _("standard input");
1485*7f2fe78bSCy Schubert     }
1486*7f2fe78bSCy Schubert 
1487*7f2fe78bSCy Schubert     /* Auto-detect dump version if we weren't told, or verify if we were. */
1488*7f2fe78bSCy Schubert     if (fgets(buf, sizeof(buf), f) == NULL) {
1489*7f2fe78bSCy Schubert         fprintf(stderr, _("%s: can't read dump header in %s\n"), progname,
1490*7f2fe78bSCy Schubert                 dumpfile);
1491*7f2fe78bSCy Schubert         goto error;
1492*7f2fe78bSCy Schubert     }
1493*7f2fe78bSCy Schubert     if (load) {
1494*7f2fe78bSCy Schubert         /* Only check what we know; some headers only contain a prefix.
1495*7f2fe78bSCy Schubert          * NB: this should work for ipropx even though load is iprop */
1496*7f2fe78bSCy Schubert         if (strncmp(buf, load->header, strlen(load->header)) != 0) {
1497*7f2fe78bSCy Schubert             fprintf(stderr, _("%s: dump header bad in %s\n"), progname,
1498*7f2fe78bSCy Schubert                     dumpfile);
1499*7f2fe78bSCy Schubert             goto error;
1500*7f2fe78bSCy Schubert         }
1501*7f2fe78bSCy Schubert     } else {
1502*7f2fe78bSCy Schubert         if (strcmp(buf, beta7_version.header) == 0) {
1503*7f2fe78bSCy Schubert             load = &beta7_version;
1504*7f2fe78bSCy Schubert         } else if (strcmp(buf, r1_3_version.header) == 0) {
1505*7f2fe78bSCy Schubert             load = &r1_3_version;
1506*7f2fe78bSCy Schubert         } else if (strcmp(buf, r1_8_version.header) == 0) {
1507*7f2fe78bSCy Schubert             load = &r1_8_version;
1508*7f2fe78bSCy Schubert         } else if (strcmp(buf, r1_11_version.header) == 0) {
1509*7f2fe78bSCy Schubert             load = &r1_11_version;
1510*7f2fe78bSCy Schubert         } else {
1511*7f2fe78bSCy Schubert             fprintf(stderr, _("%s: dump header bad in %s\n"), progname,
1512*7f2fe78bSCy Schubert                     dumpfile);
1513*7f2fe78bSCy Schubert             goto error;
1514*7f2fe78bSCy Schubert         }
1515*7f2fe78bSCy Schubert     }
1516*7f2fe78bSCy Schubert 
1517*7f2fe78bSCy Schubert     if (global_params.iprop_enabled &&
1518*7f2fe78bSCy Schubert         ulog_map(util_context, global_params.iprop_logfile,
1519*7f2fe78bSCy Schubert                  global_params.iprop_ulogsize)) {
1520*7f2fe78bSCy Schubert         fprintf(stderr, _("Could not open iprop ulog\n"));
1521*7f2fe78bSCy Schubert         goto error;
1522*7f2fe78bSCy Schubert     }
1523*7f2fe78bSCy Schubert 
1524*7f2fe78bSCy Schubert     if (load->updateonly && !update) {
1525*7f2fe78bSCy Schubert         fprintf(stderr, _("%s: dump version %s can only be loaded with the "
1526*7f2fe78bSCy Schubert                           "-update flag\n"), progname, load->name);
1527*7f2fe78bSCy Schubert         goto error;
1528*7f2fe78bSCy Schubert     }
1529*7f2fe78bSCy Schubert 
1530*7f2fe78bSCy Schubert     /* If we are not in update mode, we create an alternate database and then
1531*7f2fe78bSCy Schubert      * promote it to be the live db. */
1532*7f2fe78bSCy Schubert     if (!update) {
1533*7f2fe78bSCy Schubert         if (!add_db_arg("temporary")) {
1534*7f2fe78bSCy Schubert             com_err(progname, ENOMEM, _("computing parameters for database"));
1535*7f2fe78bSCy Schubert             goto error;
1536*7f2fe78bSCy Schubert         }
1537*7f2fe78bSCy Schubert 
1538*7f2fe78bSCy Schubert         if (iprop_load && !add_db_arg("merge_nra")) {
1539*7f2fe78bSCy Schubert             com_err(progname, ENOMEM, _("computing parameters for database"));
1540*7f2fe78bSCy Schubert             goto error;
1541*7f2fe78bSCy Schubert         }
1542*7f2fe78bSCy Schubert 
1543*7f2fe78bSCy Schubert         ret = krb5_db_create(util_context, db5util_db_args);
1544*7f2fe78bSCy Schubert         if (ret) {
1545*7f2fe78bSCy Schubert             com_err(progname, ret, _("while creating database"));
1546*7f2fe78bSCy Schubert             goto error;
1547*7f2fe78bSCy Schubert         }
1548*7f2fe78bSCy Schubert         temp_db_created = TRUE;
1549*7f2fe78bSCy Schubert     } else {
1550*7f2fe78bSCy Schubert         /* Initialize the database. */
1551*7f2fe78bSCy Schubert         ret = krb5_db_open(util_context, db5util_db_args,
1552*7f2fe78bSCy Schubert                            KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
1553*7f2fe78bSCy Schubert         if (ret) {
1554*7f2fe78bSCy Schubert             com_err(progname, ret, _("while opening database"));
1555*7f2fe78bSCy Schubert             goto error;
1556*7f2fe78bSCy Schubert         }
1557*7f2fe78bSCy Schubert 
1558*7f2fe78bSCy Schubert         /* Make sure the db is left unusable if the update fails, if the db
1559*7f2fe78bSCy Schubert          * supports locking. */
1560*7f2fe78bSCy Schubert         ret = krb5_db_lock(util_context, KRB5_DB_LOCKMODE_PERMANENT);
1561*7f2fe78bSCy Schubert         if (ret == 0) {
1562*7f2fe78bSCy Schubert             db_locked = TRUE;
1563*7f2fe78bSCy Schubert         } else if (ret != KRB5_PLUGIN_OP_NOTSUPP) {
1564*7f2fe78bSCy Schubert             com_err(progname, ret, _("while permanently locking database"));
1565*7f2fe78bSCy Schubert             goto error;
1566*7f2fe78bSCy Schubert         }
1567*7f2fe78bSCy Schubert     }
1568*7f2fe78bSCy Schubert 
1569*7f2fe78bSCy Schubert     if (log_ctx != NULL && log_ctx->iproprole && !update) {
1570*7f2fe78bSCy Schubert         /* Don't record updates we are making to the temporary DB.  We will
1571*7f2fe78bSCy Schubert          * reinitialize or update the ulog header after promoting it. */
1572*7f2fe78bSCy Schubert         log_ctx->iproprole = IPROP_REPLICA;
1573*7f2fe78bSCy Schubert         if (iprop_load) {
1574*7f2fe78bSCy Schubert             /* Parse the iprop header information. */
1575*7f2fe78bSCy Schubert             if (!parse_iprop_header(buf, &load, &last))
1576*7f2fe78bSCy Schubert                 goto error;
1577*7f2fe78bSCy Schubert         }
1578*7f2fe78bSCy Schubert     }
1579*7f2fe78bSCy Schubert 
1580*7f2fe78bSCy Schubert     if (restore_dump(util_context, dumpfile ? dumpfile : _("standard input"),
1581*7f2fe78bSCy Schubert                      f, verbose, load)) {
1582*7f2fe78bSCy Schubert         fprintf(stderr, _("%s: %s restore failed\n"), progname, load->name);
1583*7f2fe78bSCy Schubert         goto error;
1584*7f2fe78bSCy Schubert     }
1585*7f2fe78bSCy Schubert 
1586*7f2fe78bSCy Schubert     if (db_locked && (ret = krb5_db_unlock(util_context))) {
1587*7f2fe78bSCy Schubert         com_err(progname, ret, _("while unlocking database"));
1588*7f2fe78bSCy Schubert         goto error;
1589*7f2fe78bSCy Schubert     }
1590*7f2fe78bSCy Schubert 
1591*7f2fe78bSCy Schubert     if (!update) {
1592*7f2fe78bSCy Schubert         /* Initialize the ulog header before promoting so we can't leave behind
1593*7f2fe78bSCy Schubert          * the pre-load ulog state if we are killed just after promoting. */
1594*7f2fe78bSCy Schubert         if (log_ctx != NULL && log_ctx->iproprole) {
1595*7f2fe78bSCy Schubert             ret = ulog_init_header(util_context);
1596*7f2fe78bSCy Schubert             if (ret) {
1597*7f2fe78bSCy Schubert                 com_err(progname, ret, _("while reinitializing update log"));
1598*7f2fe78bSCy Schubert                 goto error;
1599*7f2fe78bSCy Schubert             }
1600*7f2fe78bSCy Schubert         }
1601*7f2fe78bSCy Schubert 
1602*7f2fe78bSCy Schubert         ret = krb5_db_promote(util_context, db5util_db_args);
1603*7f2fe78bSCy Schubert         /* Ignore a not supported error since there is nothing to do about it
1604*7f2fe78bSCy Schubert          * anyway. */
1605*7f2fe78bSCy Schubert         if (ret != 0 && ret != KRB5_PLUGIN_OP_NOTSUPP) {
1606*7f2fe78bSCy Schubert             com_err(progname, ret,
1607*7f2fe78bSCy Schubert                     _("while making newly loaded database live"));
1608*7f2fe78bSCy Schubert             goto error;
1609*7f2fe78bSCy Schubert         }
1610*7f2fe78bSCy Schubert 
1611*7f2fe78bSCy Schubert         if (log_ctx != NULL && log_ctx->iproprole) {
1612*7f2fe78bSCy Schubert             /* Reinitialize the ulog header since we replaced the DB, and
1613*7f2fe78bSCy Schubert              * record the iprop state if we received it. */
1614*7f2fe78bSCy Schubert             ret = ulog_init_header(util_context);
1615*7f2fe78bSCy Schubert             if (ret) {
1616*7f2fe78bSCy Schubert                 com_err(progname, ret, _("while reinitializing update log"));
1617*7f2fe78bSCy Schubert                 goto error;
1618*7f2fe78bSCy Schubert             }
1619*7f2fe78bSCy Schubert             if (iprop_load) {
1620*7f2fe78bSCy Schubert                 ret = ulog_set_last(util_context, &last);
1621*7f2fe78bSCy Schubert                 if (ret) {
1622*7f2fe78bSCy Schubert                     com_err(progname, ret,
1623*7f2fe78bSCy Schubert                             _("while writing update log header"));
1624*7f2fe78bSCy Schubert                     goto error;
1625*7f2fe78bSCy Schubert                 }
1626*7f2fe78bSCy Schubert             }
1627*7f2fe78bSCy Schubert         }
1628*7f2fe78bSCy Schubert     }
1629*7f2fe78bSCy Schubert 
1630*7f2fe78bSCy Schubert cleanup:
1631*7f2fe78bSCy Schubert     /* If we created a temporary DB but didn't succeed, destroy it. */
1632*7f2fe78bSCy Schubert     if (exit_status && temp_db_created) {
1633*7f2fe78bSCy Schubert         ret = krb5_db_destroy(util_context, db5util_db_args);
1634*7f2fe78bSCy Schubert         /* Ignore a not supported error since there is nothing to do about
1635*7f2fe78bSCy Schubert          * it anyway. */
1636*7f2fe78bSCy Schubert         if (ret != 0 && ret != KRB5_PLUGIN_OP_NOTSUPP) {
1637*7f2fe78bSCy Schubert             com_err(progname, ret, _("while deleting bad database %s"),
1638*7f2fe78bSCy Schubert                     dbname);
1639*7f2fe78bSCy Schubert         }
1640*7f2fe78bSCy Schubert     }
1641*7f2fe78bSCy Schubert 
1642*7f2fe78bSCy Schubert     if (f != NULL && f != stdin)
1643*7f2fe78bSCy Schubert         fclose(f);
1644*7f2fe78bSCy Schubert 
1645*7f2fe78bSCy Schubert     return;
1646*7f2fe78bSCy Schubert 
1647*7f2fe78bSCy Schubert error:
1648*7f2fe78bSCy Schubert     exit_status++;
1649*7f2fe78bSCy Schubert     goto cleanup;
1650*7f2fe78bSCy Schubert }
1651