145459Sbostic /*-
2*60969Sbostic  * Copyright (c) 1990, 1993
3*60969Sbostic  *	The Regents of the University of California.  All rights reserved.
438048Skfall  *
545459Sbostic  * %sccs.include.redist.c%
638048Skfall  */
738048Skfall 
838048Skfall #ifndef lint
9*60969Sbostic static char copyright[] =
10*60969Sbostic "@(#) Copyright (c) 1990, 1993\n\
11*60969Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1238048Skfall #endif /* not lint */
1338048Skfall 
1445459Sbostic #ifndef lint
15*60969Sbostic static char sccsid[] = "@(#)registerd.c	8.1 (Berkeley) 06/01/93";
1645459Sbostic #endif /* not lint */
1745459Sbostic 
1836346Skfall #include <sys/types.h>
1936346Skfall #include <sys/time.h>
2036350Skfall #include <sys/signal.h>
2136346Skfall #include <sys/resource.h>
2236346Skfall #include <sys/param.h>
2336346Skfall #include <sys/file.h>
2436346Skfall #include <netinet/in.h>
2536346Skfall #include <syslog.h>
2641769Skfall #include <kerberosIV/des.h>
2741769Skfall #include <kerberosIV/krb.h>
2841769Skfall #include <kerberosIV/krb_db.h>
2945459Sbostic #include <stdio.h>
3045459Sbostic #include "register_proto.h"
3138699Skfall #include "pathnames.h"
3236346Skfall 
3336346Skfall #define	KBUFSIZ		(sizeof(struct keyfile_data))
3445459Sbostic #define	RCRYPT		0x00
3537171Skfall #define	CLEAR		0x01
3636346Skfall 
3745459Sbostic char	*progname, msgbuf[BUFSIZ];
3836346Skfall 
main(argc,argv)3936346Skfall main(argc, argv)
4045459Sbostic 	int argc;
4145459Sbostic 	char **argv;
4236346Skfall {
4336346Skfall 	static	Key_schedule	schedule;
4445459Sbostic 	static struct rlimit rl = { 0, 0 };
4545459Sbostic 	struct	keyfile_data	*kfile;
4636346Skfall 	u_char	code;
4745459Sbostic 	int	kf, retval, sval;
4860032Storek 	struct	sockaddr_in	sin;
4945459Sbostic 	char	keyfile[MAXPATHLEN], keybuf[KBUFSIZ];
5045459Sbostic 	void die();
5136346Skfall 
5245459Sbostic 	progname = argv[0];		/* for the library routines */
5345459Sbostic 
5437171Skfall 	openlog("registerd", LOG_PID, LOG_AUTH);
5536346Skfall 
5645459Sbostic 	(void)signal(SIGHUP, SIG_IGN);
5745459Sbostic 	(void)signal(SIGINT, SIG_IGN);
5845459Sbostic 	(void)signal(SIGTSTP, SIG_IGN);
5945459Sbostic 	(void)signal(SIGPIPE, die);
6036346Skfall 
6138699Skfall 	if (setrlimit(RLIMIT_CORE, &rl) < 0) {
6236346Skfall 		syslog(LOG_ERR, "setrlimit: %m");
6336346Skfall 		exit(1);
6436346Skfall 	}
6536346Skfall 
6636346Skfall 
6736346Skfall 	/* figure out who we are talking to */
6836346Skfall 
6936346Skfall 	sval = sizeof(sin);
7038699Skfall 	if (getpeername(0, (struct sockaddr *) &sin, &sval) < 0) {
7136346Skfall 		syslog(LOG_ERR, "getpeername: %m");
7236346Skfall 		exit(1);
7336346Skfall 	}
7436346Skfall 
7536346Skfall 	/* get encryption key */
7636346Skfall 
7738703Skfall 	(void) sprintf(keyfile, "%s%s%s",
7838699Skfall 		SERVER_KEYDIR,
7938699Skfall 		CLIENT_KEYFILE,
8038699Skfall 		inet_ntoa(sin.sin_addr));
8138699Skfall 
8238699Skfall 	if ((kf = open(keyfile, O_RDONLY)) < 0) {
8338699Skfall 		syslog(LOG_ERR,
8438699Skfall 		    "error opening Kerberos update keyfile (%s): %m", keyfile);
8538699Skfall 		(void) sprintf(msgbuf,
8638699Skfall 		    "couldn't open session keyfile for your host");
8737171Skfall 		send_packet(msgbuf, CLEAR);
8836346Skfall 		exit(1);
8936346Skfall 	}
9036346Skfall 
9138699Skfall 	if (read(kf, keybuf, KBUFSIZ) != KBUFSIZ) {
9236346Skfall 		syslog(LOG_ERR, "wrong read size of Kerberos update keyfile");
9338048Skfall 		(void) sprintf(msgbuf,
9438048Skfall 			"couldn't read session key from your host's keyfile");
9537171Skfall 		send_packet(msgbuf, CLEAR);
9636346Skfall 		exit(1);
9736346Skfall 	}
9838048Skfall 	(void) sprintf(msgbuf, GOTKEY_MSG);
9937171Skfall 	send_packet(msgbuf, CLEAR);
10036346Skfall 	kfile = (struct keyfile_data *) keybuf;
10136346Skfall 	key_sched(kfile->kf_key, schedule);
10236346Skfall 	des_set_key(kfile->kf_key, schedule);
10336346Skfall 
10436346Skfall 	/* read the command code byte */
10536346Skfall 
10638699Skfall 	if (des_read(0, &code, 1) == 1) {
10736346Skfall 
10836346Skfall 		switch(code) {
10936346Skfall 		case	APPEND_DB:
11060032Storek 			retval = do_append(&sin);
11136346Skfall 			break;
11238048Skfall 		case	ABORT:
11338048Skfall 			cleanup();
11438048Skfall 			close(0);
11538048Skfall 			exit(0);
11636346Skfall 		default:
11736346Skfall 			retval = KFAILURE;
11838048Skfall 			syslog(LOG_NOTICE,
11938699Skfall 				"invalid command code on db update (0x%x)",
12038699Skfall 				code);
12136346Skfall 		}
12236346Skfall 
12336346Skfall 	} else {
12436346Skfall 		retval = KFAILURE;
12545459Sbostic 		syslog(LOG_ERR,
12645459Sbostic 		    "couldn't read command code on Kerberos update");
12736346Skfall 	}
12836346Skfall 
12937171Skfall 	code = (u_char) retval;
13038699Skfall 	if (code != KSUCCESS) {
13137171Skfall 		(void) sprintf(msgbuf, "%s", krb_err_txt[code]);
13245459Sbostic 		send_packet(msgbuf, RCRYPT);
13337171Skfall 	} else {
13437171Skfall 		(void) sprintf(msgbuf, "Update complete.");
13545459Sbostic 		send_packet(msgbuf, RCRYPT);
13637171Skfall 	}
13736346Skfall 	cleanup();
13836346Skfall 	close(0);
13936346Skfall 	exit(0);
14036346Skfall }
14136346Skfall 
14236346Skfall #define	MAX_PRINCIPAL	10
14336346Skfall static	Principal	principal_data[MAX_PRINCIPAL];
14436346Skfall static	C_Block		key, master_key;
14536346Skfall static Key_schedule	master_key_schedule;
14636346Skfall int
do_append(sinp)14760032Storek do_append(sinp)
14860032Storek 	struct sockaddr_in *sinp;
14936346Skfall {
15036346Skfall 	Principal	default_princ;
15136346Skfall 	char		input_name[ANAME_SZ];
15236346Skfall 	char		input_instance[INST_SZ];
15336346Skfall 	int		j,n, more;
15436346Skfall 	long		mkeyversion;
15536346Skfall 
15636346Skfall 
15736346Skfall 
15836346Skfall 	/* get master key from MKEYFILE */
15938699Skfall 	if (kdb_get_master_key(0, master_key, master_key_schedule) != 0) {
16036346Skfall 		syslog(LOG_ERR, "couldn't get master key");
16136346Skfall 		return(KFAILURE);
16236346Skfall 	}
16336346Skfall 
16436346Skfall 	mkeyversion = kdb_verify_master_key(master_key, master_key_schedule, NULL);
16538699Skfall 	if (mkeyversion < 0) {
16636346Skfall 		syslog(LOG_ERR, "couldn't validate master key");
16736346Skfall 		return(KFAILURE);
16836346Skfall 	}
16936346Skfall 
17036346Skfall 	n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
17136346Skfall 		&default_princ, 1, &more);
17236346Skfall 
17338699Skfall 	if (n != 1) {
17436346Skfall 		syslog(LOG_ERR, "couldn't get default principal");
17536346Skfall 		return(KFAILURE);
17636346Skfall 	}
17736346Skfall 
17836346Skfall 	/*
17936346Skfall 	 * get principal name, instance, and password from network.
18036346Skfall 	 * convert password to key and store it
18136346Skfall 	 */
18236346Skfall 
18338699Skfall 	if (net_get_principal(input_name, input_instance, key) != 0) {
18436346Skfall 		return(KFAILURE);
18536346Skfall 	}
18636346Skfall 
18736346Skfall 
18836346Skfall 	j = kerb_get_principal(
18936346Skfall 		input_name,
19036346Skfall 		input_instance,
19136346Skfall 		principal_data,
19236346Skfall 		MAX_PRINCIPAL,
19336346Skfall 		&more
19436346Skfall 	);
19536346Skfall 
19638699Skfall 	if (j != 0) {
19736346Skfall 		/* already in database, no update */
19838699Skfall 		syslog(LOG_NOTICE,
19938699Skfall 			"attempt to add duplicate entry for principal %s.%s",
20036346Skfall 			input_name, input_instance);
20136346Skfall 		return(KDC_PR_N_UNIQUE);
20236346Skfall 	}
20336346Skfall 
20436346Skfall 	/*
20536346Skfall 	 * set up principal's name, instance
20636346Skfall 	 */
20736346Skfall 
20836346Skfall 	strcpy(principal_data[0].name, input_name);
20936346Skfall 	strcpy(principal_data[0].instance, input_instance);
21036346Skfall 	principal_data[0].old = NULL;
21136346Skfall 
21236346Skfall 
21336346Skfall 	/* and the expiration date and version #s */
21436346Skfall 
21536346Skfall 	principal_data[0].exp_date = default_princ.exp_date;
21636346Skfall 	strcpy(principal_data[0].exp_date_txt, default_princ.exp_date_txt);
21736346Skfall 	principal_data[0].max_life = default_princ.max_life;
21836346Skfall 	principal_data[0].attributes = default_princ.attributes;
21936346Skfall 	principal_data[0].kdc_key_ver = default_princ.kdc_key_ver;
22036346Skfall 
22136346Skfall 
22236346Skfall 	/* and the key */
22336346Skfall 
22436346Skfall 	kdb_encrypt_key(key, key, master_key, master_key_schedule,
22536346Skfall 			ENCRYPT);
22636346Skfall 	bcopy(key, &principal_data[0].key_low, 4);
22736346Skfall 	bcopy(((long *) key) + 1, &principal_data[0].key_high,4);
22836346Skfall 	bzero(key, sizeof(key));
22936346Skfall 
23036346Skfall 	principal_data[0].key_version = 1;	/* 1st entry */
23138699Skfall 
23238699Skfall 	/* and write it to the database */
23338699Skfall 
23438699Skfall 	if (kerb_put_principal(&principal_data[0], 1)) {
23536346Skfall 		syslog(LOG_INFO, "Kerberos update failure: put_principal failed");
23636346Skfall 		return(KFAILURE);
23736346Skfall 	}
23836346Skfall 
23936346Skfall 	syslog(LOG_NOTICE, "Kerberos update: wrote new record for %s.%s from %s",
24036346Skfall 		principal_data[0].name,
24136346Skfall 		principal_data[0].instance,
24260032Storek 		inet_ntoa(sinp->sin_addr)
24336346Skfall 	);
24436346Skfall 
24536346Skfall 	return(KSUCCESS);
24636346Skfall 
24736346Skfall }
24836346Skfall 
send_packet(msg,flag)24937171Skfall send_packet(msg,flag)
25036346Skfall 	char	*msg;
25137171Skfall 	int	flag;
25236346Skfall {
25336346Skfall 	int	len = strlen(msg);
25436346Skfall 	msg[len++] = '\n';
25536346Skfall 	msg[len] = '\0';
25637171Skfall 	if (len > sizeof(msgbuf)) {
25737171Skfall 		syslog(LOG_ERR, "send_packet: invalid msg size");
25837171Skfall 		return;
25937171Skfall 	}
26045459Sbostic 	if (flag == RCRYPT) {
26137171Skfall 		if (des_write(0, msg, len) != len)
26237171Skfall 			syslog(LOG_ERR, "couldn't write reply message");
26337171Skfall 	} else if (flag == CLEAR) {
26437171Skfall 		if (write(0, msg, len) != len)
26537171Skfall 			syslog(LOG_ERR, "couldn't write reply message");
26637171Skfall 	} else
26737171Skfall 			syslog(LOG_ERR, "send_packet: invalid flag (%d)", flag);
26837171Skfall 
26936346Skfall }
27036346Skfall 
net_get_principal(pname,iname,keyp)27136346Skfall net_get_principal(pname, iname, keyp)
27236346Skfall 	char	*pname, *iname;
27336346Skfall 	C_Block	*keyp;
27436346Skfall {
27536346Skfall 	int	cc;
27636346Skfall 	static	char	password[255];
27736346Skfall 
27836346Skfall 	cc = des_read(0, pname, ANAME_SZ);
27938699Skfall 	if (cc != ANAME_SZ) {
28036346Skfall 		syslog(LOG_ERR, "couldn't get principal name");
28136346Skfall 		return(-1);
28236346Skfall 	}
28336346Skfall 
28436346Skfall 	cc = des_read(0, iname, INST_SZ);
28538699Skfall 	if (cc != INST_SZ) {
28636346Skfall 		syslog(LOG_ERR, "couldn't get instance name");
28736346Skfall 		return(-1);
28836346Skfall 	}
28936346Skfall 
29036346Skfall 	cc = des_read(0, password, 255);
29138699Skfall 	if (cc != 255) {
29236346Skfall 		syslog(LOG_ERR, "couldn't get password");
29336346Skfall 		bzero(password, 255);
29436346Skfall 		return(-1);
29536346Skfall 	}
29636346Skfall 
29736346Skfall 	string_to_key(password, *keyp);
29836346Skfall 	bzero(password, 255);
29936346Skfall 	return(0);
30036346Skfall }
30136346Skfall 
cleanup()30236346Skfall cleanup()
30336346Skfall {
30436346Skfall 	bzero(master_key, sizeof(master_key));
30536346Skfall 	bzero(key, sizeof(key));
30636346Skfall 	bzero(master_key_schedule, sizeof(master_key_schedule));
30736346Skfall }
30836350Skfall 
30945459Sbostic void
die()31036350Skfall die()
31136350Skfall {
31236350Skfall 	syslog(LOG_ERR, "remote end died (SIGPIPE)");
31336350Skfall 	cleanup();
31436350Skfall 	exit(1);
31536350Skfall }
316