diff options
author | pst <pst@FreeBSD.org> | 1995-08-02 22:14:27 +0000 |
---|---|---|
committer | pst <pst@FreeBSD.org> | 1995-08-02 22:14:27 +0000 |
commit | 109eb67c2a4c6318c0f2cb71db786f785b7bcc1c (patch) | |
tree | 617a61ae2ac6a2f7b0b158804c56e9356003c458 /eBones/libexec | |
parent | ca1e73f49ac03ad6e37ae7ec8c37aa3daf546adb (diff) | |
download | FreeBSD-src-109eb67c2a4c6318c0f2cb71db786f785b7bcc1c.zip FreeBSD-src-109eb67c2a4c6318c0f2cb71db786f785b7bcc1c.tar.gz |
Program to receive and process a new kerberos database (this is run on
the slave server).
NOTE: This code should not be built, there is no documentation, and this
method of database transfer is highly suboptimal. It's here just
for those of us who actually have multiple K4 servers and want
something more secure than the other distribution mechanisms.
Obtained from: MIT Project Athena
Diffstat (limited to 'eBones/libexec')
-rw-r--r-- | eBones/libexec/kpropd/Makefile | 11 | ||||
-rw-r--r-- | eBones/libexec/kpropd/kpropd.c | 445 |
2 files changed, 456 insertions, 0 deletions
diff --git a/eBones/libexec/kpropd/Makefile b/eBones/libexec/kpropd/Makefile new file mode 100644 index 0000000..74d774f --- /dev/null +++ b/eBones/libexec/kpropd/Makefile @@ -0,0 +1,11 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id$ + +PROG= kpropd +CFLAGS+=-I${.CURDIR}/../include -I${.CURDIR}/../kprop +DPADD= ${LIBKRB} ${LIBDES} +LDADD= -L${KRBOBJDIR} -lkrb -L${DESOBJDIR} -ldes +BINDIR= /usr/libexec +NOMAN= noman + +.include <bsd.prog.mk> diff --git a/eBones/libexec/kpropd/kpropd.c b/eBones/libexec/kpropd/kpropd.c new file mode 100644 index 0000000..db99ae0 --- /dev/null +++ b/eBones/libexec/kpropd/kpropd.c @@ -0,0 +1,445 @@ +/* + * Copyright 1987 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * MIT.Copyright. + * + * kprop/kpropd have been abandonded by Project Athena (for good reason) + * however they still form the basis for one of the better ways for + * distributing kerberos databases. This version of kpropd has been + * adapted from the MIT distribution to work properly in a 4.4BSD + * environment. + * + * $Revision: 4.5 $ $Date: 92/10/23 15:45:46 $ $State: Exp $ + * $Source$ + * + * Log: kpropd.c,v + * Revision 4.5 92/10/23 15:45:46 tytso Make it possible + * to specify the location of the kdb_util program. + * + * Revision 4.4 91/06/15 03:20:51 probe Fixed <sys/types.h> inclusion + * + * Revision 4.3 89/05/16 15:06:04 wesommer Fix operator precedence stuff. + * Programmer: John Kohl. + * + * Revision 4.2 89/03/23 10:24:00 jtkohl NOENCRYPTION changes + * + * Revision 4.1 89/01/24 20:33:48 root name change + * + * Revision 4.0 89/01/24 18:45:06 wesommer Original version; programmer: + * wesommer auditor: jon + * + * Revision 4.5 88/01/08 18:07:46 jon formatting and rcs header changes */ + +/* + * This program is run on slave servers, to catch updates "pushed" from the + * master kerberos server in a realm. + */ + +#ifndef lint +static char rcsid_kpropd_c[] = +"$Header: /afs/net.mit.edu/project/krb4/src/slave/RCS/kpropd.c,v 4.5 92/10/23 15:45:46 tytso Exp $"; +#endif /* lint */ + +#include <ctype.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <stdio.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <syslog.h> +#include <krb.h> +#include <krb_db.h> + +#include "kprop.h" + +static char kprop_version[KPROP_PROT_VERSION_LEN] = KPROP_PROT_VERSION; + +extern int errno; +int debug = 0; + +int pause_int = 300; /* 5 minutes in seconds */ +unsigned long get_data_checksum(); +static void SlowDeath(); + /* leave room for private msg overhead */ +static char buf[KPROP_BUFSIZ + 64]; + +static void +usage() +{ + fprintf(stderr, "\nUsage: kpropd [-r realm] [-s srvtab] [-P kdb_util] fname\n"); + exit(2); +} + +main(argc, argv) + int argc; + char **argv; +{ + struct sockaddr_in from; + struct sockaddr_in sin; + struct servent *sp; + int s, s2, fd, n, fdlock; + int from_len; + char local_file[256]; + char local_temp[256]; + struct hostent *hp; + char hostname[256]; + unsigned long cksum_read; + unsigned long cksum_calc; + char from_str[128]; + u_long length; + long kerror; + AUTH_DAT auth_dat; + KTEXT_ST ticket; + char my_instance[INST_SZ]; + char my_realm[REALM_SZ]; + char cmd[1024]; + short net_transfer_mode, transfer_mode; + Key_schedule session_sched; + char version[9]; + int c; + extern char *optarg; + extern int optind; + int rflag; + char *srvtab = ""; + char *local_db = DBM_FILE; + char *kdb_util = KPROP_KDB_UTIL; + + if (argv[argc - 1][0] == 'k' && isdigit(argv[argc - 1][1])) { + argc--; /* ttys file hack */ + } + while ((c = getopt(argc, argv, "r:s:d:P:")) != EOF) { + switch (c) { + case 'r': + rflag++; + strcpy(my_realm, optarg); + break; + case 's': + srvtab = optarg; + break; + case 'd': + local_db = optarg; + break; + case 'P': + kdb_util = optarg; + break; + default: + usage(); + break; + } + } + if (optind != argc - 1) + usage(); + + openlog("kpropd", LOG_PID, LOG_AUTH); + + strcpy(local_file, argv[optind]); + strcat(strcpy(local_temp, argv[optind]), ".tmp"); + +#ifdef STANDALONE + + if ((sp = getservbyname("krb_prop", "tcp")) == NULL) { + syslog(LOG_ERR, "tcp/krb_prop: unknown service."); + SlowDeath(); + } + bzero(&sin, sizeof sin); + sin.sin_port = sp->s_port; + sin.sin_family = AF_INET; + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + syslog(LOG_ERR, "socket: %m"); + SlowDeath(); + } + if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { + syslog(LOG_ERR, "bind: %m"); + SlowDeath(); + } + +#endif /* STANDALONE */ + + if (!rflag) { + kerror = krb_get_lrealm(my_realm, 1); + if (kerror != KSUCCESS) { + syslog(LOG_ERR, "can't get local realm. %s", + krb_err_txt[kerror]); + SlowDeath(); + } + } + if (gethostname(my_instance, sizeof(my_instance)) != 0) { + syslog(LOG_ERR, "gethostname: %m"); + SlowDeath(); + } + +#ifdef STANDALONE + listen(s, 5); + for (;;) { + from_len = sizeof from; + if ((s2 = accept(s, (struct sockaddr *)&from, &from_len)) < 0) { + syslog(LOG_ERR, "accept: %m"); + continue; + } +#else /* !STANDALONE */ + + s2 = 0; + from_len = sizeof from; + if (getpeername(0, (struct sockaddr *)&from, &from_len) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + SlowDeath(); + } + +#endif /* !STANDALONE */ + + strcpy(from_str, inet_ntoa(from.sin_addr)); + + if ((hp = gethostbyaddr((char *) &(from.sin_addr.s_addr), + from_len, AF_INET)) == NULL) { + strcpy(hostname, "UNKNOWN"); + } else { + strcpy(hostname, hp->h_name); + } + + syslog(LOG_INFO, "connection from %s, %s", hostname, from_str); + + /* for krb_rd_{priv, safe} */ + n = sizeof sin; + if (getsockname(s2, (struct sockaddr *)&sin, &n) != 0) { + syslog(LOG_ERR, "can't get socketname: %m"); + SlowDeath(); + } + if (n != sizeof(sin)) { + syslog(LOG_ERR, "can't get socketname (length)"); + SlowDeath(); + } + if ((fdlock = open(local_temp, O_WRONLY | O_CREAT, 0600)) < 0) { + syslog(LOG_ERR, "open: %m"); + SlowDeath(); + } + if (flock(fdlock, LOCK_EX | LOCK_NB)) { + syslog(LOG_ERR, "flock: %m"); + SlowDeath(); + } + if ((fd = creat(local_temp, 0600)) < 0) { + syslog(LOG_ERR, "creat: %m"); + SlowDeath(); + } + if ((n = read(s2, buf, sizeof(kprop_version))) + != sizeof(kprop_version)) { + syslog(LOG_ERR, + "can't read protocol version (%d bytes)", n); + SlowDeath(); + } + if (strncmp(buf, kprop_version, sizeof(kprop_version)) != 0) { + syslog(LOG_ERR, "unsupported version %s", buf); + SlowDeath(); + } + if ((n = read(s2, &net_transfer_mode, + sizeof(net_transfer_mode))) + != sizeof(net_transfer_mode)) { + syslog(LOG_ERR, "can't read transfer mode"); + SlowDeath(); + } + transfer_mode = ntohs(net_transfer_mode); + kerror = krb_recvauth(KOPT_DO_MUTUAL, s2, &ticket, + KPROP_SERVICE_NAME, + my_instance, + &from, + &sin, + &auth_dat, + srvtab, + session_sched, + version); + if (kerror != KSUCCESS) { + syslog(LOG_ERR, "%s calling getkdata", + krb_err_txt[kerror]); + SlowDeath(); + } + syslog(LOG_INFO, "connection from %s.%s@%s", + auth_dat.pname, auth_dat.pinst, auth_dat.prealm); + + /* + * AUTHORIZATION is done here. We might want to expand this + * to read an acl file at some point, but allowing for now + * KPROP_SERVICE_NAME.KRB_MASTER@local-realm is fine ... + */ + + if ((strcmp(KPROP_SERVICE_NAME, auth_dat.pname) != 0) || + (strcmp(KRB_MASTER, auth_dat.pinst) != 0) || + (strcmp(my_realm, auth_dat.prealm) != 0)) { + syslog(LOG_NOTICE, "authorization denied"); + SlowDeath(); + } + switch (transfer_mode) { + case KPROP_TRANSFER_PRIVATE: + recv_auth(s2, fd, 1 /* private */ , &from, &sin, &auth_dat); + break; + case KPROP_TRANSFER_SAFE: + recv_auth(s2, fd, 0 /* safe */ , &from, &sin, &auth_dat); + break; + case KPROP_TRANSFER_CLEAR: + recv_clear(s2, fd); + break; + default: + syslog(LOG_ERR, "bad transfer mode %d", transfer_mode); + SlowDeath(); + } + + if (transfer_mode != KPROP_TRANSFER_PRIVATE) { + syslog(LOG_ERR, "non-private transfers not supported\n"); + SlowDeath(); +#ifdef doesnt_work_yet + lseek(fd, (long) 0, L_SET); + if (auth_dat.checksum != get_data_checksum(fd, session_sched)) { + syslog(LOG_ERR, "checksum doesn't match"); + SlowDeath(); + } +#endif + } else { + struct stat st; + fstat(fd, &st); + if (st.st_size != auth_dat.checksum) { + syslog(LOG_ERR, "length doesn't match"); + SlowDeath(); + } + } + close(fd); + close(s2); + + if (rename(local_temp, local_file) < 0) { + syslog(LOG_ERR, "rename: %m"); + SlowDeath(); + } + + if (flock(fdlock, LOCK_UN)) { + syslog(LOG_ERR, "flock (unlock): %m"); + SlowDeath(); + } + close(fdlock); + sprintf(cmd, "%s load %s %s\n", kdb_util, local_file, local_db); + if (system(cmd) != 0) { + syslog(LOG_ERR, "couldn't load database"); + SlowDeath(); + } + +#ifdef STANDALONE + } +#endif + +} + +recv_auth(in, out, private, remote, local, ad) + int in, out; + int private; + struct sockaddr_in *remote, *local; + AUTH_DAT *ad; +{ + u_long length; + long kerror; + int n; + MSG_DAT msg_data; + Key_schedule session_sched; + + if (private) +#ifdef NOENCRYPTION + bzero((char *) session_sched, sizeof(session_sched)); +#else + if (key_sched(ad->session, session_sched)) { + syslog(LOG_ERR, "can't make key schedule"); + SlowDeath(); + } +#endif + + while (1) { + n = krb_net_read(in, &length, sizeof length); + if (n == 0) + break; + if (n < 0) { + syslog(LOG_ERR, "read: %m"); + SlowDeath(); + } + length = ntohl(length); + if (length > sizeof buf) { + syslog(LOG_ERR, "read length %d, bigger than buf %d", + length, sizeof buf); + SlowDeath(); + } + n = krb_net_read(in, buf, length); + if (n < 0) { + syslog(LOG_ERR, "kpropd: read: %m"); + SlowDeath(); + } + if (private) + kerror = krb_rd_priv(buf, n, session_sched, ad->session, + remote, local, &msg_data); + else + kerror = krb_rd_safe(buf, n, ad->session, + remote, local, &msg_data); + if (kerror != KSUCCESS) { + syslog(LOG_ERR, "%s: %s", + private ? "krb_rd_priv" : "krb_rd_safe", + krb_err_txt[kerror]); + SlowDeath(); + } + if (write(out, msg_data.app_data, msg_data.app_length) != + msg_data.app_length) { + syslog(LOG_ERR, "write: %m"); + SlowDeath(); + } + } +} + +recv_clear(in, out) + int in, out; +{ + int n; + + while (1) { + n = read(in, buf, sizeof buf); + if (n == 0) + break; + if (n < 0) { + syslog(LOG_ERR, "read: %m"); + SlowDeath(); + } + if (write(out, buf, n) != n) { + syslog(LOG_ERR, "write: %m"); + SlowDeath(); + } + } +} + +static void +SlowDeath() +{ +#ifdef STANDALONE + sleep(pause_int); +#endif + exit(1); +} + +#ifdef doesnt_work_yet +unsigned long +get_data_checksum(fd, key_sched) + int fd; + Key_schedule key_sched; +{ + unsigned long cksum = 0; + unsigned long cbc_cksum(); + int n; + char buf[BUFSIZ]; + char obuf[8]; + + while (n = read(fd, buf, sizeof buf)) { + if (n < 0) { + syslog(LOG_ERR, "read (in checksum test): %m"); + SlowDeath(); + } +#ifndef NOENCRYPTION + cksum += cbc_cksum(buf, obuf, n, key_sched, key_sched); +#endif + } + return cksum; +} +#endif |