|
|
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.