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