Annotation of 43BSDReno/kerberosIV/kdb_util/kdb_util.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.