summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/kadmin/ksrvutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/kerberosIV/kadmin/ksrvutil.c')
-rw-r--r--crypto/kerberosIV/kadmin/ksrvutil.c601
1 files changed, 601 insertions, 0 deletions
diff --git a/crypto/kerberosIV/kadmin/ksrvutil.c b/crypto/kerberosIV/kadmin/ksrvutil.c
new file mode 100644
index 0000000..108481c
--- /dev/null
+++ b/crypto/kerberosIV/kadmin/ksrvutil.c
@@ -0,0 +1,601 @@
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * list and update contents of srvtab files
+ */
+
+/*
+ * ksrvutil
+ * list and update the contents of srvtab files
+ */
+
+#include "kadm_locl.h"
+
+RCSID("$Id: ksrvutil.c,v 1.39 1997/05/02 14:28:52 assar Exp $");
+
+#include "ksrvutil.h"
+
+#ifdef NOENCRYPTION
+#define read_long_pw_string placebo_read_pw_string
+#else /* NOENCRYPTION */
+#define read_long_pw_string des_read_pw_string
+#endif /* NOENCRYPTION */
+
+#define SRVTAB_MODE 0600 /* rw------- */
+#define PAD " "
+#define VNO_HEADER "Version"
+#define VNO_FORMAT "%4d "
+#define KEY_HEADER " Key " /* 17 characters long */
+#define PRINC_HEADER " Principal\n"
+#define PRINC_FORMAT "%s"
+
+char u_name[ANAME_SZ];
+char u_inst[INST_SZ];
+char u_realm[REALM_SZ];
+
+int destroyp = FALSE; /* Should the ticket file be destroyed? */
+
+static unsigned short
+get_mode(char *filename)
+{
+ struct stat statbuf;
+ unsigned short mode;
+
+ memset(&statbuf, 0, sizeof(statbuf));
+
+ if (stat(filename, &statbuf) < 0)
+ mode = SRVTAB_MODE;
+ else
+ mode = statbuf.st_mode;
+
+ return(mode);
+}
+
+static void
+copy_keyfile(char *keyfile, char *backup_keyfile)
+{
+ int keyfile_fd;
+ int backup_keyfile_fd;
+ int keyfile_mode;
+ char buf[BUFSIZ]; /* for copying keyfiles */
+ int rcount; /* for copying keyfiles */
+ int try_again;
+
+ memset(buf, 0, sizeof(buf));
+
+ do {
+ try_again = FALSE;
+ if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) {
+ if (errno != ENOENT)
+ err (1, "read %s", keyfile);
+ else {
+ try_again = TRUE;
+ if ((keyfile_fd =
+ open(keyfile,
+ O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0)
+ err(1, "create %s", keyfile);
+ else
+ if (close(keyfile_fd) < 0)
+ err (1, "close %s", keyfile);
+ }
+ }
+ } while(try_again);
+
+ keyfile_mode = get_mode(keyfile);
+
+ if ((backup_keyfile_fd =
+ open(backup_keyfile, O_WRONLY | O_TRUNC | O_CREAT,
+ keyfile_mode)) < 0)
+ err (1, "write %s", backup_keyfile);
+ do {
+ if ((rcount = read(keyfile_fd, buf, sizeof(buf))) < 0)
+ err (1, "read %s", keyfile);
+ if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount))
+ err (1, "write %s", backup_keyfile);
+ } while (rcount);
+ if (close(backup_keyfile_fd) < 0)
+ err(1, "close %s", backup_keyfile);
+ if (close(keyfile_fd) < 0)
+ err(1, "close %s", keyfile);
+}
+
+void
+leave(char *str, int x)
+{
+ if (str)
+ fprintf(stderr, "%s\n", str);
+ if (destroyp)
+ dest_tkt();
+ exit(x);
+}
+
+void
+safe_read_stdin(char *prompt, char *buf, size_t size)
+{
+ printf("%s", prompt);
+ fflush(stdout);
+ memset(buf, 0, size);
+ if (read(0, buf, size - 1) < 0) {
+ warn("read stdin");
+ leave(NULL, 1);
+ }
+ buf[strlen(buf)-1] = 0;
+}
+
+void
+safe_write(char *filename, int fd, void *buf, size_t len)
+{
+ if (write(fd, buf, len) != len) {
+ warn("write %s", filename);
+ close(fd);
+ leave("In progress srvtab in this file.", 1);
+ }
+}
+
+static int
+yes_no(char *string, int dflt)
+{
+ char ynbuf[5];
+
+ printf("%s (y,n) [%c]", string, dflt?'y':'n');
+ for (;;) {
+ safe_read_stdin("", ynbuf, sizeof(ynbuf));
+
+ if ((ynbuf[0] == 'n') || (ynbuf[0] == 'N'))
+ return(0);
+ else if ((ynbuf[0] == 'y') || (ynbuf[0] == 'Y'))
+ return(1);
+ else if(ynbuf[0] == 0)
+ return dflt;
+ else {
+ printf("Please enter 'y' or 'n': ");
+ fflush(stdout);
+ }
+ }
+}
+
+int yn(char *string)
+{
+ return yes_no(string, 1);
+}
+
+int ny(char *string)
+{
+ return yes_no(string, 0);
+}
+
+static void
+append_srvtab(char *filename, int fd, char *sname, char *sinst, char *srealm, unsigned char key_vno, unsigned char *key)
+{
+ /* Add one to append null */
+ safe_write(filename, fd, sname, strlen(sname) + 1);
+ safe_write(filename, fd, sinst, strlen(sinst) + 1);
+ safe_write(filename, fd, srealm, strlen(srealm) + 1);
+ safe_write(filename, fd, &key_vno, 1);
+ safe_write(filename, fd, key, sizeof(des_cblock));
+ fsync(fd);
+}
+
+static void
+print_key(unsigned char *key)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ printf("%02x", key[i]);
+ printf(" ");
+ for (i = 4; i < 8; i++)
+ printf("%02x", key[i]);
+}
+
+static void
+print_name(char *name, char *inst, char *realm)
+{
+ printf("%s", krb_unparse_name_long(name, inst, realm));
+}
+
+static int
+get_svc_new_key(des_cblock *new_key, char *sname, char *sinst,
+ char *srealm, char *keyfile)
+{
+ int status = KADM_SUCCESS;
+
+ if (((status = krb_get_svc_in_tkt(sname, sinst, srealm, PWSERV_NAME,
+ KADM_SINST, 1, keyfile)) == KSUCCESS) &&
+ ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, srealm)) ==
+ KADM_SUCCESS)) {
+#ifdef NOENCRYPTION
+ memset(new_key, 0, sizeof(des_cblock));
+ (*new_key)[0] = (unsigned char) 1;
+#else /* NOENCRYPTION */
+ des_new_random_key(new_key);
+#endif /* NOENCRYPTION */
+ return(KADM_SUCCESS);
+ }
+
+ return(status);
+}
+
+static void
+get_key_from_password(des_cblock (*key), char *cellname)
+{
+ char password[MAX_KPW_LEN]; /* storage for the password */
+
+ if (read_long_pw_string(password, sizeof(password)-1, "Password: ", 1))
+ leave("Error reading password.", 1);
+
+#ifdef NOENCRYPTION
+ memset(key, 0, sizeof(des_cblock));
+ (*key)[0] = (unsigned char) 1;
+#else /* NOENCRYPTION */
+ if (strlen(cellname) == 0)
+ des_string_to_key(password, key);
+ else
+ afs_string_to_key(password, cellname, key);
+#endif /* NOENCRYPTION */
+ memset(password, 0, sizeof(password));
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: ksrvutil [-f keyfile] [-i] [-k] ");
+ fprintf(stderr, "[-p principal] [-r realm] ");
+ fprintf(stderr, "[-c AFS cellname] ");
+ fprintf(stderr, "{list | change | add | get}\n");
+ fprintf(stderr, " -i causes the program to ask for ");
+ fprintf(stderr, "confirmation before changing keys.\n");
+ fprintf(stderr, " -k causes the key to printed for list or ");
+ fprintf(stderr, "change.\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ char sname[ANAME_SZ]; /* name of service */
+ char sinst[INST_SZ]; /* instance of service */
+ char srealm[REALM_SZ]; /* realm of service */
+ unsigned char key_vno; /* key version number */
+ int status; /* general purpose error status */
+ des_cblock new_key;
+ des_cblock old_key;
+ char change_tkt[MaxPathLen]; /* Ticket to use for key change */
+ char keyfile[MaxPathLen]; /* Original keyfile */
+ char work_keyfile[MaxPathLen]; /* Working copy of keyfile */
+ char backup_keyfile[MaxPathLen]; /* Backup copy of keyfile */
+ unsigned short keyfile_mode; /* Protections on keyfile */
+ int work_keyfile_fd = -1; /* Initialize so that */
+ int backup_keyfile_fd = -1; /* compiler doesn't complain */
+ char local_realm[REALM_SZ]; /* local kerberos realm */
+ char cellname[1024]; /* AFS cell name */
+ int c;
+ int interactive = FALSE;
+ int list = FALSE;
+ int change = FALSE;
+ int add = FALSE;
+ int get = FALSE;
+ int key = FALSE; /* do we show keys? */
+ int arg_entered = FALSE;
+ int change_this_key = FALSE;
+ char databuf[BUFSIZ];
+ int first_printed = FALSE; /* have we printed the first item? */
+
+ memset(sname, 0, sizeof(sname));
+ memset(sinst, 0, sizeof(sinst));
+ memset(srealm, 0, sizeof(srealm));
+
+ memset(change_tkt, 0, sizeof(change_tkt));
+ memset(keyfile, 0, sizeof(keyfile));
+ memset(work_keyfile, 0, sizeof(work_keyfile));
+ memset(backup_keyfile, 0, sizeof(backup_keyfile));
+ memset(local_realm, 0, sizeof(local_realm));
+ memset(cellname, 0, sizeof(cellname));
+
+ set_progname (argv[0]);
+
+ if (krb_get_default_principal(u_name, u_inst, u_realm) < 0)
+ errx (1, "could not get default principal");
+
+ /* This is used only as a default for adding keys */
+ if (krb_get_lrealm(local_realm, 1) != KSUCCESS)
+ strcpy(local_realm, KRB_REALM);
+
+ while((c = getopt(argc, argv, "ikc:f:p:r:")) != EOF) {
+ switch (c) {
+ case 'i':
+ interactive++;
+ break;
+ case 'k':
+ key++;
+ break;
+ case 'c':
+ strcpy(cellname, optarg);
+ break;
+ case 'f':
+ strcpy(keyfile, optarg);
+ break;
+ case 'p':
+ if((status = kname_parse (u_name, u_inst, u_realm, optarg)) !=
+ KSUCCESS)
+ errx (1, "principal %s: %s", optarg,
+ krb_get_err_text(status));
+ break;
+ case 'r':
+ strcpy(u_realm, optarg);
+ break;
+ case '?':
+ usage();
+ }
+ }
+ if (optind >= argc)
+ usage();
+ if (*u_realm == '\0')
+ strcpy (u_realm, local_realm);
+ if (strcmp(argv[optind], "list") == 0) {
+ if (arg_entered)
+ usage();
+ else {
+ arg_entered++;
+ list++;
+ }
+ }
+ else if (strcmp(argv[optind], "change") == 0) {
+ if (arg_entered)
+ usage();
+ else {
+ arg_entered++;
+ change++;
+ }
+ }
+ else if (strcmp(argv[optind], "add") == 0) {
+ if (arg_entered)
+ usage();
+ else {
+ arg_entered++;
+ add++;
+ }
+ }
+ else if (strcmp(argv[optind], "get") == 0) {
+ if (arg_entered)
+ usage();
+ else {
+ arg_entered++;
+ get++;
+ }
+ }
+ else
+ usage();
+ ++optind;
+
+ if (!arg_entered)
+ usage();
+
+ if (!keyfile[0])
+ strcpy(keyfile, KEYFILE);
+
+ strcpy(work_keyfile, keyfile);
+ strcpy(backup_keyfile, keyfile);
+
+ if (change || add || get) {
+ strcat(work_keyfile, ".work");
+ strcat(backup_keyfile, ".old");
+
+ copy_keyfile(keyfile, backup_keyfile);
+ }
+
+ if (add || get)
+ copy_keyfile(backup_keyfile, work_keyfile);
+
+ keyfile_mode = get_mode(keyfile);
+
+ if (change || list)
+ if ((backup_keyfile_fd = open(backup_keyfile, O_RDONLY, 0)) < 0)
+ err (1, "open %s", backup_keyfile);
+
+ if (change) {
+ if ((work_keyfile_fd =
+ open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC,
+ SRVTAB_MODE)) < 0)
+ err (1, "creat %s", work_keyfile);
+ }
+ else if (add) {
+ if ((work_keyfile_fd =
+ open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0)
+ err (1, "open with append %s", work_keyfile );
+ }
+ else if (get) {
+ if ((work_keyfile_fd =
+ open(work_keyfile, O_RDWR | O_CREAT, SRVTAB_MODE)) < 0)
+ err (1, "open for writing %s", work_keyfile);
+ }
+
+ if (change || list) {
+ while ((getst(backup_keyfile_fd, sname, SNAME_SZ) > 0) &&
+ (getst(backup_keyfile_fd, sinst, INST_SZ) > 0) &&
+ (getst(backup_keyfile_fd, srealm, REALM_SZ) > 0) &&
+ (read(backup_keyfile_fd, &key_vno, 1) > 0) &&
+ (read(backup_keyfile_fd, old_key, sizeof(old_key)) > 0)) {
+ if (list) {
+ if (!first_printed) {
+ printf(VNO_HEADER);
+ printf(PAD);
+ if (key) {
+ printf(KEY_HEADER);
+ printf(PAD);
+ }
+ printf(PRINC_HEADER);
+ first_printed = 1;
+ }
+ printf(VNO_FORMAT, key_vno);
+ printf(PAD);
+ if (key) {
+ print_key(old_key);
+ printf(PAD);
+ }
+ print_name(sname, sinst, srealm);
+ printf("\n");
+ }
+ else if (change) {
+ snprintf(change_tkt, sizeof(change_tkt),
+ TKT_ROOT "_ksrvutil.%u",
+ (unsigned)getpid());
+ krb_set_tkt_string(change_tkt);
+ destroyp = TRUE;
+
+ printf("\nPrincipal: ");
+ print_name(sname, sinst, srealm);
+ printf("; version %d\n", key_vno);
+ if (interactive)
+ change_this_key = yn("Change this key?");
+ else if (change)
+ change_this_key = 1;
+ else
+ change_this_key = 0;
+
+ if (change_this_key)
+ printf("Changing to version %d.\n", key_vno + 1);
+ else if (change)
+ printf("Not changing this key.\n");
+
+ if (change_this_key) {
+ /*
+ * This is not a good choice of seed when/if the
+ * key has been compromised so we also use a
+ * random sequence number!
+ */
+ des_init_random_number_generator(&old_key);
+ {
+ des_cblock seqnum;
+ des_generate_random_block(&seqnum);
+ des_set_sequence_number((unsigned char *)&seqnum);
+ }
+ /*
+ * Pick a new key and determine whether or not
+ * it is safe to change
+ */
+ if ((status =
+ get_svc_new_key(&new_key, sname, sinst,
+ srealm, keyfile)) == KADM_SUCCESS)
+ key_vno++;
+ else {
+ memcpy(new_key, old_key, sizeof(new_key));
+ warnx ("Key NOT changed: %s\n",
+ krb_get_err_text(status));
+ change_this_key = FALSE;
+ }
+ }
+ else
+ memcpy(new_key, old_key, sizeof(new_key));
+ append_srvtab(work_keyfile, work_keyfile_fd,
+ sname, sinst, srealm, key_vno, new_key);
+ if (key && change_this_key) {
+ printf("Old key: ");
+ print_key(old_key);
+ printf("; new key: ");
+ print_key(new_key);
+ printf("\n");
+ }
+ if (change_this_key) {
+ if ((status = kadm_change_pw(new_key)) == KADM_SUCCESS) {
+ printf("Key changed.\n");
+ dest_tkt();
+ }
+ else {
+ com_err(__progname, status,
+ " attempting to change password.");
+ dest_tkt();
+ /* XXX This knows the format of a keyfile */
+ if (lseek(work_keyfile_fd, -9, SEEK_CUR) >= 0) {
+ key_vno--;
+ safe_write(work_keyfile,
+ work_keyfile_fd, &key_vno, 1);
+ safe_write(work_keyfile, work_keyfile_fd,
+ old_key, sizeof(des_cblock));
+ fsync(work_keyfile_fd);
+ fprintf(stderr,"Key NOT changed.\n");
+ } else {
+ warn ("Unable to revert keyfile");
+ leave("", 1);
+ }
+ }
+ }
+ }
+ memset(old_key, 0, sizeof(des_cblock));
+ memset(new_key, 0, sizeof(des_cblock));
+ }
+ }
+ else if (add) {
+ do {
+ do {
+ safe_read_stdin("Name: ", databuf, sizeof(databuf));
+ strncpy(sname, databuf, sizeof(sname) - 1);
+ if (strchr(sname, '.') != 0) {
+ strcpy(sinst, strchr(sname, '.') + 1);
+ *(strchr(sname, '.')) = 0;
+ } else {
+ safe_read_stdin("Instance: ", databuf, sizeof(databuf));
+ strncpy(sinst, databuf, sizeof(sinst) - 1);
+ }
+ safe_read_stdin("Realm: ", databuf, sizeof(databuf));
+ strncpy(srealm, databuf, sizeof(srealm) - 1);
+ safe_read_stdin("Version number: ", databuf, sizeof(databuf));
+ key_vno = atoi(databuf);
+ if (key_vno == 0)
+ key_vno = 1; /* Version numbers are never 0 */
+ if (!srealm[0])
+ strcpy(srealm, local_realm);
+ printf("New principal: ");
+ print_name(sname, sinst, srealm);
+ printf("; version %d\n", key_vno);
+ } while (!yn("Is this correct?"));
+ get_key_from_password(&new_key, cellname);
+ if (key) {
+ printf("Key: ");
+ print_key(new_key);
+ printf("\n");
+ }
+ append_srvtab(work_keyfile, work_keyfile_fd,
+ sname, sinst, srealm, key_vno, new_key);
+ printf("Key successfully added.\n");
+ } while (yn("Would you like to add another key?"));
+ }
+ else if (get) {
+ ksrvutil_get(work_keyfile_fd, work_keyfile,
+ argc - optind, argv + optind);
+ }
+
+ if (change || list)
+ if (close(backup_keyfile_fd) < 0)
+ warn ("close %s", backup_keyfile);
+
+ if (change || add || get) {
+ if (close(work_keyfile_fd) < 0)
+ err (1, "close %s", work_keyfile);
+ if (rename(work_keyfile, keyfile) < 0)
+ err (1, "rename(%s, %s)", work_keyfile, keyfile);
+ chmod(backup_keyfile, keyfile_mode);
+ chmod(keyfile, keyfile_mode);
+ printf("Old keyfile in %s.\n", backup_keyfile);
+ }
+ return 0;
+}
OpenPOWER on IntegriCloud