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