1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)registerd.c	5.1 (Berkeley) 11/01/90";
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 struct	sockaddr_in	sin;
38 char	*progname, msgbuf[BUFSIZ];
39 
40 main(argc, argv)
41 	int argc;
42 	char **argv;
43 {
44 	static	Key_schedule	schedule;
45 	static struct rlimit rl = { 0, 0 };
46 	struct	keyfile_data	*kfile;
47 	u_char	code;
48 	int	kf, retval, sval;
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();
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
147 do_append()
148 {
149 	Principal	default_princ;
150 	char		input_name[ANAME_SZ];
151 	char		input_instance[INST_SZ];
152 	int		j,n, more;
153 	long		mkeyversion;
154 
155 
156 
157 	/* get master key from MKEYFILE */
158 	if (kdb_get_master_key(0, master_key, master_key_schedule) != 0) {
159 		syslog(LOG_ERR, "couldn't get master key");
160 		return(KFAILURE);
161 	}
162 
163 	mkeyversion = kdb_verify_master_key(master_key, master_key_schedule, NULL);
164 	if (mkeyversion < 0) {
165 		syslog(LOG_ERR, "couldn't validate master key");
166 		return(KFAILURE);
167 	}
168 
169 	n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
170 		&default_princ, 1, &more);
171 
172 	if (n != 1) {
173 		syslog(LOG_ERR, "couldn't get default principal");
174 		return(KFAILURE);
175 	}
176 
177 	/*
178 	 * get principal name, instance, and password from network.
179 	 * convert password to key and store it
180 	 */
181 
182 	if (net_get_principal(input_name, input_instance, key) != 0) {
183 		return(KFAILURE);
184 	}
185 
186 
187 	j = kerb_get_principal(
188 		input_name,
189 		input_instance,
190 		principal_data,
191 		MAX_PRINCIPAL,
192 		&more
193 	);
194 
195 	if (j != 0) {
196 		/* already in database, no update */
197 		syslog(LOG_NOTICE,
198 			"attempt to add duplicate entry for principal %s.%s",
199 			input_name, input_instance);
200 		return(KDC_PR_N_UNIQUE);
201 	}
202 
203 	/*
204 	 * set up principal's name, instance
205 	 */
206 
207 	strcpy(principal_data[0].name, input_name);
208 	strcpy(principal_data[0].instance, input_instance);
209 	principal_data[0].old = NULL;
210 
211 
212 	/* and the expiration date and version #s */
213 
214 	principal_data[0].exp_date = default_princ.exp_date;
215 	strcpy(principal_data[0].exp_date_txt, default_princ.exp_date_txt);
216 	principal_data[0].max_life = default_princ.max_life;
217 	principal_data[0].attributes = default_princ.attributes;
218 	principal_data[0].kdc_key_ver = default_princ.kdc_key_ver;
219 
220 
221 	/* and the key */
222 
223 	kdb_encrypt_key(key, key, master_key, master_key_schedule,
224 			ENCRYPT);
225 	bcopy(key, &principal_data[0].key_low, 4);
226 	bcopy(((long *) key) + 1, &principal_data[0].key_high,4);
227 	bzero(key, sizeof(key));
228 
229 	principal_data[0].key_version = 1;	/* 1st entry */
230 
231 	/* and write it to the database */
232 
233 	if (kerb_put_principal(&principal_data[0], 1)) {
234 		syslog(LOG_INFO, "Kerberos update failure: put_principal failed");
235 		return(KFAILURE);
236 	}
237 
238 	syslog(LOG_NOTICE, "Kerberos update: wrote new record for %s.%s from %s",
239 		principal_data[0].name,
240 		principal_data[0].instance,
241 		inet_ntoa(sin.sin_addr)
242 	);
243 
244 	return(KSUCCESS);
245 
246 }
247 
248 send_packet(msg,flag)
249 	char	*msg;
250 	int	flag;
251 {
252 	int	len = strlen(msg);
253 	msg[len++] = '\n';
254 	msg[len] = '\0';
255 	if (len > sizeof(msgbuf)) {
256 		syslog(LOG_ERR, "send_packet: invalid msg size");
257 		return;
258 	}
259 	if (flag == RCRYPT) {
260 		if (des_write(0, msg, len) != len)
261 			syslog(LOG_ERR, "couldn't write reply message");
262 	} else if (flag == CLEAR) {
263 		if (write(0, msg, len) != len)
264 			syslog(LOG_ERR, "couldn't write reply message");
265 	} else
266 			syslog(LOG_ERR, "send_packet: invalid flag (%d)", flag);
267 
268 }
269 
270 net_get_principal(pname, iname, keyp)
271 	char	*pname, *iname;
272 	C_Block	*keyp;
273 {
274 	int	cc;
275 	static	char	password[255];
276 
277 	cc = des_read(0, pname, ANAME_SZ);
278 	if (cc != ANAME_SZ) {
279 		syslog(LOG_ERR, "couldn't get principal name");
280 		return(-1);
281 	}
282 
283 	cc = des_read(0, iname, INST_SZ);
284 	if (cc != INST_SZ) {
285 		syslog(LOG_ERR, "couldn't get instance name");
286 		return(-1);
287 	}
288 
289 	cc = des_read(0, password, 255);
290 	if (cc != 255) {
291 		syslog(LOG_ERR, "couldn't get password");
292 		bzero(password, 255);
293 		return(-1);
294 	}
295 
296 	string_to_key(password, *keyp);
297 	bzero(password, 255);
298 	return(0);
299 }
300 
301 cleanup()
302 {
303 	bzero(master_key, sizeof(master_key));
304 	bzero(key, sizeof(key));
305 	bzero(master_key_schedule, sizeof(master_key_schedule));
306 }
307 
308 void
309 die()
310 {
311 	syslog(LOG_ERR, "remote end died (SIGPIPE)");
312 	cleanup();
313 	exit(1);
314 }
315