load.c revision 55682
1/*
2 * Copyright (c) 1997, 1998, 1999 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 "kadmin_locl.h"
35#include <kadm5/private.h>
36
37RCSID("$Id: load.c,v 1.34 1999/12/02 17:04:58 joda Exp $");
38
39struct entry{
40    char *principal;
41    char *key;
42    char *max_life;
43    char *max_renew;
44    char *created;
45    char *modified;
46    char *valid_start;
47    char *valid_end;
48    char *pw_end;
49    char *flags;
50    char *etypes;
51};
52
53static char *
54skip_next(char *p)
55{
56    while(*p && !isspace((unsigned char)*p))
57	p++;
58    *p++ = 0;
59    while(*p && isspace((unsigned char)*p)) p++;
60    return p;
61}
62
63static time_t*
64parse_time_string(time_t *t, char *s)
65{
66    int year, month, date, hour, minute, second;
67    struct tm tm;
68    if(strcmp(s, "-") == 0)
69	return NULL;
70    if(t == NULL)
71	t = malloc(sizeof(*t));
72    sscanf(s, "%04d%02d%02d%02d%02d%02d",
73	   &year, &month, &date, &hour, &minute, &second);
74    tm.tm_year = year - 1900;
75    tm.tm_mon = month - 1;
76    tm.tm_mday = date;
77    tm.tm_hour = hour;
78    tm.tm_min = minute;
79    tm.tm_sec = second;
80    tm.tm_isdst = 0;
81    *t = timegm(&tm);
82    return t;
83}
84
85static unsigned*
86parse_integer(unsigned *u, char *s)
87{
88    if(strcmp(s, "-") == 0)
89	return NULL;
90    if(u == NULL)
91	u = malloc(sizeof(*u));
92    sscanf(s, "%u", u);
93    return u;
94}
95
96static void
97parse_keys(hdb_entry *ent, char *str)
98{
99    int tmp;
100    char *p;
101    int i;
102
103    p = strsep(&str, ":");
104    sscanf(p, "%d", &tmp);
105    ent->kvno = tmp;
106    p = strsep(&str, ":");
107    while(p){
108	Key *key;
109	key = realloc(ent->keys.val,
110		      (ent->keys.len + 1) * sizeof(*ent->keys.val));
111	if(key == NULL)
112	    abort();
113	ent->keys.val = key;
114	key = ent->keys.val + ent->keys.len;
115	ent->keys.len++;
116	memset(key, 0, sizeof(*key));
117	if(sscanf(p, "%d", &tmp) == 1) {
118	    key->mkvno = malloc(sizeof(*key->mkvno));
119	    *key->mkvno = tmp;
120	} else
121	    key->mkvno = NULL;
122	p = strsep(&str, ":");
123	sscanf(p, "%d", &tmp);
124	key->key.keytype = tmp;
125	p = strsep(&str, ":");
126	krb5_data_alloc(&key->key.keyvalue, (strlen(p) - 1) / 2 + 1);
127	for(i = 0; i < strlen(p); i += 2){
128	    sscanf(p + i, "%02x", &tmp);
129	    ((u_char*)key->key.keyvalue.data)[i / 2] = tmp;
130	}
131	p = strsep(&str, ":");
132	if(strcmp(p, "-") != 0){
133	    unsigned type;
134	    size_t p_len;
135	    if(sscanf(p, "%u/", &type) != 1){
136		abort ();
137	    }
138	    p = strchr(p, '/');
139	    if(p == NULL)
140		abort ();
141	    p++;
142	    p_len = strlen(p);
143
144	    key->salt = malloc(sizeof(*key->salt));
145	    key->salt->type = type;
146
147	    if (p_len) {
148		if(*p == '\"'){
149		    krb5_data_copy(&key->salt->salt, p + 1, p_len - 2);
150		}else{
151		    krb5_data_alloc(&key->salt->salt, (p_len - 1) / 2 + 1);
152		    for(i = 0; i < p_len; i += 2){
153			sscanf(p + i, "%02x", &tmp);
154			((u_char*)key->salt->salt.data)[i / 2] = tmp;
155		    }
156		}
157	    } else
158		krb5_data_zero (&key->salt->salt);
159	}
160	p = strsep(&str, ":");
161    }
162}
163
164static Event*
165parse_event(Event *ev, char *str)
166{
167    char *p;
168    if(strcmp(str, "-") == 0)
169	return NULL;
170    if(ev == NULL)
171	ev = malloc(sizeof(*ev));
172    memset(ev, 0, sizeof(*ev));
173    p = strsep(&str, ":");
174    parse_time_string(&ev->time, p);
175    p = strsep(&str, ":");
176    krb5_parse_name(context, p, &ev->principal);
177    return ev;
178}
179
180static HDBFlags
181parse_hdbflags2int(char *str)
182{
183    unsigned i;
184    parse_integer(&i, str);
185
186    return int2HDBFlags(i);
187}
188
189#if 0
190static void
191parse_etypes(char *str, unsigned **val, unsigned *len)
192{
193    unsigned v;
194
195    *val = NULL;
196    *len = 0;
197    while(sscanf(str, "%u", &v) == 1) {
198	*val = realloc(*val, (*len+1) * sizeof(**val));
199	(*val)[(*len)++] = v;
200	str = strchr(str, ':');
201	if(str == NULL)
202	    break;
203	str++;
204    }
205}
206#endif
207
208static void
209doit(char *filename, int merge)
210{
211    krb5_error_code ret;
212    FILE *f;
213    char s[1024];
214    char *p;
215    int line;
216    int flags = O_RDWR;
217    struct entry e;
218    hdb_entry ent;
219    HDB *db = _kadm5_s_get_db(kadm_handle);
220
221    f = fopen(filename, "r");
222    if(f == NULL){
223	krb5_warn(context, errno, "fopen(%s)", filename);
224	return;
225    }
226    if(!merge)
227	flags |= O_CREAT | O_TRUNC;
228    ret = db->open(context, db, flags, 0600);
229    if(ret){
230	krb5_warn(context, ret, "hdb_open");
231	fclose(f);
232	return;
233    }
234    line = 0;
235    while(fgets(s, sizeof(s), f)){
236	line++;
237	e.principal = s;
238	for(p = s; *p; p++){
239	    if(*p == '\\')
240		p++;
241	    else if(isspace((unsigned char)*p)) {
242		*p = 0;
243		break;
244	    }
245	}
246	p = skip_next(p);
247
248	e.key = p;
249	p = skip_next(p);
250
251	e.created = p;
252	p = skip_next(p);
253
254	e.modified = p;
255	p = skip_next(p);
256
257	e.valid_start = p;
258	p = skip_next(p);
259
260	e.valid_end = p;
261	p = skip_next(p);
262
263	e.pw_end = p;
264	p = skip_next(p);
265
266	e.max_life = p;
267	p = skip_next(p);
268
269	e.max_renew = p;
270	p = skip_next(p);
271
272	e.flags = p;
273	p = skip_next(p);
274
275	e.etypes = p;
276	p = skip_next(p);
277
278	memset(&ent, 0, sizeof(ent));
279	ret = krb5_parse_name(context, e.principal, &ent.principal);
280	if(ret){
281	    fprintf(stderr, "%s:%d:%s (%s)\n",
282		    filename,
283		    line,
284		    krb5_get_err_text(context, ret),
285		    e.principal);
286	    continue;
287	}
288
289	parse_keys(&ent, e.key);
290
291	parse_event(&ent.created_by, e.created);
292	ent.modified_by = parse_event(NULL, e.modified);
293	ent.valid_start = parse_time_string(NULL, e.valid_start);
294	ent.valid_end = parse_time_string(NULL, e.valid_end);
295	ent.pw_end = parse_time_string(NULL, e.pw_end);
296	ent.max_life = parse_integer(NULL, e.max_life);
297	ent.max_renew = parse_integer(NULL, e.max_renew);
298	ent.flags = parse_hdbflags2int(e.flags);
299#if 0
300	ALLOC(ent.etypes);
301	parse_etypes(e.etypes, &ent.etypes->val, &ent.etypes->len);
302	if(ent.etypes->len == 0) {
303	    free(ent.etypes);
304	    ent.etypes = NULL;
305	}
306#endif
307
308	db->store(context, db, HDB_F_REPLACE, &ent);
309	hdb_free_entry (context, &ent);
310    }
311    db->close(context, db);
312    fclose(f);
313}
314
315int
316load(int argc, char **argv)
317{
318    if(argc < 2){
319	krb5_warnx(context, "Usage: load filename");
320	return 0;
321    }
322    doit(argv[1], 0);
323    return 0;
324}
325
326int
327merge(int argc, char **argv)
328{
329    if(argc < 2){
330	krb5_warnx(context, "Usage: merge filename");
331	return 0;
332    }
333    doit(argv[1], 1);
334    return 0;
335}
336