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(®, args->names[i], REG_EXTENDED);
258*7f2fe78bSCy Schubert if (st) {
259*7f2fe78bSCy Schubert regerror(st, ®, 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(®, 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, ®, 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(®);
277*7f2fe78bSCy Schubert #elif HAVE_REGEXP_H
278*7f2fe78bSCy Schubert /* Compile the regular expression. */
279*7f2fe78bSCy Schubert compile(args->names[i], regexp_buffer, ®exp_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