1 | /* |
---|
2 | * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute |
---|
3 | * of Technology. |
---|
4 | * |
---|
5 | * For copying and distribution information, please see the file |
---|
6 | * <mit-copyright.h>. |
---|
7 | * |
---|
8 | * This routine changes the Kerberos encryption keys for principals, |
---|
9 | * i.e., users or services. |
---|
10 | */ |
---|
11 | |
---|
12 | /* |
---|
13 | * exit returns 0 ==> success -1 ==> error |
---|
14 | */ |
---|
15 | |
---|
16 | #include <mit-copyright.h> |
---|
17 | |
---|
18 | #include <stdio.h> |
---|
19 | #include <signal.h> |
---|
20 | #include <errno.h> |
---|
21 | #include <string.h> |
---|
22 | #include <sys/types.h> |
---|
23 | #include <sys/ioctl.h> |
---|
24 | #include <sys/file.h> |
---|
25 | |
---|
26 | #ifdef NEED_TIME_H |
---|
27 | #include <time.h> |
---|
28 | #endif |
---|
29 | #include <sys/time.h> |
---|
30 | |
---|
31 | #include <des.h> |
---|
32 | #include <krb.h> |
---|
33 | #include <krb_db.h> |
---|
34 | /* MKEYFILE is now defined in kdc.h */ |
---|
35 | #include <kdc.h> |
---|
36 | |
---|
37 | extern char *errmsg(); |
---|
38 | extern int errno; |
---|
39 | extern char *optarg; |
---|
40 | extern int optind; |
---|
41 | |
---|
42 | void sig_exit(); |
---|
43 | |
---|
44 | #define zaptime(foo) memset((char *)(foo), 0, sizeof(*(foo))) |
---|
45 | |
---|
46 | char prog[32]; |
---|
47 | char *progname = prog; |
---|
48 | int nflag = 0; |
---|
49 | int cflag; |
---|
50 | int lflag; |
---|
51 | int uflag; |
---|
52 | int debug; |
---|
53 | extern krb_debug; |
---|
54 | #ifndef HAVE_SYS_ERRLIST_DECL |
---|
55 | extern char *sys_errlist[]; |
---|
56 | #endif |
---|
57 | |
---|
58 | Key_schedule KS; |
---|
59 | C_Block new_key; |
---|
60 | unsigned char *input; |
---|
61 | |
---|
62 | unsigned char *ivec; |
---|
63 | int i, j; |
---|
64 | int more; |
---|
65 | |
---|
66 | char *in_ptr; |
---|
67 | char input_name[ANAME_SZ]; |
---|
68 | char input_instance[INST_SZ]; |
---|
69 | char input_string[ANAME_SZ]; |
---|
70 | |
---|
71 | #define MAX_PRINCIPAL 10 |
---|
72 | Principal principal_data[MAX_PRINCIPAL]; |
---|
73 | |
---|
74 | static Principal old_principal; |
---|
75 | static Principal default_princ; |
---|
76 | |
---|
77 | static C_Block master_key; |
---|
78 | static C_Block session_key; |
---|
79 | static Key_schedule master_key_schedule; |
---|
80 | static char pw_str[255]; |
---|
81 | static long master_key_version; |
---|
82 | static char *mkeyfile = NULL; |
---|
83 | |
---|
84 | main(argc, argv) |
---|
85 | int argc; |
---|
86 | char *argv[]; |
---|
87 | |
---|
88 | { |
---|
89 | /* Local Declarations */ |
---|
90 | |
---|
91 | int opt; |
---|
92 | long n; |
---|
93 | |
---|
94 | prog[sizeof prog - 1] = '\0'; /* make sure terminated */ |
---|
95 | strncpy(prog, argv[0], sizeof prog - 1); /* salt away invoking |
---|
96 | * program */ |
---|
97 | |
---|
98 | /* Assume a long is four bytes */ |
---|
99 | if (sizeof(KRB_INT32) != 4) { |
---|
100 | fprintf(stdout, "%s: size of long is %d.\n", prog, sizeof(KRB_INT32)); |
---|
101 | exit(-1); |
---|
102 | } |
---|
103 | |
---|
104 | #if 0 |
---|
105 | /* This code has been here for years, but I do not know why. */ |
---|
106 | /* Assume <=32 signals */ |
---|
107 | if (NSIG > 32) { |
---|
108 | fprintf(stderr, "%s: warning: more than 32 signals defined.\n", prog); |
---|
109 | } |
---|
110 | #endif |
---|
111 | |
---|
112 | while ((opt = getopt (argc, argv, "dk:ln")) != EOF) { |
---|
113 | switch (opt) { |
---|
114 | case 'd': |
---|
115 | /* debug flag */ |
---|
116 | debug = 1; |
---|
117 | break; |
---|
118 | |
---|
119 | case 'l': |
---|
120 | /* debug flag */ |
---|
121 | krb_debug |= 1; |
---|
122 | break; |
---|
123 | |
---|
124 | case 'n': |
---|
125 | /* read MKEYFILE for master key. */ |
---|
126 | nflag = 1; |
---|
127 | break; |
---|
128 | |
---|
129 | case 'k': |
---|
130 | /* read named file for master key. */ |
---|
131 | nflag = 1; |
---|
132 | mkeyfile = optarg; |
---|
133 | break; |
---|
134 | |
---|
135 | default: |
---|
136 | Usage(); /* Give message and die */ |
---|
137 | } |
---|
138 | } |
---|
139 | |
---|
140 | fprintf(stdout, "Opening database...\n"); |
---|
141 | fflush(stdout); |
---|
142 | kerb_init(); |
---|
143 | if (optind < argc) { |
---|
144 | if (kerb_db_set_name(argv[optind]) != 0) { |
---|
145 | fprintf(stderr, "Could not open altername database name\n"); |
---|
146 | exit(1); |
---|
147 | } |
---|
148 | } |
---|
149 | |
---|
150 | #ifdef notdef |
---|
151 | no_core_dumps(); /* diddle signals to avoid core dumps! */ |
---|
152 | |
---|
153 | /* ignore whatever is reasonable */ |
---|
154 | signal(SIGHUP, SIG_IGN); |
---|
155 | signal(SIGINT, SIG_IGN); |
---|
156 | signal(SIGTSTP, SIG_IGN); |
---|
157 | |
---|
158 | #endif |
---|
159 | |
---|
160 | if (kdb_get_master_key_from ((nflag == 0), |
---|
161 | master_key, master_key_schedule, 0, |
---|
162 | mkeyfile) != 0) { |
---|
163 | fprintf (stdout, "Couldn't read master key.\n"); |
---|
164 | fflush (stdout); |
---|
165 | exit (-1); |
---|
166 | } |
---|
167 | |
---|
168 | if ((master_key_version = kdb_verify_master_key(master_key, |
---|
169 | master_key_schedule, |
---|
170 | stdout)) < 0) |
---|
171 | exit (-1); |
---|
172 | |
---|
173 | des_init_random_number_generator(master_key); |
---|
174 | |
---|
175 | /* lookup the default values */ |
---|
176 | n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, |
---|
177 | &default_princ, 1, &more); |
---|
178 | if (n != 1) { |
---|
179 | fprintf(stderr, |
---|
180 | "%s: Kerberos error on default value lookup, %d found.\n", |
---|
181 | progname, n); |
---|
182 | exit(-1); |
---|
183 | } |
---|
184 | fprintf(stdout, "Previous or default values are in [brackets] ,\n"); |
---|
185 | fprintf(stdout, "enter return to leave the same, or new value.\n"); |
---|
186 | |
---|
187 | while (change_principal()) { |
---|
188 | } |
---|
189 | |
---|
190 | cleanup(); |
---|
191 | exit(0); |
---|
192 | } |
---|
193 | |
---|
194 | change_principal() |
---|
195 | { |
---|
196 | static char temp[255]; |
---|
197 | int creating = 0; |
---|
198 | int editpw = 0; |
---|
199 | int changed = 0; |
---|
200 | int temp_int; |
---|
201 | int n; |
---|
202 | time_t exp_date; |
---|
203 | struct tm *tp, edate, *localtime(); |
---|
204 | long maketime(); |
---|
205 | |
---|
206 | fprintf(stdout, "\nPrincipal name: "); |
---|
207 | fflush(stdout); |
---|
208 | if (!gets(input_name) || *input_name == '\0') |
---|
209 | return 0; |
---|
210 | fprintf(stdout, "Instance: "); |
---|
211 | fflush(stdout); |
---|
212 | /* instance can be null */ |
---|
213 | gets(input_instance); |
---|
214 | j = kerb_get_principal(input_name, input_instance, principal_data, |
---|
215 | MAX_PRINCIPAL, &more); |
---|
216 | if (!j) { |
---|
217 | fprintf(stdout, "\n\07\07<Not found>, Create [y] ? "); |
---|
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 | exp_date = principal_data[0].exp_date; |
---|
234 | tp = localtime(&exp_date); |
---|
235 | (void) sprintf(principal_data[0].exp_date_txt, "%4d-%02d-%02d", |
---|
236 | tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900, |
---|
237 | tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */ |
---|
238 | for (i = 0; i < j; i++) { |
---|
239 | for (;;) { |
---|
240 | fprintf(stdout, |
---|
241 | "\nPrincipal: %s, Instance: %s, kdc_key_ver: %d", |
---|
242 | principal_data[i].name, principal_data[i].instance, |
---|
243 | principal_data[i].kdc_key_ver); |
---|
244 | editpw = 1; |
---|
245 | changed = 0; |
---|
246 | if (!creating) { |
---|
247 | /* |
---|
248 | * copy the existing data so we can use the old values |
---|
249 | * for the qualifier clause of the replace |
---|
250 | */ |
---|
251 | principal_data[i].old = (char *) &old_principal; |
---|
252 | memcpy(&old_principal, &principal_data[i], |
---|
253 | sizeof(old_principal)); |
---|
254 | printf("\nChange password [n] ? "); |
---|
255 | gets(temp); |
---|
256 | if (strcmp("y", temp) && strcmp("Y", temp)) |
---|
257 | editpw = 0; |
---|
258 | } |
---|
259 | /* password */ |
---|
260 | if (editpw) { |
---|
261 | #ifdef NOENCRYPTION |
---|
262 | placebo_read_pw_string(pw_str, sizeof pw_str, |
---|
263 | "\nNew Password: ", TRUE); |
---|
264 | #else |
---|
265 | des_read_pw_string(pw_str, sizeof pw_str, |
---|
266 | "\nNew Password: ", TRUE); |
---|
267 | #endif |
---|
268 | if (!strcmp(pw_str, "RANDOM")) { |
---|
269 | printf("\nRandom password [y] ? "); |
---|
270 | gets(temp); |
---|
271 | if (!strcmp("n", temp) || !strcmp("N", temp)) { |
---|
272 | /* no, use literal */ |
---|
273 | #ifdef NOENCRYPTION |
---|
274 | memset(new_key, 0, sizeof(C_Block)); |
---|
275 | new_key[0] = 127; |
---|
276 | #else |
---|
277 | string_to_key(pw_str, new_key); |
---|
278 | #endif |
---|
279 | memset(pw_str, 0, sizeof pw_str); /* "RANDOM" */ |
---|
280 | } else { |
---|
281 | #ifdef NOENCRYPTION |
---|
282 | memset(new_key, 0, sizeof(C_Block)); |
---|
283 | new_key[0] = 127; |
---|
284 | #else |
---|
285 | des_new_random_key(new_key); /* yes, random */ |
---|
286 | #endif |
---|
287 | memset(pw_str, 0, sizeof pw_str); |
---|
288 | } |
---|
289 | } else if (!strcmp(pw_str, "NULL")) { |
---|
290 | printf("\nNull Key [y] ? "); |
---|
291 | gets(temp); |
---|
292 | if (!strcmp("n", temp) || !strcmp("N", temp)) { |
---|
293 | /* no, use literal */ |
---|
294 | #ifdef NOENCRYPTION |
---|
295 | memset(new_key, 0, sizeof(C_Block)); |
---|
296 | new_key[0] = 127; |
---|
297 | #else |
---|
298 | string_to_key(pw_str, new_key); |
---|
299 | #endif |
---|
300 | memset(pw_str, 0, sizeof pw_str); /* "NULL" */ |
---|
301 | } else { |
---|
302 | |
---|
303 | principal_data[i].key_low = 0; |
---|
304 | principal_data[i].key_high = 0; |
---|
305 | goto null_key; |
---|
306 | } |
---|
307 | } else { |
---|
308 | #ifdef NOENCRYPTION |
---|
309 | memset(new_key, 0, sizeof(C_Block)); |
---|
310 | new_key[0] = 127; |
---|
311 | #else |
---|
312 | string_to_key(pw_str, new_key); |
---|
313 | #endif |
---|
314 | memset(pw_str, 0, sizeof pw_str); |
---|
315 | } |
---|
316 | |
---|
317 | /* seal it under the kerberos master key */ |
---|
318 | kdb_encrypt_key (new_key, new_key, |
---|
319 | master_key, master_key_schedule, |
---|
320 | ENCRYPT); |
---|
321 | memcpy(&principal_data[i].key_low, new_key, sizeof(KRB_INT32)); |
---|
322 | memcpy(&principal_data[i].key_high, ((KRB_INT32 *) new_key) + 1, sizeof(KRB_INT32)); |
---|
323 | memset(new_key, 0, 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 | if (!(principal_data[i].exp_date = maketime(&edate, 1))) |
---|
359 | goto bad_date; |
---|
360 | changed = 1; |
---|
361 | } |
---|
362 | |
---|
363 | /* maximum lifetime */ |
---|
364 | fprintf(stdout, "Max ticket lifetime (*5 minutes) [ %d ] ? ", |
---|
365 | principal_data[i].max_life); |
---|
366 | while (gets(temp) && *temp) { |
---|
367 | if (sscanf(temp, "%d", &temp_int) != 1) |
---|
368 | goto bad_life; |
---|
369 | if (temp_int > 255 || (temp_int < 0)) { |
---|
370 | bad_life: |
---|
371 | fprintf(stdout, "\07\07Invalid, choose 0-255\n"); |
---|
372 | fprintf(stdout, |
---|
373 | "Max ticket lifetime (*5 minutes) [ %d ] ? ", |
---|
374 | principal_data[i].max_life); |
---|
375 | continue; |
---|
376 | } |
---|
377 | changed = 1; |
---|
378 | /* dont clobber */ |
---|
379 | principal_data[i].max_life = (unsigned short) temp_int; |
---|
380 | break; |
---|
381 | } |
---|
382 | |
---|
383 | /* attributes */ |
---|
384 | fprintf(stdout, "Attributes [ %d ] ? ", |
---|
385 | principal_data[i].attributes); |
---|
386 | while (gets(temp) && *temp) { |
---|
387 | if (sscanf(temp, "%d", &temp_int) != 1) |
---|
388 | goto bad_att; |
---|
389 | if (temp_int > 65535 || (temp_int < 0)) { |
---|
390 | bad_att: |
---|
391 | fprintf(stdout, "\07\07Invalid, choose 0-65535\n"); |
---|
392 | fprintf(stdout, "Attributes [ %d ] ? ", |
---|
393 | principal_data[i].attributes); |
---|
394 | continue; |
---|
395 | } |
---|
396 | changed = 1; |
---|
397 | /* dont clobber */ |
---|
398 | principal_data[i].attributes = |
---|
399 | (unsigned short) temp_int; |
---|
400 | break; |
---|
401 | } |
---|
402 | |
---|
403 | /* |
---|
404 | * remaining fields -- key versions and mod info, should |
---|
405 | * not be directly manipulated |
---|
406 | */ |
---|
407 | if (changed) { |
---|
408 | if (kerb_put_principal(&principal_data[i], 1)) { |
---|
409 | fprintf(stdout, |
---|
410 | "\nError updating Kerberos database"); |
---|
411 | } else { |
---|
412 | fprintf(stdout, "Edit O.K."); |
---|
413 | } |
---|
414 | } else { |
---|
415 | fprintf(stdout, "Unchanged"); |
---|
416 | } |
---|
417 | |
---|
418 | |
---|
419 | memset(&principal_data[i].key_low, 0, 4); |
---|
420 | memset(&principal_data[i].key_high, 0, 4); |
---|
421 | fflush(stdout); |
---|
422 | break; |
---|
423 | } |
---|
424 | } |
---|
425 | if (more) { |
---|
426 | fprintf(stdout, "\nThere were more tuples found "); |
---|
427 | fprintf(stdout, "than there were space for"); |
---|
428 | } |
---|
429 | return 1; |
---|
430 | } |
---|
431 | |
---|
432 | |
---|
433 | no_core_dumps() |
---|
434 | { |
---|
435 | |
---|
436 | signal(SIGQUIT, sig_exit); |
---|
437 | signal(SIGILL, sig_exit); |
---|
438 | signal(SIGTRAP, sig_exit); |
---|
439 | signal(SIGIOT, sig_exit); |
---|
440 | #ifdef SIGEMT |
---|
441 | signal(SIGEMT, sig_exit); |
---|
442 | #endif |
---|
443 | signal(SIGFPE, sig_exit); |
---|
444 | #ifdef SIGBUS |
---|
445 | signal(SIGBUS, sig_exit); |
---|
446 | #endif |
---|
447 | signal(SIGSEGV, sig_exit); |
---|
448 | #ifdef SIGSYS |
---|
449 | signal(SIGSYS, sig_exit); |
---|
450 | #endif |
---|
451 | } |
---|
452 | |
---|
453 | void |
---|
454 | sig_exit(sig, code, scp) |
---|
455 | int sig, code; |
---|
456 | struct sigcontext *scp; |
---|
457 | { |
---|
458 | cleanup(); |
---|
459 | |
---|
460 | #if defined(_AIX) |
---|
461 | #if defined(i386) |
---|
462 | fprintf(stderr, "\nSignal caught, sig = %d code = %d\nexiting", sig, code); |
---|
463 | #else |
---|
464 | fprintf(stderr, |
---|
465 | "\nSignal caught, sig = %d code = %d old pc = 0x%X \nexiting", |
---|
466 | sig, code, scp->sc_jmpbuf.jmp_context.iar); |
---|
467 | #endif |
---|
468 | #else /* !_AIX */ |
---|
469 | #ifdef NO_SIGCONTEXT |
---|
470 | fprintf(stderr, |
---|
471 | "\nSignal caught, sig = %d code = %d \nexiting", |
---|
472 | sig, code); |
---|
473 | #else |
---|
474 | fprintf(stderr, |
---|
475 | "\nSignal caught, sig = %d code = %d old pc = 0x%X \nexiting", |
---|
476 | sig, code, scp->sc_pc); |
---|
477 | #endif |
---|
478 | #endif |
---|
479 | exit(-1); |
---|
480 | } |
---|
481 | |
---|
482 | |
---|
483 | cleanup() |
---|
484 | { |
---|
485 | |
---|
486 | memset(master_key, 0, sizeof(master_key)); |
---|
487 | memset(session_key, 0, sizeof(session_key)); |
---|
488 | memset(master_key_schedule, 0, sizeof(master_key_schedule)); |
---|
489 | memset(principal_data, 0, sizeof(principal_data)); |
---|
490 | memset(new_key, 0, sizeof(new_key)); |
---|
491 | memset(pw_str, 0, sizeof(pw_str)); |
---|
492 | } |
---|
493 | Usage() |
---|
494 | { |
---|
495 | fprintf(stderr, |
---|
496 | "Usage: %s [-n] [-k mkeyfile] [database_pathname]\n", |
---|
497 | progname); |
---|
498 | exit(1); |
---|
499 | } |
---|