1 /*-
2  * Copyright (c) 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1990, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)registerd.c	8.1 (Berkeley) 06/01/93";
16 #endif /* not lint */
17 
18 #include <sys/types.h>
19 #include <sys/time.h>
20 #include <sys/signal.h>
21 #include <sys/resource.h>
22 #include <sys/param.h>
23 #include <sys/file.h>
24 #include <netinet/in.h>
25 #include <syslog.h>
26 #include <kerberosIV/des.h>
27 #include <kerberosIV/krb.h>
28 #include <kerberosIV/krb_db.h>
29 #include <stdio.h>
30 #include "register_proto.h"
31 #include "pathnames.h"
32 
33 #define	KBUFSIZ		(sizeof(struct keyfile_data))
34 #define	RCRYPT		0x00
35 #define	CLEAR		0x01
36 
37 char	*progname, msgbuf[BUFSIZ];
38 
main(argc,argv)39 main(argc, argv)
40 	int argc;
41 	char **argv;
42 {
43 	static	Key_schedule	schedule;
44 	static struct rlimit rl = { 0, 0 };
45 	struct	keyfile_data	*kfile;
46 	u_char	code;
47 	int	kf, retval, sval;
48 	struct	sockaddr_in	sin;
49 	char	keyfile[MAXPATHLEN], keybuf[KBUFSIZ];
50 	void die();
51 
52 	progname = argv[0];		/* for the library routines */
53 
54 	openlog("registerd", LOG_PID, LOG_AUTH);
55 
56 	(void)signal(SIGHUP, SIG_IGN);
57 	(void)signal(SIGINT, SIG_IGN);
58 	(void)signal(SIGTSTP, SIG_IGN);
59 	(void)signal(SIGPIPE, die);
60 
61 	if (setrlimit(RLIMIT_CORE, &rl) < 0) {
62 		syslog(LOG_ERR, "setrlimit: %m");
63 		exit(1);
64 	}
65 
66 
67 	/* figure out who we are talking to */
68 
69 	sval = sizeof(sin);
70 	if (getpeername(0, (struct sockaddr *) &sin, &sval) < 0) {
71 		syslog(LOG_ERR, "getpeername: %m");
72 		exit(1);
73 	}
74 
75 	/* get encryption key */
76 
77 	(void) sprintf(keyfile, "%s%s%s",
78 		SERVER_KEYDIR,
79 		CLIENT_KEYFILE,
80 		inet_ntoa(sin.sin_addr));
81 
82 	if ((kf = open(keyfile, O_RDONLY)) < 0) {
83 		syslog(LOG_ERR,
84 		    "error opening Kerberos update keyfile (%s): %m", keyfile);
85 		(void) sprintf(msgbuf,
86 		    "couldn't open session keyfile for your host");
87 		send_packet(msgbuf, CLEAR);
88 		exit(1);
89 	}
90 
91 	if (read(kf, keybuf, KBUFSIZ) != KBUFSIZ) {
92 		syslog(LOG_ERR, "wrong read size of Kerberos update keyfile");
93 		(void) sprintf(msgbuf,
94 			"couldn't read session key from your host's keyfile");
95 		send_packet(msgbuf, CLEAR);
96 		exit(1);
97 	}
98 	(void) sprintf(msgbuf, GOTKEY_MSG);
99 	send_packet(msgbuf, CLEAR);
100 	kfile = (struct keyfile_data *) keybuf;
101 	key_sched(kfile->kf_key, schedule);
102 	des_set_key(kfile->kf_key, schedule);
103 
104 	/* read the command code byte */
105 
106 	if (des_read(0, &code, 1) == 1) {
107 
108 		switch(code) {
109 		case	APPEND_DB:
110 			retval = do_append(&sin);
111 			break;
112 		case	ABORT:
113 			cleanup();
114 			close(0);
115 			exit(0);
116 		default:
117 			retval = KFAILURE;
118 			syslog(LOG_NOTICE,
119 				"invalid command code on db update (0x%x)",
120 				code);
121 		}
122 
123 	} else {
124 		retval = KFAILURE;
125 		syslog(LOG_ERR,
126 		    "couldn't read command code on Kerberos update");
127 	}
128 
129 	code = (u_char) retval;
130 	if (code != KSUCCESS) {
131 		(void) sprintf(msgbuf, "%s", krb_err_txt[code]);
132 		send_packet(msgbuf, RCRYPT);
133 	} else {
134 		(void) sprintf(msgbuf, "Update complete.");
135 		send_packet(msgbuf, RCRYPT);
136 	}
137 	cleanup();
138 	close(0);
139 	exit(0);
140 }
141 
142 #define	MAX_PRINCIPAL	10
143 static	Principal	principal_data[MAX_PRINCIPAL];
144 static	C_Block		key, master_key;
145 static Key_schedule	master_key_schedule;
146 int
do_append(sinp)147 do_append(sinp)
148 	struct sockaddr_in *sinp;
149 {
150 	Principal	default_princ;
151 	char		input_name[ANAME_SZ];
152 	char		input_instance[INST_SZ];
153 	int		j,n, more;
154 	long		mkeyversion;
155 
156 
157 
158 	/* get master key from MKEYFILE */
159 	if (kdb_get_master_key(0, master_key, master_key_schedule) != 0) {
160 		syslog(LOG_ERR, "couldn't get master key");
161 		return(KFAILURE);
162 	}
163 
164 	mkeyversion = kdb_verify_master_key(master_key, master_key_schedule, NULL);
165 	if (mkeyversion < 0) {
166 		syslog(LOG_ERR, "couldn't validate master key");
167 		return(KFAILURE);
168 	}
169 
170 	n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
171 		&default_princ, 1, &more);
172 
173 	if (n != 1) {
174 		syslog(LOG_ERR, "couldn't get default principal");
175 		return(KFAILURE);
176 	}
177 
178 	/*
179 	 * get principal name, instance, and password from network.
180 	 * convert password to key and store it
181 	 */
182 
183 	if (net_get_principal(input_name, input_instance, key) != 0) {
184 		return(KFAILURE);
185 	}
186 
187 
188 	j = kerb_get_principal(
189 		input_name,
190 		input_instance,
191 		principal_data,
192 		MAX_PRINCIPAL,
193 		&more
194 	);
195 
196 	if (j != 0) {
197 		/* already in database, no update */
198 		syslog(LOG_NOTICE,
199 			"attempt to add duplicate entry for principal %s.%s",
200 			input_name, input_instance);
201 		return(KDC_PR_N_UNIQUE);
202 	}
203 
204 	/*
205 	 * set up principal's name, instance
206 	 */
207 
208 	strcpy(principal_data[0].name, input_name);
209 	strcpy(principal_data[0].instance, input_instance);
210 	principal_data[0].old = NULL;
211 
212 
213 	/* and the expiration date and version #s */
214 
215 	principal_data[0].exp_date = default_princ.exp_date;
216 	strcpy(principal_data[0].exp_date_txt, default_princ.exp_date_txt);
217 	principal_data[0].max_life = default_princ.max_life;
218 	principal_data[0].attributes = default_princ.attributes;
219 	principal_data[0].kdc_key_ver = default_princ.kdc_key_ver;
220 
221 
222 	/* and the key */
223 
224 	kdb_encrypt_key(key, key, master_key, master_key_schedule,
225 			ENCRYPT);
226 	bcopy(key, &principal_data[0].key_low, 4);
227 	bcopy(((long *) key) + 1, &principal_data[0].key_high,4);
228 	bzero(key, sizeof(key));
229 
230 	principal_data[0].key_version = 1;	/* 1st entry */
231 
232 	/* and write it to the database */
233 
234 	if (kerb_put_principal(&principal_data[0], 1)) {
235 		syslog(LOG_INFO, "Kerberos update failure: put_principal failed");
236 		return(KFAILURE);
237 	}
238 
239 	syslog(LOG_NOTICE, "Kerberos update: wrote new record for %s.%s from %s",
240 		principal_data[0].name,
241 		principal_data[0].instance,
242 		inet_ntoa(sinp->sin_addr)
243 	);
244 
245 	return(KSUCCESS);
246 
247 }
248 
send_packet(msg,flag)249 send_packet(msg,flag)
250 	char	*msg;
251 	int	flag;
252 {
253 	int	len = strlen(msg);
254 	msg[len++] = '\n';
255 	msg[len] = '\0';
256 	if (len > sizeof(msgbuf)) {
257 		syslog(LOG_ERR, "send_packet: invalid msg size");
258 		return;
259 	}
260 	if (flag == RCRYPT) {
261 		if (des_write(0, msg, len) != len)
262 			syslog(LOG_ERR, "couldn't write reply message");
263 	} else if (flag == CLEAR) {
264 		if (write(0, msg, len) != len)
265 			syslog(LOG_ERR, "couldn't write reply message");
266 	} else
267 			syslog(LOG_ERR, "send_packet: invalid flag (%d)", flag);
268 
269 }
270 
net_get_principal(pname,iname,keyp)271 net_get_principal(pname, iname, keyp)
272 	char	*pname, *iname;
273 	C_Block	*keyp;
274 {
275 	int	cc;
276 	static	char	password[255];
277 
278 	cc = des_read(0, pname, ANAME_SZ);
279 	if (cc != ANAME_SZ) {
280 		syslog(LOG_ERR, "couldn't get principal name");
281 		return(-1);
282 	}
283 
284 	cc = des_read(0, iname, INST_SZ);
285 	if (cc != INST_SZ) {
286 		syslog(LOG_ERR, "couldn't get instance name");
287 		return(-1);
288 	}
289 
290 	cc = des_read(0, password, 255);
291 	if (cc != 255) {
292 		syslog(LOG_ERR, "couldn't get password");
293 		bzero(password, 255);
294 		return(-1);
295 	}
296 
297 	string_to_key(password, *keyp);
298 	bzero(password, 255);
299 	return(0);
300 }
301 
cleanup()302 cleanup()
303 {
304 	bzero(master_key, sizeof(master_key));
305 	bzero(key, sizeof(key));
306 	bzero(master_key_schedule, sizeof(master_key_schedule));
307 }
308 
309 void
die()310 die()
311 {
312 	syslog(LOG_ERR, "remote end died (SIGPIPE)");
313 	cleanup();
314 	exit(1);
315 }
316