2 * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
34 #include "kadmin_locl.h"
35 #include "kadmin-commands.h"
36 #include <kadm5/private.h>
56 while(*p
&& !isspace((unsigned char)*p
))
59 while(*p
&& isspace((unsigned char)*p
))
65 * Parse the time in `s', returning:
72 parse_time_string(time_t *t
, const char *s
)
74 int year
, month
, date
, hour
, minute
, second
;
77 if(strcmp(s
, "-") == 0)
79 if(sscanf(s
, "%04d%02d%02d%02d%02d%02d",
80 &year
, &month
, &date
, &hour
, &minute
, &second
) != 6)
82 tm
.tm_year
= year
- 1900;
83 tm
.tm_mon
= month
- 1;
94 * parse time, allocating space in *t if it's there
98 parse_time_string_alloc (time_t **t
, const char *s
)
104 ret
= parse_time_string (&tmp
, s
);
106 *t
= malloc (sizeof (**t
));
108 krb5_errx (context
, 1, "malloc: out of memory");
115 * see parse_time_string for calling convention
119 parse_integer(unsigned int *u
, const char *s
)
121 if(strcmp(s
, "-") == 0)
123 if (sscanf(s
, "%u", u
) != 1)
129 parse_integer_alloc (unsigned int **u
, const char *s
)
135 ret
= parse_integer (&tmp
, s
);
137 *u
= malloc (sizeof (**u
));
139 krb5_errx (context
, 1, "malloc: out of memory");
146 * Parse dumped keys in `str' and store them in `ent'
147 * return -1 if parsing failed
151 parse_keys(hdb_entry
*ent
, char *str
)
158 p
= strsep(&str
, ":");
159 if (sscanf(p
, "%d", &tmp
) != 1)
162 p
= strsep(&str
, ":");
165 key
= realloc(ent
->keys
.val
,
166 (ent
->keys
.len
+ 1) * sizeof(*ent
->keys
.val
));
168 krb5_errx (context
, 1, "realloc: out of memory");
170 key
= ent
->keys
.val
+ ent
->keys
.len
;
172 memset(key
, 0, sizeof(*key
));
173 if(sscanf(p
, "%d", &tmp
) == 1) {
174 key
->mkvno
= malloc(sizeof(*key
->mkvno
));
178 p
= strsep(&str
, ":");
179 if (sscanf(p
, "%d", &tmp
) != 1)
181 key
->key
.keytype
= tmp
;
182 p
= strsep(&str
, ":");
183 ret
= krb5_data_alloc(&key
->key
.keyvalue
, (strlen(p
) - 1) / 2 + 1);
185 krb5_err (context
, 1, ret
, "krb5_data_alloc");
186 for(i
= 0; i
< strlen(p
); i
+= 2) {
187 if(sscanf(p
+ i
, "%02x", &tmp
) != 1)
189 ((u_char
*)key
->key
.keyvalue
.data
)[i
/ 2] = tmp
;
191 p
= strsep(&str
, ":");
192 if(strcmp(p
, "-") != 0){
196 if(sscanf(p
, "%u/", &type
) != 1)
204 key
->salt
= calloc(1, sizeof(*key
->salt
));
205 if (key
->salt
== NULL
)
206 krb5_errx (context
, 1, "malloc: out of memory");
207 key
->salt
->type
= type
;
211 ret
= krb5_data_copy(&key
->salt
->salt
, p
+ 1, p_len
- 2);
213 krb5_err (context
, 1, ret
, "krb5_data_copy");
215 ret
= krb5_data_alloc(&key
->salt
->salt
,
216 (p_len
- 1) / 2 + 1);
218 krb5_err (context
, 1, ret
, "krb5_data_alloc");
219 for(i
= 0; i
< p_len
; i
+= 2){
220 if (sscanf(p
+ i
, "%02x", &tmp
) != 1)
222 ((u_char
*)key
->salt
->salt
.data
)[i
/ 2] = tmp
;
226 krb5_data_zero (&key
->salt
->salt
);
228 p
= strsep(&str
, ":");
234 * see parse_time_string for calling convention
238 parse_event(Event
*ev
, char *s
)
243 if(strcmp(s
, "-") == 0)
245 memset(ev
, 0, sizeof(*ev
));
247 if(parse_time_string(&ev
->time
, p
) != 1)
250 ret
= krb5_parse_name(context
, p
, &ev
->principal
);
257 parse_event_alloc (Event
**ev
, char *s
)
263 ret
= parse_event (&tmp
, s
);
265 *ev
= malloc (sizeof (**ev
));
267 krb5_errx (context
, 1, "malloc: out of memory");
274 parse_hdbflags2int(HDBFlags
*f
, const char *s
)
279 ret
= parse_integer (&tmp
, s
);
281 *f
= int2HDBFlags (tmp
);
286 parse_generation(char *str
, GENERATION
**gen
)
291 if(strcmp(str
, "-") == 0 || *str
== '\0') {
295 *gen
= calloc(1, sizeof(**gen
));
297 p
= strsep(&str
, ":");
298 if(parse_time_string(&(*gen
)->time
, p
) != 1)
300 p
= strsep(&str
, ":");
301 if(sscanf(p
, "%d", &v
) != 1)
304 p
= strsep(&str
, ":");
305 if(sscanf(p
, "%d", &v
) != 1)
307 (*gen
)->gen
= v
- 1; /* XXX gets bumped in _hdb_store */
312 parse_extensions(char *str
, HDB_extensions
**e
)
317 if(strcmp(str
, "-") == 0 || *str
== '\0') {
321 *e
= calloc(1, sizeof(**e
));
323 p
= strsep(&str
, ":");
333 len
= hex_decode(p
, d
, len
);
339 ret
= decode_HDB_extension(d
, len
, &ext
, NULL
);
343 d
= realloc((*e
)->val
, ((*e
)->len
+ 1) * sizeof((*e
)->val
[0]));
347 (*e
)->val
[(*e
)->len
] = ext
;
350 p
= strsep(&str
, ":");
358 * Parse the dump file in `filename' and create the database (merging
363 doit(const char *filename
, int mergep
)
365 krb5_error_code ret
= 0;
367 char s
[8192]; /* XXX should fix this properly */
373 HDB
*db
= _kadm5_s_get_db(kadm_handle
);
375 f
= fopen(filename
, "r");
377 krb5_warn(context
, errno
, "fopen(%s)", filename
);
381 * We don't have a version number in the dump, so we don't know which iprop
382 * log entries to keep, if any. We throw the log away.
384 * We could merge the ipropd-master/slave dump/load here as an option, in
385 * which case we would first load the dump.
387 * If we're merging, first recover unconfirmed records in the existing log.
390 ret
= kadm5_log_init(kadm_handle
);
392 ret
= kadm5_log_reinit(kadm_handle
, 0);
395 krb5_warn(context
, ret
, "kadm5_log_reinit");
400 flags
|= O_CREAT
| O_TRUNC
;
401 ret
= db
->hdb_open(context
, db
, flags
, 0600);
403 krb5_warn(context
, ret
, "hdb_open");
409 while(fgets(s
, sizeof(s
), f
) != NULL
) {
413 while (isspace((unsigned char)*p
))
420 else if(isspace((unsigned char)*p
)) {
460 memset(&ent
, 0, sizeof(ent
));
461 ret
= krb5_parse_name(context
, e
.principal
, &ent
.entry
.principal
);
463 const char *msg
= krb5_get_error_message(context
, ret
);
464 fprintf(stderr
, "%s:%d:%s (%s)\n",
465 filename
, line
, msg
, e
.principal
);
466 krb5_free_error_message(context
, msg
);
470 if (parse_keys(&ent
.entry
, e
.key
)) {
471 fprintf (stderr
, "%s:%d:error parsing keys (%s)\n",
472 filename
, line
, e
.key
);
473 hdb_free_entry (context
, &ent
);
477 if (parse_event(&ent
.entry
.created_by
, e
.created
) == -1) {
478 fprintf (stderr
, "%s:%d:error parsing created event (%s)\n",
479 filename
, line
, e
.created
);
480 hdb_free_entry (context
, &ent
);
483 if (parse_event_alloc (&ent
.entry
.modified_by
, e
.modified
) == -1) {
484 fprintf (stderr
, "%s:%d:error parsing event (%s)\n",
485 filename
, line
, e
.modified
);
486 hdb_free_entry (context
, &ent
);
489 if (parse_time_string_alloc (&ent
.entry
.valid_start
, e
.valid_start
) == -1) {
490 fprintf (stderr
, "%s:%d:error parsing time (%s)\n",
491 filename
, line
, e
.valid_start
);
492 hdb_free_entry (context
, &ent
);
495 if (parse_time_string_alloc (&ent
.entry
.valid_end
, e
.valid_end
) == -1) {
496 fprintf (stderr
, "%s:%d:error parsing time (%s)\n",
497 filename
, line
, e
.valid_end
);
498 hdb_free_entry (context
, &ent
);
501 if (parse_time_string_alloc (&ent
.entry
.pw_end
, e
.pw_end
) == -1) {
502 fprintf (stderr
, "%s:%d:error parsing time (%s)\n",
503 filename
, line
, e
.pw_end
);
504 hdb_free_entry (context
, &ent
);
508 if (parse_integer_alloc (&ent
.entry
.max_life
, e
.max_life
) == -1) {
509 fprintf (stderr
, "%s:%d:error parsing lifetime (%s)\n",
510 filename
, line
, e
.max_life
);
511 hdb_free_entry (context
, &ent
);
515 if (parse_integer_alloc (&ent
.entry
.max_renew
, e
.max_renew
) == -1) {
516 fprintf (stderr
, "%s:%d:error parsing lifetime (%s)\n",
517 filename
, line
, e
.max_renew
);
518 hdb_free_entry (context
, &ent
);
522 if (parse_hdbflags2int (&ent
.entry
.flags
, e
.flags
) != 1) {
523 fprintf (stderr
, "%s:%d:error parsing flags (%s)\n",
524 filename
, line
, e
.flags
);
525 hdb_free_entry (context
, &ent
);
529 if(parse_generation(e
.generation
, &ent
.entry
.generation
) == -1) {
530 fprintf (stderr
, "%s:%d:error parsing generation (%s)\n",
531 filename
, line
, e
.generation
);
532 hdb_free_entry (context
, &ent
);
536 if(parse_extensions(e
.extensions
, &ent
.entry
.extensions
) == -1) {
537 fprintf (stderr
, "%s:%d:error parsing extension (%s)\n",
538 filename
, line
, e
.extensions
);
539 hdb_free_entry (context
, &ent
);
543 ret
= db
->hdb_store(context
, db
, HDB_F_REPLACE
, &ent
);
544 hdb_free_entry (context
, &ent
);
546 krb5_warn(context
, ret
, "db_store");
550 (void) kadm5_log_end(kadm_handle
);
551 db
->hdb_close(context
, db
);
557 extern int local_flag
;
560 loadit(int mergep
, const char *name
, int argc
, char **argv
)
563 krb5_warnx(context
, "%s is only available in local (-l) mode", name
);
567 return doit(argv
[0], mergep
);
571 load(void *opt
, int argc
, char **argv
)
573 return loadit(0, "load", argc
, argv
);
577 merge(void *opt
, int argc
, char **argv
)
579 return loadit(1, "merge", argc
, argv
);