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