From 8c5c9f25772e9d94c932ad1ac2f70638394042fd Mon Sep 17 00:00:00 2001 From: Garrett Wollman Date: Fri, 20 Jan 1995 22:38:30 +0000 Subject: [PATCH] Add last piece in fully-functional Kerberos implementation: ksrvutil, a program to manage /etc/srvtab. --- eBones/ksrvutil/HOW-TO | 291 ++++++++++++++ eBones/ksrvutil/Makefile | 10 + eBones/ksrvutil/ksrvutil.c | 580 ++++++++++++++++++++++++++++ eBones/usr.sbin/ksrvutil/Makefile | 10 + eBones/usr.sbin/ksrvutil/ksrvutil.c | 580 ++++++++++++++++++++++++++++ 5 files changed, 1471 insertions(+) create mode 100644 eBones/ksrvutil/HOW-TO create mode 100644 eBones/ksrvutil/Makefile create mode 100644 eBones/ksrvutil/ksrvutil.c create mode 100644 eBones/usr.sbin/ksrvutil/Makefile create mode 100644 eBones/usr.sbin/ksrvutil/ksrvutil.c diff --git a/eBones/ksrvutil/HOW-TO b/eBones/ksrvutil/HOW-TO new file mode 100644 index 000000000000..53f719c111aa --- /dev/null +++ b/eBones/ksrvutil/HOW-TO @@ -0,0 +1,291 @@ +To re-create this export-controlled program from eBones: + +1) Copy ksrvutil.c from the kadmin directory. +2) perl -spi.bak -e 's/\$(Header[^\$]*)\$/$1/g' *.[ch] +3) Apply this patch: + +*** ksrvutil.c.orig Fri Jan 20 17:19:45 1995 +--- ksrvutil.c Fri Jan 20 17:27:38 1995 +*************** +*** 1,10 **** + /* +- * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/ksrvutil.c,v $ +- * $Author: jtkohl $ +- * + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * . + * + * list and update contents of srvtab files +--- 1,7 ---- + /* + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * Copyright.MIT. + * + * list and update contents of srvtab files +*************** +*** 12,20 **** + + #ifndef lint + static char rcsid_ksrvutil_c[] = +! "BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/ksrvutil.c,v 4.1 89/09/26 09:33:49 jtkohl Exp "; + #endif lint + +- #include + /* + * ksrvutil +--- 9,20 ---- + + #ifndef lint ++ #if 0 + static char rcsid_ksrvutil_c[] = +! "BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/ksrvutil.c,v 4.1 89/09/26 09:33:49 jtkohl Exp "; +! #endif +! static const char rcsid[] = +! "$Id$"; + #endif lint + + /* + * ksrvutil +*************** +*** 37,40 **** +--- 37,41 ---- + #include + #include ++ #include + + #ifdef NOENCRYPTION +*************** +*** 54,58 **** + + extern int errno; +- extern char *sys_errlist[]; + + extern void krb_set_tkt_string(); +--- 55,58 ---- +*************** +*** 79,85 **** + if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) { + if (errno != ENOENT) { +! (void)fprintf(stderr, "%s: Unable to read %s: %s\n", progname, +! keyfile, sys_errlist[errno]); +! exit(1); + } + else { +--- 79,83 ---- + if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) { + if (errno != ENOENT) { +! err(1, "unable to read %s", keyfile); + } + else { +*************** +*** 88,100 **** + open(keyfile, + O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0) { +! (void) fprintf(stderr, "%s: Unable to create %s: %s\n", +! progname, keyfile, sys_errlist[errno]); +! exit(1); + } + else + if (close(keyfile_fd) < 0) { +! (void) fprintf(stderr, "%s: Failure closing %s: %s\n", +! progname, keyfile, sys_errlist[errno]); +! exit(1); + } + } +--- 86,94 ---- + open(keyfile, + O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0) { +! err(1, "unable to create %s", keyfile); + } + else + if (close(keyfile_fd) < 0) { +! err(1, "failure closing %s", keyfile); + } + } +*************** +*** 107,135 **** + open(backup_keyfile, O_WRONLY | O_TRUNC | O_CREAT, + keyfile_mode)) < 0) { +! (void) fprintf(stderr, "%s: Unable to write %s: %s\n", progname, +! backup_keyfile, sys_errlist[errno]); +! exit(1); + } + do { + if ((rcount = read(keyfile_fd, (char *)buf, sizeof(buf))) < 0) { +! (void) fprintf(stderr, "%s: Error reading %s: %s\n", progname, +! keyfile, sys_errlist[errno]); +! exit(1); + } + if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount)) { +! (void) fprintf(stderr, "%s: Error writing %s: %s\n", progname, +! backup_keyfile, sys_errlist[errno]); +! exit(1); + } + } while (rcount); + if (close(backup_keyfile_fd) < 0) { +! (void) fprintf(stderr, "%s: Error closing %s: %s\n", progname, +! backup_keyfile, sys_errlist[errno]); +! exit(1); + } + if (close(keyfile_fd) < 0) { +! (void) fprintf(stderr, "%s: Error closing %s: %s\n", progname, +! keyfile, sys_errlist[errno]); +! exit(1); + } + } +--- 101,119 ---- + open(backup_keyfile, O_WRONLY | O_TRUNC | O_CREAT, + keyfile_mode)) < 0) { +! err(1, "unable to write %s", backup_keyfile); + } + do { + if ((rcount = read(keyfile_fd, (char *)buf, sizeof(buf))) < 0) { +! err(1, "error reading %s", keyfile); + } + if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount)) { +! err(1, "error writing %s", backup_keyfile); + } + } while (rcount); + if (close(backup_keyfile_fd) < 0) { +! err(1, "error closing %s", backup_keyfile); + } + if (close(keyfile_fd) < 0) { +! err(1, "error closing %s", keyfile); + } + } +*************** +*** 145,151 **** + (void) bzero(buf, size); + if (read(0, buf, size - 1) < 0) { +! (void) fprintf(stderr, "Failure reading from stdin: %s\n", +! sys_errlist[errno]); +! leave((char *)NULL, 1); + } + fflush(stdin); +--- 129,134 ---- + (void) bzero(buf, size); + if (read(0, buf, size - 1) < 0) { +! warn("failure reading from stdin"); +! leave((char *)NULL, 1); + } + fflush(stdin); +*************** +*** 163,170 **** + { + if (write(fd, buf, len) != len) { +! (void) fprintf(stderr, "%s: Failure writing to %s: %s\n", progname, +! filename, sys_errlist[errno]); +! (void) close(fd); +! leave("In progress srvtab in this file.", 1); + } + } +--- 146,152 ---- + { + if (write(fd, buf, len) != len) { +! warn("failure writing %s", filename); +! close(fd); +! leave("In progress srvtab in this file.", 1); + } + } +*************** +*** 343,349 **** + if (change || list) { + if ((backup_keyfile_fd = open(backup_keyfile, O_RDONLY, 0)) < 0) { +! (void) fprintf(stderr, "%s: Unable to read %s: %s\n", argv[0], +! backup_keyfile, sys_errlist[errno]); +! exit(1); + } + } +--- 325,329 ---- + if (change || list) { + if ((backup_keyfile_fd = open(backup_keyfile, O_RDONLY, 0)) < 0) { +! err(1, "unable to read %s", backup_keyfile); + } + } +*************** +*** 353,359 **** + open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC, + SRVTAB_MODE)) < 0) { +! (void) fprintf(stderr, "%s: Unable to write %s: %s\n", argv[0], +! work_keyfile, sys_errlist[errno]); +! exit(1); + } + } +--- 333,337 ---- + open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC, + SRVTAB_MODE)) < 0) { +! err(1, "unable to write %s", work_keyfile); + } + } +*************** +*** 361,367 **** + if ((work_keyfile_fd = + open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0) { +! (void) fprintf(stderr, "%s: Unable to open %s for append: %s\n", +! argv[0], work_keyfile, sys_errlist[errno]); +! exit(1); + } + } +--- 339,343 ---- + if ((work_keyfile_fd = + open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0) { +! err(1, "unable to append to %s", work_keyfile); + } + } +*************** +*** 456,463 **** + } + else { +! (void)fprintf(stderr, +! "%s: Unable to revert keyfile: %s\n", +! argv[0], sys_errlist[errno]); +! leave("", 1); + } + } +--- 432,437 ---- + } + else { +! warn("unable to revert keyfile"); +! leave("", 1); + } + } +*************** +*** 499,518 **** + if (change || list) + if (close(backup_keyfile_fd) < 0) { +! (void) fprintf(stderr, "%s: Failure closing %s: %s\n", +! argv[0], backup_keyfile, sys_errlist[errno]); +! (void) fprintf(stderr, "continuing...\n"); + } + + if (change || add) { + if (close(work_keyfile_fd) < 0) { +! (void) fprintf(stderr, "%s: Failure closing %s: %s\n", +! argv[0], work_keyfile, sys_errlist[errno]); +! exit(1); + } + if (rename(work_keyfile, keyfile) < 0) { +! (void) fprintf(stderr, "%s: Failure renaming %s to %s: %s\n", +! argv[0], work_keyfile, keyfile, +! sys_errlist[errno]); +! exit(1); + } + (void) chmod(backup_keyfile, keyfile_mode); +--- 473,485 ---- + if (change || list) + if (close(backup_keyfile_fd) < 0) { +! warn("failure closing %s, continuing", backup_keyfile); + } + + if (change || add) { + if (close(work_keyfile_fd) < 0) { +! err(1, "failure closing %s", work_keyfile); + } + if (rename(work_keyfile, keyfile) < 0) { +! err(1, "failure renaming %s to %s", work_keyfile, keyfile); + } + (void) chmod(backup_keyfile, keyfile_mode); diff --git a/eBones/ksrvutil/Makefile b/eBones/ksrvutil/Makefile new file mode 100644 index 000000000000..bdff452179a2 --- /dev/null +++ b/eBones/ksrvutil/Makefile @@ -0,0 +1,10 @@ +# $Id$ + +PROG= ksrvutil +SRCS= ksrvutil.c +CFLAGS+= -I${.CURDIR}/../include -I${.CURDIR}/../libkadm +LDADD+= -L${KADMOBJDIR} -lkadm -L${KRBOBJDIR} -lkrb -L${DESOBJDIR} -ldes \ + -lcom_err +NOMAN= #man page installed by ../man + +.include diff --git a/eBones/ksrvutil/ksrvutil.c b/eBones/ksrvutil/ksrvutil.c new file mode 100644 index 000000000000..e240759dca52 --- /dev/null +++ b/eBones/ksrvutil/ksrvutil.c @@ -0,0 +1,580 @@ +/* + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * list and update contents of srvtab files + */ + +#ifndef lint +#if 0 +static char rcsid_ksrvutil_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/ksrvutil.c,v 4.1 89/09/26 09:33:49 jtkohl Exp "; +#endif +static const char rcsid[] = + "$Id$"; +#endif lint + +/* + * ksrvutil + * list and update the contents of srvtab files + */ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else /* NOENCRYPTION */ +#define read_long_pw_string des_read_pw_string +#endif /* NOENCRYPTION */ +int read_long_pw_string(); + +#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" + +extern int errno; + +extern void krb_set_tkt_string(); +void leave(); +unsigned short get_mode(); + +void +copy_keyfile(progname, keyfile, backup_keyfile) + char *progname; + 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; + + (void) bzero((char *)buf, sizeof(buf)); + + do { + try_again = FALSE; + if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) { + if (errno != ENOENT) { + err(1, "unable to read %s", keyfile); + } + else { + try_again = TRUE; + if ((keyfile_fd = + open(keyfile, + O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0) { + err(1, "unable to create %s", keyfile); + } + else + if (close(keyfile_fd) < 0) { + err(1, "failure closing %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, "unable to write %s", backup_keyfile); + } + do { + if ((rcount = read(keyfile_fd, (char *)buf, sizeof(buf))) < 0) { + err(1, "error reading %s", keyfile); + } + if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount)) { + err(1, "error writing %s", backup_keyfile); + } + } while (rcount); + if (close(backup_keyfile_fd) < 0) { + err(1, "error closing %s", backup_keyfile); + } + if (close(keyfile_fd) < 0) { + err(1, "error closing %s", keyfile); + } +} + +void +safe_read_stdin(prompt, buf, size) + char *prompt; + char *buf; + int size; +{ + (void) printf(prompt); + (void) fflush(stdout); + (void) bzero(buf, size); + if (read(0, buf, size - 1) < 0) { + warn("failure reading from stdin"); + leave((char *)NULL, 1); + } + fflush(stdin); + buf[strlen(buf)-1] = 0; +} + + +void +safe_write(progname, filename, fd, buf, len) + char *progname; + char *filename; + int fd; + char *buf; + int len; +{ + if (write(fd, buf, len) != len) { + warn("failure writing %s", filename); + close(fd); + leave("In progress srvtab in this file.", 1); + } +} + +int +yn(string) + char *string; +{ + char ynbuf[5]; + + (void) printf("%s (y,n) [y] ", string); + for (;;) { + safe_read_stdin("", ynbuf, sizeof(ynbuf)); + + if ((ynbuf[0] == 'n') || (ynbuf[0] == 'N')) + return(0); + else if ((ynbuf[0] == 'y') || (ynbuf[0] == 'Y') || (ynbuf[0] == 0)) + return(1); + else { + (void) printf("Please enter 'y' or 'n': "); + fflush(stdout); + } + } +} + +void +append_srvtab(progname, filename, fd, sname, sinst, + srealm, key_vno, key) + char *progname; + char *filename; + int fd; + char *sname; + char *sinst; + char *srealm; + unsigned char key_vno; + des_cblock key; +{ + /* Add one to append null */ + safe_write(progname, filename, fd, sname, strlen(sname) + 1); + safe_write(progname, filename, fd, sinst, strlen(sinst) + 1); + safe_write(progname, filename, fd, srealm, strlen(srealm) + 1); + safe_write(progname, filename, fd, (char *)&key_vno, 1); + safe_write(progname, filename, fd, (char *)key, sizeof(des_cblock)); + (void) fsync(fd); +} + +unsigned short +get_mode(filename) + char *filename; +{ + struct stat statbuf; + unsigned short mode; + + (void) bzero((char *)&statbuf, sizeof(statbuf)); + + if (stat(filename, &statbuf) < 0) + mode = SRVTAB_MODE; + else + mode = statbuf.st_mode; + + return(mode); +} + +main(argc,argv) + 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 */ + int i; + int interactive = FALSE; + int list = FALSE; + int change = FALSE; + int add = 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? */ + + int get_svc_new_key(); + void get_key_from_password(); + void print_key(); + void print_name(); + + (void) bzero((char *)sname, sizeof(sname)); + (void) bzero((char *)sinst, sizeof(sinst)); + (void) bzero((char *)srealm, sizeof(srealm)); + + (void) bzero((char *)change_tkt, sizeof(change_tkt)); + (void) bzero((char *)keyfile, sizeof(keyfile)); + (void) bzero((char *)work_keyfile, sizeof(work_keyfile)); + (void) bzero((char *)backup_keyfile, sizeof(backup_keyfile)); + (void) bzero((char *)local_realm, sizeof(local_realm)); + + (void) sprintf(change_tkt, "/tmp/tkt_ksrvutil.%d", getpid()); + krb_set_tkt_string(change_tkt); + + /* This is used only as a default for adding keys */ + if (krb_get_lrealm(local_realm, 1) != KSUCCESS) + (void) strcpy(local_realm, KRB_REALM); + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-i") == 0) + interactive++; + else if (strcmp(argv[i], "-k") == 0) + key++; + else if (strcmp(argv[i], "list") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + list++; + } + } + else if (strcmp(argv[i], "change") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + change++; + } + } + else if (strcmp(argv[i], "add") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + add++; + } + } + else if (strcmp(argv[i], "-f") == 0) { + if (++i == argc) + usage(); + else + (void) strcpy(keyfile, argv[i]); + } + else + usage(); + } + + if (!arg_entered) + usage(); + + if (!keyfile[0]) + (void) strcpy(keyfile, KEYFILE); + + (void) strcpy(work_keyfile, keyfile); + (void) strcpy(backup_keyfile, keyfile); + + if (change || add) { + (void) strcat(work_keyfile, ".work"); + (void) strcat(backup_keyfile, ".old"); + + copy_keyfile(argv[0], keyfile, backup_keyfile); + } + + if (add) + copy_keyfile(argv[0], 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, "unable to read %s", backup_keyfile); + } + } + + if (change) { + if ((work_keyfile_fd = + open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC, + SRVTAB_MODE)) < 0) { + err(1, "unable to write %s", work_keyfile); + } + } + else if (add) { + if ((work_keyfile_fd = + open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0) { + err(1, "unable to append to %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,(char *)old_key,sizeof(old_key)) > 0)) { + if (list) { + if (!first_printed) { + (void) printf(VNO_HEADER); + (void) printf(PAD); + if (key) { + (void) printf(KEY_HEADER); + (void) printf(PAD); + } + (void) printf(PRINC_HEADER); + first_printed = 1; + } + (void) printf(VNO_FORMAT, key_vno); + (void) printf(PAD); + if (key) { + print_key(old_key); + (void) printf(PAD); + } + print_name(sname, sinst, srealm); + (void) printf("\n"); + } + else if (change) { + (void) printf("\nPrincipal: "); + print_name(sname, sinst, srealm); + (void) 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) + (void) printf("Changing to version %d.\n", key_vno + 1); + else if (change) + (void) printf("Not changing this key.\n"); + + if (change_this_key) { + /* + * 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 { + (void) bcopy(old_key, new_key, sizeof(new_key)); + (void) fprintf(stderr, "%s: Key NOT changed: %s\n", + argv[0], krb_err_txt[status]); + change_this_key = FALSE; + } + } + else + (void) bcopy(old_key, new_key, sizeof(new_key)); + append_srvtab(argv[0], work_keyfile, work_keyfile_fd, + sname, sinst, srealm, key_vno, new_key); + if (key && change_this_key) { + (void) printf("Old key: "); + print_key(old_key); + (void) printf("; new key: "); + print_key(new_key); + (void) printf("\n"); + } + if (change_this_key) { + if ((status = kadm_change_pw(new_key)) == KADM_SUCCESS) { + (void) printf("Key changed.\n"); + (void) dest_tkt(); + } + else { + com_err(argv[0], status, + " attempting to change password."); + (void) dest_tkt(); + /* XXX This knows the format of a keyfile */ + if (lseek(work_keyfile_fd, -9, L_INCR) >= 0) { + key_vno--; + safe_write(argv[0], work_keyfile, + work_keyfile_fd, (char *)&key_vno, 1); + safe_write(argv[0], work_keyfile, work_keyfile_fd, + (char *)old_key, sizeof(des_cblock)); + (void) fsync(work_keyfile_fd); + (void) fprintf(stderr,"Key NOT changed.\n"); + } + else { + warn("unable to revert keyfile"); + leave("", 1); + } + } + } + } + bzero((char *)old_key, sizeof(des_cblock)); + bzero((char *)new_key, sizeof(des_cblock)); + } + } + else if (add) { + do { + do { + safe_read_stdin("Name: ", databuf, sizeof(databuf)); + (void) strncpy(sname, databuf, sizeof(sname) - 1); + safe_read_stdin("Instance: ", databuf, sizeof(databuf)); + (void) strncpy(sinst, databuf, sizeof(sinst) - 1); + safe_read_stdin("Realm: ", databuf, sizeof(databuf)); + (void) strncpy(srealm, databuf, sizeof(srealm) - 1); + safe_read_stdin("Version number: ", databuf, sizeof(databuf)); + key_vno = atoi(databuf); + if (!srealm[0]) + (void) strcpy(srealm, local_realm); + (void) printf("New principal: "); + print_name(sname, sinst, srealm); + (void) printf("; version %d\n", key_vno); + } while (!yn("Is this correct?")); + get_key_from_password(new_key); + if (key) { + (void) printf("Key: "); + print_key(new_key); + (void) printf("\n"); + } + append_srvtab(argv[0], work_keyfile, work_keyfile_fd, + sname, sinst, srealm, key_vno, new_key); + (void) printf("Key successfully added.\n"); + } while (yn("Would you like to add another key?")); + } + + if (change || list) + if (close(backup_keyfile_fd) < 0) { + warn("failure closing %s, continuing", backup_keyfile); + } + + if (change || add) { + if (close(work_keyfile_fd) < 0) { + err(1, "failure closing %s", work_keyfile); + } + if (rename(work_keyfile, keyfile) < 0) { + err(1, "failure renaming %s to %s", work_keyfile, keyfile); + } + (void) chmod(backup_keyfile, keyfile_mode); + (void) chmod(keyfile, keyfile_mode); + (void) printf("Old keyfile in %s.\n", backup_keyfile); + } + + exit(0); +} + +void +print_key(key) + des_cblock key; +{ + int i; + + for (i = 0; i < 4; i++) + (void) printf("%02x", key[i]); + (void) printf(" "); + for (i = 4; i < 8; i++) + (void) printf("%02x", key[i]); +} + +void +print_name(name, inst, realm) + char *name; + char *inst; + char *realm; +{ + (void) printf("%s%s%s%s%s", name, inst[0] ? "." : "", inst, + realm[0] ? "@" : "", realm); +} + +int +get_svc_new_key(new_key, sname, sinst, srealm, keyfile) + 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("changepw", KRB_MASTER, srealm)) == + KADM_SUCCESS)) { +#ifdef NOENCRYPTION + (void) bzero((char *) new_key, sizeof(des_cblock)); + new_key[0] = (unsigned char) 1; +#else /* NOENCRYPTION */ + (void) des_random_key(new_key); +#endif /* NOENCRYPTION */ + return(KADM_SUCCESS); + } + + return(status); +} + +void +get_key_from_password(key) + des_cblock key; +{ + 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 + (void) bzero((char *) key, sizeof(des_cblock)); + key[0] = (unsigned char) 1; +#else /* NOENCRYPTION */ + (void) des_string_to_key(password, key); +#endif /* NOENCRYPTION */ + (void) bzero((char *)password, sizeof(password)); +} + +usage() +{ + (void) fprintf(stderr, "Usage: ksrvutil [-f keyfile] [-i] [-k] "); + (void) fprintf(stderr, "{list | change | add}\n"); + (void) fprintf(stderr, " -i causes the program to ask for "); + (void) fprintf(stderr, "confirmation before changing keys.\n"); + (void) fprintf(stderr, " -k causes the key to printed for list or "); + (void) fprintf(stderr, "change.\n"); + exit(1); +} + +void +leave(str,x) +char *str; +int x; +{ + if (str) + (void) fprintf(stderr, "%s\n", str); + (void) dest_tkt(); + exit(x); +} diff --git a/eBones/usr.sbin/ksrvutil/Makefile b/eBones/usr.sbin/ksrvutil/Makefile new file mode 100644 index 000000000000..bdff452179a2 --- /dev/null +++ b/eBones/usr.sbin/ksrvutil/Makefile @@ -0,0 +1,10 @@ +# $Id$ + +PROG= ksrvutil +SRCS= ksrvutil.c +CFLAGS+= -I${.CURDIR}/../include -I${.CURDIR}/../libkadm +LDADD+= -L${KADMOBJDIR} -lkadm -L${KRBOBJDIR} -lkrb -L${DESOBJDIR} -ldes \ + -lcom_err +NOMAN= #man page installed by ../man + +.include diff --git a/eBones/usr.sbin/ksrvutil/ksrvutil.c b/eBones/usr.sbin/ksrvutil/ksrvutil.c new file mode 100644 index 000000000000..e240759dca52 --- /dev/null +++ b/eBones/usr.sbin/ksrvutil/ksrvutil.c @@ -0,0 +1,580 @@ +/* + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * list and update contents of srvtab files + */ + +#ifndef lint +#if 0 +static char rcsid_ksrvutil_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/ksrvutil.c,v 4.1 89/09/26 09:33:49 jtkohl Exp "; +#endif +static const char rcsid[] = + "$Id$"; +#endif lint + +/* + * ksrvutil + * list and update the contents of srvtab files + */ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else /* NOENCRYPTION */ +#define read_long_pw_string des_read_pw_string +#endif /* NOENCRYPTION */ +int read_long_pw_string(); + +#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" + +extern int errno; + +extern void krb_set_tkt_string(); +void leave(); +unsigned short get_mode(); + +void +copy_keyfile(progname, keyfile, backup_keyfile) + char *progname; + 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; + + (void) bzero((char *)buf, sizeof(buf)); + + do { + try_again = FALSE; + if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) { + if (errno != ENOENT) { + err(1, "unable to read %s", keyfile); + } + else { + try_again = TRUE; + if ((keyfile_fd = + open(keyfile, + O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0) { + err(1, "unable to create %s", keyfile); + } + else + if (close(keyfile_fd) < 0) { + err(1, "failure closing %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, "unable to write %s", backup_keyfile); + } + do { + if ((rcount = read(keyfile_fd, (char *)buf, sizeof(buf))) < 0) { + err(1, "error reading %s", keyfile); + } + if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount)) { + err(1, "error writing %s", backup_keyfile); + } + } while (rcount); + if (close(backup_keyfile_fd) < 0) { + err(1, "error closing %s", backup_keyfile); + } + if (close(keyfile_fd) < 0) { + err(1, "error closing %s", keyfile); + } +} + +void +safe_read_stdin(prompt, buf, size) + char *prompt; + char *buf; + int size; +{ + (void) printf(prompt); + (void) fflush(stdout); + (void) bzero(buf, size); + if (read(0, buf, size - 1) < 0) { + warn("failure reading from stdin"); + leave((char *)NULL, 1); + } + fflush(stdin); + buf[strlen(buf)-1] = 0; +} + + +void +safe_write(progname, filename, fd, buf, len) + char *progname; + char *filename; + int fd; + char *buf; + int len; +{ + if (write(fd, buf, len) != len) { + warn("failure writing %s", filename); + close(fd); + leave("In progress srvtab in this file.", 1); + } +} + +int +yn(string) + char *string; +{ + char ynbuf[5]; + + (void) printf("%s (y,n) [y] ", string); + for (;;) { + safe_read_stdin("", ynbuf, sizeof(ynbuf)); + + if ((ynbuf[0] == 'n') || (ynbuf[0] == 'N')) + return(0); + else if ((ynbuf[0] == 'y') || (ynbuf[0] == 'Y') || (ynbuf[0] == 0)) + return(1); + else { + (void) printf("Please enter 'y' or 'n': "); + fflush(stdout); + } + } +} + +void +append_srvtab(progname, filename, fd, sname, sinst, + srealm, key_vno, key) + char *progname; + char *filename; + int fd; + char *sname; + char *sinst; + char *srealm; + unsigned char key_vno; + des_cblock key; +{ + /* Add one to append null */ + safe_write(progname, filename, fd, sname, strlen(sname) + 1); + safe_write(progname, filename, fd, sinst, strlen(sinst) + 1); + safe_write(progname, filename, fd, srealm, strlen(srealm) + 1); + safe_write(progname, filename, fd, (char *)&key_vno, 1); + safe_write(progname, filename, fd, (char *)key, sizeof(des_cblock)); + (void) fsync(fd); +} + +unsigned short +get_mode(filename) + char *filename; +{ + struct stat statbuf; + unsigned short mode; + + (void) bzero((char *)&statbuf, sizeof(statbuf)); + + if (stat(filename, &statbuf) < 0) + mode = SRVTAB_MODE; + else + mode = statbuf.st_mode; + + return(mode); +} + +main(argc,argv) + 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 */ + int i; + int interactive = FALSE; + int list = FALSE; + int change = FALSE; + int add = 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? */ + + int get_svc_new_key(); + void get_key_from_password(); + void print_key(); + void print_name(); + + (void) bzero((char *)sname, sizeof(sname)); + (void) bzero((char *)sinst, sizeof(sinst)); + (void) bzero((char *)srealm, sizeof(srealm)); + + (void) bzero((char *)change_tkt, sizeof(change_tkt)); + (void) bzero((char *)keyfile, sizeof(keyfile)); + (void) bzero((char *)work_keyfile, sizeof(work_keyfile)); + (void) bzero((char *)backup_keyfile, sizeof(backup_keyfile)); + (void) bzero((char *)local_realm, sizeof(local_realm)); + + (void) sprintf(change_tkt, "/tmp/tkt_ksrvutil.%d", getpid()); + krb_set_tkt_string(change_tkt); + + /* This is used only as a default for adding keys */ + if (krb_get_lrealm(local_realm, 1) != KSUCCESS) + (void) strcpy(local_realm, KRB_REALM); + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-i") == 0) + interactive++; + else if (strcmp(argv[i], "-k") == 0) + key++; + else if (strcmp(argv[i], "list") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + list++; + } + } + else if (strcmp(argv[i], "change") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + change++; + } + } + else if (strcmp(argv[i], "add") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + add++; + } + } + else if (strcmp(argv[i], "-f") == 0) { + if (++i == argc) + usage(); + else + (void) strcpy(keyfile, argv[i]); + } + else + usage(); + } + + if (!arg_entered) + usage(); + + if (!keyfile[0]) + (void) strcpy(keyfile, KEYFILE); + + (void) strcpy(work_keyfile, keyfile); + (void) strcpy(backup_keyfile, keyfile); + + if (change || add) { + (void) strcat(work_keyfile, ".work"); + (void) strcat(backup_keyfile, ".old"); + + copy_keyfile(argv[0], keyfile, backup_keyfile); + } + + if (add) + copy_keyfile(argv[0], 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, "unable to read %s", backup_keyfile); + } + } + + if (change) { + if ((work_keyfile_fd = + open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC, + SRVTAB_MODE)) < 0) { + err(1, "unable to write %s", work_keyfile); + } + } + else if (add) { + if ((work_keyfile_fd = + open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0) { + err(1, "unable to append to %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,(char *)old_key,sizeof(old_key)) > 0)) { + if (list) { + if (!first_printed) { + (void) printf(VNO_HEADER); + (void) printf(PAD); + if (key) { + (void) printf(KEY_HEADER); + (void) printf(PAD); + } + (void) printf(PRINC_HEADER); + first_printed = 1; + } + (void) printf(VNO_FORMAT, key_vno); + (void) printf(PAD); + if (key) { + print_key(old_key); + (void) printf(PAD); + } + print_name(sname, sinst, srealm); + (void) printf("\n"); + } + else if (change) { + (void) printf("\nPrincipal: "); + print_name(sname, sinst, srealm); + (void) 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) + (void) printf("Changing to version %d.\n", key_vno + 1); + else if (change) + (void) printf("Not changing this key.\n"); + + if (change_this_key) { + /* + * 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 { + (void) bcopy(old_key, new_key, sizeof(new_key)); + (void) fprintf(stderr, "%s: Key NOT changed: %s\n", + argv[0], krb_err_txt[status]); + change_this_key = FALSE; + } + } + else + (void) bcopy(old_key, new_key, sizeof(new_key)); + append_srvtab(argv[0], work_keyfile, work_keyfile_fd, + sname, sinst, srealm, key_vno, new_key); + if (key && change_this_key) { + (void) printf("Old key: "); + print_key(old_key); + (void) printf("; new key: "); + print_key(new_key); + (void) printf("\n"); + } + if (change_this_key) { + if ((status = kadm_change_pw(new_key)) == KADM_SUCCESS) { + (void) printf("Key changed.\n"); + (void) dest_tkt(); + } + else { + com_err(argv[0], status, + " attempting to change password."); + (void) dest_tkt(); + /* XXX This knows the format of a keyfile */ + if (lseek(work_keyfile_fd, -9, L_INCR) >= 0) { + key_vno--; + safe_write(argv[0], work_keyfile, + work_keyfile_fd, (char *)&key_vno, 1); + safe_write(argv[0], work_keyfile, work_keyfile_fd, + (char *)old_key, sizeof(des_cblock)); + (void) fsync(work_keyfile_fd); + (void) fprintf(stderr,"Key NOT changed.\n"); + } + else { + warn("unable to revert keyfile"); + leave("", 1); + } + } + } + } + bzero((char *)old_key, sizeof(des_cblock)); + bzero((char *)new_key, sizeof(des_cblock)); + } + } + else if (add) { + do { + do { + safe_read_stdin("Name: ", databuf, sizeof(databuf)); + (void) strncpy(sname, databuf, sizeof(sname) - 1); + safe_read_stdin("Instance: ", databuf, sizeof(databuf)); + (void) strncpy(sinst, databuf, sizeof(sinst) - 1); + safe_read_stdin("Realm: ", databuf, sizeof(databuf)); + (void) strncpy(srealm, databuf, sizeof(srealm) - 1); + safe_read_stdin("Version number: ", databuf, sizeof(databuf)); + key_vno = atoi(databuf); + if (!srealm[0]) + (void) strcpy(srealm, local_realm); + (void) printf("New principal: "); + print_name(sname, sinst, srealm); + (void) printf("; version %d\n", key_vno); + } while (!yn("Is this correct?")); + get_key_from_password(new_key); + if (key) { + (void) printf("Key: "); + print_key(new_key); + (void) printf("\n"); + } + append_srvtab(argv[0], work_keyfile, work_keyfile_fd, + sname, sinst, srealm, key_vno, new_key); + (void) printf("Key successfully added.\n"); + } while (yn("Would you like to add another key?")); + } + + if (change || list) + if (close(backup_keyfile_fd) < 0) { + warn("failure closing %s, continuing", backup_keyfile); + } + + if (change || add) { + if (close(work_keyfile_fd) < 0) { + err(1, "failure closing %s", work_keyfile); + } + if (rename(work_keyfile, keyfile) < 0) { + err(1, "failure renaming %s to %s", work_keyfile, keyfile); + } + (void) chmod(backup_keyfile, keyfile_mode); + (void) chmod(keyfile, keyfile_mode); + (void) printf("Old keyfile in %s.\n", backup_keyfile); + } + + exit(0); +} + +void +print_key(key) + des_cblock key; +{ + int i; + + for (i = 0; i < 4; i++) + (void) printf("%02x", key[i]); + (void) printf(" "); + for (i = 4; i < 8; i++) + (void) printf("%02x", key[i]); +} + +void +print_name(name, inst, realm) + char *name; + char *inst; + char *realm; +{ + (void) printf("%s%s%s%s%s", name, inst[0] ? "." : "", inst, + realm[0] ? "@" : "", realm); +} + +int +get_svc_new_key(new_key, sname, sinst, srealm, keyfile) + 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("changepw", KRB_MASTER, srealm)) == + KADM_SUCCESS)) { +#ifdef NOENCRYPTION + (void) bzero((char *) new_key, sizeof(des_cblock)); + new_key[0] = (unsigned char) 1; +#else /* NOENCRYPTION */ + (void) des_random_key(new_key); +#endif /* NOENCRYPTION */ + return(KADM_SUCCESS); + } + + return(status); +} + +void +get_key_from_password(key) + des_cblock key; +{ + 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 + (void) bzero((char *) key, sizeof(des_cblock)); + key[0] = (unsigned char) 1; +#else /* NOENCRYPTION */ + (void) des_string_to_key(password, key); +#endif /* NOENCRYPTION */ + (void) bzero((char *)password, sizeof(password)); +} + +usage() +{ + (void) fprintf(stderr, "Usage: ksrvutil [-f keyfile] [-i] [-k] "); + (void) fprintf(stderr, "{list | change | add}\n"); + (void) fprintf(stderr, " -i causes the program to ask for "); + (void) fprintf(stderr, "confirmation before changing keys.\n"); + (void) fprintf(stderr, " -k causes the key to printed for list or "); + (void) fprintf(stderr, "change.\n"); + exit(1); +} + +void +leave(str,x) +char *str; +int x; +{ + if (str) + (void) fprintf(stderr, "%s\n", str); + (void) dest_tkt(); + exit(x); +}