xref: /netbsd-src/crypto/external/bsd/heimdal/dist/kdc/mit_dump.c (revision 241bea01a19bbb306af27777a870b86d41cb3fda)
1 /*	$NetBSD: mit_dump.c,v 1.3 2019/12/15 22:50:46 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include "hprop.h"
37 
38 extern krb5_error_code _hdb_mdb_value2entry(krb5_context context,
39                                             krb5_data *data,
40                                             krb5_kvno target_kvno,
41                                             hdb_entry *entry);
42 
43 extern int _hdb_mit_dump2mitdb_entry(krb5_context context,
44                                      char *line,
45                                      krb5_storage *sp);
46 
47 
48 
49 /*
50 can have any number of princ stanzas.
51 format is as follows (only \n indicates newlines)
52 princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38)
53 %d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU)
54 %d\t (number of tl_data)
55 %d\t (number of key data, e.g. how many keys for this user)
56 %d\t (extra data length)
57 %s\t (principal name)
58 %d\t (attributes)
59 %d\t (max lifetime, seconds)
60 %d\t (max renewable life, seconds)
61 %d\t (expiration, seconds since epoch or 2145830400 for never)
62 %d\t (password expiration, seconds, 0 for never)
63 %d\t (last successful auth, seconds since epoch)
64 %d\t (last failed auth, per above)
65 %d\t (failed auth count)
66 foreach tl_data 0 to number of tl_data - 1 as above
67   %d\t%d\t (data type, data length)
68   foreach tl_data 0 to length-1
69     %02x (tl data contents[element n])
70   except if tl_data length is 0
71     %d (always -1)
72   \t
73 foreach key 0 to number of keys - 1 as above
74   %d\t%d\t (key data version, kvno)
75   foreach version 0 to key data version - 1 (a key or a salt)
76     %d\t%d\t(data type for this key, data length for this key)
77     foreach key data length 0 to length-1
78       %02x (key data contents[element n])
79     except if key_data length is 0
80       %d (always -1)
81     \t
82 foreach extra data length 0 to length - 1
83   %02x (extra data part)
84 unless no extra data
85   %d (always -1)
86 ;\n
87 
88 */
89 
90 static char *
nexttoken(char ** p)91 nexttoken(char **p)
92 {
93     char *q;
94     do {
95 	q = strsep(p, " \t");
96     } while(q && *q == '\0');
97     return q;
98 }
99 
100 #include <kadm5/admin.h>
101 
102 /* XXX: Principal names with '\n' cannot be dumped or loaded */
103 static int
my_fgetln(FILE * f,char ** bufp,size_t * szp,size_t * lenp)104 my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp)
105 {
106     size_t len;
107     size_t sz = *szp;
108     char *buf = *bufp;
109     char *p, *n;
110 
111     if (!buf) {
112         buf = malloc(sz ? sz : 8192);
113         if (!buf)
114             return ENOMEM;
115         if (!sz)
116             sz = 8192;
117     }
118 
119     len = 0;
120     while ((p = fgets(&buf[len], sz-len, f)) != NULL) {
121         len += strlen(&buf[len]);
122         if (buf[len-1] == '\n')
123             break;
124         if (feof(f))
125             break;
126         if (sz > SIZE_MAX/2 ||
127             (n = realloc(buf, sz += 1 + (sz >> 1))) == NULL) {
128             free(buf);
129             *bufp = NULL;
130             *szp = 0;
131             *lenp = 0;
132             return ENOMEM;
133         }
134         buf = n;
135     }
136     *bufp = buf;
137     *szp = sz;
138     *lenp = len;
139     return 0; /* *len == 0 || no EOL -> EOF */
140 }
141 
142 int
mit_prop_dump(void * arg,const char * file)143 mit_prop_dump(void *arg, const char *file)
144 {
145     krb5_error_code ret;
146     size_t line_bufsz = 0;
147     size_t line_len = 0;
148     char *line = NULL;
149     int lineno = 0;
150     FILE *f;
151     struct hdb_entry_ex ent;
152     struct prop_data *pd = arg;
153     krb5_storage *sp = NULL;
154     krb5_data kdb_ent;
155 
156     memset(&ent, 0, sizeof (ent));
157     f = fopen(file, "r");
158     if (f == NULL)
159 	return errno;
160 
161     ret = ENOMEM;
162     sp = krb5_storage_emem();
163     if (!sp)
164         goto out;
165     while ((ret = my_fgetln(f, &line, &line_bufsz, &line_len)) == 0 &&
166            line_len > 0) {
167         char *p = line;
168         char *q;
169 
170         lineno++;
171 	if(strncmp(line, "kdb5_util", strlen("kdb5_util")) == 0) {
172 	    int major;
173             q = nexttoken(&p);
174             if (strcmp(q, "kdb5_util"))
175                 errx(1, "line %d: unknown version", lineno);
176 	    q = nexttoken(&p); /* load_dump */
177 	    if (strcmp(q, "load_dump"))
178 		errx(1, "line %d: unknown version", lineno);
179 	    q = nexttoken(&p); /* load_dump */
180 	    if (strcmp(q, "version"))
181 		errx(1, "line %d: unknown version", lineno);
182 	    q = nexttoken(&p); /* x.0 */
183 	    if (sscanf(q, "%d", &major) != 1)
184 		errx(1, "line %d: unknown version", lineno);
185 	    if (major != 4 && major != 5 && major != 6)
186 		errx(1, "unknown dump file format, got %d, expected 4-6",
187 		     major);
188 	    continue;
189 	} else if(strncmp(p, "policy", strlen("policy")) == 0) {
190             warnx("line: %d: ignoring policy (not supported)", lineno);
191 	    continue;
192 	} else if(strncmp(p, "princ", strlen("princ")) != 0) {
193 	    warnx("line %d: not a principal", lineno);
194 	    continue;
195 	}
196         krb5_storage_truncate(sp, 0);
197         ret = _hdb_mit_dump2mitdb_entry(pd->context, line, sp);
198         if (ret) {
199             if (ret > 0)
200                 warn("line: %d: failed to parse; ignoring", lineno);
201             else
202                 warnx("line: %d: failed to parse; ignoring", lineno);
203             continue;
204         }
205         ret = krb5_storage_to_data(sp, &kdb_ent);
206         if (ret) break;
207         ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent.entry);
208         krb5_data_free(&kdb_ent);
209         if (ret) {
210             warnx("line: %d: failed to store; ignoring", lineno);
211             continue;
212         }
213 	ret = v5_prop(pd->context, NULL, &ent, arg);
214         hdb_free_entry(pd->context, &ent);
215         if (ret) break;
216     }
217 
218 out:
219     fclose(f);
220     free(line);
221     if (sp)
222         krb5_storage_free(sp);
223     if (ret && ret == ENOMEM)
224         errx(1, "out of memory");
225     if (ret)
226         errx(1, "line %d: problem parsing dump line", lineno);
227     return ret;
228 }
229 
230