2 Copyright (C) 1989 by the Massachusetts Institute of Technology
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.
9 WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10 distribute this software and its documentation for any purpose and
11 without fee is hereby granted, provided that the above copyright
12 notice appear in all copies and that both that copyright notice and
13 this permission notice appear in supporting documentation, and that
14 the name of M.I.T. not be used in advertising or publicity pertaining
15 to distribution of the software without specific, written prior
16 permission. M.I.T. makes no representations about the suitability of
17 this software for any purpose. It is provided "as is" without express
21 /* $FreeBSD: src/crypto/kerberosIV/kadmin/ksrvutil.c,v 1.1.1.3.2.1 2003/02/14 22:37:37 nectar Exp $ */
22 /* $DragonFly: src/crypto/kerberosIV/kadmin/Attic/ksrvutil.c,v 1.2 2003/06/17 04:24:36 dillon Exp $ */
25 * list and update contents of srvtab files
30 * list and update the contents of srvtab files
33 #include "kadm_locl.h"
35 RCSID("$Id: ksrvutil.c,v 1.50 1999/11/13 06:33:59 assar Exp $");
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 */
45 #define SRVTAB_MODE 0600 /* rw------- */
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"
53 char u_name[ANAME_SZ];
55 char u_realm[REALM_SZ];
57 int destroyp = FALSE; /* Should the ticket file be destroyed? */
60 get_mode(char *filename)
65 memset(&statbuf, 0, sizeof(statbuf));
67 if (stat(filename, &statbuf) < 0)
70 mode = statbuf.st_mode;
76 copy_keyfile(char *keyfile, char *backup_keyfile)
79 int backup_keyfile_fd;
81 char buf[BUFSIZ]; /* for copying keyfiles */
82 int rcount; /* for copying keyfiles */
85 memset(buf, 0, sizeof(buf));
89 if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) {
91 err (1, "open %s", keyfile);
96 O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0)
97 err(1, "create %s", keyfile);
99 if (close(keyfile_fd) < 0)
100 err (1, "close %s", keyfile);
105 keyfile_mode = get_mode(keyfile);
107 if ((backup_keyfile_fd =
108 open(backup_keyfile, O_WRONLY | O_TRUNC | O_CREAT,
110 err (1, "open %s", backup_keyfile);
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);
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);
124 leave(char *str, int x)
127 fprintf(stderr, "%s\n", str);
134 safe_read_stdin(char *prompt, char *buf, size_t size)
136 printf("%s", prompt);
138 memset(buf, 0, size);
139 if (read(0, buf, size - 1) < 0) {
143 buf[strlen(buf)-1] = 0;
147 safe_write(char *filename, int fd, void *buf, size_t len)
149 if (write(fd, buf, len) != len) {
150 warn("write %s", filename);
152 leave("In progress srvtab in this file.", 1);
157 yes_no(char *string, int dflt)
161 printf("%s (y,n) [%c]", string, dflt?'y':'n');
163 safe_read_stdin("", ynbuf, sizeof(ynbuf));
165 if ((ynbuf[0] == 'n') || (ynbuf[0] == 'N'))
167 else if ((ynbuf[0] == 'y') || (ynbuf[0] == 'Y'))
169 else if(ynbuf[0] == 0)
172 printf("Please enter 'y' or 'n': ");
180 return yes_no(string, 1);
185 return yes_no(string, 0);
189 append_srvtab(char *filename, int fd, char *sname, char *sinst, char *srealm,
190 unsigned char key_vno, unsigned char *key)
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));
202 print_key(unsigned char *key)
206 for (i = 0; i < 4; i++)
207 printf("%02x", key[i]);
209 for (i = 4; i < 8; i++)
210 printf("%02x", key[i]);
214 print_name(char *name, char *inst, char *realm)
216 printf("%s", krb_unparse_name_long(name, inst, realm));
220 get_svc_new_key(des_cblock *new_key, char *sname, char *sinst,
221 char *srealm, char *keyfile)
223 int status = KADM_SUCCESS;
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)) ==
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);
242 get_key_from_password(des_cblock (*key), char *cellname)
244 char password[MAX_KPW_LEN]; /* storage for the password */
246 if (read_long_pw_string(password, sizeof(password)-1, "Password: ", 1))
247 leave("Error reading password.", 1);
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);
256 afs_string_to_key(password, cellname, key);
257 #endif /* NOENCRYPTION */
258 memset(password, 0, sizeof(password));
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");
277 main(int argc, char **argv)
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 */
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 */
296 int interactive = FALSE;
299 int unique_filename = 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? */
309 memset(sname, 0, sizeof(sname));
310 memset(sinst, 0, sizeof(sinst));
311 memset(srealm, 0, sizeof(srealm));
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));
320 set_progname (argv[0]);
322 if (krb_get_default_principal(u_name, u_inst, u_realm) < 0)
323 errx (1, "could not get default principal");
325 /* This is used only as a default for adding keys */
326 if (krb_get_lrealm(local_realm, 1) != KSUCCESS)
329 sizeof(local_realm));
331 while((c = getopt(argc, argv, "ikc:f:p:r:u")) != -1) {
340 strlcpy(cellname, optarg, sizeof(cellname));
343 strlcpy(keyfile, optarg, sizeof(keyfile));
346 if((status = kname_parse (u_name, u_inst, u_realm, optarg)) !=
348 errx (1, "principal %s: %s", optarg,
349 krb_get_err_text(status));
352 strlcpy(u_realm, optarg, sizeof(u_realm));
363 if (*u_realm == '\0')
364 strlcpy (u_realm, local_realm, sizeof(u_realm));
365 if (strcmp(argv[optind], "list") == 0) {
373 else if (strcmp(argv[optind], "change") == 0) {
381 else if (strcmp(argv[optind], "add") == 0) {
389 else if (strcmp(argv[optind], "get") == 0) {
397 else if (strcmp(argv[optind], "delete") == 0) {
412 if(unique_filename && !get)
413 warnx("`-u' flag is only used with `get'");
416 strlcpy(keyfile, KEYFILE, sizeof(keyfile));
418 strlcpy(work_keyfile, keyfile, sizeof(work_keyfile));
419 strlcpy(backup_keyfile, keyfile, sizeof(backup_keyfile));
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);
427 if (add || (get && !unique_filename))
428 copy_keyfile(backup_keyfile, work_keyfile);
430 keyfile_mode = get_mode(keyfile);
432 if (change || list || delete)
433 if ((backup_keyfile_fd = open(backup_keyfile, O_RDONLY, 0)) < 0)
434 err (1, "open %s", backup_keyfile);
436 if (change || delete) {
437 if ((work_keyfile_fd =
438 open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC,
440 err (1, "creat %s", work_keyfile);
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 );
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);
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)) {
460 if (!first_printed) {
467 printf(PRINC_HEADER);
470 printf(VNO_FORMAT, key_vno);
476 print_name(sname, sinst, srealm);
480 snprintf(change_tkt, sizeof(change_tkt), "%s_ksrvutil.%u",
481 TKT_ROOT, (unsigned)getpid());
482 krb_set_tkt_string(change_tkt);
485 printf("\nPrincipal: ");
486 print_name(sname, sinst, srealm);
487 printf("; version %d\n", key_vno);
489 change_this_key = yn("Change this key?");
494 printf("Changing to version %d.\n", key_vno + 1);
496 printf("Not changing this key.\n");
498 if (change_this_key) {
500 * Pick a new key and determine whether or not
501 * it is safe to change
504 get_svc_new_key(&new_key, sname, sinst,
505 srealm, keyfile)) == KADM_SUCCESS)
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;
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) {
521 printf("; new key: ");
525 if (change_this_key) {
526 if ((status = kadm_change_pw(new_key)) == KADM_SUCCESS) {
527 printf("Key changed.\n");
531 com_err(__progname, status,
532 " attempting to change password.");
534 /* XXX This knows the format of a keyfile */
535 if (lseek(work_keyfile_fd, -9, SEEK_CUR) >= 0) {
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");
544 warn ("Unable to revert keyfile");
551 printf("\nPrincipal: ");
552 print_name(sname, sinst, srealm);
553 printf("; version %d\n", key_vno);
554 delete_this_key = yn("Delete this key?");
557 printf("Deleting this key.\n");
559 if (!delete_this_key) {
560 append_srvtab(work_keyfile, work_keyfile_fd,
561 sname, sinst, srealm, key_vno, old_key);
564 memset(old_key, 0, sizeof(des_cblock));
565 memset(new_key, 0, sizeof(des_cblock));
573 safe_read_stdin("Name: ", databuf, sizeof(databuf));
574 p = strchr(databuf, '.');
577 strlcpy (sname, databuf, sizeof(sname));
578 strlcpy (sinst, p, sizeof(sinst));
580 strlcpy (sname, databuf, sizeof(sname));
581 safe_read_stdin("Instance: ", databuf, sizeof(databuf));
582 strlcpy (sinst, databuf, sizeof(databuf));
585 safe_read_stdin("Realm: ", databuf, sizeof(databuf));
586 if (databuf[0] != '\0')
587 strlcpy (srealm, databuf, sizeof(srealm));
589 strlcpy (srealm, local_realm, sizeof(srealm));
591 safe_read_stdin("Version number: ", databuf, sizeof(databuf));
592 key_vno = atoi(databuf);
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);
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?"));
611 ksrvutil_get(unique_filename, work_keyfile_fd, work_keyfile,
612 argc - optind, argv + optind);
615 if (change || list || delete)
616 if (close(backup_keyfile_fd) < 0)
617 warn ("close %s", backup_keyfile);
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);