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.4 (Berkeley) 05/17/89";
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 <kerberos/krb.h>
33 #include <kerberos/krb_db.h>
34 #include "register_proto.h"
35 
36 #define	SKEYFILE	"/kerberos/update.key%s"
37 #define	KBUFSIZ		(sizeof(struct keyfile_data))
38 #define	CRYPT		0x00
39 #define	CLEAR		0x01
40 
41 char	*progname;
42 struct	sockaddr_in	sin;
43 char	msgbuf[BUFSIZ];
44 
45 int	die();
46 
47 main(argc, argv)
48 char	**argv;
49 {
50 	int	kf;
51 	char	keyfile[MAXPATHLEN];
52 	static	Key_schedule	schedule;
53 	u_char	code;
54 	char	keybuf[KBUFSIZ];
55 	int	retval, sval;
56 	struct	keyfile_data	*kfile;
57 	static struct rlimit rl = { 0, 0 };
58 
59 	openlog("registerd", LOG_PID, LOG_AUTH);
60 
61 	progname = argv[0];
62 
63 	signal(SIGHUP, SIG_IGN);
64 	signal(SIGINT, SIG_IGN);
65 	signal(SIGTSTP, SIG_IGN);
66 	signal(SIGPIPE, die);
67 	if(setrlimit(RLIMIT_CORE, &rl) < 0) {
68 		syslog(LOG_ERR, "setrlimit: %m");
69 		exit(1);
70 	}
71 
72 
73 	/* figure out who we are talking to */
74 
75 	sval = sizeof(sin);
76 	if(getpeername(0, (struct sockaddr *) &sin, &sval) < 0) {
77 		syslog(LOG_ERR, "getpeername: %m");
78 		exit(1);
79 	}
80 
81 	/* get encryption key */
82 
83 	(void) sprintf(keyfile, SKEYFILE, inet_ntoa(sin.sin_addr));
84 	if((kf = open(keyfile, O_RDONLY)) < 0) {
85 		syslog(LOG_ERR, "error opening Kerberos update keyfile (%s): %m", keyfile);
86 		(void) sprintf(msgbuf, "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();
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)", code);
120 		}
121 
122 	} else {
123 		retval = KFAILURE;
124 		syslog(LOG_ERR, "couldn't read command code on Kerberos update");
125 	}
126 
127 	code = (u_char) retval;
128 	if(code != KSUCCESS) {
129 		(void) sprintf(msgbuf, "%s", krb_err_txt[code]);
130 		send_packet(msgbuf,CRYPT);
131 	} else {
132 		(void) sprintf(msgbuf, "Update complete.");
133 		send_packet(msgbuf, CRYPT);
134 	}
135 	cleanup();
136 	close(0);
137 	exit(0);
138 }
139 
140 #define	MAX_PRINCIPAL	10
141 static	Principal	principal_data[MAX_PRINCIPAL];
142 static	C_Block		key, master_key;
143 static Key_schedule	master_key_schedule;
144 int
145 do_append()
146 {
147 	Principal	default_princ;
148 	char		input_name[ANAME_SZ];
149 	char		input_instance[INST_SZ];
150 	int		j,n, more;
151 	long		mkeyversion;
152 
153 
154 
155 	/* get master key from MKEYFILE */
156 	if(kdb_get_master_key(0, master_key, master_key_schedule) != 0) {
157 		syslog(LOG_ERR, "couldn't get master key");
158 		return(KFAILURE);
159 	}
160 
161 	mkeyversion = kdb_verify_master_key(master_key, master_key_schedule, NULL);
162 	if(mkeyversion < 0) {
163 		syslog(LOG_ERR, "couldn't validate master key");
164 		return(KFAILURE);
165 	}
166 
167 	n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
168 		&default_princ, 1, &more);
169 
170 	if(n != 1) {
171 		syslog(LOG_ERR, "couldn't get default principal");
172 		return(KFAILURE);
173 	}
174 
175 	/*
176 	 * get principal name, instance, and password from network.
177 	 * convert password to key and store it
178 	 */
179 
180 	if(net_get_principal(input_name, input_instance, key) != 0) {
181 		return(KFAILURE);
182 	}
183 
184 
185 	j = kerb_get_principal(
186 		input_name,
187 		input_instance,
188 		principal_data,
189 		MAX_PRINCIPAL,
190 		&more
191 	);
192 
193 	if(j != 0) {
194 		/* already in database, no update */
195 		syslog(LOG_NOTICE, "attempt to add duplicate entry for principal %s.%s",
196 			input_name, input_instance);
197 		return(KDC_PR_N_UNIQUE);
198 	}
199 
200 	/*
201 	 * set up principal's name, instance
202 	 */
203 
204 	strcpy(principal_data[0].name, input_name);
205 	strcpy(principal_data[0].instance, input_instance);
206 	principal_data[0].old = NULL;
207 
208 
209 	/* and the expiration date and version #s */
210 
211 	principal_data[0].exp_date = default_princ.exp_date;
212 	strcpy(principal_data[0].exp_date_txt, default_princ.exp_date_txt);
213 	principal_data[0].max_life = default_princ.max_life;
214 	principal_data[0].attributes = default_princ.attributes;
215 	principal_data[0].kdc_key_ver = default_princ.kdc_key_ver;
216 
217 
218 	/* and the key */
219 
220 	kdb_encrypt_key(key, key, master_key, master_key_schedule,
221 			ENCRYPT);
222 	bcopy(key, &principal_data[0].key_low, 4);
223 	bcopy(((long *) key) + 1, &principal_data[0].key_high,4);
224 	bzero(key, sizeof(key));
225 
226 	principal_data[0].key_version = 1;	/* 1st entry */
227 	if(kerb_put_principal(&principal_data[0], 1)) {
228 		syslog(LOG_INFO, "Kerberos update failure: put_principal failed");
229 		return(KFAILURE);
230 	}
231 
232 	syslog(LOG_NOTICE, "Kerberos update: wrote new record for %s.%s from %s",
233 		principal_data[0].name,
234 		principal_data[0].instance,
235 		inet_ntoa(sin.sin_addr)
236 	);
237 
238 	return(KSUCCESS);
239 
240 }
241 
242 send_packet(msg,flag)
243 	char	*msg;
244 	int	flag;
245 {
246 	int	len = strlen(msg);
247 	msg[len++] = '\n';
248 	msg[len] = '\0';
249 	if (len > sizeof(msgbuf)) {
250 		syslog(LOG_ERR, "send_packet: invalid msg size");
251 		return;
252 	}
253 	if (flag == CRYPT) {
254 		if (des_write(0, msg, len) != len)
255 			syslog(LOG_ERR, "couldn't write reply message");
256 	} else if (flag == CLEAR) {
257 		if (write(0, msg, len) != len)
258 			syslog(LOG_ERR, "couldn't write reply message");
259 	} else
260 			syslog(LOG_ERR, "send_packet: invalid flag (%d)", flag);
261 
262 }
263 
264 net_get_principal(pname, iname, keyp)
265 	char	*pname, *iname;
266 	C_Block	*keyp;
267 {
268 	int	cc;
269 	static	char	password[255];
270 
271 	cc = des_read(0, pname, ANAME_SZ);
272 	if(cc != ANAME_SZ) {
273 		syslog(LOG_ERR, "couldn't get principal name");
274 		return(-1);
275 	}
276 
277 	cc = des_read(0, iname, INST_SZ);
278 	if(cc != INST_SZ) {
279 		syslog(LOG_ERR, "couldn't get instance name");
280 		return(-1);
281 	}
282 
283 	cc = des_read(0, password, 255);
284 	if(cc != 255) {
285 		syslog(LOG_ERR, "couldn't get password");
286 		bzero(password, 255);
287 		return(-1);
288 	}
289 
290 	string_to_key(password, *keyp);
291 	bzero(password, 255);
292 	return(0);
293 }
294 
295 cleanup()
296 {
297 	bzero(master_key, sizeof(master_key));
298 	bzero(key, sizeof(key));
299 	bzero(master_key_schedule, sizeof(master_key_schedule));
300 }
301 
302 die()
303 {
304 	syslog(LOG_ERR, "remote end died (SIGPIPE)");
305 	cleanup();
306 	exit(1);
307 }
308