Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/kadmin/load.c
34865 views
1
/*
2
* Copyright (c) 1997-2005 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 "kadmin-commands.h"
36
#include <kadm5/private.h>
37
38
struct entry {
39
char *principal;
40
char *key;
41
char *max_life;
42
char *max_renew;
43
char *created;
44
char *modified;
45
char *valid_start;
46
char *valid_end;
47
char *pw_end;
48
char *flags;
49
char *generation;
50
char *extensions;
51
};
52
53
static char *
54
skip_next(char *p)
55
{
56
while(*p && !isspace((unsigned char)*p))
57
p++;
58
*p++ = 0;
59
while(*p && isspace((unsigned char)*p))
60
p++;
61
return p;
62
}
63
64
/*
65
* Parse the time in `s', returning:
66
* -1 if error parsing
67
* 0 if none present
68
* 1 if parsed ok
69
*/
70
71
static int
72
parse_time_string(time_t *t, const char *s)
73
{
74
int year, month, date, hour, minute, second;
75
struct tm tm;
76
77
if(strcmp(s, "-") == 0)
78
return 0;
79
if(sscanf(s, "%04d%02d%02d%02d%02d%02d",
80
&year, &month, &date, &hour, &minute, &second) != 6)
81
return -1;
82
tm.tm_year = year - 1900;
83
tm.tm_mon = month - 1;
84
tm.tm_mday = date;
85
tm.tm_hour = hour;
86
tm.tm_min = minute;
87
tm.tm_sec = second;
88
tm.tm_isdst = 0;
89
*t = timegm(&tm);
90
return 1;
91
}
92
93
/*
94
* parse time, allocating space in *t if it's there
95
*/
96
97
static int
98
parse_time_string_alloc (time_t **t, const char *s)
99
{
100
time_t tmp;
101
int ret;
102
103
*t = NULL;
104
ret = parse_time_string (&tmp, s);
105
if (ret == 1) {
106
*t = malloc (sizeof (**t));
107
if (*t == NULL)
108
krb5_errx (context, 1, "malloc: out of memory");
109
**t = tmp;
110
}
111
return ret;
112
}
113
114
/*
115
* see parse_time_string for calling convention
116
*/
117
118
static int
119
parse_integer(unsigned int *u, const char *s)
120
{
121
if(strcmp(s, "-") == 0)
122
return 0;
123
if (sscanf(s, "%u", u) != 1)
124
return -1;
125
return 1;
126
}
127
128
static int
129
parse_integer_alloc (unsigned int **u, const char *s)
130
{
131
unsigned int tmp;
132
int ret;
133
134
*u = NULL;
135
ret = parse_integer (&tmp, s);
136
if (ret == 1) {
137
*u = malloc (sizeof (**u));
138
if (*u == NULL)
139
krb5_errx (context, 1, "malloc: out of memory");
140
**u = tmp;
141
}
142
return ret;
143
}
144
145
/*
146
* Parse dumped keys in `str' and store them in `ent'
147
* return -1 if parsing failed
148
*/
149
150
static int
151
parse_keys(hdb_entry *ent, char *str)
152
{
153
krb5_error_code ret;
154
int tmp;
155
char *p;
156
size_t i;
157
158
p = strsep(&str, ":");
159
if (sscanf(p, "%d", &tmp) != 1)
160
return 1;
161
ent->kvno = tmp;
162
p = strsep(&str, ":");
163
while(p){
164
Key *key;
165
key = realloc(ent->keys.val,
166
(ent->keys.len + 1) * sizeof(*ent->keys.val));
167
if(key == NULL)
168
krb5_errx (context, 1, "realloc: out of memory");
169
ent->keys.val = key;
170
key = ent->keys.val + ent->keys.len;
171
ent->keys.len++;
172
memset(key, 0, sizeof(*key));
173
if(sscanf(p, "%d", &tmp) == 1) {
174
key->mkvno = malloc(sizeof(*key->mkvno));
175
*key->mkvno = tmp;
176
} else
177
key->mkvno = NULL;
178
p = strsep(&str, ":");
179
if (sscanf(p, "%d", &tmp) != 1)
180
return 1;
181
key->key.keytype = tmp;
182
p = strsep(&str, ":");
183
ret = krb5_data_alloc(&key->key.keyvalue, (strlen(p) - 1) / 2 + 1);
184
if (ret)
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)
188
return 1;
189
((u_char*)key->key.keyvalue.data)[i / 2] = tmp;
190
}
191
p = strsep(&str, ":");
192
if(strcmp(p, "-") != 0){
193
unsigned type;
194
size_t p_len;
195
196
if(sscanf(p, "%u/", &type) != 1)
197
return 1;
198
p = strchr(p, '/');
199
if(p == NULL)
200
return 1;
201
p++;
202
p_len = strlen(p);
203
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;
208
209
if (p_len) {
210
if(*p == '\"') {
211
ret = krb5_data_copy(&key->salt->salt, p + 1, p_len - 2);
212
if (ret)
213
krb5_err (context, 1, ret, "krb5_data_copy");
214
} else {
215
ret = krb5_data_alloc(&key->salt->salt,
216
(p_len - 1) / 2 + 1);
217
if (ret)
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)
221
return 1;
222
((u_char*)key->salt->salt.data)[i / 2] = tmp;
223
}
224
}
225
} else
226
krb5_data_zero (&key->salt->salt);
227
}
228
p = strsep(&str, ":");
229
}
230
return 0;
231
}
232
233
/*
234
* see parse_time_string for calling convention
235
*/
236
237
static int
238
parse_event(Event *ev, char *s)
239
{
240
krb5_error_code ret;
241
char *p;
242
243
if(strcmp(s, "-") == 0)
244
return 0;
245
memset(ev, 0, sizeof(*ev));
246
p = strsep(&s, ":");
247
if(parse_time_string(&ev->time, p) != 1)
248
return -1;
249
p = strsep(&s, ":");
250
ret = krb5_parse_name(context, p, &ev->principal);
251
if (ret)
252
return -1;
253
return 1;
254
}
255
256
static int
257
parse_event_alloc (Event **ev, char *s)
258
{
259
Event tmp;
260
int ret;
261
262
*ev = NULL;
263
ret = parse_event (&tmp, s);
264
if (ret == 1) {
265
*ev = malloc (sizeof (**ev));
266
if (*ev == NULL)
267
krb5_errx (context, 1, "malloc: out of memory");
268
**ev = tmp;
269
}
270
return ret;
271
}
272
273
static int
274
parse_hdbflags2int(HDBFlags *f, const char *s)
275
{
276
int ret;
277
unsigned int tmp;
278
279
ret = parse_integer (&tmp, s);
280
if (ret == 1)
281
*f = int2HDBFlags (tmp);
282
return ret;
283
}
284
285
static int
286
parse_generation(char *str, GENERATION **gen)
287
{
288
char *p;
289
int v;
290
291
if(strcmp(str, "-") == 0 || *str == '\0') {
292
*gen = NULL;
293
return 0;
294
}
295
*gen = calloc(1, sizeof(**gen));
296
297
p = strsep(&str, ":");
298
if(parse_time_string(&(*gen)->time, p) != 1)
299
return -1;
300
p = strsep(&str, ":");
301
if(sscanf(p, "%d", &v) != 1)
302
return -1;
303
(*gen)->usec = v;
304
p = strsep(&str, ":");
305
if(sscanf(p, "%d", &v) != 1)
306
return -1;
307
(*gen)->gen = v - 1; /* XXX gets bumped in _hdb_store */
308
return 0;
309
}
310
311
static int
312
parse_extensions(char *str, HDB_extensions **e)
313
{
314
char *p;
315
int ret;
316
317
if(strcmp(str, "-") == 0 || *str == '\0') {
318
*e = NULL;
319
return 0;
320
}
321
*e = calloc(1, sizeof(**e));
322
323
p = strsep(&str, ":");
324
325
while (p) {
326
HDB_extension ext;
327
ssize_t len;
328
void *d;
329
330
len = strlen(p);
331
d = malloc(len);
332
333
len = hex_decode(p, d, len);
334
if (len < 0) {
335
free(d);
336
return -1;
337
}
338
339
ret = decode_HDB_extension(d, len, &ext, NULL);
340
free(d);
341
if (ret)
342
return -1;
343
d = realloc((*e)->val, ((*e)->len + 1) * sizeof((*e)->val[0]));
344
if (d == NULL)
345
abort();
346
(*e)->val = d;
347
(*e)->val[(*e)->len] = ext;
348
(*e)->len++;
349
350
p = strsep(&str, ":");
351
}
352
353
return 0;
354
}
355
356
357
/*
358
* Parse the dump file in `filename' and create the database (merging
359
* iff merge)
360
*/
361
362
static int
363
doit(const char *filename, int mergep)
364
{
365
krb5_error_code ret;
366
FILE *f;
367
char s[8192]; /* XXX should fix this properly */
368
char *p;
369
int line;
370
int flags = O_RDWR;
371
struct entry e;
372
hdb_entry_ex ent;
373
HDB *db = _kadm5_s_get_db(kadm_handle);
374
375
f = fopen(filename, "r");
376
if(f == NULL){
377
krb5_warn(context, errno, "fopen(%s)", filename);
378
return 1;
379
}
380
ret = kadm5_log_truncate (kadm_handle);
381
if (ret) {
382
fclose (f);
383
krb5_warn(context, ret, "kadm5_log_truncate");
384
return 1;
385
}
386
387
if(!mergep)
388
flags |= O_CREAT | O_TRUNC;
389
ret = db->hdb_open(context, db, flags, 0600);
390
if(ret){
391
krb5_warn(context, ret, "hdb_open");
392
fclose(f);
393
return 1;
394
}
395
line = 0;
396
ret = 0;
397
while(fgets(s, sizeof(s), f) != NULL) {
398
line++;
399
400
p = s;
401
while (isspace((unsigned char)*p))
402
p++;
403
404
e.principal = p;
405
for(p = s; *p; p++){
406
if(*p == '\\')
407
p++;
408
else if(isspace((unsigned char)*p)) {
409
*p = 0;
410
break;
411
}
412
}
413
p = skip_next(p);
414
415
e.key = p;
416
p = skip_next(p);
417
418
e.created = p;
419
p = skip_next(p);
420
421
e.modified = p;
422
p = skip_next(p);
423
424
e.valid_start = p;
425
p = skip_next(p);
426
427
e.valid_end = p;
428
p = skip_next(p);
429
430
e.pw_end = p;
431
p = skip_next(p);
432
433
e.max_life = p;
434
p = skip_next(p);
435
436
e.max_renew = p;
437
p = skip_next(p);
438
439
e.flags = p;
440
p = skip_next(p);
441
442
e.generation = p;
443
p = skip_next(p);
444
445
e.extensions = p;
446
skip_next(p);
447
448
memset(&ent, 0, sizeof(ent));
449
ret = krb5_parse_name(context, e.principal, &ent.entry.principal);
450
if(ret) {
451
const char *msg = krb5_get_error_message(context, ret);
452
fprintf(stderr, "%s:%d:%s (%s)\n",
453
filename, line, msg, e.principal);
454
krb5_free_error_message(context, msg);
455
continue;
456
}
457
458
if (parse_keys(&ent.entry, e.key)) {
459
fprintf (stderr, "%s:%d:error parsing keys (%s)\n",
460
filename, line, e.key);
461
hdb_free_entry (context, &ent);
462
continue;
463
}
464
465
if (parse_event(&ent.entry.created_by, e.created) == -1) {
466
fprintf (stderr, "%s:%d:error parsing created event (%s)\n",
467
filename, line, e.created);
468
hdb_free_entry (context, &ent);
469
continue;
470
}
471
if (parse_event_alloc (&ent.entry.modified_by, e.modified) == -1) {
472
fprintf (stderr, "%s:%d:error parsing event (%s)\n",
473
filename, line, e.modified);
474
hdb_free_entry (context, &ent);
475
continue;
476
}
477
if (parse_time_string_alloc (&ent.entry.valid_start, e.valid_start) == -1) {
478
fprintf (stderr, "%s:%d:error parsing time (%s)\n",
479
filename, line, e.valid_start);
480
hdb_free_entry (context, &ent);
481
continue;
482
}
483
if (parse_time_string_alloc (&ent.entry.valid_end, e.valid_end) == -1) {
484
fprintf (stderr, "%s:%d:error parsing time (%s)\n",
485
filename, line, e.valid_end);
486
hdb_free_entry (context, &ent);
487
continue;
488
}
489
if (parse_time_string_alloc (&ent.entry.pw_end, e.pw_end) == -1) {
490
fprintf (stderr, "%s:%d:error parsing time (%s)\n",
491
filename, line, e.pw_end);
492
hdb_free_entry (context, &ent);
493
continue;
494
}
495
496
if (parse_integer_alloc (&ent.entry.max_life, e.max_life) == -1) {
497
fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n",
498
filename, line, e.max_life);
499
hdb_free_entry (context, &ent);
500
continue;
501
502
}
503
if (parse_integer_alloc (&ent.entry.max_renew, e.max_renew) == -1) {
504
fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n",
505
filename, line, e.max_renew);
506
hdb_free_entry (context, &ent);
507
continue;
508
}
509
510
if (parse_hdbflags2int (&ent.entry.flags, e.flags) != 1) {
511
fprintf (stderr, "%s:%d:error parsing flags (%s)\n",
512
filename, line, e.flags);
513
hdb_free_entry (context, &ent);
514
continue;
515
}
516
517
if(parse_generation(e.generation, &ent.entry.generation) == -1) {
518
fprintf (stderr, "%s:%d:error parsing generation (%s)\n",
519
filename, line, e.generation);
520
hdb_free_entry (context, &ent);
521
continue;
522
}
523
524
if(parse_extensions(e.extensions, &ent.entry.extensions) == -1) {
525
fprintf (stderr, "%s:%d:error parsing extension (%s)\n",
526
filename, line, e.extensions);
527
hdb_free_entry (context, &ent);
528
continue;
529
}
530
531
ret = db->hdb_store(context, db, HDB_F_REPLACE, &ent);
532
hdb_free_entry (context, &ent);
533
if (ret) {
534
krb5_warn(context, ret, "db_store");
535
break;
536
}
537
}
538
db->hdb_close(context, db);
539
fclose(f);
540
return ret != 0;
541
}
542
543
544
extern int local_flag;
545
546
static int
547
loadit(int mergep, const char *name, int argc, char **argv)
548
{
549
if(!local_flag) {
550
krb5_warnx(context, "%s is only available in local (-l) mode", name);
551
return 0;
552
}
553
554
return doit(argv[0], mergep);
555
}
556
557
int
558
load(void *opt, int argc, char **argv)
559
{
560
return loadit(0, "load", argc, argv);
561
}
562
563
int
564
merge(void *opt, int argc, char **argv)
565
{
566
return loadit(1, "merge", argc, argv);
567
}
568
569