diff options
Diffstat (limited to 'crypto/kerberosIV/kadmin')
-rw-r--r-- | crypto/kerberosIV/kadmin/Design.txt | 23 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/Makefile.in | 125 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/admin_server.c | 432 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/kadm_funcs.c | 411 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/kadm_locl.h | 148 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/kadm_ser_wrap.c | 213 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/kadm_server.c | 198 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/kadm_server.h | 66 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/kadmin.c | 845 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/kpasswd.c | 163 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/ksrvutil.c | 601 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/ksrvutil.h | 54 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/ksrvutil_get.c | 400 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/new_pwd.c | 146 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/pw_check.c | 87 | ||||
-rw-r--r-- | crypto/kerberosIV/kadmin/pw_check.h | 45 |
16 files changed, 3957 insertions, 0 deletions
diff --git a/crypto/kerberosIV/kadmin/Design.txt b/crypto/kerberosIV/kadmin/Design.txt new file mode 100644 index 0000000..7763a04 --- /dev/null +++ b/crypto/kerberosIV/kadmin/Design.txt @@ -0,0 +1,23 @@ +// This file attempts to present the internal functioning of the new kerberos +// admin server and interface.. + +// +// The calling side +// + +// Outer interface (programmers interface) +kadm_mod_entry(vals *old_dat, vals *new_dat) returns (vals *cur_dat) + // sends a command telling the server to change all entries which match + // old_dat to entries matching new_dat + // returns in cur_dat the actual current values of the modified records + // implemented with calls to _vals_to_stream, _send_out, _take_in, and + // _stream_to_vals, _interpret_ret + +// Inner calls +_vals_to_stream (vals *, unsigned char *) + // converts a vals structure to a byte stream for transmission over the net + +_stream_to_vals (unsigned char *, vals *) + // converts a byte stream recieved into a vals structure + + diff --git a/crypto/kerberosIV/kadmin/Makefile.in b/crypto/kerberosIV/kadmin/Makefile.in new file mode 100644 index 0000000..947248e --- /dev/null +++ b/crypto/kerberosIV/kadmin/Makefile.in @@ -0,0 +1,125 @@ +# $Id: Makefile.in,v 1.37 1997/05/02 17:50:35 assar Exp $ + +SHELL = /bin/sh + +srcdir = @srcdir@ +VPATH = @srcdir@ + +topdir=.. + +CC = @CC@ +AR = ar +RANLIB = @RANLIB@ +LN_S = @LN_S@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ +LD_FLAGS = @LD_FLAGS@ + +LIB_tgetent = @LIB_tgetent@ +LIB_readline = @LIB_readline@ +LIB_DBM = @LIB_DBM@ +LIBS = @LIBS@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +MKINSTALLDIRS = @top_srcdir@/mkinstalldirs + +CRACKLIB = @CRACKLIB@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +bindir = @bindir@ +sbindir = @sbindir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +PROG_BIN = kpasswd$(EXECSUFFIX) \ + kadmin$(EXECSUFFIX) +PROG_SBIN = ksrvutil$(EXECSUFFIX) +PROG_LIBEXEC = kadmind$(EXECSUFFIX) +PROGS = $(PROG_BIN) $(PROG_SBIN) $(PROG_LIBEXEC) + +SOURCES = kpasswd.c kadmin.c kadm_server.c kadm_funcs.c pw_check.c \ + admin_server.c kadm_ser_wrap.c ksrvutil.c ksrvutil_get.c \ + new_pwd.c + +OBJECTS = kpasswd.o kadmin.o kadm_server.o kadm_funcs.o \ + admin_server.o kadm_ser_wrap.o ksrvutil.o ksrvutil_get.o \ + new_pwd.o + +all: $(PROGS) + +Wall: + make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" + +.c.o: + $(CC) -c $(CPPFLAGS) $(DEFS) -I../include -I$(srcdir) $(CFLAGS) $< + +install: all + $(MKINSTALLDIRS) $(bindir) + for x in $(PROG_BIN); do \ + $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x | sed '$(transform)'`; \ + done + $(MKINSTALLDIRS) $(sbindir) + for x in $(PROG_SBIN); do \ + $(INSTALL_PROGRAM) $$x $(sbindir)/`echo $$x | sed '$(transform)'`; \ + done + $(MKINSTALLDIRS) $(libexecdir) + for x in $(PROG_LIBEXEC); do \ + $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + done + @rm -f $(prefix)/sbin/kadmin + +uninstall: + for x in $(PROG_BIN); do \ + rm -f $(bindir)/`echo $$x | sed '$(transform)'`; \ + done + for x in $(PROG_SBIN); do \ + rm -f $(sbindir)/`echo $$x | sed '$(transform)'`; \ + done + for x in $(PROG_LIBEXEC); do \ + rm -f $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + done + +TAGS: $(SOURCES) + etags $(SOURCES) + +check: + +clean: + rm -f *.a *.o $(PROGS) + +mostlyclean: clean + +distclean: clean + rm -f Makefile *.tab.c *~ + +realclean: distclean + rm -f TAGS + +dist: $(DISTFILES) + for file in $(DISTFILES); do \ + ln $$file ../`cat ../.fname`/lib \ + || cp -p $$file ../`cat ../.fname`/lib; \ + done + +KLIB=-L../lib/kadm -lkadm -L../lib/krb -lkrb -L../lib/des -ldes -L../util/et -lcom_err +LIBROKEN=-L../lib/roken -lroken + +kpasswd$(EXECSUFFIX): kpasswd.o new_pwd.o + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ kpasswd.o new_pwd.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +kadmin$(EXECSUFFIX): kadmin.o new_pwd.o + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ new_pwd.o kadmin.o -L../lib/kadm -lkadm -L../lib/krb -lkrb -L../lib/des -ldes -L../lib/sl -lsl -L../util/et -lcom_err $(LIBROKEN) $(LIBS) $(LIB_readline) $(LIBROKEN) + +KADMIND_OBJECTS=kadm_server.o kadm_funcs.o admin_server.o kadm_ser_wrap.o pw_check.o + +kadmind$(EXECSUFFIX): $(KADMIND_OBJECTS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(KADMIND_OBJECTS) -L../lib/kdb -lkdb -L../lib/acl -lacl $(KLIB) $(CRACKLIB) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN) + +ksrvutil$(EXECSUFFIX): ksrvutil.o ksrvutil_get.o + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ ksrvutil.o ksrvutil_get.o $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +$(OBJECTS): ../include/config.h diff --git a/crypto/kerberosIV/kadmin/admin_server.c b/crypto/kerberosIV/kadmin/admin_server.c new file mode 100644 index 0000000..2654c77 --- /dev/null +++ b/crypto/kerberosIV/kadmin/admin_server.c @@ -0,0 +1,432 @@ +/* + 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. + + */ + +/* + * Top-level loop of the kerberos Administration server + */ + +/* + admin_server.c + this holds the main loop and initialization and cleanup code for the server +*/ + +#include "kadm_locl.h" + +RCSID("$Id: admin_server.c,v 1.41 1997/05/27 15:52:53 bg Exp $"); + +/* Almost all procs and such need this, so it is global */ +admin_params prm; /* The command line parameters struct */ + +/* GLOBAL */ +char *acldir = DEFAULT_ACL_DIR; +static char krbrlm[REALM_SZ]; + +static unsigned pidarraysize = 0; +static int *pidarray = (int *)0; + +static int exit_now = 0; + +static +RETSIGTYPE +doexit(int sig) +{ + exit_now = 1; + SIGRETURN(0); +} + +static +RETSIGTYPE +do_child(int sig) +{ + int pid; + int i, j; + + int status; + + pid = wait(&status); + + /* Reinstall signal handlers for SysV. Must be done *after* wait */ + signal(SIGCHLD, do_child); + + for (i = 0; i < pidarraysize; i++) + if (pidarray[i] == pid) { + /* found it */ + for (j = i; j < pidarraysize-1; j++) + /* copy others down */ + pidarray[j] = pidarray[j+1]; + pidarraysize--; + if ((WIFEXITED(status) && WEXITSTATUS(status) != 0) + || WIFSIGNALED(status)) + krb_log("child %d: termsig %d, retcode %d", pid, + WTERMSIG(status), WEXITSTATUS(status)); + SIGRETURN(0); + } + krb_log("child %d not in list: termsig %d, retcode %d", pid, + WTERMSIG(status), WEXITSTATUS(status)); + SIGRETURN(0); +} + +static void +kill_children(void) +{ + int i; + + for (i = 0; i < pidarraysize; i++) { + kill(pidarray[i], SIGINT); + krb_log("killing child %d", pidarray[i]); + } +} + +/* close the system log file */ +static void +close_syslog(void) +{ + krb_log("Shutting down admin server"); +} + +static void +byebye(void) /* say goodnight gracie */ +{ + printf("Admin Server (kadm server) has completed operation.\n"); +} + +static void +clear_secrets(void) +{ + memset(server_parm.master_key, 0, sizeof(server_parm.master_key)); + memset(server_parm.master_key_schedule, 0, + sizeof(server_parm.master_key_schedule)); + server_parm.master_key_version = 0L; +} + +#ifdef DEBUG +#define cleanexit(code) {kerb_fini(); return;} +#endif + +#ifndef DEBUG +static void +cleanexit(int val) +{ + kerb_fini(); + clear_secrets(); + exit(val); +} +#endif + +static void +process_client(int fd, struct sockaddr_in *who) +{ + u_char *dat; + int dat_len; + u_short dlen; + int retval; + int on = 1; + Principal service; + des_cblock skey; + int more; + int status; + +#if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT) + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)) < 0) + krb_log("setsockopt keepalive: %d",errno); +#endif + + server_parm.recv_addr = *who; + + if (kerb_init()) { /* Open as client */ + krb_log("can't open krb db"); + cleanexit(1); + } + /* need to set service key to changepw.KRB_MASTER */ + + status = kerb_get_principal(server_parm.sname, server_parm.sinst, &service, + 1, &more); + if (status == -1) { + /* db locked */ + int32_t retcode = KADM_DB_INUSE; + char *pdat; + + dat_len = KADM_VERSIZE + sizeof(retcode); + dat = (u_char *) malloc((unsigned)dat_len); + pdat = (char *) dat; + retcode = htonl((u_int32_t) KADM_DB_INUSE); + strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + memcpy(pdat+KADM_VERSIZE, &retcode, sizeof(retcode)); + goto out; + } else if (!status) { + krb_log("no service %s.%s",server_parm.sname, server_parm.sinst); + cleanexit(2); + } + + copy_to_key(&service.key_low, &service.key_high, skey); + memset(&service, 0, sizeof(service)); + kdb_encrypt_key (&skey, &skey, &server_parm.master_key, + server_parm.master_key_schedule, DES_DECRYPT); + krb_set_key(skey, 0); /* if error, will show up when + rd_req fails */ + memset(skey, 0, sizeof(skey)); + + while (1) { + if ((retval = krb_net_read(fd, &dlen, sizeof(u_short))) != + sizeof(u_short)) { + if (retval < 0) + krb_log("dlen read: %s",error_message(errno)); + else if (retval) + krb_log("short dlen read: %d",retval); + close(fd); + cleanexit(retval ? 3 : 0); + } + if (exit_now) { + cleanexit(0); + } + dat_len = ntohs(dlen); + dat = (u_char *) malloc(dat_len); + if (!dat) { + krb_log("malloc: No memory"); + close(fd); + cleanexit(4); + } + if ((retval = krb_net_read(fd, dat, dat_len)) != dat_len) { + if (retval < 0) + krb_log("data read: %s",error_message(errno)); + else + krb_log("short read: %d vs. %d", dat_len, retval); + close(fd); + cleanexit(5); + } + if (exit_now) { + cleanexit(0); + } + if ((retval = kadm_ser_in(&dat,&dat_len)) != KADM_SUCCESS) + krb_log("processing request: %s", error_message(retval)); + + /* kadm_ser_in did the processing and returned stuff in + dat & dat_len , return the appropriate data */ + + out: + dlen = htons(dat_len); + + if (krb_net_write(fd, &dlen, sizeof(u_short)) < 0) { + krb_log("writing dlen to client: %s",error_message(errno)); + close(fd); + cleanexit(6); + } + + if (krb_net_write(fd, dat, dat_len) < 0) { + krb_log("writing to client: %s", error_message(errno)); + close(fd); + cleanexit(7); + } + free(dat); + } + /*NOTREACHED*/ +} + +/* +kadm_listen +listen on the admin servers port for a request +*/ +static int +kadm_listen(void) +{ + int found; + int admin_fd; + int peer_fd; + fd_set mask, readfds; + struct sockaddr_in peer; + int addrlen; + int pid; + + signal(SIGINT, doexit); + signal(SIGTERM, doexit); + signal(SIGHUP, doexit); + signal(SIGQUIT, doexit); + signal(SIGPIPE, SIG_IGN); /* get errors on write() */ + signal(SIGALRM, doexit); + signal(SIGCHLD, do_child); + if (setsid() < 0) + krb_log("setsid() failed"); + + if ((admin_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return KADM_NO_SOCK; +#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) + { + int one=1; + setsockopt(admin_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, + sizeof(one)); + } +#endif + if (bind(admin_fd, (struct sockaddr *)&server_parm.admin_addr, + sizeof(struct sockaddr_in)) < 0) + return KADM_NO_BIND; + listen(admin_fd, 1); + FD_ZERO(&mask); + FD_SET(admin_fd, &mask); + + for (;;) { /* loop nearly forever */ + if (exit_now) { + clear_secrets(); + kill_children(); + return(0); + } + readfds = mask; + if ((found = select(admin_fd+1, &readfds, 0, + 0, (struct timeval *)0)) == 0) + continue; /* no things read */ + if (found < 0) { + if (errno != EINTR) + krb_log("select: %s",error_message(errno)); + continue; + } + if (FD_ISSET(admin_fd, &readfds)) { + /* accept the conn */ + addrlen = sizeof(peer); + if ((peer_fd = accept(admin_fd, (struct sockaddr *)&peer, + &addrlen)) < 0) { + krb_log("accept: %s",error_message(errno)); + continue; + } +#ifndef DEBUG + /* if you want a sep daemon for each server */ + if ((pid = fork())) { + /* parent */ + if (pid < 0) { + krb_log("fork: %s",error_message(errno)); + close(peer_fd); + continue; + } + /* fork succeded: keep tabs on child */ + close(peer_fd); + if (pidarray) { + pidarray = (int *)realloc(pidarray, ++pidarraysize); + pidarray[pidarraysize-1] = pid; + } else { + pidarray = (int *)malloc(pidarraysize = 1); + pidarray[0] = pid; + } + } else { + /* child */ + close(admin_fd); +#endif /* DEBUG */ + /* + * If we are multihomed we need to figure out which + * local address that is used this time since it is + * used in "direction" comparison. + */ + getsockname(peer_fd, + (struct sockaddr *)&server_parm.admin_addr, + &addrlen); + /* do stuff */ + process_client (peer_fd, &peer); +#ifndef DEBUG + } +#endif + } else { + krb_log("something else woke me up!"); + return(0); + } + } + /*NOTREACHED*/ +} + +/* +** Main does the logical thing, it sets up the database and RPC interface, +** as well as handling the creation and maintenance of the syslog file... +*/ +int +main(int argc, char **argv) /* admin_server main routine */ +{ + int errval; + int c; + + set_progname (argv[0]); + + umask(077); /* Create protected files */ + + /* initialize the admin_params structure */ + prm.sysfile = KADM_SYSLOG; /* default file name */ + prm.inter = 0; + + memset(krbrlm, 0, sizeof(krbrlm)); + + while ((c = getopt(argc, argv, "f:hmnd:a:r:")) != EOF) + switch(c) { + case 'f': /* Syslog file name change */ + prm.sysfile = optarg; + break; + case 'n': + prm.inter = 0; + break; + case 'm': + prm.inter = 1; + break; + case 'a': /* new acl directory */ + acldir = optarg; + break; + case 'd': + /* put code to deal with alt database place */ + if ((errval = kerb_db_set_name(optarg))) + errx (1, "opening database %s: %s", + optarg, error_message(errval)); + break; + case 'r': + strncpy(krbrlm, optarg, sizeof(krbrlm) - 1); + break; + case 'h': /* get help on using admin_server */ + default: + errx(1, "Usage: kadmind [-h] [-n] [-m] [-r realm] [-d dbname] [-f filename] [-a acldir]"); + } + + if (krbrlm[0] == 0) + if (krb_get_lrealm(krbrlm, 0) != KSUCCESS) + errx (1, "Unable to get local realm. Fix krb.conf or use -r."); + + printf("KADM Server %s initializing\n",KADM_VERSTR); + printf("Please do not use 'kill -9' to kill this job, use a\n"); + printf("regular kill instead\n\n"); + + kset_logfile(prm.sysfile); + krb_log("Admin server starting"); + + kerb_db_set_lockmode(KERB_DBL_NONBLOCKING); + errval = kerb_init(); /* Open the Kerberos database */ + if (errval) { + warnx ("error: kerb_init() failed"); + close_syslog(); + byebye(); + } + /* set up the server_parm struct */ + if ((errval = kadm_ser_init(prm.inter, krbrlm))==KADM_SUCCESS) { + kerb_fini(); /* Close the Kerberos database-- + will re-open later */ + errval = kadm_listen(); /* listen for calls to server from + clients */ + } + if (errval != KADM_SUCCESS) { + warnx("error: %s",error_message(errval)); + kerb_fini(); /* Close if error */ + } + close_syslog(); /* Close syslog file, print + closing note */ + byebye(); /* Say bye bye on the terminal + in use */ + exit(1); +} /* procedure main */ diff --git a/crypto/kerberosIV/kadmin/kadm_funcs.c b/crypto/kerberosIV/kadmin/kadm_funcs.c new file mode 100644 index 0000000..34a34b0 --- /dev/null +++ b/crypto/kerberosIV/kadmin/kadm_funcs.c @@ -0,0 +1,411 @@ +/* + 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. + +*/ + +/* + * Kerberos administration server-side database manipulation routines + */ + +/* + * kadm_funcs.c + * the actual database manipulation code + */ + +#include "kadm_locl.h" + +RCSID("$Id: kadm_funcs.c,v 1.16 1997/05/02 14:28:49 assar Exp $"); + +static int +check_access(char *pname, char *pinst, char *prealm, enum acl_types acltype) +{ + char checkname[MAX_K_NAME_SZ]; + char filename[MaxPathLen]; + + snprintf(checkname, sizeof(checkname), "%s.%s@%s", pname, pinst, prealm); + + switch (acltype) { + case ADDACL: + snprintf(filename, sizeof(filename), "%s%s", acldir, ADD_ACL_FILE); + break; + case GETACL: + snprintf(filename, sizeof(filename), "%s%s", acldir, GET_ACL_FILE); + break; + case MODACL: + snprintf(filename, sizeof(filename), "%s%s", acldir, MOD_ACL_FILE); + break; + case DELACL: + snprintf(filename, sizeof(filename), "%s%s", acldir, DEL_ACL_FILE); + break; + default: + krb_log("WARNING in check_access: default case in switch"); + return 0; + } + return(acl_check(filename, checkname)); +} + +static int +wildcard(char *str) +{ + if (!strcmp(str, WILDCARD_STR)) + return(1); + return(0); +} + +static int +fail(int code, char *oper, char *princ) +{ + krb_log("ERROR: %s: %s (%s)", oper, princ, error_message(code)); + return code; +} + +#define failadd(code) { fail(code, "ADD", victim); return code; } +#define faildelete(code) { fail(code, "DELETE", victim); return code; } +#define failget(code) { fail(code, "GET", victim); return code; } +#define failmod(code) { fail(code, "MOD", victim); return code; } +#define failchange(code) { fail(code, "CHANGE", admin); return code; } + +int +kadm_add_entry (char *rname, char *rinstance, char *rrealm, + Kadm_vals *valsin, Kadm_vals *valsout) +{ + long numfound; /* check how many we get written */ + int more; /* pointer to more grabbed records */ + Principal data_i, data_o; /* temporary principal */ + u_char flags[4]; + des_cblock newpw; + Principal default_princ; + + char admin[MAX_K_NAME_SZ], victim[MAX_K_NAME_SZ]; + + strcpy(admin, krb_unparse_name_long(rname, rinstance, rrealm)); + strcpy(victim, krb_unparse_name_long(valsin->name, valsin->instance, NULL)); + + krb_log("ADD: %s by %s", victim, admin); + + if (!check_access(rname, rinstance, rrealm, ADDACL)) { + krb_log("WARNING: ADD: %s permission denied", admin); + return KADM_UNAUTH; + } + + /* Need to check here for "legal" name and instance */ + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failadd(KADM_ILL_WILDCARD); + } + + numfound = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, + &default_princ, 1, &more); + if (numfound == -1) { + failadd(KADM_DB_INUSE); + } else if (numfound != 1) { + failadd(KADM_UK_RERROR); + } + + kadm_vals_to_prin(valsin->fields, &data_i, valsin); + strncpy(data_i.name, valsin->name, ANAME_SZ); + strncpy(data_i.instance, valsin->instance, INST_SZ); + + if (!IS_FIELD(KADM_EXPDATE,valsin->fields)) + data_i.exp_date = default_princ.exp_date; + if (!IS_FIELD(KADM_ATTR,valsin->fields)) + data_i.attributes = default_princ.attributes; + if (!IS_FIELD(KADM_MAXLIFE,valsin->fields)) + data_i.max_life = default_princ.max_life; + + memset(&default_princ, 0, sizeof(default_princ)); + + /* convert to host order */ + data_i.key_low = ntohl(data_i.key_low); + data_i.key_high = ntohl(data_i.key_high); + + + copy_to_key(&data_i.key_low, &data_i.key_high, newpw); + + /* encrypt new key in master key */ + kdb_encrypt_key (&newpw, &newpw, &server_parm.master_key, + server_parm.master_key_schedule, DES_ENCRYPT); + copy_from_key(newpw, &data_i.key_low, &data_i.key_high); + memset(newpw, 0, sizeof(newpw)); + + data_o = data_i; + numfound = kerb_get_principal(valsin->name, valsin->instance, + &data_o, 1, &more); + if (numfound == -1) { + failadd(KADM_DB_INUSE); + } else if (numfound) { + failadd(KADM_INUSE); + } else { + data_i.key_version++; + data_i.kdc_key_ver = server_parm.master_key_version; + strncpy(data_i.mod_name, rname, sizeof(data_i.mod_name)-1); + strncpy(data_i.mod_instance, rinstance, + sizeof(data_i.mod_instance)-1); + + numfound = kerb_put_principal(&data_i, 1); + if (numfound == -1) { + failadd(KADM_DB_INUSE); + } else if (numfound) { + failadd(KADM_UK_SERROR); + } else { + numfound = kerb_get_principal(valsin->name, valsin->instance, + &data_o, 1, &more); + if ((numfound!=1) || (more!=0)) { + failadd(KADM_UK_RERROR); + } + memset(flags, 0, sizeof(flags)); + SET_FIELD(KADM_NAME,flags); + SET_FIELD(KADM_INST,flags); + SET_FIELD(KADM_EXPDATE,flags); + SET_FIELD(KADM_ATTR,flags); + SET_FIELD(KADM_MAXLIFE,flags); + kadm_prin_to_vals(flags, valsout, &data_o); + krb_log("ADD: %s added", victim); + return KADM_DATA; /* Set all the appropriate fields */ + } + } +} + +int +kadm_delete_entry (char *rname, char *rinstance, char *rrealm, + Kadm_vals *valsin) +{ + int ret; + + char admin[MAX_K_NAME_SZ], victim[MAX_K_NAME_SZ]; + + strcpy(admin, krb_unparse_name_long(rname, rinstance, rrealm)); + strcpy(victim, krb_unparse_name_long(valsin->name, valsin->instance, NULL)); + + krb_log("DELETE: %s by %s", victim, admin); + + if (!check_access(rname, rinstance, rrealm, DELACL)) { + krb_log("WARNING: DELETE: %s permission denied", admin); + return KADM_UNAUTH; + } + + /* Need to check here for "legal" name and instance */ + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + faildelete(KADM_ILL_WILDCARD); + } + +#define EQ(V,N,I) (strcmp((V)->name, (N)) == 0 && strcmp((V)->instance, (I)) == 0) + + if(EQ(valsin, PWSERV_NAME, KRB_MASTER) || + EQ(valsin, "K", "M") || + EQ(valsin, "default", "") || + EQ(valsin, KRB_TICKET_GRANTING_TICKET, server_parm.krbrlm)){ + krb_log("WARNING: DELETE: %s is immutable", victim); + return KADM_IMMUTABLE; /* XXX */ + } + + ret = kerb_delete_principal(valsin->name, valsin->instance); + if(ret == -1) + return KADM_DB_INUSE; /* XXX */ + krb_log("DELETE: %s removed.", victim); + return KADM_SUCCESS; +} + + +int +kadm_get_entry (char *rname, char *rinstance, char *rrealm, + Kadm_vals *valsin, u_char *flags, Kadm_vals *valsout) +{ + long numfound; /* check how many were returned */ + int more; /* To point to more name.instances */ + Principal data_o; /* Data object to hold Principal */ + + char admin[MAX_K_NAME_SZ], victim[MAX_K_NAME_SZ]; + + strcpy(admin, krb_unparse_name_long(rname, rinstance, rrealm)); + strcpy(victim, krb_unparse_name_long(valsin->name, valsin->instance, NULL)); + + krb_log("GET: %s by %s", victim, admin); + + if (!check_access(rname, rinstance, rrealm, GETACL)) { + krb_log("WARNING: GET: %s permission denied", admin); + return KADM_UNAUTH; + } + + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failget(KADM_ILL_WILDCARD); + } + + /* Look up the record in the database */ + numfound = kerb_get_principal(valsin->name, valsin->instance, + &data_o, 1, &more); + if (numfound == -1) { + failget(KADM_DB_INUSE); + } else if (numfound) { /* We got the record, let's return it */ + kadm_prin_to_vals(flags, valsout, &data_o); + krb_log("GET: %s retrieved", victim); + return KADM_DATA; /* Set all the appropriate fields */ + } else { + failget(KADM_NOENTRY); /* Else whimper and moan */ + } +} + +int +kadm_mod_entry (char *rname, char *rinstance, char *rrealm, + Kadm_vals *valsin, Kadm_vals *valsin2, Kadm_vals *valsout) +{ + long numfound; + int more; + Principal data_o, temp_key; + u_char fields[4]; + des_cblock newpw; + + char admin[MAX_K_NAME_SZ], victim[MAX_K_NAME_SZ]; + + strcpy(admin, krb_unparse_name_long(rname, rinstance, rrealm)); + strcpy(victim, krb_unparse_name_long(valsin->name, valsin->instance, NULL)); + + krb_log("MOD: %s by %s", victim, admin); + + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failmod(KADM_ILL_WILDCARD); + } + + if (!check_access(rname, rinstance, rrealm, MODACL)) { + krb_log("WARNING: MOD: %s permission denied", admin); + return KADM_UNAUTH; + } + + numfound = kerb_get_principal(valsin->name, valsin->instance, + &data_o, 1, &more); + if (numfound == -1) { + failmod(KADM_DB_INUSE); + } else if (numfound) { + kadm_vals_to_prin(valsin2->fields, &temp_key, valsin2); + strncpy(data_o.name, valsin->name, ANAME_SZ); + strncpy(data_o.instance, valsin->instance, INST_SZ); + if (IS_FIELD(KADM_EXPDATE,valsin2->fields)) + data_o.exp_date = temp_key.exp_date; + if (IS_FIELD(KADM_ATTR,valsin2->fields)) + data_o.attributes = temp_key.attributes; + if (IS_FIELD(KADM_MAXLIFE,valsin2->fields)) + data_o.max_life = temp_key.max_life; + if (IS_FIELD(KADM_DESKEY,valsin2->fields)) { + data_o.key_version++; + data_o.kdc_key_ver = server_parm.master_key_version; + + + /* convert to host order */ + temp_key.key_low = ntohl(temp_key.key_low); + temp_key.key_high = ntohl(temp_key.key_high); + + + copy_to_key(&temp_key.key_low, &temp_key.key_high, newpw); + + /* encrypt new key in master key */ + kdb_encrypt_key (&newpw, &newpw, &server_parm.master_key, + server_parm.master_key_schedule, DES_ENCRYPT); + copy_from_key(newpw, &data_o.key_low, &data_o.key_high); + memset(newpw, 0, sizeof(newpw)); + } + memset(&temp_key, 0, sizeof(temp_key)); + + strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + + memset(&data_o, 0, sizeof(data_o)); + + if (more == -1) { + failmod(KADM_DB_INUSE); + } else if (more) { + failmod(KADM_UK_SERROR); + } else { + numfound = kerb_get_principal(valsin->name, valsin->instance, + &data_o, 1, &more); + if ((more!=0)||(numfound!=1)) { + failmod(KADM_UK_RERROR); + } + memset(fields, 0, sizeof(fields)); + SET_FIELD(KADM_NAME,fields); + SET_FIELD(KADM_INST,fields); + SET_FIELD(KADM_EXPDATE,fields); + SET_FIELD(KADM_ATTR,fields); + SET_FIELD(KADM_MAXLIFE,fields); + kadm_prin_to_vals(fields, valsout, &data_o); + krb_log("MOD: %s modified", victim); + return KADM_DATA; /* Set all the appropriate fields */ + } + } + else { + failmod(KADM_NOENTRY); + } +} + +int +kadm_change (char *rname, char *rinstance, char *rrealm, unsigned char *newpw) +{ + long numfound; + int more; + Principal data_o; + des_cblock local_pw; + + char admin[MAX_K_NAME_SZ]; + + strcpy(admin, krb_unparse_name_long(rname, rinstance, rrealm)); + + krb_log("CHANGE: %s", admin); + + if (strcmp(server_parm.krbrlm, rrealm)) { + krb_log("ERROR: CHANGE: request from wrong realm %s", rrealm); + return(KADM_WRONG_REALM); + } + + if (wildcard(rname) || wildcard(rinstance)) { + failchange(KADM_ILL_WILDCARD); + } + + memcpy(local_pw, newpw, sizeof(local_pw)); + + /* encrypt new key in master key */ + kdb_encrypt_key (&local_pw, &local_pw, &server_parm.master_key, + server_parm.master_key_schedule, DES_ENCRYPT); + + numfound = kerb_get_principal(rname, rinstance, + &data_o, 1, &more); + if (numfound == -1) { + failchange(KADM_DB_INUSE); + } else if (numfound) { + copy_from_key(local_pw, &data_o.key_low, &data_o.key_high); + data_o.key_version++; + data_o.kdc_key_ver = server_parm.master_key_version; + strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + memset(local_pw, 0, sizeof(local_pw)); + memset(&data_o, 0, sizeof(data_o)); + if (more == -1) { + failchange(KADM_DB_INUSE); + } else if (more) { + failchange(KADM_UK_SERROR); + } else { + krb_log("CHANGE: %s's password changed", admin); + return KADM_SUCCESS; + } + } + else { + failchange(KADM_NOENTRY); + } +} diff --git a/crypto/kerberosIV/kadmin/kadm_locl.h b/crypto/kerberosIV/kadmin/kadm_locl.h new file mode 100644 index 0000000..07f9093 --- /dev/null +++ b/crypto/kerberosIV/kadmin/kadm_locl.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: kadm_locl.h,v 1.25 1997/05/20 18:40:43 bg Exp $ */ + +#include "config.h" +#include "protos.h" + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include <errno.h> +#include <signal.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif /* HAVE_SYS_RESOURCE_H */ +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#endif + +#include <err.h> + +#ifdef SOCKS +#include <socks.h> +#endif + +#include <roken.h> + +#include <com_err.h> +#include <sl.h> + +#include <des.h> +#include <krb.h> +#include <krb_err.h> +#include <krb_db.h> +#include <kadm.h> +#include <kadm_err.h> +#include <acl.h> + +#include "kadm_server.h" +#include "pw_check.h" + +/* from libacl */ +/* int acl_check(char *acl, char *principal); */ + +/* GLOBALS */ +extern char *acldir; +extern Kadm_Server server_parm; + +/* Utils */ +int kadm_change __P((char *, char *, char *, des_cblock)); +int kadm_add_entry __P((char *, char *, char *, Kadm_vals *, Kadm_vals *)); +int kadm_mod_entry __P((char *, char *, char *, Kadm_vals *, Kadm_vals *, Kadm_vals *)); +int kadm_get_entry __P((char *, char *, char *, Kadm_vals *, u_char *, Kadm_vals *)); +int kadm_delete_entry __P((char *, char *, char *, Kadm_vals *)); +int kadm_ser_cpw __P((u_char *, int, AUTH_DAT *, u_char **, int *)); +int kadm_ser_add __P((u_char *, int, AUTH_DAT *, u_char **, int *)); +int kadm_ser_mod __P((u_char *, int, AUTH_DAT *, u_char **, int *)); +int kadm_ser_get __P((u_char *, int, AUTH_DAT *, u_char **, int *)); +int kadm_ser_delete __P((u_char *, int, AUTH_DAT *, u_char **, int *)); +int kadm_ser_init __P((int inter, char realm[])); +int kadm_ser_in __P((u_char **, int *)); + +int get_pw_new_pwd __P((char *pword, int pwlen, krb_principal *pr, int print_realm)); + +/* cracklib */ +char *FascistCheck __P((char *password, char *path, char **strings)); diff --git a/crypto/kerberosIV/kadmin/kadm_ser_wrap.c b/crypto/kerberosIV/kadmin/kadm_ser_wrap.c new file mode 100644 index 0000000..6909a9f --- /dev/null +++ b/crypto/kerberosIV/kadmin/kadm_ser_wrap.c @@ -0,0 +1,213 @@ +/* + 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. + + */ + +/* + * Kerberos administration server-side support functions + */ + +/* +kadm_ser_wrap.c +unwraps wrapped packets and calls the appropriate server subroutine +*/ + +#include "kadm_locl.h" + +RCSID("$Id: kadm_ser_wrap.c,v 1.20 1997/05/02 10:29:14 joda Exp $"); + +/* GLOBAL */ +Kadm_Server server_parm; + +/* +kadm_ser_init +set up the server_parm structure +*/ +int +kadm_ser_init(int inter, char *realm) + /* interactive or from file */ + +{ + struct hostent *hp; + char hostname[MaxHostNameLen]; + + init_kadm_err_tbl(); + init_krb_err_tbl(); + if (k_gethostname(hostname, sizeof(hostname))) + return KADM_NO_HOSTNAME; + + strcpy(server_parm.sname, PWSERV_NAME); + strcpy(server_parm.sinst, KRB_MASTER); + strcpy(server_parm.krbrlm, realm); + + server_parm.admin_fd = -1; + /* setting up the addrs */ + memset(&server_parm.admin_addr,0, sizeof(server_parm.admin_addr)); + + server_parm.admin_addr.sin_port = k_getportbyname (KADM_SNAME, + "tcp", + htons(751)); + server_parm.admin_addr.sin_family = AF_INET; + if ((hp = gethostbyname(hostname)) == NULL) + return KADM_NO_HOSTNAME; + server_parm.admin_addr.sin_addr.s_addr = INADDR_ANY; + /* setting up the database */ + if (kdb_get_master_key((inter==1), &server_parm.master_key, + server_parm.master_key_schedule) != 0) + return KADM_NO_MAST; + if ((server_parm.master_key_version = + kdb_verify_master_key(&server_parm.master_key, + server_parm.master_key_schedule,stderr))<0) + return KADM_NO_VERI; + return KADM_SUCCESS; +} + +static void errpkt(u_char **dat, int *dat_len, int code) +{ + u_int32_t retcode; + char *pdat; + + free(*dat); /* free up req */ + *dat_len = KADM_VERSIZE + sizeof(u_int32_t); + *dat = (u_char *) malloc((unsigned)*dat_len); + pdat = (char *) *dat; + retcode = htonl((u_int32_t) code); + strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + memcpy(&pdat[KADM_VERSIZE], &retcode, sizeof(u_int32_t)); + return; +} + +/* +kadm_ser_in +unwrap the data stored in dat, process, and return it. +*/ +int +kadm_ser_in(u_char **dat, int *dat_len) +{ + u_char *in_st; /* pointer into the sent packet */ + int in_len,retc; /* where in packet we are, for + returns */ + u_int32_t r_len; /* length of the actual packet */ + KTEXT_ST authent; /* the authenticator */ + AUTH_DAT ad; /* who is this, klink */ + u_int32_t ncksum; /* checksum of encrypted data */ + des_key_schedule sess_sched; /* our schedule */ + MSG_DAT msg_st; + u_char *retdat, *tmpdat; + int retval, retlen; + + if (strncmp(KADM_VERSTR, (char *)*dat, KADM_VERSIZE)) { + errpkt(dat, dat_len, KADM_BAD_VER); + return KADM_BAD_VER; + } + in_len = KADM_VERSIZE; + /* get the length */ + if ((retc = stv_long(*dat, &r_len, in_len, *dat_len)) < 0) + return KADM_LENGTH_ERROR; + in_len += retc; + authent.length = *dat_len - r_len - KADM_VERSIZE - sizeof(u_int32_t); + memcpy(authent.dat, (char *)(*dat) + in_len, authent.length); + authent.mbz = 0; + /* service key should be set before here */ + if ((retc = krb_rd_req(&authent, server_parm.sname, server_parm.sinst, + server_parm.recv_addr.sin_addr.s_addr, &ad, NULL))) + { + errpkt(dat, dat_len,retc + krb_err_base); + return retc + krb_err_base; + } + +#define clr_cli_secrets() {memset(sess_sched, 0, sizeof(sess_sched)); memset(ad.session, 0,sizeof(ad.session));} + + in_st = *dat + *dat_len - r_len; +#ifdef NOENCRYPTION + ncksum = 0; +#else + ncksum = des_quad_cksum((des_cblock *)in_st, (des_cblock *)0, (long) r_len, 0, &ad.session); +#endif + if (ncksum!=ad.checksum) { /* yow, are we correct yet */ + clr_cli_secrets(); + errpkt(dat, dat_len,KADM_BAD_CHK); + return KADM_BAD_CHK; + } +#ifdef NOENCRYPTION + memset(sess_sched, 0, sizeof(sess_sched)); +#else + des_key_sched(&ad.session, sess_sched); +#endif + if ((retc = (int) krb_rd_priv(in_st, r_len, sess_sched, &ad.session, + &server_parm.recv_addr, + &server_parm.admin_addr, &msg_st))) { + clr_cli_secrets(); + errpkt(dat, dat_len,retc + krb_err_base); + return retc + krb_err_base; + } + switch (msg_st.app_data[0]) { + case CHANGE_PW: + retval = kadm_ser_cpw(msg_st.app_data+1,(int) msg_st.app_length - 1, + &ad, &retdat, &retlen); + break; + case ADD_ENT: + retval = kadm_ser_add(msg_st.app_data+1,(int) msg_st.app_length - 1, + &ad, &retdat, &retlen); + break; + case GET_ENT: + retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length - 1, + &ad, &retdat, &retlen); + break; + case MOD_ENT: + retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length - 1, + &ad, &retdat, &retlen); + break; + case DEL_ENT: + retval = kadm_ser_delete(msg_st.app_data + 1, msg_st.app_length - 1, + &ad, &retdat, &retlen); + break; + default: + clr_cli_secrets(); + errpkt(dat, dat_len, KADM_NO_OPCODE); + return KADM_NO_OPCODE; + } + /* Now seal the response back into a priv msg */ + free(*dat); + tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE + + sizeof(u_int32_t))); + strncpy((char *)tmpdat, KADM_VERSTR, KADM_VERSIZE); + retval = htonl((u_int32_t)retval); + memcpy((char *)tmpdat + KADM_VERSIZE, &retval, sizeof(u_int32_t)); + if (retlen) { + memcpy((char *)tmpdat + KADM_VERSIZE + sizeof(u_int32_t), retdat, + retlen); + free(retdat); + } + /* slop for mk_priv stuff */ + *dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE + + sizeof(u_int32_t) + 200)); + if ((*dat_len = krb_mk_priv(tmpdat, *dat, + (u_int32_t) (retlen + KADM_VERSIZE + + sizeof(u_int32_t)), + sess_sched, + &ad.session, &server_parm.admin_addr, + &server_parm.recv_addr)) < 0) { + clr_cli_secrets(); + errpkt(dat, dat_len, KADM_NO_ENCRYPT); + return KADM_NO_ENCRYPT; + } + clr_cli_secrets(); + return KADM_SUCCESS; +} diff --git a/crypto/kerberosIV/kadmin/kadm_server.c b/crypto/kerberosIV/kadmin/kadm_server.c new file mode 100644 index 0000000..1006f20 --- /dev/null +++ b/crypto/kerberosIV/kadmin/kadm_server.c @@ -0,0 +1,198 @@ +/* + 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. + + */ + +/* + * Kerberos administration server-side subroutines + */ + +#include "kadm_locl.h" + +RCSID("$Id: kadm_server.c,v 1.9 1997/05/02 10:29:08 joda Exp $"); + +/* +kadm_ser_cpw - the server side of the change_password routine + recieves : KTEXT, {key} + returns : CKSUM, RETCODE + acl : caller can change only own password + +Replaces the password (i.e. des key) of the caller with that specified in key. +Returns no actual data from the master server, since this is called by a user +*/ +int +kadm_ser_cpw(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, int *outlen) +{ + u_int32_t keylow, keyhigh; + des_cblock newkey; + int status; + int stvlen=0; + char *pw_msg; + char pword[MAX_KPW_LEN]; + char *strings[4]; + + /* take key off the stream, and change the database */ + + if ((status = stv_long(dat, &keyhigh, 0, len)) < 0) + return(KADM_LENGTH_ERROR); + stvlen=status; + if ((status = stv_long(dat, &keylow, stvlen, len)) < 0) + return(KADM_LENGTH_ERROR); + stvlen+=status; + + if((status = stv_string(dat, pword, stvlen, sizeof(pword), len))<0) + pword[0]=0; + + keylow = ntohl(keylow); + keyhigh = ntohl(keyhigh); + memcpy(((char *)newkey) + 4, &keyhigh, 4); + memcpy(newkey, &keylow, 4); + + strings[0] = ad->pname; + strings[1] = ad->pinst; + strings[2] = ad->prealm; + strings[3] = NULL; + status = kadm_pw_check(pword, &newkey, &pw_msg, strings); + + memset(pword, 0, sizeof(pword)); + memset(dat, 0, len); + + if(status != KADM_SUCCESS){ + *datout=malloc(0); + *outlen=vts_string(pw_msg, datout, 0); + return status; + } + *datout=0; + *outlen=0; + + return(kadm_change(ad->pname, ad->pinst, ad->prealm, newkey)); +} + + +/* +kadm_ser_add - the server side of the add_entry routine + recieves : KTEXT, {values} + returns : CKSUM, RETCODE, {values} + acl : su, sms (as alloc) + +Adds and entry containing values to the database +returns the values of the entry, so if you leave certain fields blank you will + be able to determine the default values they are set to +*/ +int +kadm_ser_add(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, int *outlen) +{ + Kadm_vals values, retvals; + long status; + + if ((status = stream_to_vals(dat, &values, len)) < 0) + return(KADM_LENGTH_ERROR); + if ((status = kadm_add_entry(ad->pname, ad->pinst, ad->prealm, + &values, &retvals)) == KADM_DATA) { + *outlen = vals_to_stream(&retvals,datout); + return KADM_SUCCESS; + } else { + *outlen = 0; + return status; + } +} + +/* +kadm_ser_mod - the server side of the mod_entry routine + recieves : KTEXT, {values, values} + returns : CKSUM, RETCODE, {values} + acl : su, sms (as register or dealloc) + +Modifies all entries corresponding to the first values so they match the + second values. +returns the values for the changed entries +*/ +int +kadm_ser_mod(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, int *outlen) +{ + Kadm_vals vals1, vals2, retvals; + int wh; + long status; + + if ((wh = stream_to_vals(dat, &vals1, len)) < 0) + return KADM_LENGTH_ERROR; + if ((status = stream_to_vals(dat+wh,&vals2, len-wh)) < 0) + return KADM_LENGTH_ERROR; + if ((status = kadm_mod_entry(ad->pname, ad->pinst, ad->prealm, &vals1, + &vals2, &retvals)) == KADM_DATA) { + *outlen = vals_to_stream(&retvals,datout); + return KADM_SUCCESS; + } else { + *outlen = 0; + return status; + } +} + +int +kadm_ser_delete(u_char *dat, int len, AUTH_DAT *ad, + u_char **datout, int *outlen) +{ + Kadm_vals values; + int wh; + int status; + + if((wh = stream_to_vals(dat, &values, len)) < 0) + return KADM_LENGTH_ERROR; + if(wh != len) + return KADM_LENGTH_ERROR; + status = kadm_delete_entry(ad->pname, ad->pinst, ad->prealm, + &values); + *outlen = 0; + return status; +} + +/* +kadm_ser_get + recieves : KTEXT, {values, flags} + returns : CKSUM, RETCODE, {count, values, values, values} + acl : su + +gets the fields requested by flags from all entries matching values +returns this data for each matching recipient, after a count of how many such + matches there were +*/ +int +kadm_ser_get(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, int *outlen) +{ + Kadm_vals values, retvals; + u_char fl[FLDSZ]; + int loop,wh; + long status; + + if ((wh = stream_to_vals(dat, &values, len)) < 0) + return KADM_LENGTH_ERROR; + if (wh + FLDSZ > len) + return KADM_LENGTH_ERROR; + for (loop=FLDSZ-1; loop>=0; loop--) + fl[loop] = dat[wh++]; + if ((status = kadm_get_entry(ad->pname, ad->pinst, ad->prealm, + &values, fl, &retvals)) == KADM_DATA) { + *outlen = vals_to_stream(&retvals,datout); + return KADM_SUCCESS; + } else { + *outlen = 0; + return status; + } +} + diff --git a/crypto/kerberosIV/kadmin/kadm_server.h b/crypto/kerberosIV/kadmin/kadm_server.h new file mode 100644 index 0000000..c730574 --- /dev/null +++ b/crypto/kerberosIV/kadmin/kadm_server.h @@ -0,0 +1,66 @@ +/* + 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. + + */ + +/* $Id: kadm_server.h,v 1.10 1997/05/11 04:08:26 assar Exp $ */ + +/* + * Definitions for Kerberos administration server & client + */ + +#ifndef KADM_SERVER_DEFS +#define KADM_SERVER_DEFS + +/* + * kadm_server.h + * Header file for the fourth attempt at an admin server + * Doug Church, December 28, 1989, MIT Project Athena + * ps. Yes that means this code belongs to athena etc... + * as part of our ongoing attempt to copyright all greek names + */ + +typedef struct { + struct sockaddr_in admin_addr; + struct sockaddr_in recv_addr; + int recv_addr_len; + int admin_fd; /* our link to clients */ + char sname[ANAME_SZ]; + char sinst[INST_SZ]; + char krbrlm[REALM_SZ]; + des_cblock master_key; + des_cblock session_key; + des_key_schedule master_key_schedule; + long master_key_version; +} Kadm_Server; + +/* the default syslog file */ +#ifndef KADM_SYSLOG +#define KADM_SYSLOG "/var/log/admin_server.syslog" +#endif /* KADM_SYSLOG */ + +#ifndef DEFAULT_ACL_DIR +#define DEFAULT_ACL_DIR "/var/kerberos" +#endif /* DEFAULT_ACL_DIR */ +#define ADD_ACL_FILE "/admin_acl.add" +#define GET_ACL_FILE "/admin_acl.get" +#define MOD_ACL_FILE "/admin_acl.mod" +#define DEL_ACL_FILE "/admin_acl.del" + +#endif /* KADM_SERVER_DEFS */ diff --git a/crypto/kerberosIV/kadmin/kadmin.c b/crypto/kerberosIV/kadmin/kadmin.c new file mode 100644 index 0000000..f117b6b --- /dev/null +++ b/crypto/kerberosIV/kadmin/kadmin.c @@ -0,0 +1,845 @@ +/* + 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. + + */ + +/* + * Kerberos database administrator's tool. + * + * The default behavior of kadmin is if the -m option is given + * on the commandline, multiple requests are allowed to be given + * with one entry of the admin password (until the tickets expire). + */ + +#include "kadm_locl.h" + +RCSID("$Id: kadmin.c,v 1.48 1997/05/13 09:43:06 bg Exp $"); + +static void change_password(int argc, char **argv); +static void change_key(int argc, char **argv); +static void change_admin_password(int argc, char **argv); +static void add_new_key(int argc, char **argv); +static void del_entry(int argc, char **argv); +static void get_entry(int argc, char **argv); +static void mod_entry(int argc, char **argv); +static void help(int argc, char **argv); +static void clean_up_cmd(int argc, char **argv); +static void quit_cmd(int argc, char **argv); + +static SL_cmd cmds[] = { + {"change_password", change_password, "Change a user's password"}, + {"cpw"}, + {"passwd"}, + {"change_key", change_key, "Change a user's password as a DES binary key"}, + {"ckey"}, + {"change_admin_password", change_admin_password, + "Change your admin password"}, + {"cap"}, + {"add_new_key", add_new_key, "Add new user to kerberos database"}, + {"ank"}, + {"del_entry", del_entry, "Delete entry from database"}, + {"del"}, + {"delete"}, + {"get_entry", get_entry, "Get entry from kerberos database"}, + {"mod_entry", mod_entry, "Modify entry in kerberos database"}, + {"destroy_tickets", clean_up_cmd, "Destroy admin tickets"}, + {"exit", quit_cmd, "Exit program"}, + {"quit"}, + {"help", help, "Help"}, + {"?"}, + {NULL} +}; + +#define BAD_PW 1 +#define GOOD_PW 0 +#define FUDGE_VALUE 15 /* for ticket expiration time */ +#define PE_NO 0 +#define PE_YES 1 +#define PE_UNSURE 2 + +/* for get_password, whether it should do the swapping...necessary for + using vals structure, unnecessary for change_pw requests */ +#define DONTSWAP 0 +#define SWAP 1 + +static krb_principal pr; +static char default_realm[REALM_SZ]; /* default kerberos realm */ +static char krbrlm[REALM_SZ]; /* current realm being administered */ +static int multiple = 0; /* Allow multiple requests per ticket */ + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else +#define read_long_pw_string des_read_pw_string +#endif + +static void +get_maxlife(Kadm_vals *vals) +{ + char buff[BUFSIZ]; + time_t life; + int l; + + do { + printf("Maximum ticket lifetime? (%d) [%s] ", + vals->max_life, krb_life_to_atime(vals->max_life)); + fflush(stdout); + if (fgets(buff, sizeof(buff), stdin) == NULL || *buff == '\n') { + clearerr(stdin); + return; + } + life = krb_atime_to_life(buff); + } while (life <= 0); + + l = strlen(buff); + if (buff[l-2] == 'm') + life = krb_time_to_life(0L, life*60); + if (buff[l-2] == 'h') + life = krb_time_to_life(0L, life*60*60); + + vals->max_life = life; + SET_FIELD(KADM_MAXLIFE,vals->fields); +} + +static void +get_attr(Kadm_vals *vals) +{ + char buff[BUFSIZ], *out; + int attr; + + do { + printf("Attributes? [0x%.2x] ", vals->attributes); + fflush(stdout); + if (fgets(buff, sizeof(buff), stdin) == NULL || *buff == '\n') { + clearerr(stdin); + return; + } + attr = strtol(buff, &out, 0); + if (attr == 0 && out == buff) + attr = -1; + } while (attr < 0 || attr > 0xffff); + + vals->attributes = attr; + SET_FIELD(KADM_ATTR,vals->fields); +} + +static void +get_expdate(Kadm_vals *vals) +{ + char buff[BUFSIZ]; + struct tm edate; + + memset(&edate, 0, sizeof(edate)); + do { + printf("Expiration date (enter yyyy-mm-dd) ? [%.24s] ", + asctime(k_localtime(&vals->exp_date))); + fflush(stdout); + if (fgets(buff, sizeof(buff), stdin) == NULL || *buff == '\n') { + clearerr(stdin); + return; + } + if (sscanf(buff, "%d-%d-%d", + &edate.tm_year, &edate.tm_mon, &edate.tm_mday) == 3) { + edate.tm_mon--; /* January is 0, not 1 */ + edate.tm_hour = 23; /* nearly midnight at the end of the */ + edate.tm_min = 59; /* specified day */ + } + } while (krb_check_tm (edate)); + + edate.tm_year -= 1900; + vals->exp_date = tm2time (edate, 1); + SET_FIELD(KADM_EXPDATE,vals->fields); +} + +static int +princ_exists(char *name, char *instance, char *realm) +{ + int status; + + status = krb_get_pw_in_tkt(name, instance, realm, + KRB_TICKET_GRANTING_TICKET, + realm, 1, ""); + + if ((status == KSUCCESS) || (status == INTK_BADPW)) + return(PE_YES); + else if (status == KDC_PR_UNKNOWN) + return(PE_NO); + else + return(PE_UNSURE); +} + +static int +get_password(u_int32_t *low, u_int32_t *high, char *prompt, int byteswap) +{ + char new_passwd[MAX_KPW_LEN]; /* new password */ + des_cblock newkey; + + if (read_long_pw_string(new_passwd, sizeof(new_passwd)-1, prompt, 1)) + return(BAD_PW); + if (strlen(new_passwd) == 0) { + printf("Using random password.\n"); +#ifdef NOENCRYPTION + memset(newkey, 0, sizeof(newkey)); +#else + des_new_random_key(&newkey); +#endif + } else { +#ifdef NOENCRYPTION + memset(newkey, 0, sizeof(newkey)); +#else + des_string_to_key(new_passwd, &newkey); +#endif + memset(new_passwd, 0, sizeof(new_passwd)); + } + + memcpy(low, newkey, 4); + memcpy(high, ((char *)newkey) + 4, 4); + + memset(newkey, 0, sizeof(newkey)); + +#ifdef NOENCRYPTION + *low = 1; +#endif + + if (byteswap != DONTSWAP) { + *low = htonl(*low); + *high = htonl(*high); + } + return(GOOD_PW); +} + +static int +get_admin_password(void) +{ + int status; + char admin_passwd[MAX_KPW_LEN]; /* Admin's password */ + int ticket_life = 1; /* minimum ticket lifetime */ + CREDENTIALS c; + + if (multiple) { + /* If admin tickets exist and are valid, just exit. */ + memset(&c, 0, sizeof(c)); + if (krb_get_cred(PWSERV_NAME, KADM_SINST, krbrlm, &c) == KSUCCESS) + /* + * If time is less than lifetime - FUDGE_VALUE after issue date, + * tickets will probably last long enough for the next + * transaction. + */ + if (time(0) < (c.issue_date + (5 * 60 * c.lifetime) - FUDGE_VALUE)) + return(KADM_SUCCESS); + ticket_life = DEFAULT_TKT_LIFE; + } + + if (princ_exists(pr.name, pr.instance, pr.realm) != PE_NO) { + char prompt[256]; + snprintf(prompt, sizeof(prompt), "%s's Password: ", krb_unparse_name(&pr)); + if (read_long_pw_string(admin_passwd, + sizeof(admin_passwd)-1, + prompt, 0)) { + warnx ("Error reading admin password."); + goto bad; + } + status = krb_get_pw_in_tkt(pr.name, pr.instance, pr.realm, + PWSERV_NAME, KADM_SINST, + ticket_life, admin_passwd); + memset(admin_passwd, 0, sizeof(admin_passwd)); + + /* Initialize non shared random sequence from session key. */ + memset(&c, 0, sizeof(c)); + krb_get_cred(PWSERV_NAME, KADM_SINST, krbrlm, &c); + des_init_random_number_generator(&c.session); + } + else + status = KDC_PR_UNKNOWN; + + switch(status) { + case GT_PW_OK: + return(GOOD_PW); + case KDC_PR_UNKNOWN: + printf("Principal %s does not exist.\n", krb_unparse_name(&pr)); + goto bad; + case GT_PW_BADPW: + printf("Incorrect admin password.\n"); + goto bad; + default: + com_err("kadmin", status+krb_err_base, + "while getting password tickets"); + goto bad; + } + + bad: + memset(admin_passwd, 0, sizeof(admin_passwd)); + dest_tkt(); + return(BAD_PW); +} + +static void +usage(void) +{ + fprintf (stderr, "Usage: kadmin [[-u|-p] admin_name] [-r default_realm]" + " [-m]\n" + " -m allows multiple admin requests to be " + "serviced with one entry of admin\n" + " password.\n"); + exit (1); +} + +/* GLOBAL */ +static void +clean_up() +{ + dest_tkt(); +} + +static void +clean_up_cmd (int argc, char **argv) +{ + clean_up(); +} + +/* GLOBAL */ +static void +quit() +{ + printf("Cleaning up and exiting.\n"); + clean_up(); + exit(0); +} + +static void +quit_cmd (int argc, char **argv) +{ + quit(); +} + +static void +do_init(int argc, char **argv) +{ + int c; + int tflag = 0; + char tktstring[MaxPathLen]; + int k_errno; + + set_progname (argv[0]); + + memset(&pr, 0, sizeof(pr)); + if (krb_get_default_principal(pr.name, pr.instance, default_realm) < 0) + errx (1, "I could not even guess who you might be"); + while ((c = getopt(argc, argv, "p:u:r:mt")) != EOF) + switch (c) { + case 'p': + case 'u': + if((k_errno = krb_parse_name(optarg, &pr)) != KSUCCESS) + errx (1, "%s", krb_get_err_text(k_errno)); + break; + case 'r': + memset(default_realm, 0, sizeof(default_realm)); + strncpy(default_realm, optarg, sizeof(default_realm) - 1); + break; + case 'm': + multiple++; + break; + case 't': + tflag++; + break; + default: + usage(); + break; + } + if (optind < argc) + usage(); + strcpy(krbrlm, default_realm); + + if (kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm) != KADM_SUCCESS) + *krbrlm = '\0'; + if (pr.realm[0] == '\0') + strcpy (pr.realm, krbrlm); + if (pr.instance[0] == '\0') + strcpy(pr.instance, "admin"); + + if (!tflag) { + snprintf(tktstring, sizeof(tktstring), TKT_ROOT "_adm_%d",(int)getpid()); + krb_set_tkt_string(tktstring); + } + +} + +int +main(int argc, char **argv) +{ + do_init(argc, argv); + + printf("Welcome to the Kerberos Administration Program, version 2\n"); + printf("Type \"help\" if you need it.\n"); + sl_loop (cmds, "kadmin: "); + printf("\n"); + quit(); + exit(0); +} + +static int +setvals(Kadm_vals *vals, char *string) +{ + char realm[REALM_SZ]; + int status = KADM_SUCCESS; + + memset(vals, 0, sizeof(*vals)); + memset(realm, 0, sizeof(realm)); + + SET_FIELD(KADM_NAME,vals->fields); + SET_FIELD(KADM_INST,vals->fields); + if ((status = kname_parse(vals->name, vals->instance, realm, string))) { + printf("kerberos error: %s\n", krb_get_err_text(status)); + return status; + } + if (!realm[0]) + strcpy(realm, default_realm); + if (strcmp(realm, krbrlm)) { + strcpy(krbrlm, realm); + if ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm)) + != KADM_SUCCESS) + printf("kadm error for realm %s: %s\n", + krbrlm, error_message(status)); + } + if (status) + return 1; + else + return KADM_SUCCESS; +} + +static void +change_password(int argc, char **argv) +{ + Kadm_vals old, new; + int status; + char pw_prompt[BUFSIZ]; + + if (argc != 2) { + printf("Usage: change_password loginname\n"); + return; + } + + if (setvals(&old, argv[1]) != KADM_SUCCESS) + return; + + new = old; + + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(old.name, old.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + /* get the new password */ + snprintf(pw_prompt, sizeof(pw_prompt), "New password for %s:", argv[1]); + + if (get_password(&new.key_low, &new.key_high, + pw_prompt, SWAP) == GOOD_PW) { + status = kadm_mod(&old, &new); + if (status == KADM_SUCCESS) { + printf("Password changed for %s.\n", argv[1]); + } else { + printf("kadmin: %s\nwhile changing password for %s", + error_message(status), argv[1]); + } + } else + printf("Error reading password; password unchanged\n"); + memset(&new, 0, sizeof(new)); + if (!multiple) + clean_up(); + } + else + printf("kadmin: Principal %s does not exist.\n", + krb_unparse_name_long (old.name, old.instance, krbrlm)); + return; +} + +static int +getkey(unsigned char *k) +{ + int i, c; + for (i = 0; i < 8; i++) + { + c = getchar(); + if (c == EOF) + return 0; + else if (c == '\\') + { + int oct = -1; + scanf("%03o", &oct); + if (oct < 0 || oct > 255) + return 0; + k[i] = oct; + } + else if (!isalpha(c)) + return 0; + else + k[i] = c; + } + c = getchar(); + if (c != '\n') + return 0; + return 1; /* Success */ +} + +static void +printkey(unsigned char *tkey) +{ + int j; + for(j = 0; j < 8; j++) + if(tkey[j] != '\\' && isalpha(tkey[j]) != 0) + printf("%c", tkey[j]); + else + printf("\\%03o",(unsigned char)tkey[j]); + printf("\n"); +} + +static void +change_key(int argc, char **argv) +{ + Kadm_vals old, new; + unsigned char newkey[8]; + int status; + + if (argc != 2) { + printf("Usage: change_key principal-name\n"); + return; + } + + if (setvals(&old, argv[1]) != KADM_SUCCESS) + return; + + new = old; + + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(old.name, old.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + /* get the new password */ + printf("New DES key for %s: ", argv[1]); + + if (getkey(newkey)) { + memcpy(&new.key_low, newkey, 4); + memcpy(&new.key_high, ((char *)newkey) + 4, 4); + printf("Entered key for %s: ", argv[1]); + printkey(newkey); + memset(newkey, 0, sizeof(newkey)); + + status = kadm_mod(&old, &new); + if (status == KADM_SUCCESS) { + printf("Key changed for %s.\n", argv[1]); + } else { + printf("kadmin: %s\nwhile changing key for %s", + error_message(status), argv[1]); + } + } else + printf("Error reading key; key unchanged\n"); + memset(&new, 0, sizeof(new)); + if (!multiple) + clean_up(); + } + else + printf("kadmin: Principal %s does not exist.\n", + krb_unparse_name_long (old.name, old.instance, krbrlm)); + return; +} + +static void +change_admin_password(int argc, char **argv) +{ + des_cblock newkey; + int status; + char pword[MAX_KPW_LEN]; + char *pw_msg; + + if (argc != 1) { + printf("Usage: change_admin_password\n"); + return; + } + if (get_pw_new_pwd(pword, sizeof(pword), &pr, 1) == 0) { + des_string_to_key(pword, &newkey); + status = kadm_change_pw_plain(newkey, pword, &pw_msg); + if(status == KADM_INSECURE_PW) + printf("Insecure password: %s\n", pw_msg); + else if (status == KADM_SUCCESS) + printf("Admin password changed\n"); + else + printf("kadm error: %s\n",error_message(status)); + memset(newkey, 0, sizeof(newkey)); + memset(pword, 0, sizeof(pword)); + } + if (!multiple) + clean_up(); + return; +} + +static void +add_new_key(int argc, char **argv) +{ + Kadm_vals new; + char pw_prompt[BUFSIZ]; + int status; + + if (argc != 2) { + printf("Usage: add_new_key user_name.\n"); + return; + } + if (setvals(&new, argv[1]) != KADM_SUCCESS) + return; + + SET_FIELD(KADM_EXPDATE,new.fields); + SET_FIELD(KADM_ATTR,new.fields); + SET_FIELD(KADM_MAXLIFE,new.fields); + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(new.name, new.instance, krbrlm) != PE_YES) { + Kadm_vals vals; + u_char fields[4]; + char n[ANAME_SZ + INST_SZ + 1]; + + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + memset(fields, 0, sizeof(fields)); + SET_FIELD(KADM_NAME,fields); + SET_FIELD(KADM_INST,fields); + SET_FIELD(KADM_EXPDATE,fields); + SET_FIELD(KADM_ATTR,fields); + SET_FIELD(KADM_MAXLIFE,fields); + snprintf (n, sizeof(n), "default.%s", new.instance); + if (setvals(&vals, n) != KADM_SUCCESS) + return; + + if (kadm_get(&vals, fields) != KADM_SUCCESS) { + if (setvals(&vals, "default") != KADM_SUCCESS) + return; + if ((status = kadm_get(&vals, fields)) != KADM_SUCCESS) { + printf ("kadm error: %s\n", error_message(status)); + return; + } + } + + if (vals.max_life == 255) /* Defaults not set! */ { + /* This is the default maximum lifetime for new principals. */ + if (strcmp(new.instance, "admin") == 0) + vals.max_life = 1 + (CLOCK_SKEW/(5*60)); /* 5+5 minutes */ + else if (strcmp(new.instance, "root") == 0) + vals.max_life = 96; /* 8 hours */ + else if (krb_life_to_time(0, 162) >= 24*60*60) + vals.max_life = 162; /* ca 100 hours */ + else + vals.max_life = 255; /* ca 21 hours (maximum) */ + + /* Also fix expiration date. */ + if (strcmp(new.name, "rcmd") == 0) + vals.exp_date = 1104814999; /* Tue Jan 4 06:03:19 2005 */ + else + vals.exp_date = time(0) + 2*(365*24*60*60); /* + ca 2 years */ + } + + new.max_life = vals.max_life; + new.exp_date = vals.exp_date; + new.attributes = vals.attributes; + get_maxlife(&new); + get_attr(&new); + get_expdate(&new); + + /* get the new password */ + snprintf(pw_prompt, sizeof(pw_prompt), "Password for %s:", argv[1]); + + if (get_password(&new.key_low, &new.key_high, + pw_prompt, SWAP) == GOOD_PW) { + status = kadm_add(&new); + if (status == KADM_SUCCESS) { + printf("%s added to database.\n", argv[1]); + } else { + printf("kadm error: %s\n",error_message(status)); + } + } else + printf("Error reading password; %s not added\n",argv[1]); + memset(&new, 0, sizeof(new)); + if (!multiple) + clean_up(); + } + else + printf("kadmin: Principal already exists.\n"); + return; +} + +static void +del_entry(int argc, char **argv) +{ + int status; + Kadm_vals vals; + + if (argc != 2) { + printf("Usage: del_entry username\n"); + return; + } + + if (setvals(&vals, argv[1]) != KADM_SUCCESS) + return; + + if (princ_exists(vals.name, vals.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + if ((status = kadm_del(&vals)) == KADM_SUCCESS){ + printf("%s removed from database.\n", argv[1]); + } else { + printf("kadm error: %s\n",error_message(status)); + } + + if (!multiple) + clean_up(); + } + else + printf("kadmin: Principal %s does not exist.\n", + krb_unparse_name_long (vals.name, vals.instance, krbrlm)); + return; +} + +static void +get_entry(int argc, char **argv) +{ + int status; + u_char fields[4]; + Kadm_vals vals; + + if (argc != 2) { + printf("Usage: get_entry username\n"); + return; + } + + memset(fields, 0, sizeof(fields)); + + SET_FIELD(KADM_NAME,fields); + SET_FIELD(KADM_INST,fields); + SET_FIELD(KADM_EXPDATE,fields); + SET_FIELD(KADM_ATTR,fields); + SET_FIELD(KADM_MAXLIFE,fields); +#if 0 + SET_FIELD(KADM_DESKEY,fields); +#endif + + if (setvals(&vals, argv[1]) != KADM_SUCCESS) + return; + + + if (princ_exists(vals.name, vals.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + if ((status = kadm_get(&vals, fields)) == KADM_SUCCESS) + prin_vals(&vals); + else + printf("kadm error: %s\n",error_message(status)); + + if (!multiple) + clean_up(); + } + else + printf("kadmin: Principal %s does not exist.\n", + krb_unparse_name_long (vals.name, vals.instance, krbrlm)); + return; +} + +static void +mod_entry(int argc, char **argv) +{ + int status; + u_char fields[4]; + Kadm_vals ovals, nvals; + + if (argc != 2) { + printf("Usage: mod_entry username\n"); + return; + } + + memset(fields, 0, sizeof(fields)); + + SET_FIELD(KADM_NAME,fields); + SET_FIELD(KADM_INST,fields); + SET_FIELD(KADM_EXPDATE,fields); + SET_FIELD(KADM_ATTR,fields); + SET_FIELD(KADM_MAXLIFE,fields); + + if (setvals(&ovals, argv[1]) != KADM_SUCCESS) + return; + + nvals = ovals; + + if (princ_exists(ovals.name, ovals.instance, krbrlm) == PE_NO) { + printf("kadmin: Principal %s does not exist.\n", + krb_unparse_name_long (ovals.name, ovals.instance, krbrlm)); + return; + } + + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + if ((status = kadm_get(&ovals, fields)) != KADM_SUCCESS) { + printf("[ unable to retrieve current settings: %s ]\n", + error_message(status)); + nvals.max_life = DEFAULT_TKT_LIFE; + nvals.exp_date = 0; + nvals.attributes = 0; + } else { + nvals.max_life = ovals.max_life; + nvals.exp_date = ovals.exp_date; + nvals.attributes = ovals.attributes; + } + + get_maxlife(&nvals); + get_attr(&nvals); + get_expdate(&nvals); + + if (IS_FIELD(KADM_MAXLIFE, nvals.fields) || + IS_FIELD(KADM_ATTR, nvals.fields) || + IS_FIELD(KADM_EXPDATE, nvals.fields)) { + if ((status = kadm_mod(&ovals, &nvals)) != KADM_SUCCESS) { + printf("kadm error: %s\n",error_message(status)); + goto out; + } + if ((status = kadm_get(&ovals, fields)) != KADM_SUCCESS) { + printf("kadm error: %s\n",error_message(status)); + goto out; + } + } + prin_vals(&ovals); + +out: + if (!multiple) + clean_up(); + return; +} + +static void +help(int argc, char **argv) +{ + sl_help (cmds, argc, argv); +} diff --git a/crypto/kerberosIV/kadmin/kpasswd.c b/crypto/kerberosIV/kadmin/kpasswd.c new file mode 100644 index 0000000..f4c0cda --- /dev/null +++ b/crypto/kerberosIV/kadmin/kpasswd.c @@ -0,0 +1,163 @@ +/* + 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. + + */ + +/* + * change your password with kerberos + */ + +#include "kadm_locl.h" + +RCSID("$Id: kpasswd.c,v 1.25 1997/05/02 14:28:51 assar Exp $"); + +static void +usage(int value) +{ + fprintf(stderr, "Usage: "); + fprintf(stderr, "kpasswd [-h ] [-n user] [-i instance] [-r realm] "); + fprintf(stderr, "[-u fullname]\n"); + exit(value); +} + +int +main(int argc, char **argv) +{ + krb_principal principal; + krb_principal default_principal; + int realm_given = 0; /* True if realm was give on cmdline */ + int use_default = 1; /* True if we should use default name */ + int status; /* return code */ + char pword[MAX_KPW_LEN]; + int c; + char tktstring[MaxPathLen]; + + set_progname (argv[0]); + + memset (&principal, 0, sizeof(principal)); + memset (&default_principal, 0, sizeof(default_principal)); + + krb_get_default_principal (default_principal.name, + default_principal.instance, + default_principal.realm); + + while ((c = getopt(argc, argv, "u:n:i:r:h")) != EOF) { + switch (c) { + case 'u': + status = krb_parse_name (optarg, &principal); + if (status != KSUCCESS) + errx (2, "%s", krb_get_err_text(status)); + if (principal.realm[0]) + realm_given++; + else if (krb_get_lrealm(principal.realm, 1) != KSUCCESS) + errx (1, "Could not find default realm!"); + break; + case 'n': + if (k_isname(optarg)) + strncpy(principal.name, optarg, sizeof(principal.name) - 1); + else { + warnx("Bad name: %s", optarg); + usage(1); + } + break; + case 'i': + if (k_isinst(optarg)) + strncpy(principal.instance, + optarg, + sizeof(principal.instance) - 1); + else { + warnx("Bad instance: %s", optarg); + usage(1); + } + break; + case 'r': + if (k_isrealm(optarg)) { + strncpy(principal.realm, optarg, sizeof(principal.realm) - 1); + realm_given++; + } else { + warnx("Bad realm: %s", optarg); + usage(1); + } + break; + case 'h': + usage(0); + break; + default: + usage(1); + break; + } + use_default = 0; + } + if (optind < argc) { + use_default = 0; + status = krb_parse_name (argv[optind], &principal); + if(status != KSUCCESS) + errx (1, "%s", krb_get_err_text (status)); + } + + if (use_default) { + strcpy(principal.name, default_principal.name); + strcpy(principal.instance, default_principal.instance); + strcpy(principal.realm, default_principal.realm); + } else { + if (!principal.name[0]) + strcpy(principal.name, default_principal.name); + if (!principal.realm[0]) + strcpy(principal.realm, default_principal.realm); + } + + snprintf(tktstring, sizeof(tktstring), + TKT_ROOT "_cpw_%u", (unsigned)getpid()); + krb_set_tkt_string(tktstring); + + if (get_pw_new_pwd(pword, sizeof(pword), &principal, + realm_given)) { + dest_tkt (); + exit(1); + } + + status = kadm_init_link (PWSERV_NAME, KRB_MASTER, principal.realm); + if (status != KADM_SUCCESS) + com_err(argv[0], status, "while initializing"); + else { + des_cblock newkey; + char *pw_msg; /* message from server */ + + des_string_to_key(pword, &newkey); + status = kadm_change_pw_plain((unsigned char*)&newkey, pword, &pw_msg); + memset(newkey, 0, sizeof(newkey)); + + if (status == KADM_INSECURE_PW) + warnx ("Insecure password: %s", pw_msg); + else if (status != KADM_SUCCESS) + com_err(argv[0], status, " attempting to change password."); + } + memset(pword, 0, sizeof(pword)); + + if (status != KADM_SUCCESS) + fprintf(stderr,"Password NOT changed.\n"); + else + printf("Password changed.\n"); + + dest_tkt(); + if (status) + return 2; + else + return 0; +} 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; +} diff --git a/crypto/kerberosIV/kadmin/ksrvutil.h b/crypto/kerberosIV/kadmin/ksrvutil.h new file mode 100644 index 0000000..64e2fe4 --- /dev/null +++ b/crypto/kerberosIV/kadmin/ksrvutil.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: ksrvutil.h,v 1.8 1997/04/01 03:58:55 assar Exp $ + * + */ + +extern char u_name[], u_inst[], u_realm[]; +extern int destroyp; + +void leave(char *str, int x); +void safe_read_stdin(char *prompt, char *buf, size_t size); +void safe_write(char *filename, int fd, void *buf, size_t len); + +int yn(char *string); +int ny(char *string); + +void ksrvutil_get(int fd, char *filename, int argc, char **argv); diff --git a/crypto/kerberosIV/kadmin/ksrvutil_get.c b/crypto/kerberosIV/kadmin/ksrvutil_get.c new file mode 100644 index 0000000..7b97d35 --- /dev/null +++ b/crypto/kerberosIV/kadmin/ksrvutil_get.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadm_locl.h" +#include "ksrvutil.h" + +RCSID("$Id: ksrvutil_get.c,v 1.32 1997/05/05 21:14:57 assar Exp $"); + +#define BAD_PW 1 +#define GOOD_PW 0 +#define FUDGE_VALUE 15 /* for ticket expiration time */ +#define PE_NO 0 +#define PE_YES 1 +#define PE_UNSURE 2 + +static char tktstring[128]; + +static int +princ_exists(char *name, char *instance, char *realm) +{ + int status; + + status = krb_get_pw_in_tkt(name, instance, realm, + KRB_TICKET_GRANTING_TICKET, + realm, 1, ""); + + if ((status == KSUCCESS) || (status == INTK_BADPW)) + return(PE_YES); + else if (status == KDC_PR_UNKNOWN) + return(PE_NO); + else + return(PE_UNSURE); +} + +static int +get_admin_password(char *myname, char *myinst, char *myrealm) +{ + int status; + char admin_passwd[MAX_KPW_LEN]; /* Admin's password */ + int ticket_life = 1; /* minimum ticket lifetime */ + char buf[1024]; + CREDENTIALS c; + + if (princ_exists(myname, myinst, myrealm) != PE_NO) { + snprintf(buf, sizeof(buf), "Password for %s: ", + krb_unparse_name_long (myname, myinst, myrealm)); + if (des_read_pw_string(admin_passwd, sizeof(admin_passwd)-1, + buf, 0)) { + fprintf(stderr, "Error reading admin password.\n"); + goto bad; + } + status = krb_get_pw_in_tkt(myname, myinst, myrealm, PWSERV_NAME, + KADM_SINST, ticket_life, admin_passwd); + memset(admin_passwd, 0, sizeof(admin_passwd)); + + /* Initialize non shared random sequence from session key. */ + memset(&c, 0, sizeof(c)); + krb_get_cred(PWSERV_NAME, KADM_SINST, myrealm, &c); + des_init_random_number_generator(&c.session); + } + else + status = KDC_PR_UNKNOWN; + + switch(status) { + case GT_PW_OK: + return(GOOD_PW); + case KDC_PR_UNKNOWN: + printf("Principal %s does not exist.\n", + krb_unparse_name_long(myname, myinst, myrealm)); + goto bad; + case GT_PW_BADPW: + printf("Incorrect admin password.\n"); + goto bad; + default: + com_err("kadmin", status+krb_err_base, + "while getting password tickets"); + goto bad; + } + +bad: + memset(admin_passwd, 0, sizeof(admin_passwd)); + dest_tkt(); + return(BAD_PW); +} + +static void +srvtab_put_key (int fd, char *filename, char *name, char *inst, char *realm, + int8_t kvno, des_cblock key) +{ + char sname[ANAME_SZ]; /* name of service */ + char sinst[INST_SZ]; /* instance of service */ + char srealm[REALM_SZ]; /* realm of service */ + int8_t skvno; + des_cblock skey; + + lseek(fd, 0, SEEK_SET); + + while(getst(fd, sname, SNAME_SZ) > 0 && + getst(fd, sinst, INST_SZ) > 0 && + getst(fd, srealm, REALM_SZ) > 0 && + read(fd, &skvno, sizeof(skvno)) > 0 && + read(fd, skey, sizeof(skey)) > 0) { + if(strcmp(name, sname) == 0 && + strcmp(inst, sinst) == 0 && + strcmp(realm, srealm) == 0) { + lseek(fd, lseek(fd,0,SEEK_CUR)-(sizeof(skvno) + sizeof(skey)), SEEK_SET); + safe_write(filename, fd, &kvno, sizeof(kvno)); + safe_write(filename, fd, key, sizeof(des_cblock)); + return; + } + } + safe_write(filename, fd, name, strlen(name) + 1); + safe_write(filename, fd, inst, strlen(inst) + 1); + safe_write(filename, fd, realm, strlen(realm) + 1); + safe_write(filename, fd, &kvno, sizeof(kvno)); + safe_write(filename, fd, key, sizeof(des_cblock)); +} + +/* + * node list of services + */ + +struct srv_ent{ + char name[SNAME_SZ]; + char inst[INST_SZ]; + char realm[REALM_SZ]; + struct srv_ent *next; +}; + +static int +key_to_key(char *user, char *instance, char *realm, void *arg, + des_cblock *key) +{ + memcpy(key, arg, sizeof(des_cblock)); + return 0; +} + +static void +get_srvtab_ent(int fd, char *filename, char *name, char *inst, char *realm) +{ + char chname[128]; + des_cblock newkey; + char old_tktfile[MaxPathLen], new_tktfile[MaxPathLen]; + char garbage_name[ANAME_SZ]; + char garbage_inst[ANAME_SZ]; + CREDENTIALS c; + u_int8_t kvno; + Kadm_vals values; + int ret; + + strncpy(chname, krb_get_phost(inst), sizeof(chname)); + if(strcmp(inst, chname)) + fprintf(stderr, + "Warning: Are you sure `%s' should not be `%s'?\n", + inst, chname); + + memset(&values, 0, sizeof(values)); + strcpy(values.name, name); + strcpy(values.instance, inst); + des_new_random_key(&newkey); + values.key_low = (newkey[0] << 24) | (newkey[1] << 16) + | (newkey[2] << 8) | (newkey[3] << 0); + values.key_high = (newkey[4] << 24) | (newkey[5] << 16) + | (newkey[6] << 8) | (newkey[7] << 0); + + SET_FIELD(KADM_NAME,values.fields); + SET_FIELD(KADM_INST,values.fields); + SET_FIELD(KADM_DESKEY,values.fields); + + ret = kadm_mod(&values, &values); + if(ret == KADM_NOENTRY) + ret = kadm_add(&values); + if (ret != KSUCCESS) { + warnx ("Couldn't get srvtab entry for %s.%s: %s", + name, inst, error_message(ret)); + return; + } + + values.key_low = values.key_high = 0; + + /* get the key version number */ + + strcpy(old_tktfile, tkt_string()); + snprintf(new_tktfile, sizeof(new_tktfile), + TKT_ROOT "_ksrvutil-get.%u", + (unsigned)getpid()); + krb_set_tkt_string(new_tktfile); + + ret = krb_get_in_tkt(name, inst, realm, name, inst, + 1, key_to_key, NULL, &newkey); + + if (ret == KSUCCESS && + (ret = tf_init(tkt_string(), R_TKT_FIL)) == KSUCCESS && + (ret = tf_get_pname(garbage_name)) == KSUCCESS && + (ret = tf_get_pinst(garbage_inst)) == KSUCCESS && + (ret = tf_get_cred(&c)) == KSUCCESS) + kvno = c.kvno; + else { + warnx ("Could not find the cred in the ticket file"); + return; + } + + tf_close(); + krb_set_tkt_string(old_tktfile); + unlink(new_tktfile); + + if(ret != KSUCCESS) { + memset(&newkey, 0, sizeof(newkey)); + warnx ("Could not get a ticket for %s: %s\n", + krb_unparse_name_long(name, inst, realm), + krb_get_err_text(ret)); + return; + } + + /* Write the new key & c:o to the srvtab file */ + + srvtab_put_key (fd, filename, name, inst, realm, kvno, newkey); + memset(&newkey, 0, sizeof(newkey)); + + fprintf (stderr, "Added %s\n", krb_unparse_name_long (name, inst, realm)); +} + +static void +ksrvutil_kadm(int fd, char *filename, struct srv_ent *p) +{ + int ret; + CREDENTIALS c; + + ret = kadm_init_link(PWSERV_NAME, KADM_SINST, u_realm); + if (ret != KADM_SUCCESS) { + warnx("Couldn't initialize kadmin link: %s", error_message(ret)); + leave(NULL, 1); + } + + ret = krb_get_cred (PWSERV_NAME, KADM_SINST, u_realm, &c); + if (ret == KSUCCESS) + des_init_random_number_generator (&c.session); + else { + umask(077); + + /* + * create ticket file and get admin tickets + */ + snprintf(tktstring, sizeof(tktstring), TKT_ROOT "_ksrvutil_%d", (int)getpid()); + krb_set_tkt_string(tktstring); + destroyp = TRUE; + + ret = get_admin_password(u_name, u_inst, u_realm); + if (ret) { + warnx("Couldn't get admin password."); + leave(NULL, 1); + } + } + for(;p;){ + get_srvtab_ent(fd, filename, p->name, p->inst, p->realm); + p=p->next; + } + unlink(tktstring); +} + +static void +parseinput (char *result, size_t sz, char *val, char *def) +{ + char *lim; + int inq; + + if (val[0] == '\0') { + strncpy (result, def, sz-1); + return; + } + lim = result + sz - 1; + inq = 0; + while(*val && result < lim) { + switch(*val) { + case '\'' : + inq = !inq; + ++val; + break; + case '\\' : + if(!inq) + val++; + default: + *result++ = *val++; + break; + } + } + *result = '\0'; +} + +void +ksrvutil_get(int fd, char *filename, 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 */ + char databuf[BUFSIZ]; + char local_hostname[100]; + char prompt[100]; + struct srv_ent *head=NULL; + int i; + + k_gethostname(local_hostname, sizeof(local_hostname)); + strcpy(local_hostname, krb_get_phost(local_hostname)); + + if (argc) + for(i=0; i < argc; ++i) { + struct srv_ent *p=malloc(sizeof(*p)); + + if(p == NULL) { + warnx ("out of memory in malloc"); + leave(NULL,1); + } + p->next = head; + strcpy (p->realm, u_realm); + if (kname_parse (p->name, p->inst, p->realm, argv[i]) != + KSUCCESS) { + warnx ("parse error on '%s'\n", argv[i]); + free(p); + continue; + } + if (p->name[0] == '\0') + strcpy(p->name, "rcmd"); + if (p->inst[0] == '\0') + strcpy(p->inst, local_hostname); + if (p->realm[0] == '\0') + strcpy(p->realm, u_realm); + head = p; + } + + else + do{ + safe_read_stdin("Name [rcmd]: ", databuf, sizeof(databuf)); + parseinput (sname, sizeof(sname), databuf, "rcmd"); + + snprintf(prompt, sizeof(prompt), "Instance [%s]: ", local_hostname); + safe_read_stdin(prompt, databuf, sizeof(databuf)); + parseinput (sinst, sizeof(sinst), databuf, local_hostname); + + snprintf(prompt, sizeof(prompt), "Realm [%s]: ", u_realm); + safe_read_stdin(prompt, databuf, sizeof(databuf)); + parseinput (srealm, sizeof(srealm), databuf, u_realm); + + if(yn("Is this correct?")){ + struct srv_ent *p=(struct srv_ent*)malloc(sizeof(struct srv_ent)); + p->next=head; + head=p; + strcpy(p->name, sname); + strcpy(p->inst, sinst); + strcpy(p->realm, srealm); + } + }while(ny("Add more keys?")); + + + ksrvutil_kadm(fd, filename, head); + + { + struct srv_ent *p=head, *q; + while(p){ + q=p; + p=p->next; + free(q); + } + } + +} diff --git a/crypto/kerberosIV/kadmin/new_pwd.c b/crypto/kerberosIV/kadmin/new_pwd.c new file mode 100644 index 0000000..88fb7a9 --- /dev/null +++ b/crypto/kerberosIV/kadmin/new_pwd.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadm_locl.h" + +RCSID("$Id: new_pwd.c,v 1.11 1997/05/02 14:28:54 assar Exp $"); + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else +#define read_long_pw_string des_read_pw_string +#endif + +static char * +check_pw (char *pword) +{ + if (strlen(pword) == 0) + return "Null passwords are not allowed - Please enter a longer password."; + + if (strlen(pword) < MIN_KPW_LEN) + return "Password is to short - Please enter a longer password."; + + /* Don't allow all lower case passwords regardless of length */ + { + char *t; + for (t = pword; *t && islower(*t); t++) + ; + if (*t == 0) + return "Please don't use an all-lower case password.\n" + "\tUnusual capitalization, delimiter characters or " + "digits are suggested."; + } + + return NULL; +} + +int +get_pw_new_pwd(char *pword, int pwlen, krb_principal *pr, int print_realm) +{ + char ppromp[40+ANAME_SZ+INST_SZ+REALM_SZ]; /* for the password prompt */ + char npromp[40+ANAME_SZ+INST_SZ+REALM_SZ]; /* for the password prompt */ + + char p[MAX_K_NAME_SZ]; + + char local_realm[REALM_SZ]; + int status; + char *expl; + + /* + * We don't care about failure; this is to determine whether or + * not to print the realm in the prompt for a new password. + */ + krb_get_lrealm(local_realm, 1); + + if (strcmp(local_realm, pr->realm)) + print_realm++; + + { + char *q; + krb_unparse_name_r(pr, p); + if(print_realm == 0 && (q = strrchr(p, '@'))) + *q = 0; + } + + snprintf(ppromp, sizeof(ppromp), "Old password for %s:", p); + if (read_long_pw_string(pword, pwlen-1, ppromp, 0)) { + fprintf(stderr, "Error reading old password.\n"); + return -1; + } + + status = krb_get_pw_in_tkt(pr->name, pr->instance, pr->realm, + PWSERV_NAME, KADM_SINST, 1, pword); + if (status != KSUCCESS) { + if (status == INTK_BADPW) { + printf("Incorrect old password.\n"); + return -1; + } + else { + fprintf(stderr, "Kerberos error: %s\n", krb_get_err_text(status)); + return -1; + } + } + memset(pword, 0, pwlen); + + do { + char verify[MAX_KPW_LEN]; + snprintf(npromp, sizeof(npromp), "New Password for %s:",p); + if (read_long_pw_string(pword, pwlen-1, npromp, 0)) { + fprintf(stderr, + "Error reading new password, password unchanged.\n"); + return -1; + } + expl = check_pw (pword); + if (expl) { + printf("\n\t%s\n\n", expl); + continue; + } + /* Now we got an ok password, verify it. */ + snprintf(npromp, sizeof(npromp), "Verifying New Password for %s:", p); + if (read_long_pw_string(verify, MAX_KPW_LEN-1, npromp, 0)) { + fprintf(stderr, + "Error reading new password, password unchanged.\n"); + return -1; + } + if (strcmp(pword, verify) != 0) { + printf("Verify failure - try again\n"); + expl = ""; /* continue */ + } + } while (expl); + return 0; +} diff --git a/crypto/kerberosIV/kadmin/pw_check.c b/crypto/kerberosIV/kadmin/pw_check.c new file mode 100644 index 0000000..ac6912b --- /dev/null +++ b/crypto/kerberosIV/kadmin/pw_check.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadm_locl.h" + +RCSID("$Id: pw_check.c,v 1.13 1997/04/01 08:17:50 joda Exp $"); + +/* + * kadm_pw_check + * + * pw : new password or "" if none passed + * newkey : key for pw as passed from client + * strings : interesting strings to check for + * + * returns NULL if pw is ok, else an explanatory string + */ +int +kadm_pw_check(char *pw, des_cblock *newkey, char **pw_msg, + char **strings) +{ + des_cblock pwkey; + int status=KADM_SUCCESS; + + if (pw == NULL || *pw == '\0') + return status; /* XXX - Change this later */ + +#ifndef NO_PW_CHECK + *pw_msg = NULL; + des_string_to_key(pw, &pwkey); /* Check AFS string to key also! */ + if (memcmp(pwkey, *newkey, sizeof(pwkey)) != 0) + { + /* no password or bad key */ + status=KADM_PW_MISMATCH; + *pw_msg = "Password doesn't match supplied DES key"; + } + else if (strlen(pw) < MIN_KPW_LEN) + { + status = KADM_INSECURE_PW; + *pw_msg="Password is too short"; + } + +#ifdef DICTPATH + *pw_msg = FascistCheck(pw, DICTPATH, strings); + if (*pw_msg) + return KADM_INSECURE_PW; +#endif + + memset(pwkey, 0, sizeof(pwkey)); +#endif + + return status; +} diff --git a/crypto/kerberosIV/kadmin/pw_check.h b/crypto/kerberosIV/kadmin/pw_check.h new file mode 100644 index 0000000..c5a5d69 --- /dev/null +++ b/crypto/kerberosIV/kadmin/pw_check.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pw_check.h,v 1.6 1997/04/01 08:17:50 joda Exp $ + */ + +int kadm_pw_check(char *pw, des_cblock *newkey, + char **pw_msg, char **strings); + |