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