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