diff options
Diffstat (limited to 'crypto/kerberosIV/kadmin/admin_server.c')
-rw-r--r-- | crypto/kerberosIV/kadmin/admin_server.c | 610 |
1 files changed, 0 insertions, 610 deletions
diff --git a/crypto/kerberosIV/kadmin/admin_server.c b/crypto/kerberosIV/kadmin/admin_server.c deleted file mode 100644 index 14347fd..0000000 --- a/crypto/kerberosIV/kadmin/admin_server.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - Copyright (C) 1989 by the Massachusetts Institute of Technology - - Export of this software from the United States of America is assumed - to require a specific license from the United States Government. - It is the responsibility of any person or organization contemplating - export to obtain such a license before exporting. - -WITHIN THAT CONSTRAINT, permission to use, copy, modify, and -distribute this software and its documentation for any purpose and -without fee is hereby granted, provided that the above copyright -notice appear in all copies and that both that copyright notice and -this permission notice appear in supporting documentation, and that -the name of M.I.T. not be used in advertising or publicity pertaining -to distribution of the software without specific, written prior -permission. M.I.T. makes no representations about the suitability of -this software for any purpose. It is provided "as is" without express -or implied warranty. - - */ - -/* - * Top-level loop of the kerberos Administration server - */ - -/* - admin_server.c - this holds the main loop and initialization and cleanup code for the server -*/ - -#include "kadm_locl.h" - -RCSID("$Id: admin_server.c,v 1.49.2.2 2000/10/18 20:24:57 assar Exp $"); - -/* Almost all procs and such need this, so it is global */ -admin_params prm; /* The command line parameters struct */ - -/* GLOBAL */ -char *acldir = DEFAULT_ACL_DIR; -static char krbrlm[REALM_SZ]; - -#define MAXCHILDREN 100 - -struct child { - pid_t pid; - int pipe_fd; - int authenticated; -}; - -static unsigned nchildren = 0; -static struct child children[MAXCHILDREN]; - -static int exit_now = 0; - -static -RETSIGTYPE -doexit(int sig) -{ - exit_now = 1; - SIGRETURN(0); -} - -static sig_atomic_t do_wait; - -static -RETSIGTYPE -do_child(int sig) -{ - do_wait = 1; - SIGRETURN(0); -} - - -static void -kill_children(void) -{ - int i; - - for (i = 0; i < nchildren; i++) { - kill(children[i].pid, SIGINT); - close (children[i].pipe_fd); - krb_log("killing child %d", children[i].pid); - } -} - -/* close the system log file */ -static void -close_syslog(void) -{ - krb_log("Shutting down admin server"); -} - -static void -byebye(void) /* say goodnight gracie */ -{ - printf("Admin Server (kadm server) has completed operation.\n"); -} - -static void -clear_secrets(void) -{ - memset(server_parm.master_key, 0, sizeof(server_parm.master_key)); - memset(server_parm.master_key_schedule, 0, - sizeof(server_parm.master_key_schedule)); - server_parm.master_key_version = 0L; -} - -static void -cleanexit(int val) -{ - kerb_fini(); - clear_secrets(); - exit(val); -} - -static RETSIGTYPE -sigalrm(int sig) -{ - cleanexit(1); -} - -/* - * handle the client on the socket `fd' from `who' - * `signal_fd' is a pipe on which to signal when the user has been - * authenticated - */ - -static void -process_client(int fd, struct sockaddr_in *who, int signal_fd) -{ - u_char *dat; - int dat_len; - u_short dlen; - int retval; - Principal service; - des_cblock skey; - int more; - int status; - int authenticated = 0; - - /* make this connection time-out after 1 second if the user has - not managed one transaction succesfully in kadm_ser_in */ - - signal(SIGALRM, sigalrm); - alarm(2); - -#if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT) - { - int on = 1; - - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, - (void *)&on, sizeof(on)) < 0) - krb_log("setsockopt keepalive: %d",errno); - } -#endif - - server_parm.recv_addr = *who; - - if (kerb_init()) { /* Open as client */ - krb_log("can't open krb db"); - cleanexit(1); - } - /* need to set service key to changepw.KRB_MASTER */ - - status = kerb_get_principal(server_parm.sname, server_parm.sinst, &service, - 1, &more); - if (status == -1) { - /* db locked */ - char *pdat; - - dat_len = KADM_VERSIZE + 4; - dat = (u_char *) malloc(dat_len); - if (dat == NULL) { - krb_log("malloc failed"); - cleanexit(4); - } - pdat = (char *) dat; - memcpy(pdat, KADM_ULOSE, KADM_VERSIZE); - krb_put_int (KADM_DB_INUSE, pdat + KADM_VERSIZE, 4, 4); - goto out; - } else if (!status) { - krb_log("no service %s.%s",server_parm.sname, server_parm.sinst); - cleanexit(2); - } - - copy_to_key(&service.key_low, &service.key_high, skey); - memset(&service, 0, sizeof(service)); - kdb_encrypt_key (&skey, &skey, &server_parm.master_key, - server_parm.master_key_schedule, DES_DECRYPT); - krb_set_key(skey, 0); /* if error, will show up when - rd_req fails */ - memset(skey, 0, sizeof(skey)); - - while (1) { - void *errpkt; - - errpkt = malloc(KADM_VERSIZE + 4); - if (errpkt == NULL) { - krb_log("malloc: no memory"); - close(fd); - cleanexit(4); - } - - if ((retval = krb_net_read(fd, &dlen, sizeof(u_short))) != - sizeof(u_short)) { - if (retval < 0) - krb_log("dlen read: %s",error_message(errno)); - else if (retval) - krb_log("short dlen read: %d",retval); - close(fd); - cleanexit(retval ? 3 : 0); - } - if (exit_now) { - cleanexit(0); - } - dat_len = ntohs(dlen); - dat = (u_char *) malloc(dat_len); - if (dat == NULL) { - krb_log("malloc: No memory"); - close(fd); - cleanexit(4); - } - if ((retval = krb_net_read(fd, dat, dat_len)) != dat_len) { - if (retval < 0) - krb_log("data read: %s",error_message(errno)); - else - krb_log("short read: %d vs. %d", dat_len, retval); - close(fd); - cleanexit(5); - } - if (exit_now) { - cleanexit(0); - } - retval = kadm_ser_in(&dat, &dat_len, errpkt); - - if (retval == KADM_SUCCESS) { - if (!authenticated) { - unsigned char one = 1; - - authenticated = 1; - alarm (0); - write (signal_fd, &one, 1); - } - } else { - krb_log("processing request: %s", error_message(retval)); - } - - /* kadm_ser_in did the processing and returned stuff in - dat & dat_len , return the appropriate data */ - - out: - dlen = htons(dat_len); - - if (krb_net_write(fd, &dlen, sizeof(u_short)) < 0) { - krb_log("writing dlen to client: %s",error_message(errno)); - close(fd); - cleanexit(6); - } - - if (krb_net_write(fd, dat, dat_len) < 0) { - krb_log("writing to client: %s", error_message(errno)); - close(fd); - cleanexit(7); - } - free(dat); - } - /*NOTREACHED*/ -} - -static void -accept_client (int admin_fd) -{ - int pipe_fd[2]; - int addrlen; - struct sockaddr_in peer; - pid_t pid; - int peer_fd; - - /* using up the maximum number of children, try to get rid - of one unauthenticated one */ - - if (nchildren >= MAXCHILDREN) { - int i, nunauth = 0; - int victim; - - for (;;) { - for (i = 0; i < nchildren; ++i) - if (children[i].authenticated == 0) - ++nunauth; - if (nunauth == 0) - return; - - victim = rand() % nchildren; - if (children[victim].authenticated == 0) { - kill(children[victim].pid, SIGINT); - close(children[victim].pipe_fd); - for (i = victim; i < nchildren; ++i) - children[i] = children[i + 1]; - --nchildren; - break; - } - } - } - - /* accept the conn */ - addrlen = sizeof(peer); - peer_fd = accept(admin_fd, (struct sockaddr *)&peer, &addrlen); - if (peer_fd < 0) { - krb_log("accept: %s",error_message(errno)); - return; - } - if (pipe (pipe_fd) < 0) { - krb_log ("pipe: %s", error_message(errno)); - return; - } - - if (pipe_fd[0] >= FD_SETSIZE - || pipe_fd[1] >= FD_SETSIZE) { - krb_log ("pipe fds too large"); - close (pipe_fd[0]); - close (pipe_fd[1]); - return; - } - - pid = fork (); - - if (pid < 0) { - krb_log ("fork: %s", error_message(errno)); - close (pipe_fd[0]); - close (pipe_fd[1]); - return; - } - - if (pid != 0) { - /* parent */ - /* fork succeded: keep tabs on child */ - close(peer_fd); - children[nchildren].pid = pid; - children[nchildren].pipe_fd = pipe_fd[0]; - children[nchildren].authenticated = 0; - ++nchildren; - close (pipe_fd[1]); - - } else { - int i; - - /* child */ - close(admin_fd); - close(pipe_fd[0]); - - for (i = 0; i < nchildren; ++i) - close (children[i].pipe_fd); - - /* - * If we are multihomed we need to figure out which - * local address that is used this time since it is - * used in "direction" comparison. - */ - getsockname(peer_fd, - (struct sockaddr *)&server_parm.admin_addr, - &addrlen); - /* do stuff */ - process_client (peer_fd, &peer, pipe_fd[1]); - } -} - -/* - * handle data signaled from child `child' kadmind - */ - -static void -handle_child_signal (int child) -{ - int ret; - unsigned char data[1]; - - ret = read (children[child].pipe_fd, data, 1); - if (ret < 0) { - if (errno != EINTR) - krb_log ("read from child %d: %s", child, - error_message(errno)); - return; - } - if (ret == 0) { - close (children[child].pipe_fd); - children[child].pipe_fd = -1; - return; - } - if (data) - children[child].authenticated = 1; -} - -/* - * handle dead children - */ - -static void -handle_sigchld (void) -{ - pid_t pid; - int status; - int i, j; - - for (;;) { - int found = 0; - - pid = waitpid(-1, &status, WNOHANG|WUNTRACED); - if (pid == 0 || (pid < 0 && errno == ECHILD)) - break; - if (pid < 0) { - krb_log("waitpid: %s", error_message(errno)); - break; - } - for (i = 0; i < nchildren; i++) - if (children[i].pid == pid) { - /* found it */ - close(children[i].pipe_fd); - for (j = i; j < nchildren; j++) - /* copy others down */ - children[j] = children[j+1]; - --nchildren; -#if 0 - if ((WIFEXITED(status) && WEXITSTATUS(status) != 0) - || WIFSIGNALED(status)) - krb_log("child %d: termsig %d, retcode %d", pid, - WTERMSIG(status), WEXITSTATUS(status)); -#endif - found = 1; - } -#if 0 - if (!found) - krb_log("child %d not in list: termsig %d, retcode %d", pid, - WTERMSIG(status), WEXITSTATUS(status)); -#endif - } - do_wait = 0; -} - -/* -kadm_listen -listen on the admin servers port for a request -*/ -static int -kadm_listen(void) -{ - int found; - int admin_fd; - fd_set readfds; - - signal(SIGINT, doexit); - signal(SIGTERM, doexit); - signal(SIGHUP, doexit); - signal(SIGQUIT, doexit); - signal(SIGPIPE, SIG_IGN); /* get errors on write() */ - signal(SIGALRM, doexit); - signal(SIGCHLD, do_child); - if (setsid() < 0) - krb_log("setsid() failed"); - - if ((admin_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - return KADM_NO_SOCK; - - if (admin_fd >= FD_SETSIZE) { - krb_log("admin_fd too big"); - return KADM_NO_BIND; - } - -#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) - { - int one = 1; - setsockopt(admin_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, - sizeof(one)); - } -#endif - if (bind(admin_fd, (struct sockaddr *)&server_parm.admin_addr, - sizeof(struct sockaddr_in)) < 0) - return KADM_NO_BIND; - if (listen(admin_fd, SOMAXCONN) < 0) - return KADM_NO_BIND; - - for (;;) { /* loop nearly forever */ - int i; - int maxfd = -1; - - if (exit_now) { - clear_secrets(); - kill_children(); - return(0); - } - if (do_wait) - handle_sigchld (); - - FD_ZERO(&readfds); - FD_SET(admin_fd, &readfds); - maxfd = max(maxfd, admin_fd); - for (i = 0; i < nchildren; ++i) - if (children[i].pipe_fd >= 0) { - FD_SET(children[i].pipe_fd, &readfds); - maxfd = max(maxfd, children[i].pipe_fd); - } - - found = select(maxfd + 1, &readfds, NULL, NULL, NULL); - if (found < 0) { - if (errno != EINTR) - krb_log("select: %s",error_message(errno)); - continue; - } - if (FD_ISSET(admin_fd, &readfds)) - accept_client (admin_fd); - for (i = 0; i < nchildren; ++i) - if (children[i].pipe_fd >= 0 - && FD_ISSET(children[i].pipe_fd, &readfds)) { - handle_child_signal (i); - } - } - /*NOTREACHED*/ -} - -/* -** Main does the logical thing, it sets up the database and RPC interface, -** as well as handling the creation and maintenance of the syslog file... -*/ -int -main(int argc, char **argv) /* admin_server main routine */ -{ - int errval; - int c; - struct in_addr i_addr; - - set_progname (argv[0]); - - umask(077); /* Create protected files */ - - i_addr.s_addr = INADDR_ANY; - /* initialize the admin_params structure */ - prm.sysfile = KADM_SYSLOG; /* default file name */ - prm.inter = 0; - - memset(krbrlm, 0, sizeof(krbrlm)); - - while ((c = getopt(argc, argv, "f:hmnd:a:r:i:")) != -1) - switch(c) { - case 'f': /* Syslog file name change */ - prm.sysfile = optarg; - break; - case 'n': - prm.inter = 0; - break; - case 'm': - prm.inter = 1; - break; - case 'a': /* new acl directory */ - acldir = optarg; - break; - case 'd': - /* put code to deal with alt database place */ - if ((errval = kerb_db_set_name(optarg))) - errx (1, "opening database %s: %s", - optarg, error_message(errval)); - break; - case 'r': - strlcpy (krbrlm, optarg, sizeof(krbrlm)); - break; - case 'i': - /* Only listen on this address */ - if(inet_aton (optarg, &i_addr) == 0) { - fprintf (stderr, "Bad address: %s\n", optarg); - exit (1); - } - break; - case 'h': /* get help on using admin_server */ - default: - errx(1, "Usage: kadmind [-h] [-n] [-m] [-r realm] [-d dbname] [-f filename] [-a acldir] [-i address_to_listen_on]"); - } - - if (krbrlm[0] == 0) - if (krb_get_lrealm(krbrlm, 1) != KSUCCESS) - errx (1, "Unable to get local realm. Fix krb.conf or use -r."); - - printf("KADM Server %s initializing\n",KADM_VERSTR); - printf("Please do not use 'kill -9' to kill this job, use a\n"); - printf("regular kill instead\n\n"); - - kset_logfile(prm.sysfile); - krb_log("Admin server starting"); - - kerb_db_set_lockmode(KERB_DBL_NONBLOCKING); - errval = kerb_init(); /* Open the Kerberos database */ - if (errval) { - warnx ("error: kerb_init() failed"); - close_syslog(); - byebye(); - } - /* set up the server_parm struct */ - if ((errval = kadm_ser_init(prm.inter, krbrlm, i_addr))==KADM_SUCCESS) { - kerb_fini(); /* Close the Kerberos database-- - will re-open later */ - errval = kadm_listen(); /* listen for calls to server from - clients */ - } - if (errval != KADM_SUCCESS) { - warnx("error: %s",error_message(errval)); - kerb_fini(); /* Close if error */ - } - close_syslog(); /* Close syslog file, print - closing note */ - byebye(); /* Say bye bye on the terminal - in use */ - exit(1); -} /* procedure main */ |