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 $ */
24 * list and update contents of srvtab files
29 * list and update the contents of srvtab files
32 #include "kadm_locl.h"
34 RCSID("$Id: ksrvutil.c,v 1.50 1999/11/13 06:33:59 assar Exp $");
39 #define read_long_pw_string placebo_read_pw_string
40 #else /* NOENCRYPTION */
41 #define read_long_pw_string des_read_pw_string
42 #endif /* NOENCRYPTION */
44 #define SRVTAB_MODE 0600 /* rw------- */
46 #define VNO_HEADER "Version"
47 #define VNO_FORMAT "%4d "
48 #define KEY_HEADER " Key " /* 17 characters long */
49 #define PRINC_HEADER " Principal\n"
50 #define PRINC_FORMAT "%s"
52 char u_name[ANAME_SZ];
54 char u_realm[REALM_SZ];
56 int destroyp = FALSE; /* Should the ticket file be destroyed? */
59 get_mode(char *filename)
64 memset(&statbuf, 0, sizeof(statbuf));
66 if (stat(filename, &statbuf) < 0)
69 mode = statbuf.st_mode;
75 copy_keyfile(char *keyfile, char *backup_keyfile)
78 int backup_keyfile_fd;
80 char buf[BUFSIZ]; /* for copying keyfiles */
81 int rcount; /* for copying keyfiles */
84 memset(buf, 0, sizeof(buf));
88 if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) {
90 err (1, "open %s", keyfile);
95 O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0)
96 err(1, "create %s", keyfile);
98 if (close(keyfile_fd) < 0)
99 err (1, "close %s", keyfile);
104 keyfile_mode = get_mode(keyfile);
106 if ((backup_keyfile_fd =
107 open(backup_keyfile, O_WRONLY | O_TRUNC | O_CREAT,
109 err (1, "open %s", backup_keyfile);
111 if ((rcount = read(keyfile_fd, buf, sizeof(buf))) < 0)
112 err (1, "read %s", keyfile);
113 if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount))
114 err (1, "write %s", backup_keyfile);
116 if (close(backup_keyfile_fd) < 0)
117 err(1, "close %s", backup_keyfile);
118 if (close(keyfile_fd) < 0)
119 err(1, "close %s", keyfile);
123 leave(char *str, int x)
126 fprintf(stderr, "%s\n", str);
133 safe_read_stdin(char *prompt, char *buf, size_t size)
135 printf("%s", prompt);
137 memset(buf, 0, size);
138 if (read(0, buf, size - 1) < 0) {
142 buf[strlen(buf)-1] = 0;
146 safe_write(char *filename, int fd, void *buf, size_t len)
148 if (write(fd, buf, len) != len) {
149 warn("write %s", filename);
151 leave("In progress srvtab in this file.", 1);
156 yes_no(char *string, int dflt)
160 printf("%s (y,n) [%c]", string, dflt?'y':'n');
162 safe_read_stdin("", ynbuf, sizeof(ynbuf));
164 if ((ynbuf[0] == 'n') || (ynbuf[0] == 'N'))
166 else if ((ynbuf[0] == 'y') || (ynbuf[0] == 'Y'))
168 else if(ynbuf[0] == 0)
171 printf("Please enter 'y' or 'n': ");
179 return yes_no(string, 1);
184 return yes_no(string, 0);
188 append_srvtab(char *filename, int fd, char *sname, char *sinst, char *srealm,
189 unsigned char key_vno, unsigned char *key)
191 /* Add one to append null */
192 safe_write(filename, fd, sname, strlen(sname) + 1);
193 safe_write(filename, fd, sinst, strlen(sinst) + 1);
194 safe_write(filename, fd, srealm, strlen(srealm) + 1);
195 safe_write(filename, fd, &key_vno, 1);
196 safe_write(filename, fd, key, sizeof(des_cblock));
201 print_key(unsigned char *key)
205 for (i = 0; i < 4; i++)
206 printf("%02x", key[i]);
208 for (i = 4; i < 8; i++)
209 printf("%02x", key[i]);
213 print_name(char *name, char *inst, char *realm)
215 printf("%s", krb_unparse_name_long(name, inst, realm));
219 get_svc_new_key(des_cblock *new_key, char *sname, char *sinst,
220 char *srealm, char *keyfile)
222 int status = KADM_SUCCESS;
224 if (((status = krb_get_svc_in_tkt(sname, sinst, srealm, PWSERV_NAME,
225 KADM_SINST, 1, keyfile)) == KSUCCESS) &&
226 ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, srealm)) ==
229 memset(new_key, 0, sizeof(des_cblock));
230 (*new_key)[0] = (unsigned char) 1;
231 #else /* NOENCRYPTION */
232 des_random_key(*new_key);
233 #endif /* NOENCRYPTION */
234 return(KADM_SUCCESS);
241 get_key_from_password(des_cblock (*key), char *cellname)
243 char password[MAX_KPW_LEN]; /* storage for the password */
245 if (read_long_pw_string(password, sizeof(password)-1, "Password: ", 1))
246 leave("Error reading password.", 1);
249 memset(key, 0, sizeof(des_cblock));
250 (*key)[0] = (unsigned char) 1;
251 #else /* NOENCRYPTION */
252 if (strlen(cellname) == 0)
253 des_string_to_key(password, key);
255 afs_string_to_key(password, cellname, key);
256 #endif /* NOENCRYPTION */
257 memset(password, 0, sizeof(password));
263 fprintf(stderr, "Usage: ksrvutil [-f keyfile] [-i] [-k] ");
264 fprintf(stderr, "[-p principal] [-r realm] [-u]");
265 fprintf(stderr, "[-c AFS cellname] ");
266 fprintf(stderr, "{list | change | add | get | delete}\n");
267 fprintf(stderr, " -i causes the program to ask for "
268 "confirmation before changing keys.\n");
269 fprintf(stderr, " -k causes the key to printed for list or change.\n");
270 fprintf(stderr, " -u creates one keyfile for each principal "
271 "(only used with `get')\n");
276 main(int argc, char **argv)
278 char sname[ANAME_SZ]; /* name of service */
279 char sinst[INST_SZ]; /* instance of service */
280 char srealm[REALM_SZ]; /* realm of service */
281 unsigned char key_vno; /* key version number */
282 int status; /* general purpose error status */
285 char change_tkt[MaxPathLen]; /* Ticket to use for key change */
286 char keyfile[MaxPathLen]; /* Original keyfile */
287 char work_keyfile[MaxPathLen]; /* Working copy of keyfile */
288 char backup_keyfile[MaxPathLen]; /* Backup copy of keyfile */
289 unsigned short keyfile_mode; /* Protections on keyfile */
290 int work_keyfile_fd = -1; /* Initialize so that */
291 int backup_keyfile_fd = -1; /* compiler doesn't complain */
292 char local_realm[REALM_SZ]; /* local kerberos realm */
293 char cellname[1024]; /* AFS cell name */
295 int interactive = FALSE;
298 int unique_filename = FALSE;
302 int key = FALSE; /* do we show keys? */
303 int arg_entered = FALSE;
304 int change_this_key = FALSE;
305 char databuf[BUFSIZ];
306 int first_printed = FALSE; /* have we printed the first item? */
308 memset(sname, 0, sizeof(sname));
309 memset(sinst, 0, sizeof(sinst));
310 memset(srealm, 0, sizeof(srealm));
312 memset(change_tkt, 0, sizeof(change_tkt));
313 memset(keyfile, 0, sizeof(keyfile));
314 memset(work_keyfile, 0, sizeof(work_keyfile));
315 memset(backup_keyfile, 0, sizeof(backup_keyfile));
316 memset(local_realm, 0, sizeof(local_realm));
317 memset(cellname, 0, sizeof(cellname));
319 set_progname (argv[0]);
321 if (krb_get_default_principal(u_name, u_inst, u_realm) < 0)
322 errx (1, "could not get default principal");
324 /* This is used only as a default for adding keys */
325 if (krb_get_lrealm(local_realm, 1) != KSUCCESS)
328 sizeof(local_realm));
330 while((c = getopt(argc, argv, "ikc:f:p:r:u")) != -1) {
339 strlcpy(cellname, optarg, sizeof(cellname));
342 strlcpy(keyfile, optarg, sizeof(keyfile));
345 if((status = kname_parse (u_name, u_inst, u_realm, optarg)) !=
347 errx (1, "principal %s: %s", optarg,
348 krb_get_err_text(status));
351 strlcpy(u_realm, optarg, sizeof(u_realm));
362 if (*u_realm == '\0')
363 strlcpy (u_realm, local_realm, sizeof(u_realm));
364 if (strcmp(argv[optind], "list") == 0) {
372 else if (strcmp(argv[optind], "change") == 0) {
380 else if (strcmp(argv[optind], "add") == 0) {
388 else if (strcmp(argv[optind], "get") == 0) {
396 else if (strcmp(argv[optind], "delete") == 0) {
411 if(unique_filename && !get)
412 warnx("`-u' flag is only used with `get'");
415 strlcpy(keyfile, KEYFILE, sizeof(keyfile));
417 strlcpy(work_keyfile, keyfile, sizeof(work_keyfile));
418 strlcpy(backup_keyfile, keyfile, sizeof(backup_keyfile));
420 if (change || add || (get && !unique_filename) || delete) {
421 snprintf(work_keyfile, sizeof(work_keyfile), "%s.work", keyfile);
422 snprintf(backup_keyfile, sizeof(backup_keyfile), "%s.old", keyfile);
423 copy_keyfile(keyfile, backup_keyfile);
426 if (add || (get && !unique_filename))
427 copy_keyfile(backup_keyfile, work_keyfile);
429 keyfile_mode = get_mode(keyfile);
431 if (change || list || delete)
432 if ((backup_keyfile_fd = open(backup_keyfile, O_RDONLY, 0)) < 0)
433 err (1, "open %s", backup_keyfile);
435 if (change || delete) {
436 if ((work_keyfile_fd =
437 open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC,
439 err (1, "creat %s", work_keyfile);
442 if ((work_keyfile_fd =
443 open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0)
444 err (1, "open with append %s", work_keyfile );
446 else if (get && !unique_filename) {
447 if ((work_keyfile_fd =
448 open(work_keyfile, O_RDWR | O_CREAT, SRVTAB_MODE)) < 0)
449 err (1, "open for writing %s", work_keyfile);
452 if (change || list || delete) {
453 while ((getst(backup_keyfile_fd, sname, SNAME_SZ) > 0) &&
454 (getst(backup_keyfile_fd, sinst, INST_SZ) > 0) &&
455 (getst(backup_keyfile_fd, srealm, REALM_SZ) > 0) &&
456 (read(backup_keyfile_fd, &key_vno, 1) > 0) &&
457 (read(backup_keyfile_fd, old_key, sizeof(old_key)) > 0)) {
459 if (!first_printed) {
466 printf(PRINC_HEADER);
469 printf(VNO_FORMAT, key_vno);
475 print_name(sname, sinst, srealm);
479 snprintf(change_tkt, sizeof(change_tkt), "%s_ksrvutil.%u",
480 TKT_ROOT, (unsigned)getpid());
481 krb_set_tkt_string(change_tkt);
484 printf("\nPrincipal: ");
485 print_name(sname, sinst, srealm);
486 printf("; version %d\n", key_vno);
488 change_this_key = yn("Change this key?");
493 printf("Changing to version %d.\n", key_vno + 1);
495 printf("Not changing this key.\n");
497 if (change_this_key) {
499 * Pick a new key and determine whether or not
500 * it is safe to change
503 get_svc_new_key(&new_key, sname, sinst,
504 srealm, keyfile)) == KADM_SUCCESS)
507 memcpy(new_key, old_key, sizeof(new_key));
508 warnx ("Key NOT changed: %s\n",
509 krb_get_err_text(status));
510 change_this_key = FALSE;
514 memcpy(new_key, old_key, sizeof(new_key));
515 append_srvtab(work_keyfile, work_keyfile_fd,
516 sname, sinst, srealm, key_vno, new_key);
517 if (key && change_this_key) {
520 printf("; new key: ");
524 if (change_this_key) {
525 if ((status = kadm_change_pw(new_key)) == KADM_SUCCESS) {
526 printf("Key changed.\n");
530 com_err(__progname, status,
531 " attempting to change password.");
533 /* XXX This knows the format of a keyfile */
534 if (lseek(work_keyfile_fd, -9, SEEK_CUR) >= 0) {
536 safe_write(work_keyfile,
537 work_keyfile_fd, &key_vno, 1);
538 safe_write(work_keyfile, work_keyfile_fd,
539 old_key, sizeof(des_cblock));
540 fsync(work_keyfile_fd);
541 fprintf(stderr,"Key NOT changed.\n");
543 warn ("Unable to revert keyfile");
550 printf("\nPrincipal: ");
551 print_name(sname, sinst, srealm);
552 printf("; version %d\n", key_vno);
553 delete_this_key = yn("Delete this key?");
556 printf("Deleting this key.\n");
558 if (!delete_this_key) {
559 append_srvtab(work_keyfile, work_keyfile_fd,
560 sname, sinst, srealm, key_vno, old_key);
563 memset(old_key, 0, sizeof(des_cblock));
564 memset(new_key, 0, sizeof(des_cblock));
572 safe_read_stdin("Name: ", databuf, sizeof(databuf));
573 p = strchr(databuf, '.');
576 strlcpy (sname, databuf, sizeof(sname));
577 strlcpy (sinst, p, sizeof(sinst));
579 strlcpy (sname, databuf, sizeof(sname));
580 safe_read_stdin("Instance: ", databuf, sizeof(databuf));
581 strlcpy (sinst, databuf, sizeof(databuf));
584 safe_read_stdin("Realm: ", databuf, sizeof(databuf));
585 if (databuf[0] != '\0')
586 strlcpy (srealm, databuf, sizeof(srealm));
588 strlcpy (srealm, local_realm, sizeof(srealm));
590 safe_read_stdin("Version number: ", databuf, sizeof(databuf));
591 key_vno = atoi(databuf);
593 strlcpy(srealm, local_realm, sizeof(srealm));
594 printf("New principal: ");
595 print_name(sname, sinst, srealm);
596 printf("; version %d\n", key_vno);
597 } while (!yn("Is this correct?"));
598 get_key_from_password(&new_key, cellname);
604 append_srvtab(work_keyfile, work_keyfile_fd,
605 sname, sinst, srealm, key_vno, new_key);
606 printf("Key successfully added.\n");
607 } while (yn("Would you like to add another key?"));
610 ksrvutil_get(unique_filename, work_keyfile_fd, work_keyfile,
611 argc - optind, argv + optind);
614 if (change || list || delete)
615 if (close(backup_keyfile_fd) < 0)
616 warn ("close %s", backup_keyfile);
618 if (change || add || (get && !unique_filename) || delete) {
619 if (close(work_keyfile_fd) < 0)
620 err (1, "close %s", work_keyfile);
621 if (rename(work_keyfile, keyfile) < 0)
622 err (1, "rename(%s, %s)", work_keyfile, keyfile);
623 chmod(backup_keyfile, keyfile_mode);
624 chmod(keyfile, keyfile_mode);
625 printf("Old keyfile in %s.\n", backup_keyfile);