1*46731Skarels /* 2*46731Skarels * $Source: /mit/kerberos/src/admin/RCS/kdb_edit.c,v $ 3*46731Skarels * $Author: jtkohl $ 4*46731Skarels * 5*46731Skarels * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute 6*46731Skarels * of Technology. 7*46731Skarels * 8*46731Skarels * For copying and distribution information, please see the file 9*46731Skarels * <mit-copyright.h>. 10*46731Skarels * 11*46731Skarels * This routine changes the Kerberos encryption keys for principals, 12*46731Skarels * i.e., users or services. 13*46731Skarels */ 14*46731Skarels 15*46731Skarels /* 16*46731Skarels * exit returns 0 ==> success -1 ==> error 17*46731Skarels */ 18*46731Skarels 19*46731Skarels #ifndef lint 20*46731Skarels static char rcsid_kdb_edit_c[] = 21*46731Skarels "$Header: kdb_edit.c,v 4.1 89/03/23 09:58:18 jtkohl Exp $"; 22*46731Skarels #endif lint 23*46731Skarels 24*46731Skarels #include <mit-copyright.h> 25*46731Skarels 26*46731Skarels #include <stdio.h> 27*46731Skarels #include <signal.h> 28*46731Skarels #include <errno.h> 29*46731Skarels #include <strings.h> 30*46731Skarels #include <sys/ioctl.h> 31*46731Skarels #include <sys/file.h> 32*46731Skarels #include "time.h" 33*46731Skarels #include <des.h> 34*46731Skarels #include <krb.h> 35*46731Skarels #include <krb_db.h> 36*46731Skarels /* MKEYFILE is now defined in kdc.h */ 37*46731Skarels #include <kdc.h> 38*46731Skarels 39*46731Skarels extern char *errmsg(); 40*46731Skarels extern int errno; 41*46731Skarels extern char *strcpy(); 42*46731Skarels 43*46731Skarels void sig_exit(); 44*46731Skarels 45*46731Skarels char prog[32]; 46*46731Skarels char *progname = prog; 47*46731Skarels int nflag = 0; 48*46731Skarels int cflag; 49*46731Skarels int lflag; 50*46731Skarels int uflag; 51*46731Skarels int debug; 52*46731Skarels extern kerb_debug; 53*46731Skarels extern char *sys_errlist[]; 54*46731Skarels 55*46731Skarels Key_schedule KS; 56*46731Skarels C_Block new_key; 57*46731Skarels unsigned char *input; 58*46731Skarels 59*46731Skarels unsigned char *ivec; 60*46731Skarels int i, j; 61*46731Skarels int more; 62*46731Skarels 63*46731Skarels char *in_ptr; 64*46731Skarels char input_name[ANAME_SZ]; 65*46731Skarels char input_instance[INST_SZ]; 66*46731Skarels char input_string[ANAME_SZ]; 67*46731Skarels 68*46731Skarels #define MAX_PRINCIPAL 10 69*46731Skarels Principal principal_data[MAX_PRINCIPAL]; 70*46731Skarels 71*46731Skarels static Principal old_principal; 72*46731Skarels static Principal default_princ; 73*46731Skarels 74*46731Skarels static C_Block master_key; 75*46731Skarels static C_Block session_key; 76*46731Skarels static Key_schedule master_key_schedule; 77*46731Skarels static char pw_str[255]; 78*46731Skarels static long master_key_version; 79*46731Skarels 80*46731Skarels main(argc, argv) 81*46731Skarels int argc; 82*46731Skarels char *argv[]; 83*46731Skarels 84*46731Skarels { 85*46731Skarels /* Local Declarations */ 86*46731Skarels 87*46731Skarels long n; 88*46731Skarels 89*46731Skarels prog[sizeof prog - 1] = '\0'; /* make sure terminated */ 90*46731Skarels strncpy(prog, argv[0], sizeof prog - 1); /* salt away invoking 91*46731Skarels * program */ 92*46731Skarels 93*46731Skarels /* Assume a long is four bytes */ 94*46731Skarels if (sizeof(long) != 4) { 95*46731Skarels fprintf(stdout, "%s: size of long is %d.\n", sizeof(long), prog); 96*46731Skarels exit(-1); 97*46731Skarels } 98*46731Skarels /* Assume <=32 signals */ 99*46731Skarels if (NSIG > 32) { 100*46731Skarels fprintf(stderr, "%s: more than 32 signals defined.\n", prog); 101*46731Skarels exit(-1); 102*46731Skarels } 103*46731Skarels while (--argc > 0 && (*++argv)[0] == '-') 104*46731Skarels for (i = 1; argv[0][i] != '\0'; i++) { 105*46731Skarels switch (argv[0][i]) { 106*46731Skarels 107*46731Skarels /* debug flag */ 108*46731Skarels case 'd': 109*46731Skarels debug = 1; 110*46731Skarels continue; 111*46731Skarels 112*46731Skarels /* debug flag */ 113*46731Skarels case 'l': 114*46731Skarels kerb_debug |= 1; 115*46731Skarels continue; 116*46731Skarels 117*46731Skarels case 'n': /* read MKEYFILE for master key */ 118*46731Skarels nflag = 1; 119*46731Skarels continue; 120*46731Skarels 121*46731Skarels default: 122*46731Skarels fprintf(stderr, "%s: illegal flag \"%c\"\n", 123*46731Skarels progname, argv[0][i]); 124*46731Skarels Usage(); /* Give message and die */ 125*46731Skarels } 126*46731Skarels }; 127*46731Skarels 128*46731Skarels fprintf(stdout, "Opening database...\n"); 129*46731Skarels fflush(stdout); 130*46731Skarels kerb_init(); 131*46731Skarels if (argc > 0) { 132*46731Skarels if (kerb_db_set_name(*argv) != 0) { 133*46731Skarels fprintf(stderr, "Could not open altername database name\n"); 134*46731Skarels exit(1); 135*46731Skarels } 136*46731Skarels } 137*46731Skarels 138*46731Skarels #ifdef notdef 139*46731Skarels no_core_dumps(); /* diddle signals to avoid core dumps! */ 140*46731Skarels 141*46731Skarels /* ignore whatever is reasonable */ 142*46731Skarels signal(SIGHUP, SIG_IGN); 143*46731Skarels signal(SIGINT, SIG_IGN); 144*46731Skarels signal(SIGTSTP, SIG_IGN); 145*46731Skarels 146*46731Skarels #endif 147*46731Skarels 148*46731Skarels if (kdb_get_master_key ((nflag == 0), 149*46731Skarels master_key, master_key_schedule) != 0) { 150*46731Skarels fprintf (stdout, "Couldn't read master key.\n"); 151*46731Skarels fflush (stdout); 152*46731Skarels exit (-1); 153*46731Skarels } 154*46731Skarels 155*46731Skarels if ((master_key_version = kdb_verify_master_key(master_key, 156*46731Skarels master_key_schedule, 157*46731Skarels stdout)) < 0) 158*46731Skarels exit (-1); 159*46731Skarels 160*46731Skarels /* lookup the default values */ 161*46731Skarels n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, 162*46731Skarels &default_princ, 1, &more); 163*46731Skarels if (n != 1) { 164*46731Skarels fprintf(stderr, 165*46731Skarels "%s: Kerberos error on default value lookup, %d found.\n", 166*46731Skarels progname, n); 167*46731Skarels exit(-1); 168*46731Skarels } 169*46731Skarels fprintf(stdout, "Previous or default values are in [brackets] ,\n"); 170*46731Skarels fprintf(stdout, "enter return to leave the same, or new value.\n"); 171*46731Skarels 172*46731Skarels while (change_principal()) { 173*46731Skarels } 174*46731Skarels 175*46731Skarels cleanup(); 176*46731Skarels } 177*46731Skarels 178*46731Skarels change_principal() 179*46731Skarels { 180*46731Skarels static char temp[255]; 181*46731Skarels int creating = 0; 182*46731Skarels int editpw = 0; 183*46731Skarels int changed = 0; 184*46731Skarels long temp_long; 185*46731Skarels int n; 186*46731Skarels struct tm *tp, edate, *localtime(); 187*46731Skarels long maketime(); 188*46731Skarels 189*46731Skarels fprintf(stdout, "\nPrincipal name: "); 190*46731Skarels fflush(stdout); 191*46731Skarels if (!gets(input_name) || *input_name == '\0') 192*46731Skarels return 0; 193*46731Skarels fprintf(stdout, "Instance: "); 194*46731Skarels fflush(stdout); 195*46731Skarels /* instance can be null */ 196*46731Skarels gets(input_instance); 197*46731Skarels j = kerb_get_principal(input_name, input_instance, principal_data, 198*46731Skarels MAX_PRINCIPAL, &more); 199*46731Skarels if (!j) { 200*46731Skarels fprintf(stdout, "\n\07\07<Not found>, Create [y] ? "); 201*46731Skarels gets(temp); /* Default case should work, it didn't */ 202*46731Skarels if (temp[0] != 'y' && temp[0] != 'Y' && temp[0] != '\0') 203*46731Skarels return -1; 204*46731Skarels /* make a new principal, fill in defaults */ 205*46731Skarels j = 1; 206*46731Skarels creating = 1; 207*46731Skarels strcpy(principal_data[0].name, input_name); 208*46731Skarels strcpy(principal_data[0].instance, input_instance); 209*46731Skarels principal_data[0].old = NULL; 210*46731Skarels principal_data[0].exp_date = default_princ.exp_date; 211*46731Skarels principal_data[0].max_life = default_princ.max_life; 212*46731Skarels principal_data[0].attributes = default_princ.attributes; 213*46731Skarels principal_data[0].kdc_key_ver = (unsigned char) master_key_version; 214*46731Skarels principal_data[0].key_version = 0; /* bumped up later */ 215*46731Skarels } 216*46731Skarels tp = localtime(&principal_data[0].exp_date); 217*46731Skarels (void) sprintf(principal_data[0].exp_date_txt, "%4d-%02d-%02d", 218*46731Skarels tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900, 219*46731Skarels tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */ 220*46731Skarels for (i = 0; i < j; i++) { 221*46731Skarels for (;;) { 222*46731Skarels fprintf(stdout, 223*46731Skarels "\nPrincipal: %s, Instance: %s, kdc_key_ver: %d", 224*46731Skarels principal_data[i].name, principal_data[i].instance, 225*46731Skarels principal_data[i].kdc_key_ver); 226*46731Skarels editpw = 1; 227*46731Skarels changed = 0; 228*46731Skarels if (!creating) { 229*46731Skarels /* 230*46731Skarels * copy the existing data so we can use the old values 231*46731Skarels * for the qualifier clause of the replace 232*46731Skarels */ 233*46731Skarels principal_data[i].old = (char *) &old_principal; 234*46731Skarels bcopy(&principal_data[i], &old_principal, 235*46731Skarels sizeof(old_principal)); 236*46731Skarels printf("\nChange password [n] ? "); 237*46731Skarels gets(temp); 238*46731Skarels if (strcmp("y", temp) && strcmp("Y", temp)) 239*46731Skarels editpw = 0; 240*46731Skarels } 241*46731Skarels /* password */ 242*46731Skarels if (editpw) { 243*46731Skarels #ifdef NOENCRYPTION 244*46731Skarels placebo_read_pw_string(pw_str, sizeof pw_str, 245*46731Skarels "\nNew Password: ", TRUE); 246*46731Skarels #else 247*46731Skarels des_read_pw_string(pw_str, sizeof pw_str, 248*46731Skarels "\nNew Password: ", TRUE); 249*46731Skarels #endif 250*46731Skarels if (!strcmp(pw_str, "RANDOM")) { 251*46731Skarels printf("\nRandom password [y] ? "); 252*46731Skarels gets(temp); 253*46731Skarels if (!strcmp("n", temp) || !strcmp("N", temp)) { 254*46731Skarels /* no, use literal */ 255*46731Skarels #ifdef NOENCRYPTION 256*46731Skarels bzero(new_key, sizeof(C_Block)); 257*46731Skarels new_key[0] = 127; 258*46731Skarels #else 259*46731Skarels string_to_key(pw_str, new_key); 260*46731Skarels #endif 261*46731Skarels bzero(pw_str, sizeof pw_str); /* "RANDOM" */ 262*46731Skarels } else { 263*46731Skarels #ifdef NOENCRYPTION 264*46731Skarels bzero(new_key, sizeof(C_Block)); 265*46731Skarels new_key[0] = 127; 266*46731Skarels #else 267*46731Skarels random_key(new_key); /* yes, random */ 268*46731Skarels #endif 269*46731Skarels bzero(pw_str, sizeof pw_str); 270*46731Skarels } 271*46731Skarels } else if (!strcmp(pw_str, "NULL")) { 272*46731Skarels printf("\nNull Key [y] ? "); 273*46731Skarels gets(temp); 274*46731Skarels if (!strcmp("n", temp) || !strcmp("N", temp)) { 275*46731Skarels /* no, use literal */ 276*46731Skarels #ifdef NOENCRYPTION 277*46731Skarels bzero(new_key, sizeof(C_Block)); 278*46731Skarels new_key[0] = 127; 279*46731Skarels #else 280*46731Skarels string_to_key(pw_str, new_key); 281*46731Skarels #endif 282*46731Skarels bzero(pw_str, sizeof pw_str); /* "NULL" */ 283*46731Skarels } else { 284*46731Skarels 285*46731Skarels principal_data[i].key_low = 0; 286*46731Skarels principal_data[i].key_high = 0; 287*46731Skarels goto null_key; 288*46731Skarels } 289*46731Skarels } else { 290*46731Skarels #ifdef NOENCRYPTION 291*46731Skarels bzero(new_key, sizeof(C_Block)); 292*46731Skarels new_key[0] = 127; 293*46731Skarels #else 294*46731Skarels string_to_key(pw_str, new_key); 295*46731Skarels #endif 296*46731Skarels bzero(pw_str, sizeof pw_str); 297*46731Skarels } 298*46731Skarels 299*46731Skarels /* seal it under the kerberos master key */ 300*46731Skarels kdb_encrypt_key (new_key, new_key, 301*46731Skarels master_key, master_key_schedule, 302*46731Skarels ENCRYPT); 303*46731Skarels bcopy(new_key, &principal_data[i].key_low, 4); 304*46731Skarels bcopy(((long *) new_key) + 1, 305*46731Skarels &principal_data[i].key_high, 4); 306*46731Skarels bzero(new_key, sizeof(new_key)); 307*46731Skarels null_key: 308*46731Skarels /* set master key version */ 309*46731Skarels principal_data[i].kdc_key_ver = 310*46731Skarels (unsigned char) master_key_version; 311*46731Skarels /* bump key version # */ 312*46731Skarels principal_data[i].key_version++; 313*46731Skarels fprintf(stdout, 314*46731Skarels "\nPrincipal's new key version = %d\n", 315*46731Skarels principal_data[i].key_version); 316*46731Skarels fflush(stdout); 317*46731Skarels changed = 1; 318*46731Skarels } 319*46731Skarels /* expiration date */ 320*46731Skarels fprintf(stdout, "Expiration date (enter yyyy-mm-dd) [ %s ] ? ", 321*46731Skarels principal_data[i].exp_date_txt); 322*46731Skarels zaptime(&edate); 323*46731Skarels while (gets(temp) && ((n = strlen(temp)) > 324*46731Skarels sizeof(principal_data[0].exp_date_txt))) { 325*46731Skarels bad_date: 326*46731Skarels fprintf(stdout, "\07\07Date Invalid\n"); 327*46731Skarels fprintf(stdout, 328*46731Skarels "Expiration date (enter yyyy-mm-dd) [ %s ] ? ", 329*46731Skarels principal_data[i].exp_date_txt); 330*46731Skarels zaptime(&edate); 331*46731Skarels } 332*46731Skarels 333*46731Skarels if (*temp) { 334*46731Skarels if (sscanf(temp, "%d-%d-%d", &edate.tm_year, 335*46731Skarels &edate.tm_mon, &edate.tm_mday) != 3) 336*46731Skarels goto bad_date; 337*46731Skarels (void) strcpy(principal_data[i].exp_date_txt, temp); 338*46731Skarels edate.tm_mon--; /* January is 0, not 1 */ 339*46731Skarels edate.tm_hour = 23; /* nearly midnight at the end of the */ 340*46731Skarels edate.tm_min = 59; /* specified day */ 341*46731Skarels edate.tm_zon = 1; /* local time, not GMT */ 342*46731Skarels if (!(principal_data[i].exp_date = maketime(&edate))) 343*46731Skarels goto bad_date; 344*46731Skarels changed = 1; 345*46731Skarels } 346*46731Skarels 347*46731Skarels /* maximum lifetime */ 348*46731Skarels fprintf(stdout, "Max ticket lifetime (*5 minutes) [ %d ] ? ", 349*46731Skarels principal_data[i].max_life); 350*46731Skarels while (gets(temp) && *temp) { 351*46731Skarels if (sscanf(temp, "%d", &temp_long) != 1) 352*46731Skarels goto bad_life; 353*46731Skarels if (temp_long > 255 || (temp_long < 0)) { 354*46731Skarels bad_life: 355*46731Skarels fprintf(stdout, "\07\07Invalid, choose 0-255\n"); 356*46731Skarels fprintf(stdout, 357*46731Skarels "Max ticket lifetime (*5 minutes) [ %d ] ? ", 358*46731Skarels principal_data[i].max_life); 359*46731Skarels continue; 360*46731Skarels } 361*46731Skarels changed = 1; 362*46731Skarels /* dont clobber */ 363*46731Skarels principal_data[i].max_life = (unsigned short) temp_long; 364*46731Skarels break; 365*46731Skarels } 366*46731Skarels 367*46731Skarels /* attributes */ 368*46731Skarels fprintf(stdout, "Attributes [ %d ] ? ", 369*46731Skarels principal_data[i].attributes); 370*46731Skarels while (gets(temp) && *temp) { 371*46731Skarels if (sscanf(temp, "%d", &temp_long) != 1) 372*46731Skarels goto bad_att; 373*46731Skarels if (temp_long > 65535 || (temp_long < 0)) { 374*46731Skarels bad_att: 375*46731Skarels fprintf(stdout, "\07\07Invalid, choose 0-65535\n"); 376*46731Skarels fprintf(stdout, "Attributes [ %d ] ? ", 377*46731Skarels principal_data[i].attributes); 378*46731Skarels continue; 379*46731Skarels } 380*46731Skarels changed = 1; 381*46731Skarels /* dont clobber */ 382*46731Skarels principal_data[i].attributes = 383*46731Skarels (unsigned short) temp_long; 384*46731Skarels break; 385*46731Skarels } 386*46731Skarels 387*46731Skarels /* 388*46731Skarels * remaining fields -- key versions and mod info, should 389*46731Skarels * not be directly manipulated 390*46731Skarels */ 391*46731Skarels if (changed) { 392*46731Skarels if (kerb_put_principal(&principal_data[i], 1)) { 393*46731Skarels fprintf(stdout, 394*46731Skarels "\nError updating Kerberos database"); 395*46731Skarels } else { 396*46731Skarels fprintf(stdout, "Edit O.K."); 397*46731Skarels } 398*46731Skarels } else { 399*46731Skarels fprintf(stdout, "Unchanged"); 400*46731Skarels } 401*46731Skarels 402*46731Skarels 403*46731Skarels bzero(&principal_data[i].key_low, 4); 404*46731Skarels bzero(&principal_data[i].key_high, 4); 405*46731Skarels fflush(stdout); 406*46731Skarels break; 407*46731Skarels } 408*46731Skarels } 409*46731Skarels if (more) { 410*46731Skarels fprintf(stdout, "\nThere were more tuples found "); 411*46731Skarels fprintf(stdout, "than there were space for"); 412*46731Skarels } 413*46731Skarels return 1; 414*46731Skarels } 415*46731Skarels 416*46731Skarels 417*46731Skarels no_core_dumps() 418*46731Skarels { 419*46731Skarels 420*46731Skarels signal(SIGQUIT, sig_exit); 421*46731Skarels signal(SIGILL, sig_exit); 422*46731Skarels signal(SIGTRAP, sig_exit); 423*46731Skarels signal(SIGIOT, sig_exit); 424*46731Skarels signal(SIGEMT, sig_exit); 425*46731Skarels signal(SIGFPE, sig_exit); 426*46731Skarels signal(SIGBUS, sig_exit); 427*46731Skarels signal(SIGSEGV, sig_exit); 428*46731Skarels signal(SIGSYS, sig_exit); 429*46731Skarels } 430*46731Skarels 431*46731Skarels void 432*46731Skarels sig_exit(sig, code, scp) 433*46731Skarels int sig, code; 434*46731Skarels struct sigcontext *scp; 435*46731Skarels { 436*46731Skarels cleanup(); 437*46731Skarels fprintf(stderr, 438*46731Skarels "\nSignal caught, sig = %d code = %d old pc = 0x%X \nexiting", 439*46731Skarels sig, code, scp->sc_pc); 440*46731Skarels exit(-1); 441*46731Skarels } 442*46731Skarels 443*46731Skarels 444*46731Skarels cleanup() 445*46731Skarels { 446*46731Skarels 447*46731Skarels bzero(master_key, sizeof(master_key)); 448*46731Skarels bzero(session_key, sizeof(session_key)); 449*46731Skarels bzero(master_key_schedule, sizeof(master_key_schedule)); 450*46731Skarels bzero(principal_data, sizeof(principal_data)); 451*46731Skarels bzero(new_key, sizeof(new_key)); 452*46731Skarels bzero(pw_str, sizeof(pw_str)); 453*46731Skarels } 454*46731Skarels Usage() 455*46731Skarels { 456*46731Skarels fprintf(stderr, "Usage: %s [-n]\n", progname); 457*46731Skarels exit(1); 458*46731Skarels } 459*46731Skarels 460*46731Skarels /* zaptime code taken from: */ 461*46731Skarels /* 462*46731Skarels * PARTIME parse date/time string into a TM structure 463*46731Skarels * 464*46731Skarels * Usage: 465*46731Skarels * #include "time.h" -- expanded tm structure 466*46731Skarels * char *str; struct tm *tp; 467*46731Skarels * partime(str,tp); 468*46731Skarels * Returns: 469*46731Skarels * 0 if parsing failed 470*46731Skarels * else time values in specified TM structure (unspecified values 471*46731Skarels * set to TMNULL) 472*46731Skarels * Notes: 473*46731Skarels * This code is quasi-public; it may be used freely in like software. 474*46731Skarels * It is not to be sold, nor used in licensed software without 475*46731Skarels * permission of the author. 476*46731Skarels * For everyone's benefit, please report bugs and improvements! 477*46731Skarels * Copyright 1980 by Ken Harrenstien, SRI International. 478*46731Skarels * (ARPANET: KLH @ SRI) 479*46731Skarels */ 480*46731Skarels 481*46731Skarels zaptime(atm) 482*46731Skarels register struct tm *atm; 483*46731Skarels /* clears atm */ 484*46731Skarels { 485*46731Skarels atm->tm_sec = TMNULL; 486*46731Skarels atm->tm_min = TMNULL; 487*46731Skarels atm->tm_hour = TMNULL; 488*46731Skarels atm->tm_mday = TMNULL; 489*46731Skarels atm->tm_mon = TMNULL; 490*46731Skarels atm->tm_year = TMNULL; 491*46731Skarels atm->tm_wday = TMNULL; 492*46731Skarels atm->tm_yday = TMNULL; 493*46731Skarels atm->tm_isdst = TMNULL; 494*46731Skarels atm->tm_zon = TMNULL; 495*46731Skarels atm->tm_ampm = TMNULL; 496*46731Skarels } 497