Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / crypto / kerberosIV / kadmin / ksrvutil.c
CommitLineData
984263bc
MD
1/*
2 Copyright (C) 1989 by the Massachusetts Institute of Technology
3
4 Export of this software from the United States of America is assumed
5 to require a specific license from the United States Government.
6 It is the responsibility of any person or organization contemplating
7 export to obtain such a license before exporting.
8
9WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10distribute this software and its documentation for any purpose and
11without fee is hereby granted, provided that the above copyright
12notice appear in all copies and that both that copyright notice and
13this permission notice appear in supporting documentation, and that
14the name of M.I.T. not be used in advertising or publicity pertaining
15to distribution of the software without specific, written prior
16permission. M.I.T. makes no representations about the suitability of
17this software for any purpose. It is provided "as is" without express
18or implied warranty.
19
20 */
21/* $FreeBSD: src/crypto/kerberosIV/kadmin/ksrvutil.c,v 1.1.1.3.2.1 2003/02/14 22:37:37 nectar Exp $ */
1de703da 22/* $DragonFly: src/crypto/kerberosIV/kadmin/Attic/ksrvutil.c,v 1.2 2003/06/17 04:24:36 dillon Exp $ */
984263bc
MD
23
24/*
25 * list and update contents of srvtab files
26 */
27
28/*
29 * ksrvutil
30 * list and update the contents of srvtab files
31 */
32
33#include "kadm_locl.h"
34
35RCSID("$Id: ksrvutil.c,v 1.50 1999/11/13 06:33:59 assar Exp $");
36
37#include "ksrvutil.h"
38
39#ifdef NOENCRYPTION
40#define read_long_pw_string placebo_read_pw_string
41#else /* NOENCRYPTION */
42#define read_long_pw_string des_read_pw_string
43#endif /* NOENCRYPTION */
44
45#define SRVTAB_MODE 0600 /* rw------- */
46#define PAD " "
47#define VNO_HEADER "Version"
48#define VNO_FORMAT "%4d "
49#define KEY_HEADER " Key " /* 17 characters long */
50#define PRINC_HEADER " Principal\n"
51#define PRINC_FORMAT "%s"
52
53char u_name[ANAME_SZ];
54char u_inst[INST_SZ];
55char u_realm[REALM_SZ];
56
57int destroyp = FALSE; /* Should the ticket file be destroyed? */
58
59static unsigned short
60get_mode(char *filename)
61{
62 struct stat statbuf;
63 unsigned short mode;
64
65 memset(&statbuf, 0, sizeof(statbuf));
66
67 if (stat(filename, &statbuf) < 0)
68 mode = SRVTAB_MODE;
69 else
70 mode = statbuf.st_mode;
71
72 return(mode);
73}
74
75static void
76copy_keyfile(char *keyfile, char *backup_keyfile)
77{
78 int keyfile_fd;
79 int backup_keyfile_fd;
80 int keyfile_mode;
81 char buf[BUFSIZ]; /* for copying keyfiles */
82 int rcount; /* for copying keyfiles */
83 int try_again;
84
85 memset(buf, 0, sizeof(buf));
86
87 do {
88 try_again = FALSE;
89 if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) {
90 if (errno != ENOENT)
91 err (1, "open %s", keyfile);
92 else {
93 try_again = TRUE;
94 if ((keyfile_fd =
95 open(keyfile,
96 O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0)
97 err(1, "create %s", keyfile);
98 else
99 if (close(keyfile_fd) < 0)
100 err (1, "close %s", keyfile);
101 }
102 }
103 } while(try_again);
104
105 keyfile_mode = get_mode(keyfile);
106
107 if ((backup_keyfile_fd =
108 open(backup_keyfile, O_WRONLY | O_TRUNC | O_CREAT,
109 keyfile_mode)) < 0)
110 err (1, "open %s", backup_keyfile);
111 do {
112 if ((rcount = read(keyfile_fd, buf, sizeof(buf))) < 0)
113 err (1, "read %s", keyfile);
114 if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount))
115 err (1, "write %s", backup_keyfile);
116 } while (rcount);
117 if (close(backup_keyfile_fd) < 0)
118 err(1, "close %s", backup_keyfile);
119 if (close(keyfile_fd) < 0)
120 err(1, "close %s", keyfile);
121}
122
123void
124leave(char *str, int x)
125{
126 if (str)
127 fprintf(stderr, "%s\n", str);
128 if (destroyp)
129 dest_tkt();
130 exit(x);
131}
132
133void
134safe_read_stdin(char *prompt, char *buf, size_t size)
135{
136 printf("%s", prompt);
137 fflush(stdout);
138 memset(buf, 0, size);
139 if (read(0, buf, size - 1) < 0) {
140 warn("read stdin");
141 leave(NULL, 1);
142 }
143 buf[strlen(buf)-1] = 0;
144}
145
146void
147safe_write(char *filename, int fd, void *buf, size_t len)
148{
149 if (write(fd, buf, len) != len) {
150 warn("write %s", filename);
151 close(fd);
152 leave("In progress srvtab in this file.", 1);
153 }
154}
155
156static int
157yes_no(char *string, int dflt)
158{
159 char ynbuf[5];
160
161 printf("%s (y,n) [%c]", string, dflt?'y':'n');
162 for (;;) {
163 safe_read_stdin("", ynbuf, sizeof(ynbuf));
164
165 if ((ynbuf[0] == 'n') || (ynbuf[0] == 'N'))
166 return(0);
167 else if ((ynbuf[0] == 'y') || (ynbuf[0] == 'Y'))
168 return(1);
169 else if(ynbuf[0] == 0)
170 return dflt;
171 else {
172 printf("Please enter 'y' or 'n': ");
173 fflush(stdout);
174 }
175 }
176}
177
178int yn(char *string)
179{
180 return yes_no(string, 1);
181}
182
183int ny(char *string)
184{
185 return yes_no(string, 0);
186}
187
188static void
189append_srvtab(char *filename, int fd, char *sname, char *sinst, char *srealm,
190 unsigned char key_vno, unsigned char *key)
191{
192 /* Add one to append null */
193 safe_write(filename, fd, sname, strlen(sname) + 1);
194 safe_write(filename, fd, sinst, strlen(sinst) + 1);
195 safe_write(filename, fd, srealm, strlen(srealm) + 1);
196 safe_write(filename, fd, &key_vno, 1);
197 safe_write(filename, fd, key, sizeof(des_cblock));
198 fsync(fd);
199}
200
201static void
202print_key(unsigned char *key)
203{
204 int i;
205
206 for (i = 0; i < 4; i++)
207 printf("%02x", key[i]);
208 printf(" ");
209 for (i = 4; i < 8; i++)
210 printf("%02x", key[i]);
211}
212
213static void
214print_name(char *name, char *inst, char *realm)
215{
216 printf("%s", krb_unparse_name_long(name, inst, realm));
217}
218
219static int
220get_svc_new_key(des_cblock *new_key, char *sname, char *sinst,
221 char *srealm, char *keyfile)
222{
223 int status = KADM_SUCCESS;
224
225 if (((status = krb_get_svc_in_tkt(sname, sinst, srealm, PWSERV_NAME,
226 KADM_SINST, 1, keyfile)) == KSUCCESS) &&
227 ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, srealm)) ==
228 KADM_SUCCESS)) {
229#ifdef NOENCRYPTION
230 memset(new_key, 0, sizeof(des_cblock));
231 (*new_key)[0] = (unsigned char) 1;
232#else /* NOENCRYPTION */
233 des_random_key(*new_key);
234#endif /* NOENCRYPTION */
235 return(KADM_SUCCESS);
236 }
237
238 return(status);
239}
240
241static void
242get_key_from_password(des_cblock (*key), char *cellname)
243{
244 char password[MAX_KPW_LEN]; /* storage for the password */
245
246 if (read_long_pw_string(password, sizeof(password)-1, "Password: ", 1))
247 leave("Error reading password.", 1);
248
249#ifdef NOENCRYPTION
250 memset(key, 0, sizeof(des_cblock));
251 (*key)[0] = (unsigned char) 1;
252#else /* NOENCRYPTION */
253 if (strlen(cellname) == 0)
254 des_string_to_key(password, key);
255 else
256 afs_string_to_key(password, cellname, key);
257#endif /* NOENCRYPTION */
258 memset(password, 0, sizeof(password));
259}
260
261static void
262usage(void)
263{
264 fprintf(stderr, "Usage: ksrvutil [-f keyfile] [-i] [-k] ");
265 fprintf(stderr, "[-p principal] [-r realm] [-u]");
266 fprintf(stderr, "[-c AFS cellname] ");
267 fprintf(stderr, "{list | change | add | get | delete}\n");
268 fprintf(stderr, " -i causes the program to ask for "
269 "confirmation before changing keys.\n");
270 fprintf(stderr, " -k causes the key to printed for list or change.\n");
271 fprintf(stderr, " -u creates one keyfile for each principal "
272 "(only used with `get')\n");
273 exit(1);
274}
275
276int
277main(int argc, char **argv)
278{
279 char sname[ANAME_SZ]; /* name of service */
280 char sinst[INST_SZ]; /* instance of service */
281 char srealm[REALM_SZ]; /* realm of service */
282 unsigned char key_vno; /* key version number */
283 int status; /* general purpose error status */
284 des_cblock new_key;
285 des_cblock old_key;
286 char change_tkt[MaxPathLen]; /* Ticket to use for key change */
287 char keyfile[MaxPathLen]; /* Original keyfile */
288 char work_keyfile[MaxPathLen]; /* Working copy of keyfile */
289 char backup_keyfile[MaxPathLen]; /* Backup copy of keyfile */
290 unsigned short keyfile_mode; /* Protections on keyfile */
291 int work_keyfile_fd = -1; /* Initialize so that */
292 int backup_keyfile_fd = -1; /* compiler doesn't complain */
293 char local_realm[REALM_SZ]; /* local kerberos realm */
294 char cellname[1024]; /* AFS cell name */
295 int c;
296 int interactive = FALSE;
297 int list = FALSE;
298 int change = FALSE;
299 int unique_filename = FALSE;
300 int add = FALSE;
301 int delete = FALSE;
302 int get = FALSE;
303 int key = FALSE; /* do we show keys? */
304 int arg_entered = FALSE;
305 int change_this_key = FALSE;
306 char databuf[BUFSIZ];
307 int first_printed = FALSE; /* have we printed the first item? */
308
309 memset(sname, 0, sizeof(sname));
310 memset(sinst, 0, sizeof(sinst));
311 memset(srealm, 0, sizeof(srealm));
312
313 memset(change_tkt, 0, sizeof(change_tkt));
314 memset(keyfile, 0, sizeof(keyfile));
315 memset(work_keyfile, 0, sizeof(work_keyfile));
316 memset(backup_keyfile, 0, sizeof(backup_keyfile));
317 memset(local_realm, 0, sizeof(local_realm));
318 memset(cellname, 0, sizeof(cellname));
319
320 set_progname (argv[0]);
321
322 if (krb_get_default_principal(u_name, u_inst, u_realm) < 0)
323 errx (1, "could not get default principal");
324
325 /* This is used only as a default for adding keys */
326 if (krb_get_lrealm(local_realm, 1) != KSUCCESS)
327 strlcpy(local_realm,
328 KRB_REALM,
329 sizeof(local_realm));
330
331 while((c = getopt(argc, argv, "ikc:f:p:r:u")) != -1) {
332 switch (c) {
333 case 'i':
334 interactive++;
335 break;
336 case 'k':
337 key++;
338 break;
339 case 'c':
340 strlcpy(cellname, optarg, sizeof(cellname));
341 break;
342 case 'f':
343 strlcpy(keyfile, optarg, sizeof(keyfile));
344 break;
345 case 'p':
346 if((status = kname_parse (u_name, u_inst, u_realm, optarg)) !=
347 KSUCCESS)
348 errx (1, "principal %s: %s", optarg,
349 krb_get_err_text(status));
350 break;
351 case 'r':
352 strlcpy(u_realm, optarg, sizeof(u_realm));
353 break;
354 case 'u':
355 unique_filename = 1;
356 break;
357 case '?':
358 usage();
359 }
360 }
361 if (optind >= argc)
362 usage();
363 if (*u_realm == '\0')
364 strlcpy (u_realm, local_realm, sizeof(u_realm));
365 if (strcmp(argv[optind], "list") == 0) {
366 if (arg_entered)
367 usage();
368 else {
369 arg_entered++;
370 list++;
371 }
372 }
373 else if (strcmp(argv[optind], "change") == 0) {
374 if (arg_entered)
375 usage();
376 else {
377 arg_entered++;
378 change++;
379 }
380 }
381 else if (strcmp(argv[optind], "add") == 0) {
382 if (arg_entered)
383 usage();
384 else {
385 arg_entered++;
386 add++;
387 }
388 }
389 else if (strcmp(argv[optind], "get") == 0) {
390 if (arg_entered)
391 usage();
392 else {
393 arg_entered++;
394 get++;
395 }
396 }
397 else if (strcmp(argv[optind], "delete") == 0) {
398 if (arg_entered)
399 usage();
400 else {
401 arg_entered++;
402 delete++;
403 }
404 }
405 else
406 usage();
407 ++optind;
408
409 if (!arg_entered)
410 usage();
411
412 if(unique_filename && !get)
413 warnx("`-u' flag is only used with `get'");
414
415 if (!keyfile[0])
416 strlcpy(keyfile, KEYFILE, sizeof(keyfile));
417
418 strlcpy(work_keyfile, keyfile, sizeof(work_keyfile));
419 strlcpy(backup_keyfile, keyfile, sizeof(backup_keyfile));
420
421 if (change || add || (get && !unique_filename) || delete) {
422 snprintf(work_keyfile, sizeof(work_keyfile), "%s.work", keyfile);
423 snprintf(backup_keyfile, sizeof(backup_keyfile), "%s.old", keyfile);
424 copy_keyfile(keyfile, backup_keyfile);
425 }
426
427 if (add || (get && !unique_filename))
428 copy_keyfile(backup_keyfile, work_keyfile);
429
430 keyfile_mode = get_mode(keyfile);
431
432 if (change || list || delete)
433 if ((backup_keyfile_fd = open(backup_keyfile, O_RDONLY, 0)) < 0)
434 err (1, "open %s", backup_keyfile);
435
436 if (change || delete) {
437 if ((work_keyfile_fd =
438 open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC,
439 SRVTAB_MODE)) < 0)
440 err (1, "creat %s", work_keyfile);
441 }
442 else if (add) {
443 if ((work_keyfile_fd =
444 open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0)
445 err (1, "open with append %s", work_keyfile );
446 }
447 else if (get && !unique_filename) {
448 if ((work_keyfile_fd =
449 open(work_keyfile, O_RDWR | O_CREAT, SRVTAB_MODE)) < 0)
450 err (1, "open for writing %s", work_keyfile);
451 }
452
453 if (change || list || delete) {
454 while ((getst(backup_keyfile_fd, sname, SNAME_SZ) > 0) &&
455 (getst(backup_keyfile_fd, sinst, INST_SZ) > 0) &&
456 (getst(backup_keyfile_fd, srealm, REALM_SZ) > 0) &&
457 (read(backup_keyfile_fd, &key_vno, 1) > 0) &&
458 (read(backup_keyfile_fd, old_key, sizeof(old_key)) > 0)) {
459 if (list) {
460 if (!first_printed) {
461 printf(VNO_HEADER);
462 printf(PAD);
463 if (key) {
464 printf(KEY_HEADER);
465 printf(PAD);
466 }
467 printf(PRINC_HEADER);
468 first_printed = 1;
469 }
470 printf(VNO_FORMAT, key_vno);
471 printf(PAD);
472 if (key) {
473 print_key(old_key);
474 printf(PAD);
475 }
476 print_name(sname, sinst, srealm);
477 printf("\n");
478 }
479 else if (change) {
480 snprintf(change_tkt, sizeof(change_tkt), "%s_ksrvutil.%u",
481 TKT_ROOT, (unsigned)getpid());
482 krb_set_tkt_string(change_tkt);
483 destroyp = TRUE;
484
485 printf("\nPrincipal: ");
486 print_name(sname, sinst, srealm);
487 printf("; version %d\n", key_vno);
488 if (interactive)
489 change_this_key = yn("Change this key?");
490 else
491 change_this_key = 1;
492
493 if (change_this_key)
494 printf("Changing to version %d.\n", key_vno + 1);
495 else if (change)
496 printf("Not changing this key.\n");
497
498 if (change_this_key) {
499 /*
500 * Pick a new key and determine whether or not
501 * it is safe to change
502 */
503 if ((status =
504 get_svc_new_key(&new_key, sname, sinst,
505 srealm, keyfile)) == KADM_SUCCESS)
506 key_vno++;
507 else {
508 memcpy(new_key, old_key, sizeof(new_key));
509 warnx ("Key NOT changed: %s\n",
510 krb_get_err_text(status));
511 change_this_key = FALSE;
512 }
513 }
514 else
515 memcpy(new_key, old_key, sizeof(new_key));
516 append_srvtab(work_keyfile, work_keyfile_fd,
517 sname, sinst, srealm, key_vno, new_key);
518 if (key && change_this_key) {
519 printf("Old key: ");
520 print_key(old_key);
521 printf("; new key: ");
522 print_key(new_key);
523 printf("\n");
524 }
525 if (change_this_key) {
526 if ((status = kadm_change_pw(new_key)) == KADM_SUCCESS) {
527 printf("Key changed.\n");
528 dest_tkt();
529 }
530 else {
531 com_err(__progname, status,
532 " attempting to change password.");
533 dest_tkt();
534 /* XXX This knows the format of a keyfile */
535 if (lseek(work_keyfile_fd, -9, SEEK_CUR) >= 0) {
536 key_vno--;
537 safe_write(work_keyfile,
538 work_keyfile_fd, &key_vno, 1);
539 safe_write(work_keyfile, work_keyfile_fd,
540 old_key, sizeof(des_cblock));
541 fsync(work_keyfile_fd);
542 fprintf(stderr,"Key NOT changed.\n");
543 } else {
544 warn ("Unable to revert keyfile");
545 leave("", 1);
546 }
547 }
548 }
549 } else if(delete) {
550 int delete_this_key;
551 printf("\nPrincipal: ");
552 print_name(sname, sinst, srealm);
553 printf("; version %d\n", key_vno);
554 delete_this_key = yn("Delete this key?");
555
556 if (delete_this_key)
557 printf("Deleting this key.\n");
558
559 if (!delete_this_key) {
560 append_srvtab(work_keyfile, work_keyfile_fd,
561 sname, sinst, srealm, key_vno, old_key);
562 }
563 }
564 memset(old_key, 0, sizeof(des_cblock));
565 memset(new_key, 0, sizeof(des_cblock));
566 }
567 }
568 else if (add) {
569 do {
570 do {
571 char *p;
572
573 safe_read_stdin("Name: ", databuf, sizeof(databuf));
574 p = strchr(databuf, '.');
575 if (p != NULL) {
576 *p++ = '\0';
577 strlcpy (sname, databuf, sizeof(sname));
578 strlcpy (sinst, p, sizeof(sinst));
579 } else {
580 strlcpy (sname, databuf, sizeof(sname));
581 safe_read_stdin("Instance: ", databuf, sizeof(databuf));
582 strlcpy (sinst, databuf, sizeof(databuf));
583 }
584
585 safe_read_stdin("Realm: ", databuf, sizeof(databuf));
586 if (databuf[0] != '\0')
587 strlcpy (srealm, databuf, sizeof(srealm));
588 else
589 strlcpy (srealm, local_realm, sizeof(srealm));
590
591 safe_read_stdin("Version number: ", databuf, sizeof(databuf));
592 key_vno = atoi(databuf);
593 if (!srealm[0])
594 strlcpy(srealm, local_realm, sizeof(srealm));
595 printf("New principal: ");
596 print_name(sname, sinst, srealm);
597 printf("; version %d\n", key_vno);
598 } while (!yn("Is this correct?"));
599 get_key_from_password(&new_key, cellname);
600 if (key) {
601 printf("Key: ");
602 print_key(new_key);
603 printf("\n");
604 }
605 append_srvtab(work_keyfile, work_keyfile_fd,
606 sname, sinst, srealm, key_vno, new_key);
607 printf("Key successfully added.\n");
608 } while (yn("Would you like to add another key?"));
609 }
610 else if (get) {
611 ksrvutil_get(unique_filename, work_keyfile_fd, work_keyfile,
612 argc - optind, argv + optind);
613 }
614
615 if (change || list || delete)
616 if (close(backup_keyfile_fd) < 0)
617 warn ("close %s", backup_keyfile);
618
619 if (change || add || (get && !unique_filename) || delete) {
620 if (close(work_keyfile_fd) < 0)
621 err (1, "close %s", work_keyfile);
622 if (rename(work_keyfile, keyfile) < 0)
623 err (1, "rename(%s, %s)", work_keyfile, keyfile);
624 chmod(backup_keyfile, keyfile_mode);
625 chmod(keyfile, keyfile_mode);
626 printf("Old keyfile in %s.\n", backup_keyfile);
627 }
628 return 0;
629}