|
|
1.1 root 1: /*
2: * $Source: /usr/src/kerberosIV/kdb_util/RCS/kdb_util.c,v $
3: * $Author: kfall $
4: *
5: * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
6: *
7: * For copying and distribution information, please see the file
8: * <mit-copyright.h>.
9: *
10: * Kerberos database manipulation utility. This program allows you to
11: * dump a kerberos database to an ascii readable file and load this
12: * file into the database. Read locking of the database is done during a
13: * dump operation. NO LOCKING is done during a load operation. Loads
14: * should happen with other processes shutdown.
15: *
16: * Written July 9, 1987 by Jeffrey I. Schiller
17: */
18:
19: #ifndef lint
20: static char rcsid_kdb_util_c[] =
21: "$Id: kdb_util.c,v 4.5 90/06/25 22:12:42 kfall Exp $";
22: #endif lint
23:
24: #include <mit-copyright.h>
25: #include <sys/types.h>
26: #include <sys/file.h>
27: #include <netinet/in.h>
28: #include <string.h>
29: #include <stdio.h>
30: #include "time.h"
31: #include <des.h>
32: #include <krb.h>
33: #include <krb_db.h>
34:
35: #define TRUE 1
36:
37: Principal aprinc;
38:
39: static des_cblock master_key, new_master_key;
40: static des_key_schedule master_key_schedule, new_master_key_schedule;
41:
42: #define zaptime(foo) bzero((char *)(foo), sizeof(*(foo)))
43:
44: extern long kdb_get_master_key(), kdb_verify_master_key();
45: extern char *malloc();
46: extern int errno;
47:
48: char *progname;
49:
50: main(argc, argv)
51: int argc;
52: char **argv;
53: {
54: FILE *file;
55: enum {
56: OP_LOAD,
57: OP_DUMP,
58: OP_SLAVE_DUMP,
59: OP_NEW_MASTER,
60: OP_CONVERT_OLD_DB,
61: } op;
62: char *file_name;
63: char *prog = argv[0];
64: char *db_name;
65:
66: progname = prog; /* required by libkdb (yuck!) */
67:
68: if (argc != 3 && argc != 4) {
69: fprintf(stderr, "Usage: %s operation file-name [database name].\n",
70: argv[0]);
71: exit(1);
72: }
73: if (argc == 3)
74: db_name = DBM_FILE;
75: else
76: db_name = argv[3];
77:
78: if (kerb_db_set_name (db_name) != 0) {
79: perror("Can't open database");
80: exit(1);
81: }
82:
83: if (!strcmp(argv[1], "load"))
84: op = OP_LOAD;
85: else if (!strcmp(argv[1], "dump"))
86: op = OP_DUMP;
87: else if (!strcmp(argv[1], "slave_dump"))
88: op = OP_SLAVE_DUMP;
89: else if (!strcmp(argv[1], "new_master_key"))
90: op = OP_NEW_MASTER;
91: else if (!strcmp(argv[1], "convert_old_db"))
92: op = OP_CONVERT_OLD_DB;
93: else {
94: fprintf(stderr,
95: "%s: %s is an invalid operation.\n", prog, argv[1]);
96: fprintf(stderr,
97: "%s: Valid operations are \"dump\", \"slave_dump\",", argv[0]);
98: fprintf(stderr,
99: "\"load\", \"new_master_key\", and \"convert_old_db\".\n");
100: exit(1);
101: }
102:
103: file_name = argv[2];
104: file = fopen(file_name, op == OP_LOAD ? "r" : "w");
105: if (file == NULL) {
106: fprintf(stderr, "%s: Unable to open %s\n", prog, argv[2]);
107: (void) fflush(stderr);
108: perror("open");
109: exit(1);
110: }
111:
112: switch (op) {
113: case OP_DUMP:
114: if ((dump_db (db_name, file, (void (*)()) 0) == EOF) ||
115: (fclose(file) == EOF)) {
116: fprintf(stderr, "error on file %s:", file_name);
117: perror("");
118: exit(1);
119: }
120: break;
121: case OP_SLAVE_DUMP:
122: if ((dump_db (db_name, file, (void (*)()) 0) == EOF) ||
123: (fclose(file) == EOF)) {
124: fprintf(stderr, "error on file %s:", file_name);
125: perror("");
126: exit(1);
127: }
128: update_ok_file (file_name);
129: break;
130: case OP_LOAD:
131: load_db (db_name, file);
132: break;
133: case OP_NEW_MASTER:
134: convert_new_master_key (db_name, file);
135: printf("Don't forget to do a `kdb_util load %s' to reload the database!\n", file_name);
136: break;
137: case OP_CONVERT_OLD_DB:
138: convert_old_format_db (db_name, file);
139: printf("Don't forget to do a `kdb_util load %s' to reload the database!\n", file_name);
140: break;
141: }
142: exit(0);
143: }
144:
145: clear_secrets ()
146: {
147: bzero((char *)master_key, sizeof (des_cblock));
148: bzero((char *)master_key_schedule, sizeof (Key_schedule));
149: bzero((char *)new_master_key, sizeof (des_cblock));
150: bzero((char *)new_master_key_schedule, sizeof (Key_schedule));
151: }
152:
153: /* cv_key is a procedure which takes a principle and changes its key,
154: either for a new method of encrypting the keys, or a new master key.
155: if cv_key is null no transformation of key is done (other than net byte
156: order). */
157:
158: struct callback_args {
159: void (*cv_key)();
160: FILE *output_file;
161: };
162:
163: static int dump_db_1(arg, principal)
164: char *arg;
165: Principal *principal;
166: { /* replace null strings with "*" */
167: struct callback_args *a = (struct callback_args *)arg;
168:
169: if (principal->instance[0] == '\0') {
170: principal->instance[0] = '*';
171: principal->instance[1] = '\0';
172: }
173: if (principal->mod_name[0] == '\0') {
174: principal->mod_name[0] = '*';
175: principal->mod_name[1] = '\0';
176: }
177: if (principal->mod_instance[0] == '\0') {
178: principal->mod_instance[0] = '*';
179: principal->mod_instance[1] = '\0';
180: }
181: if (a->cv_key != NULL) {
182: (*a->cv_key) (principal);
183: }
184: fprintf(a->output_file, "%s %s %d %d %d %d %x %x",
185: principal->name,
186: principal->instance,
187: principal->max_life,
188: principal->kdc_key_ver,
189: principal->key_version,
190: principal->attributes,
191: htonl (principal->key_low),
192: htonl (principal->key_high));
193: print_time(a->output_file, principal->exp_date);
194: print_time(a->output_file, principal->mod_date);
195: fprintf(a->output_file, " %s %s\n",
196: principal->mod_name,
197: principal->mod_instance);
198: return 0;
199: }
200:
201: dump_db (db_file, output_file, cv_key)
202: char *db_file;
203: FILE *output_file;
204: void (*cv_key)();
205: {
206: struct callback_args a;
207:
208: a.cv_key = cv_key;
209: a.output_file = output_file;
210:
211: kerb_db_iterate (dump_db_1, (char *)&a);
212: return fflush(output_file);
213: }
214:
215: load_db (db_file, input_file)
216: char *db_file;
217: FILE *input_file;
218: {
219: char exp_date_str[50];
220: char mod_date_str[50];
221: int temp1, temp2, temp3;
222: long time_explode();
223: int code;
224: extern char *sys_errlist[];
225: char *temp_db_file;
226: temp1 = strlen(db_file+2);
227: temp_db_file = malloc (temp1);
228: strcpy(temp_db_file, db_file);
229: strcat(temp_db_file, "~");
230:
231: /* Create the database */
232: if ((code = kerb_db_create(temp_db_file)) != 0) {
233: fprintf(stderr, "Couldn't create temp database %s: %s\n",
234: temp_db_file, sys_errlist[code]);
235: exit(1);
236: }
237: kerb_db_set_name(temp_db_file);
238: for (;;) { /* explicit break on eof from fscanf */
239: bzero((char *)&aprinc, sizeof(aprinc));
240: if (fscanf(input_file,
241: "%s %s %d %d %d %hd %x %x %s %s %s %s\n",
242: aprinc.name,
243: aprinc.instance,
244: &temp1,
245: &temp2,
246: &temp3,
247: &aprinc.attributes,
248: &aprinc.key_low,
249: &aprinc.key_high,
250: exp_date_str,
251: mod_date_str,
252: aprinc.mod_name,
253: aprinc.mod_instance) == EOF)
254: break;
255: aprinc.key_low = ntohl (aprinc.key_low);
256: aprinc.key_high = ntohl (aprinc.key_high);
257: aprinc.max_life = (unsigned char) temp1;
258: aprinc.kdc_key_ver = (unsigned char) temp2;
259: aprinc.key_version = (unsigned char) temp3;
260: aprinc.exp_date = time_explode(exp_date_str);
261: aprinc.mod_date = time_explode(mod_date_str);
262: if (aprinc.instance[0] == '*')
263: aprinc.instance[0] = '\0';
264: if (aprinc.mod_name[0] == '*')
265: aprinc.mod_name[0] = '\0';
266: if (aprinc.mod_instance[0] == '*')
267: aprinc.mod_instance[0] = '\0';
268: if (kerb_db_put_principal(&aprinc, 1) != 1) {
269: fprintf(stderr, "Couldn't store %s.%s: %s; load aborted\n",
270: aprinc.name, aprinc.instance,
271: sys_errlist[errno]);
272: exit(1);
273: };
274: }
275: if ((code = kerb_db_rename(temp_db_file, db_file)) != 0)
276: perror("database rename failed");
277: (void) fclose(input_file);
278: free(temp_db_file);
279: }
280:
281: print_time(file, timeval)
282: FILE *file;
283: unsigned long timeval;
284: {
285: struct tm *tm;
286: struct tm *gmtime();
287: tm = gmtime((long *)&timeval);
288: fprintf(file, " %04d%02d%02d%02d%02d",
289: tm->tm_year < 1900 ? tm->tm_year + 1900: tm->tm_year,
290: tm->tm_mon + 1,
291: tm->tm_mday,
292: tm->tm_hour,
293: tm->tm_min);
294: }
295:
296: /*ARGSUSED*/
297: update_ok_file (file_name)
298: char *file_name;
299: {
300: /* handle slave locking/failure stuff */
301: char *file_ok;
302: int fd;
303: static char ok[]=".dump_ok";
304:
305: if ((file_ok = (char *)malloc(strlen(file_name) + strlen(ok) + 1))
306: == NULL) {
307: fprintf(stderr, "kdb_util: out of memory.\n");
308: (void) fflush (stderr);
309: perror ("malloc");
310: exit (1);
311: }
312: strcpy(file_ok, file_name);
313: strcat(file_ok, ok);
314: if ((fd = open(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0400)) < 0) {
315: fprintf(stderr, "Error creating 'ok' file, '%s'", file_ok);
316: perror("");
317: (void) fflush (stderr);
318: exit (1);
319: }
320: free(file_ok);
321: close(fd);
322: }
323:
324: void
325: convert_key_new_master (p)
326: Principal *p;
327: {
328: des_cblock key;
329:
330: /* leave null keys alone */
331: if ((p->key_low == 0) && (p->key_high == 0)) return;
332:
333: /* move current key to des_cblock for encryption, special case master key
334: since that's changing */
335: if ((strncmp (p->name, KERB_M_NAME, ANAME_SZ) == 0) &&
336: (strncmp (p->instance, KERB_M_INST, INST_SZ) == 0)) {
337: bcopy((char *)new_master_key, (char *) key, sizeof (des_cblock));
338: (p->key_version)++;
339: } else {
340: bcopy((char *)&(p->key_low), (char *)key, 4);
341: bcopy((char *)&(p->key_high), (char *) (((long *) key) + 1), 4);
342: kdb_encrypt_key (key, key, master_key, master_key_schedule, DECRYPT);
343: }
344:
345: kdb_encrypt_key (key, key, new_master_key, new_master_key_schedule, ENCRYPT);
346:
347: bcopy((char *)key, (char *)&(p->key_low), 4);
348: bcopy((char *)(((long *) key) + 1), (char *)&(p->key_high), 4);
349: bzero((char *)key, sizeof (key)); /* a little paranoia ... */
350:
351: (p->kdc_key_ver)++;
352: }
353:
354: convert_new_master_key (db_file, out)
355: char *db_file;
356: FILE *out;
357: {
358:
359: printf ("\n\nEnter the CURRENT master key.");
360: if (kdb_get_master_key (TRUE, master_key, master_key_schedule) != 0) {
361: fprintf (stderr, "%s: Couldn't get master key.\n");
362: clear_secrets ();
363: exit (-1);
364: }
365:
366: if (kdb_verify_master_key (master_key, master_key_schedule, stderr) < 0) {
367: clear_secrets ();
368: exit (-1);
369: }
370:
371: printf ("\n\nNow enter the NEW master key. Do not forget it!!");
372: if (kdb_get_master_key (TRUE, new_master_key, new_master_key_schedule) != 0) {
373: fprintf (stderr, "%s: Couldn't get new master key.\n");
374: clear_secrets ();
375: exit (-1);
376: }
377:
378: dump_db (db_file, out, convert_key_new_master);
379: }
380:
381: void
382: convert_key_old_db (p)
383: Principal *p;
384: {
385: des_cblock key;
386:
387: /* leave null keys alone */
388: if ((p->key_low == 0) && (p->key_high == 0)) return;
389:
390: bcopy((char *)&(p->key_low), (char *)key, 4);
391: bcopy((char *)&(p->key_high), (char *)(((long *) key) + 1), 4);
392:
393: #ifndef NOENCRYPTION
394: /* get clear key, old style */
395: (void) des_pcbc_encrypt ((des_cblock *) key, (des_cblock *) key,
396: (long) sizeof(des_cblock),
397: master_key_schedule, (des_cblock *)master_key_schedule,
398: DECRYPT);
399: #endif
400:
401: /* make new key, new style */
402: kdb_encrypt_key (key, key, master_key, master_key_schedule, ENCRYPT);
403:
404: bcopy((char *)key, (char *)&(p->key_low), 4);
405: bcopy((char *)(((long *) key) + 1), (char *)&(p->key_high), 4);
406: bzero((char *)key, sizeof (key)); /* a little paranoia ... */
407: }
408:
409: convert_old_format_db (db_file, out)
410: char *db_file;
411: FILE *out;
412: {
413: des_cblock key_from_db;
414: Principal principal_data[1];
415: int n, more;
416:
417: if (kdb_get_master_key (TRUE, master_key, master_key_schedule) != 0L) {
418: fprintf (stderr, "%s: Couldn't get master key.\n");
419: clear_secrets();
420: exit (-1);
421: }
422:
423: /* can't call kdb_verify_master_key because this is an old style db */
424: /* lookup the master key version */
425: n = kerb_get_principal(KERB_M_NAME, KERB_M_INST, principal_data,
426: 1 /* only one please */, &more);
427: if ((n != 1) || more) {
428: fprintf(stderr, "verify_master_key: ",
429: "Kerberos error on master key lookup, %d found.\n",
430: n);
431: exit (-1);
432: }
433:
434: /* set up the master key */
435: fprintf(stderr, "Current Kerberos master key version is %d.\n",
436: principal_data[0].kdc_key_ver);
437:
438: /*
439: * now use the master key to decrypt (old style) the key in the db, had better
440: * be the same!
441: */
442: bcopy((char *)&principal_data[0].key_low, (char *)key_from_db, 4);
443: bcopy((char *)&principal_data[0].key_high,
444: (char *)(((long *) key_from_db) + 1), 4);
445: #ifndef NOENCRYPTION
446: (void) des_pcbc_encrypt (key_from_db, key_from_db,
447: (long) sizeof(key_from_db),
448: master_key_schedule,
449: (des_cblock *) master_key_schedule, DECRYPT);
450: #endif
451: /* the decrypted database key had better equal the master key */
452: n = bcmp((char *) master_key, (char *) key_from_db,
453: sizeof(master_key));
454: bzero((char *)key_from_db, sizeof(key_from_db));
455:
456: if (n) {
457: fprintf(stderr, "\n\07\07%verify_master_key: Invalid master key, ");
458: fprintf(stderr, "does not match database.\n");
459: exit (-1);
460: }
461:
462: fprintf(stderr, "Master key verified.\n");
463: (void) fflush(stderr);
464:
465: dump_db (db_file, out, convert_key_old_db);
466: }
467:
468: long
469: time_explode(cp)
470: register char *cp;
471: {
472: char wbuf[5];
473: struct tm tp;
474: long maketime();
475: int local;
476:
477: zaptime(&tp); /* clear out the struct */
478:
479: if (strlen(cp) > 10) { /* new format */
480: (void) strncpy(wbuf, cp, 4);
481: wbuf[4] = 0;
482: tp.tm_year = atoi(wbuf);
483: cp += 4; /* step over the year */
484: local = 0; /* GMT */
485: } else { /* old format: local time,
486: year is 2 digits, assuming 19xx */
487: wbuf[0] = *cp++;
488: wbuf[1] = *cp++;
489: wbuf[2] = 0;
490: tp.tm_year = 1900 + atoi(wbuf);
491: local = 1; /* local */
492: }
493:
494: wbuf[0] = *cp++;
495: wbuf[1] = *cp++;
496: wbuf[2] = 0;
497: tp.tm_mon = atoi(wbuf)-1;
498:
499: wbuf[0] = *cp++;
500: wbuf[1] = *cp++;
501: tp.tm_mday = atoi(wbuf);
502:
503: wbuf[0] = *cp++;
504: wbuf[1] = *cp++;
505: tp.tm_hour = atoi(wbuf);
506:
507: wbuf[0] = *cp++;
508: wbuf[1] = *cp++;
509: tp.tm_min = atoi(wbuf);
510:
511:
512: return(maketime(&tp, local));
513: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.