diff options
author | wollman <wollman@FreeBSD.org> | 1995-01-20 03:13:00 +0000 |
---|---|---|
committer | wollman <wollman@FreeBSD.org> | 1995-01-20 03:13:00 +0000 |
commit | cba76fbeed5aa6487c0855ac6a42f9ceb8bd8bd5 (patch) | |
tree | 2af41fdfa6d2d0cd79a1bdbf91b596bccb1e1f24 /eBones | |
parent | 736fb60fc383e229208816a1cba94f34ce63bcc4 (diff) | |
download | FreeBSD-src-cba76fbeed5aa6487c0855ac6a42f9ceb8bd8bd5.zip FreeBSD-src-cba76fbeed5aa6487c0855ac6a42f9ceb8bd8bd5.tar.gz |
Add kadmind. HOW-TO documents how to get here from raw eBones.
Diffstat (limited to 'eBones')
-rw-r--r-- | eBones/kadmind/HOW-TO | 267 | ||||
-rw-r--r-- | eBones/kadmind/Makefile | 11 | ||||
-rw-r--r-- | eBones/kadmind/admin_server.c | 447 | ||||
-rw-r--r-- | eBones/kadmind/kadm_funcs.c | 373 | ||||
-rw-r--r-- | eBones/kadmind/kadm_ser_wrap.c | 206 | ||||
-rw-r--r-- | eBones/kadmind/kadm_server.c | 159 | ||||
-rw-r--r-- | eBones/kadmind/kadm_server.h | 51 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmin/Makefile | 11 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmin/admin_server.c | 447 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmin/kadm_funcs.c | 373 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmin/kadm_ser_wrap.c | 206 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmin/kadm_server.c | 159 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmin/kadm_server.h | 51 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmind/Makefile | 11 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmind/admin_server.c | 447 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmind/kadm_funcs.c | 373 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmind/kadm_ser_wrap.c | 206 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmind/kadm_server.c | 159 | ||||
-rw-r--r-- | eBones/usr.sbin/kadmind/kadm_server.h | 51 |
19 files changed, 4008 insertions, 0 deletions
diff --git a/eBones/kadmind/HOW-TO b/eBones/kadmind/HOW-TO new file mode 100644 index 0000000..f41982a --- /dev/null +++ b/eBones/kadmind/HOW-TO @@ -0,0 +1,267 @@ +This directory was created from eBones by the following procedure: + +1) Get the files listed in the Makefile + +2) perl -spi.bak -e 's/\$(Header[^\$]*)\$/$1/g' + +3) Apply the patch listed below. + +diff -rc2 ../kadmind.orig/admin_server.c ./admin_server.c +*** ../kadmind.orig/admin_server.c Thu Jan 19 18:04:04 1995 +--- ./admin_server.c Thu Jan 19 21:58:51 1995 +*************** +*** 1,10 **** + /* +- * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/admin_server.c,v $ +- * $Author: jtkohl $ +- * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * <mit-copyright.h>. + * + * Top-level loop of the kerberos Administration server +--- 1,7 ---- + /* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * Copyright.MIT. + * + * Top-level loop of the kerberos Administration server +*************** +*** 12,20 **** + + #ifndef lint + static char rcsid_admin_server_c[] = +! "$Id: admin_server.c,v 4.8 90/01/02 13:50:38 jtkohl Exp $"; + #endif lint + +- #include <mit-copyright.h> + /* + admin_server.c +--- 9,20 ---- + + #ifndef lint ++ #if 0 + static char rcsid_admin_server_c[] = +! "Id: admin_server.c,v 4.8 90/01/02 13:50:38 jtkohl Exp "; +! #endif +! static const char rcsid[] = +! "$Id"; + #endif lint + + /* + admin_server.c +*************** +*** 389,393 **** +--- 389,397 ---- + register int i, j; + ++ #ifdef POSIX ++ int status; ++ #else + union wait status; ++ #endif + + pid = wait(&status); +*************** +*** 400,406 **** + pidarray[j] = pidarray[j+1]; + pidarraysize--; +! if (status.w_retcode || status.w_coredump || status.w_termsig) + log("child %d: termsig %d, coredump %d, retcode %d", pid, +! status.w_termsig, status.w_coredump, status.w_retcode); + #ifdef POSIX + return; +--- 404,410 ---- + pidarray[j] = pidarray[j+1]; + pidarraysize--; +! if (WEXITSTATUS(status) || WCOREDUMP(status) || WIFSIGNALED(status)) + log("child %d: termsig %d, coredump %d, retcode %d", pid, +! WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); + #ifdef POSIX + return; +*************** +*** 410,414 **** + } + log("child %d not in list: termsig %d, coredump %d, retcode %d", pid, +! status.w_termsig, status.w_coredump, status.w_retcode); + #ifdef POSIX + return; +--- 414,418 ---- + } + log("child %d not in list: termsig %d, coredump %d, retcode %d", pid, +! WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); + #ifdef POSIX + return; +Only in .: admin_server.c~ +diff -rc2 ../kadmind.orig/kadm_funcs.c ./kadm_funcs.c +*** ../kadmind.orig/kadm_funcs.c Thu Jan 19 18:04:04 1995 +--- ./kadm_funcs.c Thu Jan 19 21:56:31 1995 +*************** +*** 1,10 **** + /* +- * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_funcs.c,v $ +- * $Author: jon $ +- * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * <mit-copyright.h>. + * + * Kerberos administration server-side database manipulation routines +--- 1,7 ---- + /* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * Copyright.MIT + * + * Kerberos administration server-side database manipulation routines +*************** +*** 12,20 **** + + #ifndef lint + static char rcsid_kadm_funcs_c[] = +! "$Id: kadm_funcs.c,v 4.3 90/03/20 01:39:51 jon Exp $"; + #endif lint + +- #include <mit-copyright.h> + /* + kadm_funcs.c +--- 9,20 ---- + + #ifndef lint ++ #if 0 + static char rcsid_kadm_funcs_c[] = +! "Id: kadm_funcs.c,v 4.3 90/03/20 01:39:51 jon Exp "; +! #endif +! static const char rcsid[] = +! "$Id$"; + #endif lint + + /* + kadm_funcs.c +Only in .: kadm_funcs.c~ +diff -rc2 ../kadmind.orig/kadm_ser_wrap.c ./kadm_ser_wrap.c +*** ../kadmind.orig/kadm_ser_wrap.c Thu Jan 19 18:04:04 1995 +--- ./kadm_ser_wrap.c Thu Jan 19 21:59:15 1995 +*************** +*** 1,10 **** + /* +- * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_ser_wrap.c,v $ +- * $Author: jtkohl $ +- * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * <mit-copyright.h>. + * + * Kerberos administration server-side support functions +--- 1,7 ---- + /* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * Copyright.MIT. + * + * Kerberos administration server-side support functions +*************** +*** 16,20 **** + #endif lint + +- #include <mit-copyright.h> + /* + kadm_ser_wrap.c +--- 13,16 ---- +Only in .: kadm_ser_wrap.c~ +diff -rc2 ../kadmind.orig/kadm_server.c ./kadm_server.c +*** ../kadmind.orig/kadm_server.c Thu Jan 19 18:04:04 1995 +--- ./kadm_server.c Thu Jan 19 21:59:31 1995 +*************** +*** 1,10 **** + /* +- * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.c,v $ +- * $Author: jtkohl $ +- * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * <mit-copyright.h>. + * + * Kerberos administration server-side subroutines +--- 1,7 ---- + /* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file +! * Copyright.MIT. + * + * Kerberos administration server-side subroutines +*************** +*** 15,20 **** + "Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.c,v 4.2 89/09/26 09:30:23 jtkohl Exp "; + #endif lint +- +- #include <mit-copyright.h> + + #include <kadm.h> +--- 12,15 ---- +Only in .: kadm_server.c~ +diff -rc2 ../kadmind.orig/kadm_server.h ./kadm_server.h +*** ../kadmind.orig/kadm_server.h Thu Jan 19 18:04:05 1995 +--- ./kadm_server.h Thu Jan 19 18:06:36 1995 +*************** +*** 7,11 **** + * + * For copying and distribution information, please see the file +! * <mit-copyright.h>. + * + * Definitions for Kerberos administration server & client +--- 7,11 ---- + * + * For copying and distribution information, please see the file +! * Copyright.MIT. + * + * Definitions for Kerberos administration server & client +*************** +*** 15,19 **** + #define KADM_SERVER_DEFS + +- #include <mit-copyright.h> + /* + * kadm_server.h +--- 15,18 ---- +*************** +*** 25,30 **** + + #include <sys/types.h> +! #include <krb.h> +! #include <des.h> + + typedef struct { +--- 24,29 ---- + + #include <sys/types.h> +! #include <kerberosIV/krb.h> +! #include <kerberosIV/des.h> + + typedef struct { +*************** +*** 43,49 **** + + /* the default syslog file */ +! #define KADM_SYSLOG "/kerberos/admin_server.syslog" + +! #define DEFAULT_ACL_DIR "/kerberos" + #define ADD_ACL_FILE "/admin_acl.add" + #define GET_ACL_FILE "/admin_acl.get" +--- 42,48 ---- + + /* the default syslog file */ +! #define KADM_SYSLOG "/var/log/kadmind.syslog" + +! #define DEFAULT_ACL_DIR "/etc/kerberosIV" + #define ADD_ACL_FILE "/admin_acl.add" + #define GET_ACL_FILE "/admin_acl.get" diff --git a/eBones/kadmind/Makefile b/eBones/kadmind/Makefile new file mode 100644 index 0000000..77069be --- /dev/null +++ b/eBones/kadmind/Makefile @@ -0,0 +1,11 @@ +# $Id$ + +PROG= kadmind +SRCS= admin_server.c kadm_funcs.c kadm_ser_wrap.c kadm_server.c +CFLAGS+=-DPOSIX -I${.CURDIR}/../include -I${KRBOBJDIR} \ + -I${.CURDIR}/../libkadm -I${KADMOBJDIR} +LDADD+= -L${KADMOBJDIR} -lkadm -L${KDBOBJDIR} -lkdb -L${KRBOBJDIR} -lkrb \ + -L${DESOBJDIR} -ldes -L${ACLOBJDIR} -lacl -lcom_err +NOMAN= # man page in ../man + +.include <bsd.prog.mk> diff --git a/eBones/kadmind/admin_server.c b/eBones/kadmind/admin_server.c new file mode 100644 index 0000000..cca1aaf --- /dev/null +++ b/eBones/kadmind/admin_server.c @@ -0,0 +1,447 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Top-level loop of the kerberos Administration server + */ + +#ifndef lint +#if 0 +static char rcsid_admin_server_c[] = +"Id: admin_server.c,v 4.8 90/01/02 13:50:38 jtkohl Exp "; +#endif +static const char rcsid[] = + "$Id"; +#endif lint + +/* + admin_server.c + this holds the main loop and initialization and cleanup code for the server +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <signal.h> +#ifndef sigmask +#define sigmask(m) (1 <<((m)-1)) +#endif +#include <sys/wait.h> +#include <errno.h> +#include <sys/socket.h> +#include <syslog.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_db.h> +#include "kadm_server.h" + +/* Almost all procs and such need this, so it is global */ +admin_params prm; /* The command line parameters struct */ + +char prog[32]; /* WHY IS THIS NEEDED??????? */ +char *progname = prog; +char *acldir = DEFAULT_ACL_DIR; +char krbrlm[REALM_SZ]; +extern Kadm_Server server_parm; + +/* +** 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... +*/ +main(argc, argv) /* admin_server main routine */ +int argc; +char *argv[]; +{ + int errval; + int c; + extern char *optarg; + + prog[sizeof(prog)-1]='\0'; /* Terminate... */ + (void) strncpy(prog, argv[0], sizeof(prog)-1); + + /* initialize the admin_params structure */ + prm.sysfile = KADM_SYSLOG; /* default file name */ + prm.inter = 1; + + bzero(krbrlm, sizeof(krbrlm)); + + while ((c = getopt(argc, argv, "f:hnd:a:r:")) != EOF) + switch(c) { + case 'f': /* Syslog file name change */ + prm.sysfile = optarg; + break; + case 'n': + prm.inter = 0; + 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)) { + fprintf(stderr, "opening database %s: %s", + optarg, error_message(errval)); + exit(1); + } + break; + case 'r': + (void) strncpy(krbrlm, optarg, sizeof(krbrlm) - 1); + break; + case 'h': /* get help on using admin_server */ + default: + printf("Usage: admin_server [-h] [-n] [-r realm] [-d dbname] [-f filename] [-a acldir]\n"); + exit(-1); /* failure */ + } + + if (krbrlm[0] == 0) + if (krb_get_lrealm(krbrlm, 0) != KSUCCESS) { + fprintf(stderr, + "Unable to get local realm. Fix krb.conf or use -r.\n"); + exit(1); + } + + 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"); + + set_logfile(prm.sysfile); + log("Admin server starting"); + + (void) kerb_db_set_lockmode(KERB_DBL_NONBLOCKING); + errval = kerb_init(); /* Open the Kerberos database */ + if (errval) { + fprintf(stderr, "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) { + fprintf(stderr,"error: %s\n",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 */ +} /* procedure main */ + + +/* close the system log file */ +close_syslog() +{ + log("Shutting down admin server"); +} + +byebye() /* say goodnight gracie */ +{ + printf("Admin Server (kadm server) has completed operation.\n"); +} + +static clear_secrets() +{ + bzero((char *)server_parm.master_key, sizeof(server_parm.master_key)); + bzero((char *)server_parm.master_key_schedule, + sizeof(server_parm.master_key_schedule)); + server_parm.master_key_version = 0L; + return; +} + +static exit_now = 0; + +sigtype +doexit() +{ + exit_now = 1; +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ +} + +unsigned pidarraysize = 0; +int *pidarray = (int *)0; + +/* +kadm_listen +listen on the admin servers port for a request +*/ +kadm_listen() +{ + extern int errno; + int found; + int admin_fd; + int peer_fd; + fd_set mask, readfds; + struct sockaddr_in peer; + int addrlen; + void process_client(), kill_children(); + int pid; + sigtype do_child(); + + (void) signal(SIGINT, doexit); + (void) signal(SIGTERM, doexit); + (void) signal(SIGHUP, doexit); + (void) signal(SIGQUIT, doexit); + (void) signal(SIGPIPE, SIG_IGN); /* get errors on write() */ + (void) signal(SIGALRM, doexit); + (void) signal(SIGCHLD, do_child); + + if ((admin_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return KADM_NO_SOCK; + if (bind(admin_fd, (struct sockaddr *)&server_parm.admin_addr, + sizeof(struct sockaddr_in)) < 0) + return KADM_NO_BIND; + (void) 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,(fd_set *)0, + (fd_set *)0, (struct timeval *)0)) == 0) + continue; /* no things read */ + if (found < 0) { + if (errno != EINTR) + 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) { + 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) { + log("fork: %s",error_message(errno)); + (void) close(peer_fd); + continue; + } + /* fork succeded: keep tabs on child */ + (void) close(peer_fd); + if (pidarray) { + pidarray = (int *)realloc((char *)pidarray, ++pidarraysize); + pidarray[pidarraysize-1] = pid; + } else { + pidarray = (int *)malloc(pidarraysize = 1); + pidarray[0] = pid; + } + } else { + /* child */ + (void) close(admin_fd); +#endif /* DEBUG */ + /* do stuff */ + process_client (peer_fd, &peer); +#ifndef DEBUG + } +#endif + } else { + log("something else woke me up!"); + return(0); + } + } + /*NOTREACHED*/ +} + +#ifdef DEBUG +#define cleanexit(code) {kerb_fini(); return;} +#endif + +void +process_client(fd, who) +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 (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) + log("setsockopt keepalive: %d",errno); + + server_parm.recv_addr = *who; + + if (kerb_init()) { /* Open as client */ + 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 */ + u_long retcode = KADM_DB_INUSE; + char *pdat; + + dat_len = KADM_VERSIZE + sizeof(u_long); + dat = (u_char *) malloc((unsigned)dat_len); + pdat = (char *) dat; + retcode = htonl((u_long) KADM_DB_INUSE); + (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long)); + goto out; + } else if (!status) { + log("no service %s.%s",server_parm.sname, server_parm.sinst); + cleanexit(2); + } + + bcopy((char *)&service.key_low, (char *)skey, 4); + bcopy((char *)&service.key_high, (char *)(((long *) skey) + 1), 4); + bzero((char *)&service, sizeof(service)); + kdb_encrypt_key (skey, skey, server_parm.master_key, + server_parm.master_key_schedule, DECRYPT); + (void) krb_set_key((char *)skey, 0); /* if error, will show up when + rd_req fails */ + bzero((char *)skey, sizeof(skey)); + + while (1) { + if ((retval = krb_net_read(fd, (char *)&dlen, sizeof(u_short))) != + sizeof(u_short)) { + if (retval < 0) + log("dlen read: %s",error_message(errno)); + else if (retval) + log("short dlen read: %d",retval); + (void) close(fd); + cleanexit(retval ? 3 : 0); + } + if (exit_now) { + cleanexit(0); + } + dat_len = (int) ntohs(dlen); + dat = (u_char *) malloc((unsigned)dat_len); + if (!dat) { + log("malloc: No memory"); + (void) close(fd); + cleanexit(4); + } + if ((retval = krb_net_read(fd, (char *)dat, dat_len)) != dat_len) { + if (retval < 0) + log("data read: %s",error_message(errno)); + else + log("short read: %d vs. %d", dat_len, retval); + (void) close(fd); + cleanexit(5); + } + if (exit_now) { + cleanexit(0); + } + if ((retval = kadm_ser_in(&dat,&dat_len)) != KADM_SUCCESS) + 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 = (u_short) dat_len; + + if (dat_len != (int)dlen) { + clear_secrets(); + abort(); /* XXX */ + } + dlen = htons(dlen); + + if (krb_net_write(fd, (char *)&dlen, sizeof(u_short)) < 0) { + log("writing dlen to client: %s",error_message(errno)); + (void) close(fd); + cleanexit(6); + } + + if (krb_net_write(fd, (char *)dat, dat_len) < 0) { + log(LOG_ERR, "writing to client: %s",error_message(errno)); + (void) close(fd); + cleanexit(7); + } + free((char *)dat); + } + /*NOTREACHED*/ +} + +sigtype +do_child() +{ + /* SIGCHLD brings us here */ + int pid; + register int i, j; + +#ifdef POSIX + int status; +#else + union wait status; +#endif + + pid = wait(&status); + + 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 (WEXITSTATUS(status) || WCOREDUMP(status) || WIFSIGNALED(status)) + log("child %d: termsig %d, coredump %d, retcode %d", pid, + WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ + } + log("child %d not in list: termsig %d, coredump %d, retcode %d", pid, + WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ +} + +#ifndef DEBUG +cleanexit(val) +{ + kerb_fini(); + clear_secrets(); + exit(val); +} +#endif + +void +kill_children() +{ + register int i; + int osigmask; + + osigmask = sigblock(sigmask(SIGCHLD)); + + for (i = 0; i < pidarraysize; i++) { + kill(pidarray[i], SIGINT); + log("killing child %d", pidarray[i]); + } + sigsetmask(osigmask); + return; +} diff --git a/eBones/kadmind/kadm_funcs.c b/eBones/kadmind/kadm_funcs.c new file mode 100644 index 0000000..585a834 --- /dev/null +++ b/eBones/kadmind/kadm_funcs.c @@ -0,0 +1,373 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT + * + * Kerberos administration server-side database manipulation routines + */ + +#ifndef lint +#if 0 +static char rcsid_kadm_funcs_c[] = +"Id: kadm_funcs.c,v 4.3 90/03/20 01:39:51 jon Exp "; +#endif +static const char rcsid[] = + "$Id$"; +#endif lint + +/* +kadm_funcs.c +the actual database manipulation code +*/ + +#include <sys/param.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_db.h> +#include "kadm_server.h" + +extern Kadm_Server server_parm; + +check_access(pname, pinst, prealm, acltype) +char *pname; +char *pinst; +char *prealm; +enum acl_types acltype; +{ + char checkname[MAX_K_NAME_SZ]; + char filename[MAXPATHLEN]; + extern char *acldir; + + (void) sprintf(checkname, "%s.%s@%s", pname, pinst, prealm); + + switch (acltype) { + case ADDACL: + (void) sprintf(filename, "%s%s", acldir, ADD_ACL_FILE); + break; + case GETACL: + (void) sprintf(filename, "%s%s", acldir, GET_ACL_FILE); + break; + case MODACL: + (void) sprintf(filename, "%s%s", acldir, MOD_ACL_FILE); + break; + } + return(acl_check(filename, checkname)); +} + +int +wildcard(str) +char *str; +{ + if (!strcmp(str, WILDCARD_STR)) + return(1); + return(0); +} + +#define failadd(code) { (void) log("FAILED addding '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; } + +kadm_add_entry (rname, rinstance, rrealm, valsin, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +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; + + if (!check_access(rname, rinstance, rrealm, ADDACL)) { + (void) log("WARNING: '%s.%s@%s' tried to add an entry for '%s.%s'", + rname, rinstance, rrealm, valsin->name, valsin->instance); + return KADM_UNAUTH; + } + + /* Need to check here for "legal" name and instance */ + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failadd(KADM_ILL_WILDCARD); + } + + (void) log("request to add an entry for '%s.%s' from '%s.%s@%s'", + valsin->name, valsin->instance, rname, rinstance, rrealm); + + 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); + (void) strncpy(data_i.name, valsin->name, ANAME_SZ); + (void) 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; + + bzero((char *)&default_princ, 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); + + + bcopy(&data_i.key_low,newpw,4); + bcopy(&data_i.key_high,(char *)(((long *) newpw) + 1),4); + + /* encrypt new key in master key */ + kdb_encrypt_key (newpw, newpw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + bcopy(newpw,&data_i.key_low,4); + bcopy((char *)(((long *) newpw) + 1), &data_i.key_high,4); + bzero((char *)newpw, 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; + (void) strncpy(data_i.mod_name, rname, sizeof(data_i.mod_name)-1); + (void) 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); + } + bzero((char *)flags, 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); + (void) log("'%s.%s' added.", valsin->name, valsin->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } + } +} +#undef failadd + +#define failget(code) { (void) log("FAILED retrieving '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; } + +kadm_get_entry (rname, rinstance, rrealm, valsin, flags, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin; /* what they wannt to get */ +u_char *flags; /* which fields we want */ +Kadm_vals *valsout; /* what data is there */ +{ + long numfound; /* check how many were returned */ + int more; /* To point to more name.instances */ + Principal data_o; /* Data object to hold Principal */ + + + if (!check_access(rname, rinstance, rrealm, GETACL)) { + (void) log("WARNING: '%s.%s@%s' tried to get '%s.%s's entry", + rname, rinstance, rrealm, valsin->name, valsin->instance); + return KADM_UNAUTH; + } + + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failget(KADM_ILL_WILDCARD); + } + + (void) log("retrieve '%s.%s's entry for '%s.%s@%s'", + valsin->name, valsin->instance, rname, rinstance, rrealm); + + /* 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); + (void) log("'%s.%s' retrieved.", valsin->name, valsin->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } else { + failget(KADM_NOENTRY); /* Else whimper and moan */ + } +} +#undef failget + +#define failmod(code) { (void) log("FAILED modifying '%s.%s' (%s)", valsin1->name, valsin1->instance, error_message(code)); return code; } + +kadm_mod_entry (rname, rinstance, rrealm, valsin1, valsin2, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin1, *valsin2; /* holds the parameters being + passed in */ +Kadm_vals *valsout; /* the actual record which is returned */ +{ + long numfound; + int more; + Principal data_o, temp_key; + u_char fields[4]; + des_cblock newpw; + + if (wildcard(valsin1->name) || wildcard(valsin1->instance)) { + failmod(KADM_ILL_WILDCARD); + } + + if (!check_access(rname, rinstance, rrealm, MODACL)) { + (void) log("WARNING: '%s.%s@%s' tried to change '%s.%s's entry", + rname, rinstance, rrealm, valsin1->name, valsin1->instance); + return KADM_UNAUTH; + } + + (void) log("request to modify '%s.%s's entry from '%s.%s@%s' ", + valsin1->name, valsin1->instance, rname, rinstance, rrealm); + + numfound = kerb_get_principal(valsin1->name, valsin1->instance, + &data_o, 1, &more); + if (numfound == -1) { + failmod(KADM_DB_INUSE); + } else if (numfound) { + kadm_vals_to_prin(valsin2->fields, &temp_key, valsin2); + (void) strncpy(data_o.name, valsin1->name, ANAME_SZ); + (void) strncpy(data_o.instance, valsin1->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); + + + bcopy(&temp_key.key_low,newpw,4); + bcopy(&temp_key.key_high,(char *)(((long *) newpw) + 1),4); + + /* encrypt new key in master key */ + kdb_encrypt_key (newpw, newpw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + bcopy(newpw,&data_o.key_low,4); + bcopy((char *)(((long *) newpw) + 1), &data_o.key_high,4); + bzero((char *)newpw, sizeof(newpw)); + } + bzero((char *)&temp_key, sizeof(temp_key)); + + (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + (void) strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + + bzero((char *)&data_o, sizeof(data_o)); + + if (more == -1) { + failmod(KADM_DB_INUSE); + } else if (more) { + failmod(KADM_UK_SERROR); + } else { + numfound = kerb_get_principal(valsin1->name, valsin1->instance, + &data_o, 1, &more); + if ((more!=0)||(numfound!=1)) { + failmod(KADM_UK_RERROR); + } + bzero((char *) fields, 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); + (void) log("'%s.%s' modified.", valsin1->name, valsin1->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } + } + else { + failmod(KADM_NOENTRY); + } +} +#undef failmod + +#define failchange(code) { (void) log("FAILED changing key for '%s.%s@%s' (%s)", rname, rinstance, rrealm, error_message(code)); return code; } + +kadm_change (rname, rinstance, rrealm, newpw) +char *rname; +char *rinstance; +char *rrealm; +des_cblock newpw; +{ + long numfound; + int more; + Principal data_o; + des_cblock local_pw; + + if (strcmp(server_parm.krbrlm, rrealm)) { + (void) log("change key request from wrong realm, '%s.%s@%s'!\n", + rname, rinstance, rrealm); + return(KADM_WRONG_REALM); + } + + if (wildcard(rname) || wildcard(rinstance)) { + failchange(KADM_ILL_WILDCARD); + } + (void) log("'%s.%s@%s' wants to change its password", + rname, rinstance, rrealm); + + bcopy(newpw, local_pw, 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, ENCRYPT); + + numfound = kerb_get_principal(rname, rinstance, + &data_o, 1, &more); + if (numfound == -1) { + failchange(KADM_DB_INUSE); + } else if (numfound) { + bcopy(local_pw,&data_o.key_low,4); + bcopy((char *)(((long *) local_pw) + 1), &data_o.key_high,4); + data_o.key_version++; + data_o.kdc_key_ver = server_parm.master_key_version; + (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + (void) strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + bzero((char *) local_pw, sizeof(local_pw)); + bzero((char *) &data_o, sizeof(data_o)); + if (more == -1) { + failchange(KADM_DB_INUSE); + } else if (more) { + failchange(KADM_UK_SERROR); + } else { + (void) log("'%s.%s@%s' password changed.", rname, rinstance, rrealm); + return KADM_SUCCESS; + } + } + else { + failchange(KADM_NOENTRY); + } +} +#undef failchange diff --git a/eBones/kadmind/kadm_ser_wrap.c b/eBones/kadmind/kadm_ser_wrap.c new file mode 100644 index 0000000..c019bc0 --- /dev/null +++ b/eBones/kadmind/kadm_ser_wrap.c @@ -0,0 +1,206 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server-side support functions + */ + +#ifndef lint +static char rcsid_module_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_ser_wrap.c,v 4.4 89/09/26 09:29:36 jtkohl Exp "; +#endif lint + +/* +kadm_ser_wrap.c +unwraps wrapped packets and calls the appropriate server subroutine +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <netdb.h> +#include <sys/socket.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_err.h> +#include "kadm_server.h" + +Kadm_Server server_parm; + +/* +kadm_ser_init +set up the server_parm structure +*/ +kadm_ser_init(inter, realm) +int inter; /* interactive or from file */ +char realm[]; +{ + struct servent *sep; + struct hostent *hp; + char hostname[MAXHOSTNAMELEN]; + + (void) init_kadm_err_tbl(); + (void) init_krb_err_tbl(); + if (gethostname(hostname, sizeof(hostname))) + return KADM_NO_HOSTNAME; + + (void) strcpy(server_parm.sname, PWSERV_NAME); + (void) strcpy(server_parm.sinst, KRB_MASTER); + (void) strcpy(server_parm.krbrlm, realm); + + server_parm.admin_fd = -1; + /* setting up the addrs */ + if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL) + return KADM_NO_SERV; + bzero((char *)&server_parm.admin_addr,sizeof(server_parm.admin_addr)); + server_parm.admin_addr.sin_family = AF_INET; + if ((hp = gethostbyname(hostname)) == NULL) + return KADM_NO_HOSTNAME; + bcopy(hp->h_addr, (char *) &server_parm.admin_addr.sin_addr.s_addr, + hp->h_length); + server_parm.admin_addr.sin_port = sep->s_port; + /* 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(dat, dat_len, code) +u_char **dat; +int *dat_len; +int code; +{ + u_long retcode; + char *pdat; + + free((char *)*dat); /* free up req */ + *dat_len = KADM_VERSIZE + sizeof(u_long); + *dat = (u_char *) malloc((unsigned)*dat_len); + pdat = (char *) *dat; + retcode = htonl((u_long) code); + (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long)); + return; +} + +/* +kadm_ser_in +unwrap the data stored in dat, process, and return it. +*/ +kadm_ser_in(dat,dat_len) +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_long r_len; /* length of the actual packet */ + KTEXT_ST authent; /* the authenticator */ + AUTH_DAT ad; /* who is this, klink */ + u_long 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_long); + bcopy((char *)(*dat) + in_len, (char *)authent.dat, 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, (char *)0)) + { + errpkt(dat, dat_len,retc + krb_err_base); + return retc + krb_err_base; + } + +#define clr_cli_secrets() {bzero((char *)sess_sched, sizeof(sess_sched)); bzero((char *)ad.session, sizeof(ad.session));} + + in_st = *dat + *dat_len - r_len; +#ifdef NOENCRYPTION + ncksum = 0; +#else + ncksum = quad_cksum(in_st, (u_long *)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 + bzero(sess_sched, 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,&ad, + &retdat, &retlen); + break; + case ADD_ENT: + retval = kadm_ser_add(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case GET_ENT: + retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case MOD_ENT: + retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length,&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((char *)*dat); + tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE + + sizeof(u_long))); + (void) strncpy((char *)tmpdat, KADM_VERSTR, KADM_VERSIZE); + retval = htonl((u_long)retval); + bcopy((char *)&retval, (char *)tmpdat + KADM_VERSIZE, sizeof(u_long)); + if (retlen) { + bcopy((char *)retdat, (char *)tmpdat + KADM_VERSIZE + sizeof(u_long), + retlen); + free((char *)retdat); + } + /* slop for mk_priv stuff */ + *dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE + + sizeof(u_long) + 200)); + if ((*dat_len = krb_mk_priv(tmpdat, *dat, + (u_long) (retlen + KADM_VERSIZE + + sizeof(u_long)), + 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/eBones/kadmind/kadm_server.c b/eBones/kadmind/kadm_server.c new file mode 100644 index 0000000..56631d3 --- /dev/null +++ b/eBones/kadmind/kadm_server.c @@ -0,0 +1,159 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server-side subroutines + */ + +#ifndef lint +static char rcsid_kadm_server_c[] = +"Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.c,v 4.2 89/09/26 09:30:23 jtkohl Exp "; +#endif lint + +#include <kadm.h> +#include <kadm_err.h> + +/* +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 +*/ +kadm_ser_cpw(dat, len, ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + unsigned long keylow, keyhigh; + des_cblock newkey; + int stvlen; + + /* take key off the stream, and change the database */ + + if ((stvlen = stv_long(dat, &keyhigh, 0, len)) < 0) + return(KADM_LENGTH_ERROR); + if (stv_long(dat, &keylow, stvlen, len) < 0) + return(KADM_LENGTH_ERROR); + + keylow = ntohl(keylow); + keyhigh = ntohl(keyhigh); + bcopy((char *)&keyhigh, (char *)(((long *)newkey) + 1), 4); + bcopy((char *)&keylow, (char *)newkey, 4); + *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 +*/ +kadm_ser_add(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals values, retvals; + int 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 +*/ +kadm_ser_mod(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals vals1, vals2, retvals; + int wh; + int 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; + } +} + +/* +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 +*/ +kadm_ser_get(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals values, retvals; + u_char fl[FLDSZ]; + int loop,wh; + int 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/eBones/kadmind/kadm_server.h b/eBones/kadmind/kadm_server.h new file mode 100644 index 0000000..db9d21f --- /dev/null +++ b/eBones/kadmind/kadm_server.h @@ -0,0 +1,51 @@ +/* + * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.h,v $ + * $Author: jtkohl $ + * Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.h,v 4.1 89/12/21 17:46:51 jtkohl Exp + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * 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 + */ + +#include <sys/types.h> +#include <kerberosIV/krb.h> +#include <kerberosIV/des.h> + +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]; + C_Block master_key; + C_Block session_key; + Key_schedule master_key_schedule; + long master_key_version; +} Kadm_Server; + +/* the default syslog file */ +#define KADM_SYSLOG "/var/log/kadmind.syslog" + +#define DEFAULT_ACL_DIR "/etc/kerberosIV" +#define ADD_ACL_FILE "/admin_acl.add" +#define GET_ACL_FILE "/admin_acl.get" +#define MOD_ACL_FILE "/admin_acl.mod" + +#endif KADM_SERVER_DEFS diff --git a/eBones/usr.sbin/kadmin/Makefile b/eBones/usr.sbin/kadmin/Makefile new file mode 100644 index 0000000..77069be --- /dev/null +++ b/eBones/usr.sbin/kadmin/Makefile @@ -0,0 +1,11 @@ +# $Id$ + +PROG= kadmind +SRCS= admin_server.c kadm_funcs.c kadm_ser_wrap.c kadm_server.c +CFLAGS+=-DPOSIX -I${.CURDIR}/../include -I${KRBOBJDIR} \ + -I${.CURDIR}/../libkadm -I${KADMOBJDIR} +LDADD+= -L${KADMOBJDIR} -lkadm -L${KDBOBJDIR} -lkdb -L${KRBOBJDIR} -lkrb \ + -L${DESOBJDIR} -ldes -L${ACLOBJDIR} -lacl -lcom_err +NOMAN= # man page in ../man + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kadmin/admin_server.c b/eBones/usr.sbin/kadmin/admin_server.c new file mode 100644 index 0000000..cca1aaf --- /dev/null +++ b/eBones/usr.sbin/kadmin/admin_server.c @@ -0,0 +1,447 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Top-level loop of the kerberos Administration server + */ + +#ifndef lint +#if 0 +static char rcsid_admin_server_c[] = +"Id: admin_server.c,v 4.8 90/01/02 13:50:38 jtkohl Exp "; +#endif +static const char rcsid[] = + "$Id"; +#endif lint + +/* + admin_server.c + this holds the main loop and initialization and cleanup code for the server +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <signal.h> +#ifndef sigmask +#define sigmask(m) (1 <<((m)-1)) +#endif +#include <sys/wait.h> +#include <errno.h> +#include <sys/socket.h> +#include <syslog.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_db.h> +#include "kadm_server.h" + +/* Almost all procs and such need this, so it is global */ +admin_params prm; /* The command line parameters struct */ + +char prog[32]; /* WHY IS THIS NEEDED??????? */ +char *progname = prog; +char *acldir = DEFAULT_ACL_DIR; +char krbrlm[REALM_SZ]; +extern Kadm_Server server_parm; + +/* +** 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... +*/ +main(argc, argv) /* admin_server main routine */ +int argc; +char *argv[]; +{ + int errval; + int c; + extern char *optarg; + + prog[sizeof(prog)-1]='\0'; /* Terminate... */ + (void) strncpy(prog, argv[0], sizeof(prog)-1); + + /* initialize the admin_params structure */ + prm.sysfile = KADM_SYSLOG; /* default file name */ + prm.inter = 1; + + bzero(krbrlm, sizeof(krbrlm)); + + while ((c = getopt(argc, argv, "f:hnd:a:r:")) != EOF) + switch(c) { + case 'f': /* Syslog file name change */ + prm.sysfile = optarg; + break; + case 'n': + prm.inter = 0; + 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)) { + fprintf(stderr, "opening database %s: %s", + optarg, error_message(errval)); + exit(1); + } + break; + case 'r': + (void) strncpy(krbrlm, optarg, sizeof(krbrlm) - 1); + break; + case 'h': /* get help on using admin_server */ + default: + printf("Usage: admin_server [-h] [-n] [-r realm] [-d dbname] [-f filename] [-a acldir]\n"); + exit(-1); /* failure */ + } + + if (krbrlm[0] == 0) + if (krb_get_lrealm(krbrlm, 0) != KSUCCESS) { + fprintf(stderr, + "Unable to get local realm. Fix krb.conf or use -r.\n"); + exit(1); + } + + 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"); + + set_logfile(prm.sysfile); + log("Admin server starting"); + + (void) kerb_db_set_lockmode(KERB_DBL_NONBLOCKING); + errval = kerb_init(); /* Open the Kerberos database */ + if (errval) { + fprintf(stderr, "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) { + fprintf(stderr,"error: %s\n",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 */ +} /* procedure main */ + + +/* close the system log file */ +close_syslog() +{ + log("Shutting down admin server"); +} + +byebye() /* say goodnight gracie */ +{ + printf("Admin Server (kadm server) has completed operation.\n"); +} + +static clear_secrets() +{ + bzero((char *)server_parm.master_key, sizeof(server_parm.master_key)); + bzero((char *)server_parm.master_key_schedule, + sizeof(server_parm.master_key_schedule)); + server_parm.master_key_version = 0L; + return; +} + +static exit_now = 0; + +sigtype +doexit() +{ + exit_now = 1; +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ +} + +unsigned pidarraysize = 0; +int *pidarray = (int *)0; + +/* +kadm_listen +listen on the admin servers port for a request +*/ +kadm_listen() +{ + extern int errno; + int found; + int admin_fd; + int peer_fd; + fd_set mask, readfds; + struct sockaddr_in peer; + int addrlen; + void process_client(), kill_children(); + int pid; + sigtype do_child(); + + (void) signal(SIGINT, doexit); + (void) signal(SIGTERM, doexit); + (void) signal(SIGHUP, doexit); + (void) signal(SIGQUIT, doexit); + (void) signal(SIGPIPE, SIG_IGN); /* get errors on write() */ + (void) signal(SIGALRM, doexit); + (void) signal(SIGCHLD, do_child); + + if ((admin_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return KADM_NO_SOCK; + if (bind(admin_fd, (struct sockaddr *)&server_parm.admin_addr, + sizeof(struct sockaddr_in)) < 0) + return KADM_NO_BIND; + (void) 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,(fd_set *)0, + (fd_set *)0, (struct timeval *)0)) == 0) + continue; /* no things read */ + if (found < 0) { + if (errno != EINTR) + 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) { + 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) { + log("fork: %s",error_message(errno)); + (void) close(peer_fd); + continue; + } + /* fork succeded: keep tabs on child */ + (void) close(peer_fd); + if (pidarray) { + pidarray = (int *)realloc((char *)pidarray, ++pidarraysize); + pidarray[pidarraysize-1] = pid; + } else { + pidarray = (int *)malloc(pidarraysize = 1); + pidarray[0] = pid; + } + } else { + /* child */ + (void) close(admin_fd); +#endif /* DEBUG */ + /* do stuff */ + process_client (peer_fd, &peer); +#ifndef DEBUG + } +#endif + } else { + log("something else woke me up!"); + return(0); + } + } + /*NOTREACHED*/ +} + +#ifdef DEBUG +#define cleanexit(code) {kerb_fini(); return;} +#endif + +void +process_client(fd, who) +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 (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) + log("setsockopt keepalive: %d",errno); + + server_parm.recv_addr = *who; + + if (kerb_init()) { /* Open as client */ + 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 */ + u_long retcode = KADM_DB_INUSE; + char *pdat; + + dat_len = KADM_VERSIZE + sizeof(u_long); + dat = (u_char *) malloc((unsigned)dat_len); + pdat = (char *) dat; + retcode = htonl((u_long) KADM_DB_INUSE); + (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long)); + goto out; + } else if (!status) { + log("no service %s.%s",server_parm.sname, server_parm.sinst); + cleanexit(2); + } + + bcopy((char *)&service.key_low, (char *)skey, 4); + bcopy((char *)&service.key_high, (char *)(((long *) skey) + 1), 4); + bzero((char *)&service, sizeof(service)); + kdb_encrypt_key (skey, skey, server_parm.master_key, + server_parm.master_key_schedule, DECRYPT); + (void) krb_set_key((char *)skey, 0); /* if error, will show up when + rd_req fails */ + bzero((char *)skey, sizeof(skey)); + + while (1) { + if ((retval = krb_net_read(fd, (char *)&dlen, sizeof(u_short))) != + sizeof(u_short)) { + if (retval < 0) + log("dlen read: %s",error_message(errno)); + else if (retval) + log("short dlen read: %d",retval); + (void) close(fd); + cleanexit(retval ? 3 : 0); + } + if (exit_now) { + cleanexit(0); + } + dat_len = (int) ntohs(dlen); + dat = (u_char *) malloc((unsigned)dat_len); + if (!dat) { + log("malloc: No memory"); + (void) close(fd); + cleanexit(4); + } + if ((retval = krb_net_read(fd, (char *)dat, dat_len)) != dat_len) { + if (retval < 0) + log("data read: %s",error_message(errno)); + else + log("short read: %d vs. %d", dat_len, retval); + (void) close(fd); + cleanexit(5); + } + if (exit_now) { + cleanexit(0); + } + if ((retval = kadm_ser_in(&dat,&dat_len)) != KADM_SUCCESS) + 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 = (u_short) dat_len; + + if (dat_len != (int)dlen) { + clear_secrets(); + abort(); /* XXX */ + } + dlen = htons(dlen); + + if (krb_net_write(fd, (char *)&dlen, sizeof(u_short)) < 0) { + log("writing dlen to client: %s",error_message(errno)); + (void) close(fd); + cleanexit(6); + } + + if (krb_net_write(fd, (char *)dat, dat_len) < 0) { + log(LOG_ERR, "writing to client: %s",error_message(errno)); + (void) close(fd); + cleanexit(7); + } + free((char *)dat); + } + /*NOTREACHED*/ +} + +sigtype +do_child() +{ + /* SIGCHLD brings us here */ + int pid; + register int i, j; + +#ifdef POSIX + int status; +#else + union wait status; +#endif + + pid = wait(&status); + + 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 (WEXITSTATUS(status) || WCOREDUMP(status) || WIFSIGNALED(status)) + log("child %d: termsig %d, coredump %d, retcode %d", pid, + WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ + } + log("child %d not in list: termsig %d, coredump %d, retcode %d", pid, + WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ +} + +#ifndef DEBUG +cleanexit(val) +{ + kerb_fini(); + clear_secrets(); + exit(val); +} +#endif + +void +kill_children() +{ + register int i; + int osigmask; + + osigmask = sigblock(sigmask(SIGCHLD)); + + for (i = 0; i < pidarraysize; i++) { + kill(pidarray[i], SIGINT); + log("killing child %d", pidarray[i]); + } + sigsetmask(osigmask); + return; +} diff --git a/eBones/usr.sbin/kadmin/kadm_funcs.c b/eBones/usr.sbin/kadmin/kadm_funcs.c new file mode 100644 index 0000000..585a834 --- /dev/null +++ b/eBones/usr.sbin/kadmin/kadm_funcs.c @@ -0,0 +1,373 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT + * + * Kerberos administration server-side database manipulation routines + */ + +#ifndef lint +#if 0 +static char rcsid_kadm_funcs_c[] = +"Id: kadm_funcs.c,v 4.3 90/03/20 01:39:51 jon Exp "; +#endif +static const char rcsid[] = + "$Id$"; +#endif lint + +/* +kadm_funcs.c +the actual database manipulation code +*/ + +#include <sys/param.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_db.h> +#include "kadm_server.h" + +extern Kadm_Server server_parm; + +check_access(pname, pinst, prealm, acltype) +char *pname; +char *pinst; +char *prealm; +enum acl_types acltype; +{ + char checkname[MAX_K_NAME_SZ]; + char filename[MAXPATHLEN]; + extern char *acldir; + + (void) sprintf(checkname, "%s.%s@%s", pname, pinst, prealm); + + switch (acltype) { + case ADDACL: + (void) sprintf(filename, "%s%s", acldir, ADD_ACL_FILE); + break; + case GETACL: + (void) sprintf(filename, "%s%s", acldir, GET_ACL_FILE); + break; + case MODACL: + (void) sprintf(filename, "%s%s", acldir, MOD_ACL_FILE); + break; + } + return(acl_check(filename, checkname)); +} + +int +wildcard(str) +char *str; +{ + if (!strcmp(str, WILDCARD_STR)) + return(1); + return(0); +} + +#define failadd(code) { (void) log("FAILED addding '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; } + +kadm_add_entry (rname, rinstance, rrealm, valsin, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +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; + + if (!check_access(rname, rinstance, rrealm, ADDACL)) { + (void) log("WARNING: '%s.%s@%s' tried to add an entry for '%s.%s'", + rname, rinstance, rrealm, valsin->name, valsin->instance); + return KADM_UNAUTH; + } + + /* Need to check here for "legal" name and instance */ + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failadd(KADM_ILL_WILDCARD); + } + + (void) log("request to add an entry for '%s.%s' from '%s.%s@%s'", + valsin->name, valsin->instance, rname, rinstance, rrealm); + + 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); + (void) strncpy(data_i.name, valsin->name, ANAME_SZ); + (void) 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; + + bzero((char *)&default_princ, 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); + + + bcopy(&data_i.key_low,newpw,4); + bcopy(&data_i.key_high,(char *)(((long *) newpw) + 1),4); + + /* encrypt new key in master key */ + kdb_encrypt_key (newpw, newpw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + bcopy(newpw,&data_i.key_low,4); + bcopy((char *)(((long *) newpw) + 1), &data_i.key_high,4); + bzero((char *)newpw, 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; + (void) strncpy(data_i.mod_name, rname, sizeof(data_i.mod_name)-1); + (void) 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); + } + bzero((char *)flags, 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); + (void) log("'%s.%s' added.", valsin->name, valsin->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } + } +} +#undef failadd + +#define failget(code) { (void) log("FAILED retrieving '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; } + +kadm_get_entry (rname, rinstance, rrealm, valsin, flags, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin; /* what they wannt to get */ +u_char *flags; /* which fields we want */ +Kadm_vals *valsout; /* what data is there */ +{ + long numfound; /* check how many were returned */ + int more; /* To point to more name.instances */ + Principal data_o; /* Data object to hold Principal */ + + + if (!check_access(rname, rinstance, rrealm, GETACL)) { + (void) log("WARNING: '%s.%s@%s' tried to get '%s.%s's entry", + rname, rinstance, rrealm, valsin->name, valsin->instance); + return KADM_UNAUTH; + } + + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failget(KADM_ILL_WILDCARD); + } + + (void) log("retrieve '%s.%s's entry for '%s.%s@%s'", + valsin->name, valsin->instance, rname, rinstance, rrealm); + + /* 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); + (void) log("'%s.%s' retrieved.", valsin->name, valsin->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } else { + failget(KADM_NOENTRY); /* Else whimper and moan */ + } +} +#undef failget + +#define failmod(code) { (void) log("FAILED modifying '%s.%s' (%s)", valsin1->name, valsin1->instance, error_message(code)); return code; } + +kadm_mod_entry (rname, rinstance, rrealm, valsin1, valsin2, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin1, *valsin2; /* holds the parameters being + passed in */ +Kadm_vals *valsout; /* the actual record which is returned */ +{ + long numfound; + int more; + Principal data_o, temp_key; + u_char fields[4]; + des_cblock newpw; + + if (wildcard(valsin1->name) || wildcard(valsin1->instance)) { + failmod(KADM_ILL_WILDCARD); + } + + if (!check_access(rname, rinstance, rrealm, MODACL)) { + (void) log("WARNING: '%s.%s@%s' tried to change '%s.%s's entry", + rname, rinstance, rrealm, valsin1->name, valsin1->instance); + return KADM_UNAUTH; + } + + (void) log("request to modify '%s.%s's entry from '%s.%s@%s' ", + valsin1->name, valsin1->instance, rname, rinstance, rrealm); + + numfound = kerb_get_principal(valsin1->name, valsin1->instance, + &data_o, 1, &more); + if (numfound == -1) { + failmod(KADM_DB_INUSE); + } else if (numfound) { + kadm_vals_to_prin(valsin2->fields, &temp_key, valsin2); + (void) strncpy(data_o.name, valsin1->name, ANAME_SZ); + (void) strncpy(data_o.instance, valsin1->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); + + + bcopy(&temp_key.key_low,newpw,4); + bcopy(&temp_key.key_high,(char *)(((long *) newpw) + 1),4); + + /* encrypt new key in master key */ + kdb_encrypt_key (newpw, newpw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + bcopy(newpw,&data_o.key_low,4); + bcopy((char *)(((long *) newpw) + 1), &data_o.key_high,4); + bzero((char *)newpw, sizeof(newpw)); + } + bzero((char *)&temp_key, sizeof(temp_key)); + + (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + (void) strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + + bzero((char *)&data_o, sizeof(data_o)); + + if (more == -1) { + failmod(KADM_DB_INUSE); + } else if (more) { + failmod(KADM_UK_SERROR); + } else { + numfound = kerb_get_principal(valsin1->name, valsin1->instance, + &data_o, 1, &more); + if ((more!=0)||(numfound!=1)) { + failmod(KADM_UK_RERROR); + } + bzero((char *) fields, 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); + (void) log("'%s.%s' modified.", valsin1->name, valsin1->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } + } + else { + failmod(KADM_NOENTRY); + } +} +#undef failmod + +#define failchange(code) { (void) log("FAILED changing key for '%s.%s@%s' (%s)", rname, rinstance, rrealm, error_message(code)); return code; } + +kadm_change (rname, rinstance, rrealm, newpw) +char *rname; +char *rinstance; +char *rrealm; +des_cblock newpw; +{ + long numfound; + int more; + Principal data_o; + des_cblock local_pw; + + if (strcmp(server_parm.krbrlm, rrealm)) { + (void) log("change key request from wrong realm, '%s.%s@%s'!\n", + rname, rinstance, rrealm); + return(KADM_WRONG_REALM); + } + + if (wildcard(rname) || wildcard(rinstance)) { + failchange(KADM_ILL_WILDCARD); + } + (void) log("'%s.%s@%s' wants to change its password", + rname, rinstance, rrealm); + + bcopy(newpw, local_pw, 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, ENCRYPT); + + numfound = kerb_get_principal(rname, rinstance, + &data_o, 1, &more); + if (numfound == -1) { + failchange(KADM_DB_INUSE); + } else if (numfound) { + bcopy(local_pw,&data_o.key_low,4); + bcopy((char *)(((long *) local_pw) + 1), &data_o.key_high,4); + data_o.key_version++; + data_o.kdc_key_ver = server_parm.master_key_version; + (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + (void) strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + bzero((char *) local_pw, sizeof(local_pw)); + bzero((char *) &data_o, sizeof(data_o)); + if (more == -1) { + failchange(KADM_DB_INUSE); + } else if (more) { + failchange(KADM_UK_SERROR); + } else { + (void) log("'%s.%s@%s' password changed.", rname, rinstance, rrealm); + return KADM_SUCCESS; + } + } + else { + failchange(KADM_NOENTRY); + } +} +#undef failchange diff --git a/eBones/usr.sbin/kadmin/kadm_ser_wrap.c b/eBones/usr.sbin/kadmin/kadm_ser_wrap.c new file mode 100644 index 0000000..c019bc0 --- /dev/null +++ b/eBones/usr.sbin/kadmin/kadm_ser_wrap.c @@ -0,0 +1,206 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server-side support functions + */ + +#ifndef lint +static char rcsid_module_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_ser_wrap.c,v 4.4 89/09/26 09:29:36 jtkohl Exp "; +#endif lint + +/* +kadm_ser_wrap.c +unwraps wrapped packets and calls the appropriate server subroutine +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <netdb.h> +#include <sys/socket.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_err.h> +#include "kadm_server.h" + +Kadm_Server server_parm; + +/* +kadm_ser_init +set up the server_parm structure +*/ +kadm_ser_init(inter, realm) +int inter; /* interactive or from file */ +char realm[]; +{ + struct servent *sep; + struct hostent *hp; + char hostname[MAXHOSTNAMELEN]; + + (void) init_kadm_err_tbl(); + (void) init_krb_err_tbl(); + if (gethostname(hostname, sizeof(hostname))) + return KADM_NO_HOSTNAME; + + (void) strcpy(server_parm.sname, PWSERV_NAME); + (void) strcpy(server_parm.sinst, KRB_MASTER); + (void) strcpy(server_parm.krbrlm, realm); + + server_parm.admin_fd = -1; + /* setting up the addrs */ + if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL) + return KADM_NO_SERV; + bzero((char *)&server_parm.admin_addr,sizeof(server_parm.admin_addr)); + server_parm.admin_addr.sin_family = AF_INET; + if ((hp = gethostbyname(hostname)) == NULL) + return KADM_NO_HOSTNAME; + bcopy(hp->h_addr, (char *) &server_parm.admin_addr.sin_addr.s_addr, + hp->h_length); + server_parm.admin_addr.sin_port = sep->s_port; + /* 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(dat, dat_len, code) +u_char **dat; +int *dat_len; +int code; +{ + u_long retcode; + char *pdat; + + free((char *)*dat); /* free up req */ + *dat_len = KADM_VERSIZE + sizeof(u_long); + *dat = (u_char *) malloc((unsigned)*dat_len); + pdat = (char *) *dat; + retcode = htonl((u_long) code); + (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long)); + return; +} + +/* +kadm_ser_in +unwrap the data stored in dat, process, and return it. +*/ +kadm_ser_in(dat,dat_len) +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_long r_len; /* length of the actual packet */ + KTEXT_ST authent; /* the authenticator */ + AUTH_DAT ad; /* who is this, klink */ + u_long 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_long); + bcopy((char *)(*dat) + in_len, (char *)authent.dat, 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, (char *)0)) + { + errpkt(dat, dat_len,retc + krb_err_base); + return retc + krb_err_base; + } + +#define clr_cli_secrets() {bzero((char *)sess_sched, sizeof(sess_sched)); bzero((char *)ad.session, sizeof(ad.session));} + + in_st = *dat + *dat_len - r_len; +#ifdef NOENCRYPTION + ncksum = 0; +#else + ncksum = quad_cksum(in_st, (u_long *)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 + bzero(sess_sched, 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,&ad, + &retdat, &retlen); + break; + case ADD_ENT: + retval = kadm_ser_add(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case GET_ENT: + retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case MOD_ENT: + retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length,&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((char *)*dat); + tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE + + sizeof(u_long))); + (void) strncpy((char *)tmpdat, KADM_VERSTR, KADM_VERSIZE); + retval = htonl((u_long)retval); + bcopy((char *)&retval, (char *)tmpdat + KADM_VERSIZE, sizeof(u_long)); + if (retlen) { + bcopy((char *)retdat, (char *)tmpdat + KADM_VERSIZE + sizeof(u_long), + retlen); + free((char *)retdat); + } + /* slop for mk_priv stuff */ + *dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE + + sizeof(u_long) + 200)); + if ((*dat_len = krb_mk_priv(tmpdat, *dat, + (u_long) (retlen + KADM_VERSIZE + + sizeof(u_long)), + 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/eBones/usr.sbin/kadmin/kadm_server.c b/eBones/usr.sbin/kadmin/kadm_server.c new file mode 100644 index 0000000..56631d3 --- /dev/null +++ b/eBones/usr.sbin/kadmin/kadm_server.c @@ -0,0 +1,159 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server-side subroutines + */ + +#ifndef lint +static char rcsid_kadm_server_c[] = +"Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.c,v 4.2 89/09/26 09:30:23 jtkohl Exp "; +#endif lint + +#include <kadm.h> +#include <kadm_err.h> + +/* +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 +*/ +kadm_ser_cpw(dat, len, ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + unsigned long keylow, keyhigh; + des_cblock newkey; + int stvlen; + + /* take key off the stream, and change the database */ + + if ((stvlen = stv_long(dat, &keyhigh, 0, len)) < 0) + return(KADM_LENGTH_ERROR); + if (stv_long(dat, &keylow, stvlen, len) < 0) + return(KADM_LENGTH_ERROR); + + keylow = ntohl(keylow); + keyhigh = ntohl(keyhigh); + bcopy((char *)&keyhigh, (char *)(((long *)newkey) + 1), 4); + bcopy((char *)&keylow, (char *)newkey, 4); + *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 +*/ +kadm_ser_add(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals values, retvals; + int 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 +*/ +kadm_ser_mod(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals vals1, vals2, retvals; + int wh; + int 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; + } +} + +/* +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 +*/ +kadm_ser_get(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals values, retvals; + u_char fl[FLDSZ]; + int loop,wh; + int 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/eBones/usr.sbin/kadmin/kadm_server.h b/eBones/usr.sbin/kadmin/kadm_server.h new file mode 100644 index 0000000..db9d21f --- /dev/null +++ b/eBones/usr.sbin/kadmin/kadm_server.h @@ -0,0 +1,51 @@ +/* + * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.h,v $ + * $Author: jtkohl $ + * Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.h,v 4.1 89/12/21 17:46:51 jtkohl Exp + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * 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 + */ + +#include <sys/types.h> +#include <kerberosIV/krb.h> +#include <kerberosIV/des.h> + +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]; + C_Block master_key; + C_Block session_key; + Key_schedule master_key_schedule; + long master_key_version; +} Kadm_Server; + +/* the default syslog file */ +#define KADM_SYSLOG "/var/log/kadmind.syslog" + +#define DEFAULT_ACL_DIR "/etc/kerberosIV" +#define ADD_ACL_FILE "/admin_acl.add" +#define GET_ACL_FILE "/admin_acl.get" +#define MOD_ACL_FILE "/admin_acl.mod" + +#endif KADM_SERVER_DEFS diff --git a/eBones/usr.sbin/kadmind/Makefile b/eBones/usr.sbin/kadmind/Makefile new file mode 100644 index 0000000..77069be --- /dev/null +++ b/eBones/usr.sbin/kadmind/Makefile @@ -0,0 +1,11 @@ +# $Id$ + +PROG= kadmind +SRCS= admin_server.c kadm_funcs.c kadm_ser_wrap.c kadm_server.c +CFLAGS+=-DPOSIX -I${.CURDIR}/../include -I${KRBOBJDIR} \ + -I${.CURDIR}/../libkadm -I${KADMOBJDIR} +LDADD+= -L${KADMOBJDIR} -lkadm -L${KDBOBJDIR} -lkdb -L${KRBOBJDIR} -lkrb \ + -L${DESOBJDIR} -ldes -L${ACLOBJDIR} -lacl -lcom_err +NOMAN= # man page in ../man + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kadmind/admin_server.c b/eBones/usr.sbin/kadmind/admin_server.c new file mode 100644 index 0000000..cca1aaf --- /dev/null +++ b/eBones/usr.sbin/kadmind/admin_server.c @@ -0,0 +1,447 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Top-level loop of the kerberos Administration server + */ + +#ifndef lint +#if 0 +static char rcsid_admin_server_c[] = +"Id: admin_server.c,v 4.8 90/01/02 13:50:38 jtkohl Exp "; +#endif +static const char rcsid[] = + "$Id"; +#endif lint + +/* + admin_server.c + this holds the main loop and initialization and cleanup code for the server +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <signal.h> +#ifndef sigmask +#define sigmask(m) (1 <<((m)-1)) +#endif +#include <sys/wait.h> +#include <errno.h> +#include <sys/socket.h> +#include <syslog.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_db.h> +#include "kadm_server.h" + +/* Almost all procs and such need this, so it is global */ +admin_params prm; /* The command line parameters struct */ + +char prog[32]; /* WHY IS THIS NEEDED??????? */ +char *progname = prog; +char *acldir = DEFAULT_ACL_DIR; +char krbrlm[REALM_SZ]; +extern Kadm_Server server_parm; + +/* +** 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... +*/ +main(argc, argv) /* admin_server main routine */ +int argc; +char *argv[]; +{ + int errval; + int c; + extern char *optarg; + + prog[sizeof(prog)-1]='\0'; /* Terminate... */ + (void) strncpy(prog, argv[0], sizeof(prog)-1); + + /* initialize the admin_params structure */ + prm.sysfile = KADM_SYSLOG; /* default file name */ + prm.inter = 1; + + bzero(krbrlm, sizeof(krbrlm)); + + while ((c = getopt(argc, argv, "f:hnd:a:r:")) != EOF) + switch(c) { + case 'f': /* Syslog file name change */ + prm.sysfile = optarg; + break; + case 'n': + prm.inter = 0; + 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)) { + fprintf(stderr, "opening database %s: %s", + optarg, error_message(errval)); + exit(1); + } + break; + case 'r': + (void) strncpy(krbrlm, optarg, sizeof(krbrlm) - 1); + break; + case 'h': /* get help on using admin_server */ + default: + printf("Usage: admin_server [-h] [-n] [-r realm] [-d dbname] [-f filename] [-a acldir]\n"); + exit(-1); /* failure */ + } + + if (krbrlm[0] == 0) + if (krb_get_lrealm(krbrlm, 0) != KSUCCESS) { + fprintf(stderr, + "Unable to get local realm. Fix krb.conf or use -r.\n"); + exit(1); + } + + 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"); + + set_logfile(prm.sysfile); + log("Admin server starting"); + + (void) kerb_db_set_lockmode(KERB_DBL_NONBLOCKING); + errval = kerb_init(); /* Open the Kerberos database */ + if (errval) { + fprintf(stderr, "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) { + fprintf(stderr,"error: %s\n",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 */ +} /* procedure main */ + + +/* close the system log file */ +close_syslog() +{ + log("Shutting down admin server"); +} + +byebye() /* say goodnight gracie */ +{ + printf("Admin Server (kadm server) has completed operation.\n"); +} + +static clear_secrets() +{ + bzero((char *)server_parm.master_key, sizeof(server_parm.master_key)); + bzero((char *)server_parm.master_key_schedule, + sizeof(server_parm.master_key_schedule)); + server_parm.master_key_version = 0L; + return; +} + +static exit_now = 0; + +sigtype +doexit() +{ + exit_now = 1; +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ +} + +unsigned pidarraysize = 0; +int *pidarray = (int *)0; + +/* +kadm_listen +listen on the admin servers port for a request +*/ +kadm_listen() +{ + extern int errno; + int found; + int admin_fd; + int peer_fd; + fd_set mask, readfds; + struct sockaddr_in peer; + int addrlen; + void process_client(), kill_children(); + int pid; + sigtype do_child(); + + (void) signal(SIGINT, doexit); + (void) signal(SIGTERM, doexit); + (void) signal(SIGHUP, doexit); + (void) signal(SIGQUIT, doexit); + (void) signal(SIGPIPE, SIG_IGN); /* get errors on write() */ + (void) signal(SIGALRM, doexit); + (void) signal(SIGCHLD, do_child); + + if ((admin_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return KADM_NO_SOCK; + if (bind(admin_fd, (struct sockaddr *)&server_parm.admin_addr, + sizeof(struct sockaddr_in)) < 0) + return KADM_NO_BIND; + (void) 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,(fd_set *)0, + (fd_set *)0, (struct timeval *)0)) == 0) + continue; /* no things read */ + if (found < 0) { + if (errno != EINTR) + 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) { + 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) { + log("fork: %s",error_message(errno)); + (void) close(peer_fd); + continue; + } + /* fork succeded: keep tabs on child */ + (void) close(peer_fd); + if (pidarray) { + pidarray = (int *)realloc((char *)pidarray, ++pidarraysize); + pidarray[pidarraysize-1] = pid; + } else { + pidarray = (int *)malloc(pidarraysize = 1); + pidarray[0] = pid; + } + } else { + /* child */ + (void) close(admin_fd); +#endif /* DEBUG */ + /* do stuff */ + process_client (peer_fd, &peer); +#ifndef DEBUG + } +#endif + } else { + log("something else woke me up!"); + return(0); + } + } + /*NOTREACHED*/ +} + +#ifdef DEBUG +#define cleanexit(code) {kerb_fini(); return;} +#endif + +void +process_client(fd, who) +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 (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) + log("setsockopt keepalive: %d",errno); + + server_parm.recv_addr = *who; + + if (kerb_init()) { /* Open as client */ + 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 */ + u_long retcode = KADM_DB_INUSE; + char *pdat; + + dat_len = KADM_VERSIZE + sizeof(u_long); + dat = (u_char *) malloc((unsigned)dat_len); + pdat = (char *) dat; + retcode = htonl((u_long) KADM_DB_INUSE); + (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long)); + goto out; + } else if (!status) { + log("no service %s.%s",server_parm.sname, server_parm.sinst); + cleanexit(2); + } + + bcopy((char *)&service.key_low, (char *)skey, 4); + bcopy((char *)&service.key_high, (char *)(((long *) skey) + 1), 4); + bzero((char *)&service, sizeof(service)); + kdb_encrypt_key (skey, skey, server_parm.master_key, + server_parm.master_key_schedule, DECRYPT); + (void) krb_set_key((char *)skey, 0); /* if error, will show up when + rd_req fails */ + bzero((char *)skey, sizeof(skey)); + + while (1) { + if ((retval = krb_net_read(fd, (char *)&dlen, sizeof(u_short))) != + sizeof(u_short)) { + if (retval < 0) + log("dlen read: %s",error_message(errno)); + else if (retval) + log("short dlen read: %d",retval); + (void) close(fd); + cleanexit(retval ? 3 : 0); + } + if (exit_now) { + cleanexit(0); + } + dat_len = (int) ntohs(dlen); + dat = (u_char *) malloc((unsigned)dat_len); + if (!dat) { + log("malloc: No memory"); + (void) close(fd); + cleanexit(4); + } + if ((retval = krb_net_read(fd, (char *)dat, dat_len)) != dat_len) { + if (retval < 0) + log("data read: %s",error_message(errno)); + else + log("short read: %d vs. %d", dat_len, retval); + (void) close(fd); + cleanexit(5); + } + if (exit_now) { + cleanexit(0); + } + if ((retval = kadm_ser_in(&dat,&dat_len)) != KADM_SUCCESS) + 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 = (u_short) dat_len; + + if (dat_len != (int)dlen) { + clear_secrets(); + abort(); /* XXX */ + } + dlen = htons(dlen); + + if (krb_net_write(fd, (char *)&dlen, sizeof(u_short)) < 0) { + log("writing dlen to client: %s",error_message(errno)); + (void) close(fd); + cleanexit(6); + } + + if (krb_net_write(fd, (char *)dat, dat_len) < 0) { + log(LOG_ERR, "writing to client: %s",error_message(errno)); + (void) close(fd); + cleanexit(7); + } + free((char *)dat); + } + /*NOTREACHED*/ +} + +sigtype +do_child() +{ + /* SIGCHLD brings us here */ + int pid; + register int i, j; + +#ifdef POSIX + int status; +#else + union wait status; +#endif + + pid = wait(&status); + + 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 (WEXITSTATUS(status) || WCOREDUMP(status) || WIFSIGNALED(status)) + log("child %d: termsig %d, coredump %d, retcode %d", pid, + WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ + } + log("child %d not in list: termsig %d, coredump %d, retcode %d", pid, + WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ +} + +#ifndef DEBUG +cleanexit(val) +{ + kerb_fini(); + clear_secrets(); + exit(val); +} +#endif + +void +kill_children() +{ + register int i; + int osigmask; + + osigmask = sigblock(sigmask(SIGCHLD)); + + for (i = 0; i < pidarraysize; i++) { + kill(pidarray[i], SIGINT); + log("killing child %d", pidarray[i]); + } + sigsetmask(osigmask); + return; +} diff --git a/eBones/usr.sbin/kadmind/kadm_funcs.c b/eBones/usr.sbin/kadmind/kadm_funcs.c new file mode 100644 index 0000000..585a834 --- /dev/null +++ b/eBones/usr.sbin/kadmind/kadm_funcs.c @@ -0,0 +1,373 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT + * + * Kerberos administration server-side database manipulation routines + */ + +#ifndef lint +#if 0 +static char rcsid_kadm_funcs_c[] = +"Id: kadm_funcs.c,v 4.3 90/03/20 01:39:51 jon Exp "; +#endif +static const char rcsid[] = + "$Id$"; +#endif lint + +/* +kadm_funcs.c +the actual database manipulation code +*/ + +#include <sys/param.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_db.h> +#include "kadm_server.h" + +extern Kadm_Server server_parm; + +check_access(pname, pinst, prealm, acltype) +char *pname; +char *pinst; +char *prealm; +enum acl_types acltype; +{ + char checkname[MAX_K_NAME_SZ]; + char filename[MAXPATHLEN]; + extern char *acldir; + + (void) sprintf(checkname, "%s.%s@%s", pname, pinst, prealm); + + switch (acltype) { + case ADDACL: + (void) sprintf(filename, "%s%s", acldir, ADD_ACL_FILE); + break; + case GETACL: + (void) sprintf(filename, "%s%s", acldir, GET_ACL_FILE); + break; + case MODACL: + (void) sprintf(filename, "%s%s", acldir, MOD_ACL_FILE); + break; + } + return(acl_check(filename, checkname)); +} + +int +wildcard(str) +char *str; +{ + if (!strcmp(str, WILDCARD_STR)) + return(1); + return(0); +} + +#define failadd(code) { (void) log("FAILED addding '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; } + +kadm_add_entry (rname, rinstance, rrealm, valsin, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +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; + + if (!check_access(rname, rinstance, rrealm, ADDACL)) { + (void) log("WARNING: '%s.%s@%s' tried to add an entry for '%s.%s'", + rname, rinstance, rrealm, valsin->name, valsin->instance); + return KADM_UNAUTH; + } + + /* Need to check here for "legal" name and instance */ + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failadd(KADM_ILL_WILDCARD); + } + + (void) log("request to add an entry for '%s.%s' from '%s.%s@%s'", + valsin->name, valsin->instance, rname, rinstance, rrealm); + + 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); + (void) strncpy(data_i.name, valsin->name, ANAME_SZ); + (void) 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; + + bzero((char *)&default_princ, 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); + + + bcopy(&data_i.key_low,newpw,4); + bcopy(&data_i.key_high,(char *)(((long *) newpw) + 1),4); + + /* encrypt new key in master key */ + kdb_encrypt_key (newpw, newpw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + bcopy(newpw,&data_i.key_low,4); + bcopy((char *)(((long *) newpw) + 1), &data_i.key_high,4); + bzero((char *)newpw, 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; + (void) strncpy(data_i.mod_name, rname, sizeof(data_i.mod_name)-1); + (void) 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); + } + bzero((char *)flags, 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); + (void) log("'%s.%s' added.", valsin->name, valsin->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } + } +} +#undef failadd + +#define failget(code) { (void) log("FAILED retrieving '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; } + +kadm_get_entry (rname, rinstance, rrealm, valsin, flags, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin; /* what they wannt to get */ +u_char *flags; /* which fields we want */ +Kadm_vals *valsout; /* what data is there */ +{ + long numfound; /* check how many were returned */ + int more; /* To point to more name.instances */ + Principal data_o; /* Data object to hold Principal */ + + + if (!check_access(rname, rinstance, rrealm, GETACL)) { + (void) log("WARNING: '%s.%s@%s' tried to get '%s.%s's entry", + rname, rinstance, rrealm, valsin->name, valsin->instance); + return KADM_UNAUTH; + } + + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failget(KADM_ILL_WILDCARD); + } + + (void) log("retrieve '%s.%s's entry for '%s.%s@%s'", + valsin->name, valsin->instance, rname, rinstance, rrealm); + + /* 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); + (void) log("'%s.%s' retrieved.", valsin->name, valsin->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } else { + failget(KADM_NOENTRY); /* Else whimper and moan */ + } +} +#undef failget + +#define failmod(code) { (void) log("FAILED modifying '%s.%s' (%s)", valsin1->name, valsin1->instance, error_message(code)); return code; } + +kadm_mod_entry (rname, rinstance, rrealm, valsin1, valsin2, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin1, *valsin2; /* holds the parameters being + passed in */ +Kadm_vals *valsout; /* the actual record which is returned */ +{ + long numfound; + int more; + Principal data_o, temp_key; + u_char fields[4]; + des_cblock newpw; + + if (wildcard(valsin1->name) || wildcard(valsin1->instance)) { + failmod(KADM_ILL_WILDCARD); + } + + if (!check_access(rname, rinstance, rrealm, MODACL)) { + (void) log("WARNING: '%s.%s@%s' tried to change '%s.%s's entry", + rname, rinstance, rrealm, valsin1->name, valsin1->instance); + return KADM_UNAUTH; + } + + (void) log("request to modify '%s.%s's entry from '%s.%s@%s' ", + valsin1->name, valsin1->instance, rname, rinstance, rrealm); + + numfound = kerb_get_principal(valsin1->name, valsin1->instance, + &data_o, 1, &more); + if (numfound == -1) { + failmod(KADM_DB_INUSE); + } else if (numfound) { + kadm_vals_to_prin(valsin2->fields, &temp_key, valsin2); + (void) strncpy(data_o.name, valsin1->name, ANAME_SZ); + (void) strncpy(data_o.instance, valsin1->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); + + + bcopy(&temp_key.key_low,newpw,4); + bcopy(&temp_key.key_high,(char *)(((long *) newpw) + 1),4); + + /* encrypt new key in master key */ + kdb_encrypt_key (newpw, newpw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + bcopy(newpw,&data_o.key_low,4); + bcopy((char *)(((long *) newpw) + 1), &data_o.key_high,4); + bzero((char *)newpw, sizeof(newpw)); + } + bzero((char *)&temp_key, sizeof(temp_key)); + + (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + (void) strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + + bzero((char *)&data_o, sizeof(data_o)); + + if (more == -1) { + failmod(KADM_DB_INUSE); + } else if (more) { + failmod(KADM_UK_SERROR); + } else { + numfound = kerb_get_principal(valsin1->name, valsin1->instance, + &data_o, 1, &more); + if ((more!=0)||(numfound!=1)) { + failmod(KADM_UK_RERROR); + } + bzero((char *) fields, 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); + (void) log("'%s.%s' modified.", valsin1->name, valsin1->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } + } + else { + failmod(KADM_NOENTRY); + } +} +#undef failmod + +#define failchange(code) { (void) log("FAILED changing key for '%s.%s@%s' (%s)", rname, rinstance, rrealm, error_message(code)); return code; } + +kadm_change (rname, rinstance, rrealm, newpw) +char *rname; +char *rinstance; +char *rrealm; +des_cblock newpw; +{ + long numfound; + int more; + Principal data_o; + des_cblock local_pw; + + if (strcmp(server_parm.krbrlm, rrealm)) { + (void) log("change key request from wrong realm, '%s.%s@%s'!\n", + rname, rinstance, rrealm); + return(KADM_WRONG_REALM); + } + + if (wildcard(rname) || wildcard(rinstance)) { + failchange(KADM_ILL_WILDCARD); + } + (void) log("'%s.%s@%s' wants to change its password", + rname, rinstance, rrealm); + + bcopy(newpw, local_pw, 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, ENCRYPT); + + numfound = kerb_get_principal(rname, rinstance, + &data_o, 1, &more); + if (numfound == -1) { + failchange(KADM_DB_INUSE); + } else if (numfound) { + bcopy(local_pw,&data_o.key_low,4); + bcopy((char *)(((long *) local_pw) + 1), &data_o.key_high,4); + data_o.key_version++; + data_o.kdc_key_ver = server_parm.master_key_version; + (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + (void) strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + bzero((char *) local_pw, sizeof(local_pw)); + bzero((char *) &data_o, sizeof(data_o)); + if (more == -1) { + failchange(KADM_DB_INUSE); + } else if (more) { + failchange(KADM_UK_SERROR); + } else { + (void) log("'%s.%s@%s' password changed.", rname, rinstance, rrealm); + return KADM_SUCCESS; + } + } + else { + failchange(KADM_NOENTRY); + } +} +#undef failchange diff --git a/eBones/usr.sbin/kadmind/kadm_ser_wrap.c b/eBones/usr.sbin/kadmind/kadm_ser_wrap.c new file mode 100644 index 0000000..c019bc0 --- /dev/null +++ b/eBones/usr.sbin/kadmind/kadm_ser_wrap.c @@ -0,0 +1,206 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server-side support functions + */ + +#ifndef lint +static char rcsid_module_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_ser_wrap.c,v 4.4 89/09/26 09:29:36 jtkohl Exp "; +#endif lint + +/* +kadm_ser_wrap.c +unwraps wrapped packets and calls the appropriate server subroutine +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <netdb.h> +#include <sys/socket.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_err.h> +#include "kadm_server.h" + +Kadm_Server server_parm; + +/* +kadm_ser_init +set up the server_parm structure +*/ +kadm_ser_init(inter, realm) +int inter; /* interactive or from file */ +char realm[]; +{ + struct servent *sep; + struct hostent *hp; + char hostname[MAXHOSTNAMELEN]; + + (void) init_kadm_err_tbl(); + (void) init_krb_err_tbl(); + if (gethostname(hostname, sizeof(hostname))) + return KADM_NO_HOSTNAME; + + (void) strcpy(server_parm.sname, PWSERV_NAME); + (void) strcpy(server_parm.sinst, KRB_MASTER); + (void) strcpy(server_parm.krbrlm, realm); + + server_parm.admin_fd = -1; + /* setting up the addrs */ + if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL) + return KADM_NO_SERV; + bzero((char *)&server_parm.admin_addr,sizeof(server_parm.admin_addr)); + server_parm.admin_addr.sin_family = AF_INET; + if ((hp = gethostbyname(hostname)) == NULL) + return KADM_NO_HOSTNAME; + bcopy(hp->h_addr, (char *) &server_parm.admin_addr.sin_addr.s_addr, + hp->h_length); + server_parm.admin_addr.sin_port = sep->s_port; + /* 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(dat, dat_len, code) +u_char **dat; +int *dat_len; +int code; +{ + u_long retcode; + char *pdat; + + free((char *)*dat); /* free up req */ + *dat_len = KADM_VERSIZE + sizeof(u_long); + *dat = (u_char *) malloc((unsigned)*dat_len); + pdat = (char *) *dat; + retcode = htonl((u_long) code); + (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long)); + return; +} + +/* +kadm_ser_in +unwrap the data stored in dat, process, and return it. +*/ +kadm_ser_in(dat,dat_len) +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_long r_len; /* length of the actual packet */ + KTEXT_ST authent; /* the authenticator */ + AUTH_DAT ad; /* who is this, klink */ + u_long 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_long); + bcopy((char *)(*dat) + in_len, (char *)authent.dat, 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, (char *)0)) + { + errpkt(dat, dat_len,retc + krb_err_base); + return retc + krb_err_base; + } + +#define clr_cli_secrets() {bzero((char *)sess_sched, sizeof(sess_sched)); bzero((char *)ad.session, sizeof(ad.session));} + + in_st = *dat + *dat_len - r_len; +#ifdef NOENCRYPTION + ncksum = 0; +#else + ncksum = quad_cksum(in_st, (u_long *)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 + bzero(sess_sched, 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,&ad, + &retdat, &retlen); + break; + case ADD_ENT: + retval = kadm_ser_add(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case GET_ENT: + retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case MOD_ENT: + retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length,&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((char *)*dat); + tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE + + sizeof(u_long))); + (void) strncpy((char *)tmpdat, KADM_VERSTR, KADM_VERSIZE); + retval = htonl((u_long)retval); + bcopy((char *)&retval, (char *)tmpdat + KADM_VERSIZE, sizeof(u_long)); + if (retlen) { + bcopy((char *)retdat, (char *)tmpdat + KADM_VERSIZE + sizeof(u_long), + retlen); + free((char *)retdat); + } + /* slop for mk_priv stuff */ + *dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE + + sizeof(u_long) + 200)); + if ((*dat_len = krb_mk_priv(tmpdat, *dat, + (u_long) (retlen + KADM_VERSIZE + + sizeof(u_long)), + 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/eBones/usr.sbin/kadmind/kadm_server.c b/eBones/usr.sbin/kadmind/kadm_server.c new file mode 100644 index 0000000..56631d3 --- /dev/null +++ b/eBones/usr.sbin/kadmind/kadm_server.c @@ -0,0 +1,159 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server-side subroutines + */ + +#ifndef lint +static char rcsid_kadm_server_c[] = +"Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.c,v 4.2 89/09/26 09:30:23 jtkohl Exp "; +#endif lint + +#include <kadm.h> +#include <kadm_err.h> + +/* +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 +*/ +kadm_ser_cpw(dat, len, ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + unsigned long keylow, keyhigh; + des_cblock newkey; + int stvlen; + + /* take key off the stream, and change the database */ + + if ((stvlen = stv_long(dat, &keyhigh, 0, len)) < 0) + return(KADM_LENGTH_ERROR); + if (stv_long(dat, &keylow, stvlen, len) < 0) + return(KADM_LENGTH_ERROR); + + keylow = ntohl(keylow); + keyhigh = ntohl(keyhigh); + bcopy((char *)&keyhigh, (char *)(((long *)newkey) + 1), 4); + bcopy((char *)&keylow, (char *)newkey, 4); + *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 +*/ +kadm_ser_add(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals values, retvals; + int 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 +*/ +kadm_ser_mod(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals vals1, vals2, retvals; + int wh; + int 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; + } +} + +/* +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 +*/ +kadm_ser_get(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals values, retvals; + u_char fl[FLDSZ]; + int loop,wh; + int 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/eBones/usr.sbin/kadmind/kadm_server.h b/eBones/usr.sbin/kadmind/kadm_server.h new file mode 100644 index 0000000..db9d21f --- /dev/null +++ b/eBones/usr.sbin/kadmind/kadm_server.h @@ -0,0 +1,51 @@ +/* + * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.h,v $ + * $Author: jtkohl $ + * Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.h,v 4.1 89/12/21 17:46:51 jtkohl Exp + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * 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 + */ + +#include <sys/types.h> +#include <kerberosIV/krb.h> +#include <kerberosIV/des.h> + +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]; + C_Block master_key; + C_Block session_key; + Key_schedule master_key_schedule; + long master_key_version; +} Kadm_Server; + +/* the default syslog file */ +#define KADM_SYSLOG "/var/log/kadmind.syslog" + +#define DEFAULT_ACL_DIR "/etc/kerberosIV" +#define ADD_ACL_FILE "/admin_acl.add" +#define GET_ACL_FILE "/admin_acl.get" +#define MOD_ACL_FILE "/admin_acl.mod" + +#endif KADM_SERVER_DEFS |