home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / kerberosIV / kdb_util / kdb_util.c next >
Encoding:
C/C++ Source or Header  |  1991-03-07  |  13.3 KB  |  514 lines

  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 Locker: bostic $";
  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. }
  514.