xref: /freebsd/usr.sbin/keyserv/keyserv.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
1 /*
2  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3  * unrestricted use provided that this legend is included on all tape
4  * media and as a part of the software program in whole or part.  Users
5  * may copy or modify Sun RPC without charge, but are not authorized
6  * to license or distribute it to anyone else except as part of a product or
7  * program developed by the user.
8  *
9  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12  *
13  * Sun RPC is provided with no support and without any obligation on the
14  * part of Sun Microsystems, Inc. to assist in its use, correction,
15  * modification or enhancement.
16  *
17  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19  * OR ANY PART THEREOF.
20  *
21  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22  * or profits or other special, indirect and consequential damages, even if
23  * Sun has been advised of the possibility of such damages.
24  *
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  */
29 
30 #ifndef lint
31 #if 0
32 static char sccsid[] = "@(#)keyserv.c	1.15	94/04/25 SMI";
33 #endif
34 static const char rcsid[] =
35   "$FreeBSD$";
36 #endif /* not lint */
37 
38 /*
39  * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
40  */
41 
42 /*
43  * Keyserver
44  * Store secret keys per uid. Do public key encryption and decryption
45  * operations. Generate "random" keys.
46  * Do not talk to anything but a local root
47  * process on the local transport only
48  */
49 
50 #include <err.h>
51 #include <pwd.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <unistd.h>
56 #include <sys/stat.h>
57 #include <sys/types.h>
58 #include <rpc/rpc.h>
59 #include <rpc/pmap_clnt.h>
60 #include <sys/param.h>
61 #include <sys/file.h>
62 #include <rpc/des_crypt.h>
63 #include <rpc/des.h>
64 #include <rpc/key_prot.h>
65 #include <rpcsvc/crypt.h>
66 #include "keyserv.h"
67 
68 #ifndef NGROUPS
69 #define	NGROUPS 16
70 #endif
71 
72 #ifndef KEYSERVSOCK
73 #define KEYSERVSOCK "/var/run/keyservsock"
74 #endif
75 
76 static void randomize __P(( des_block * ));
77 static void usage __P(( void ));
78 static int getrootkey __P(( des_block *, int ));
79 static int root_auth __P(( SVCXPRT *, struct svc_req * ));
80 
81 #ifdef DEBUG
82 static int debugging = 1;
83 #else
84 static int debugging = 0;
85 #endif
86 
87 static void keyprogram();
88 static des_block masterkey;
89 char *getenv();
90 static char ROOTKEY[] = "/etc/.rootkey";
91 
92 /*
93  * Hack to allow the keyserver to use AUTH_DES (for authenticated
94  * NIS+ calls, for example).  The only functions that get called
95  * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
96  *
97  * The approach is to have the keyserver fill in pointers to local
98  * implementations of these functions, and to call those in key_call().
99  */
100 
101 extern cryptkeyres *(*__key_encryptsession_pk_LOCAL)();
102 extern cryptkeyres *(*__key_decryptsession_pk_LOCAL)();
103 extern des_block *(*__key_gendes_LOCAL)();
104 extern int (*__des_crypt_LOCAL)();
105 
106 cryptkeyres *key_encrypt_pk_2_svc_prog __P(( uid_t, cryptkeyarg2 * ));
107 cryptkeyres *key_decrypt_pk_2_svc_prog __P(( uid_t, cryptkeyarg2 * ));
108 des_block *key_gen_1_svc_prog __P(( void *, struct svc_req * ));
109 
110 int
111 main(argc, argv)
112 	int argc;
113 	char *argv[];
114 {
115 	int nflag = 0;
116 	int c;
117 	register SVCXPRT *transp;
118 	int sock = RPC_ANYSOCK;
119 	int warn = 0;
120 	char *path = NULL;
121 
122 	__key_encryptsession_pk_LOCAL = &key_encrypt_pk_2_svc_prog;
123 	__key_decryptsession_pk_LOCAL = &key_decrypt_pk_2_svc_prog;
124 	__key_gendes_LOCAL = &key_gen_1_svc_prog;
125 
126 	while ((c = getopt(argc, argv, "ndDvp:")) != -1)
127 		switch (c) {
128 		case 'n':
129 			nflag++;
130 			break;
131 		case 'd':
132 			pk_nodefaultkeys();
133 			break;
134 		case 'D':
135 			debugging = 1;
136 			break;
137 		case 'v':
138 			warn = 1;
139 			break;
140 		case 'p':
141 			path = optarg;
142 			break;
143 		default:
144 			usage();
145 		}
146 
147 	load_des(warn, path);
148 	__des_crypt_LOCAL = _my_crypt;
149 	if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1)
150 		errx(1, "failed to register AUTH_DES authenticator");
151 
152 	if (optind != argc) {
153 		usage();
154 	}
155 
156 	/*
157 	 * Initialize
158 	 */
159 	(void) umask(066);	/* paranoia */
160 	if (geteuid() != 0)
161 		errx(1, "keyserv must be run as root");
162 	setmodulus(HEXMODULUS);
163 	getrootkey(&masterkey, nflag);
164 
165 
166 	/* Create services. */
167 
168 	(void) pmap_unset(KEY_PROG, KEY_VERS);
169 	(void) pmap_unset(KEY_PROG, KEY_VERS2);
170 	unlink(KEYSERVSOCK);
171 
172 	transp = svcudp_create(RPC_ANYSOCK);
173 	if (transp == NULL)
174 		errx(1, "cannot create udp service");
175 	if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, IPPROTO_UDP))
176 		errx(1, "unable to register (KEY_PROG, KEY_VERS, udp)");
177 	if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, IPPROTO_UDP))
178 		errx(1, "unable to register (KEY_PROG, KEY_VERS2, udp)");
179 
180 	transp = svctcp_create(RPC_ANYSOCK, 0, 0);
181 	if (transp == NULL)
182 		errx(1, "cannot create tcp service");
183 	if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, IPPROTO_TCP))
184 		errx(1, "unable to register (KEY_PROG, KEY_VERS, tcp)");
185 	if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, IPPROTO_TCP))
186 		errx(1, "unable to register (KEY_PROG, KEY_VERS2, tcp)");
187 
188 	transp = svcunix_create(sock, 0, 0, KEYSERVSOCK);
189 	chmod(KEYSERVSOCK, 0666);
190 	if (transp == NULL)
191 		errx(1, "cannot create AF_UNIX service");
192 	if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, 0))
193 		errx(1, "unable to register (KEY_PROG, KEY_VERS, unix)");
194 	if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, 0))
195 		errx(1, "unable to register (KEY_PROG, KEY_VERS2, unix)");
196 	if (!svc_register(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, 0))
197 		errx(1, "unable to register (CRYPT_PROG, CRYPT_VERS, unix)");
198 
199 	if (!debugging) {
200 		daemon(0,0);
201 	}
202 
203 	signal(SIGPIPE, SIG_IGN);
204 
205 	svc_run();
206 	abort();
207 	/* NOTREACHED */
208 }
209 
210 /*
211  * In the event that we don't get a root password, we try to
212  * randomize the master key the best we can
213  */
214 static void
215 randomize(master)
216 	des_block *master;
217 {
218 	int i;
219 	int seed;
220 	struct timeval tv;
221 	int shift;
222 
223 	seed = 0;
224 	for (i = 0; i < 1024; i++) {
225 		(void) gettimeofday(&tv, (struct timezone *) NULL);
226 		shift = i % 8 * sizeof (int);
227 		seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift));
228 	}
229 #ifdef KEYSERV_RANDOM
230 	srandom(seed);
231 	master->key.low = random();
232 	master->key.high = random();
233 	srandom(seed);
234 #else
235 	/* use stupid dangerous bad rand() */
236 	srand(seed);
237 	master->key.low = rand();
238 	master->key.high = rand();
239 	srand(seed);
240 #endif
241 }
242 
243 /*
244  * Try to get root's secret key, by prompting if terminal is a tty, else trying
245  * from standard input.
246  * Returns 1 on success.
247  */
248 static int
249 getrootkey(master, prompt)
250 	des_block *master;
251 	int prompt;
252 {
253 	char *passwd;
254 	char name[MAXNETNAMELEN + 1];
255 	char secret[HEXKEYBYTES];
256 	key_netstarg netstore;
257 	int fd;
258 
259 	if (!prompt) {
260 		/*
261 		 * Read secret key out of ROOTKEY
262 		 */
263 		fd = open(ROOTKEY, O_RDONLY, 0);
264 		if (fd < 0) {
265 			randomize(master);
266 			return (0);
267 		}
268 		if (read(fd, secret, HEXKEYBYTES) < HEXKEYBYTES) {
269 			warnx("the key read from %s was too short", ROOTKEY);
270 			(void) close(fd);
271 			return (0);
272 		}
273 		(void) close(fd);
274 		if (!getnetname(name)) {
275 		    warnx(
276 	"failed to generate host's netname when establishing root's key");
277 		    return (0);
278 		}
279 		memcpy(netstore.st_priv_key, secret, HEXKEYBYTES);
280 		memset(netstore.st_pub_key, 0, HEXKEYBYTES);
281 		netstore.st_netname = name;
282 		if (pk_netput(0, &netstore) != KEY_SUCCESS) {
283 		    warnx("could not set root's key and netname");
284 		    return (0);
285 		}
286 		return (1);
287 	}
288 	/*
289 	 * Decrypt yellow pages publickey entry to get secret key
290 	 */
291 	passwd = getpass("root password:");
292 	passwd2des(passwd, (char *)master);
293 	getnetname(name);
294 	if (!getsecretkey(name, secret, passwd)) {
295 		warnx("can't find %s's secret key", name);
296 		return (0);
297 	}
298 	if (secret[0] == 0) {
299 		warnx("password does not decrypt secret key for %s", name);
300 		return (0);
301 	}
302 	(void) pk_setkey(0, secret);
303 	/*
304 	 * Store it for future use in $ROOTKEY, if possible
305 	 */
306 	fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0);
307 	if (fd > 0) {
308 		char newline = '\n';
309 
310 		write(fd, secret, strlen(secret));
311 		write(fd, &newline, sizeof (newline));
312 		close(fd);
313 	}
314 	return (1);
315 }
316 
317 /*
318  * Procedures to implement RPC service
319  */
320 char *
321 strstatus(status)
322 	keystatus status;
323 {
324 	switch (status) {
325 	case KEY_SUCCESS:
326 		return ("KEY_SUCCESS");
327 	case KEY_NOSECRET:
328 		return ("KEY_NOSECRET");
329 	case KEY_UNKNOWN:
330 		return ("KEY_UNKNOWN");
331 	case KEY_SYSTEMERR:
332 		return ("KEY_SYSTEMERR");
333 	default:
334 		return ("(bad result code)");
335 	}
336 }
337 
338 keystatus *
339 key_set_1_svc_prog(uid, key)
340 	uid_t uid;
341 	keybuf key;
342 {
343 	static keystatus status;
344 
345 	if (debugging) {
346 		(void) fprintf(stderr, "set(%ld, %.*s) = ", uid,
347 				(int) sizeof (keybuf), key);
348 	}
349 	status = pk_setkey(uid, key);
350 	if (debugging) {
351 		(void) fprintf(stderr, "%s\n", strstatus(status));
352 		(void) fflush(stderr);
353 	}
354 	return (&status);
355 }
356 
357 cryptkeyres *
358 key_encrypt_pk_2_svc_prog(uid, arg)
359 	uid_t uid;
360 	cryptkeyarg2 *arg;
361 {
362 	static cryptkeyres res;
363 
364 	if (debugging) {
365 		(void) fprintf(stderr, "encrypt(%ld, %s, %08x%08x) = ", uid,
366 				arg->remotename, arg->deskey.key.high,
367 				arg->deskey.key.low);
368 	}
369 	res.cryptkeyres_u.deskey = arg->deskey;
370 	res.status = pk_encrypt(uid, arg->remotename, &(arg->remotekey),
371 				&res.cryptkeyres_u.deskey);
372 	if (debugging) {
373 		if (res.status == KEY_SUCCESS) {
374 			(void) fprintf(stderr, "%08x%08x\n",
375 					res.cryptkeyres_u.deskey.key.high,
376 					res.cryptkeyres_u.deskey.key.low);
377 		} else {
378 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
379 		}
380 		(void) fflush(stderr);
381 	}
382 	return (&res);
383 }
384 
385 cryptkeyres *
386 key_decrypt_pk_2_svc_prog(uid, arg)
387 	uid_t uid;
388 	cryptkeyarg2 *arg;
389 {
390 	static cryptkeyres res;
391 
392 	if (debugging) {
393 		(void) fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid,
394 				arg->remotename, arg->deskey.key.high,
395 				arg->deskey.key.low);
396 	}
397 	res.cryptkeyres_u.deskey = arg->deskey;
398 	res.status = pk_decrypt(uid, arg->remotename, &(arg->remotekey),
399 				&res.cryptkeyres_u.deskey);
400 	if (debugging) {
401 		if (res.status == KEY_SUCCESS) {
402 			(void) fprintf(stderr, "%08x%08x\n",
403 					res.cryptkeyres_u.deskey.key.high,
404 					res.cryptkeyres_u.deskey.key.low);
405 		} else {
406 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
407 		}
408 		(void) fflush(stderr);
409 	}
410 	return (&res);
411 }
412 
413 keystatus *
414 key_net_put_2_svc_prog(uid, arg)
415 	uid_t uid;
416 	key_netstarg *arg;
417 {
418 	static keystatus status;
419 
420 	if (debugging) {
421 		(void) fprintf(stderr, "net_put(%s, %.*s, %.*s) = ",
422 			arg->st_netname, (int)sizeof (arg->st_pub_key),
423 			arg->st_pub_key, (int)sizeof (arg->st_priv_key),
424 			arg->st_priv_key);
425 	};
426 
427 	status = pk_netput(uid, arg);
428 
429 	if (debugging) {
430 		(void) fprintf(stderr, "%s\n", strstatus(status));
431 		(void) fflush(stderr);
432 	}
433 
434 	return (&status);
435 }
436 
437 key_netstres *
438 key_net_get_2_svc_prog(uid, arg)
439 	uid_t uid;
440 	void *arg;
441 {
442 	static key_netstres keynetname;
443 
444 	if (debugging)
445 		(void) fprintf(stderr, "net_get(%ld) = ", uid);
446 
447 	keynetname.status = pk_netget(uid, &keynetname.key_netstres_u.knet);
448 	if (debugging) {
449 		if (keynetname.status == KEY_SUCCESS) {
450 			fprintf(stderr, "<%s, %.*s, %.*s>\n",
451 			keynetname.key_netstres_u.knet.st_netname,
452 			(int)sizeof (keynetname.key_netstres_u.knet.st_pub_key),
453 			keynetname.key_netstres_u.knet.st_pub_key,
454 			(int)sizeof (keynetname.key_netstres_u.knet.st_priv_key),
455 			keynetname.key_netstres_u.knet.st_priv_key);
456 		} else {
457 			(void) fprintf(stderr, "NOT FOUND\n");
458 		}
459 		(void) fflush(stderr);
460 	}
461 
462 	return (&keynetname);
463 
464 }
465 
466 cryptkeyres *
467 key_get_conv_2_svc_prog(uid, arg)
468 	uid_t uid;
469 	keybuf arg;
470 {
471 	static cryptkeyres  res;
472 
473 	if (debugging)
474 		(void) fprintf(stderr, "get_conv(%ld, %.*s) = ", uid,
475 			(int)sizeof (arg), arg);
476 
477 
478 	res.status = pk_get_conv_key(uid, arg, &res);
479 
480 	if (debugging) {
481 		if (res.status == KEY_SUCCESS) {
482 			(void) fprintf(stderr, "%08x%08x\n",
483 				res.cryptkeyres_u.deskey.key.high,
484 				res.cryptkeyres_u.deskey.key.low);
485 		} else {
486 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
487 		}
488 		(void) fflush(stderr);
489 	}
490 	return (&res);
491 }
492 
493 
494 cryptkeyres *
495 key_encrypt_1_svc_prog(uid, arg)
496 	uid_t uid;
497 	cryptkeyarg *arg;
498 {
499 	static cryptkeyres res;
500 
501 	if (debugging) {
502 		(void) fprintf(stderr, "encrypt(%ld, %s, %08x%08x) = ", uid,
503 				arg->remotename, arg->deskey.key.high,
504 				arg->deskey.key.low);
505 	}
506 	res.cryptkeyres_u.deskey = arg->deskey;
507 	res.status = pk_encrypt(uid, arg->remotename, NULL,
508 				&res.cryptkeyres_u.deskey);
509 	if (debugging) {
510 		if (res.status == KEY_SUCCESS) {
511 			(void) fprintf(stderr, "%08x%08x\n",
512 					res.cryptkeyres_u.deskey.key.high,
513 					res.cryptkeyres_u.deskey.key.low);
514 		} else {
515 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
516 		}
517 		(void) fflush(stderr);
518 	}
519 	return (&res);
520 }
521 
522 cryptkeyres *
523 key_decrypt_1_svc_prog(uid, arg)
524 	uid_t uid;
525 	cryptkeyarg *arg;
526 {
527 	static cryptkeyres res;
528 
529 	if (debugging) {
530 		(void) fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid,
531 				arg->remotename, arg->deskey.key.high,
532 				arg->deskey.key.low);
533 	}
534 	res.cryptkeyres_u.deskey = arg->deskey;
535 	res.status = pk_decrypt(uid, arg->remotename, NULL,
536 				&res.cryptkeyres_u.deskey);
537 	if (debugging) {
538 		if (res.status == KEY_SUCCESS) {
539 			(void) fprintf(stderr, "%08x%08x\n",
540 					res.cryptkeyres_u.deskey.key.high,
541 					res.cryptkeyres_u.deskey.key.low);
542 		} else {
543 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
544 		}
545 		(void) fflush(stderr);
546 	}
547 	return (&res);
548 }
549 
550 /* ARGSUSED */
551 des_block *
552 key_gen_1_svc_prog(v, s)
553 	void	*v;
554 	struct svc_req	*s;
555 {
556 	struct timeval time;
557 	static des_block keygen;
558 	static des_block key;
559 
560 	(void) gettimeofday(&time, (struct timezone *) NULL);
561 	keygen.key.high += (time.tv_sec ^ time.tv_usec);
562 	keygen.key.low += (time.tv_sec ^ time.tv_usec);
563 	ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen),
564 		DES_ENCRYPT | DES_HW);
565 	key = keygen;
566 	des_setparity((char *)&key);
567 	if (debugging) {
568 		(void) fprintf(stderr, "gen() = %08x%08x\n", key.key.high,
569 					key.key.low);
570 		(void) fflush(stderr);
571 	}
572 	return (&key);
573 }
574 
575 getcredres *
576 key_getcred_1_svc_prog(uid, name)
577 	uid_t uid;
578 	netnamestr *name;
579 {
580 	static getcredres res;
581 	static u_int gids[NGROUPS];
582 	struct unixcred *cred;
583 
584 	cred = &res.getcredres_u.cred;
585 	cred->gids.gids_val = gids;
586 	if (!netname2user(*name, (uid_t *) &cred->uid, (gid_t *) &cred->gid,
587 			(int *)&cred->gids.gids_len, (gid_t *)gids)) {
588 		res.status = KEY_UNKNOWN;
589 	} else {
590 		res.status = KEY_SUCCESS;
591 	}
592 	if (debugging) {
593 		(void) fprintf(stderr, "getcred(%s) = ", *name);
594 		if (res.status == KEY_SUCCESS) {
595 			(void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n",
596 				cred->uid, cred->gid, cred->gids.gids_len);
597 		} else {
598 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
599 		}
600 		(void) fflush(stderr);
601 	}
602 	return (&res);
603 }
604 
605 /*
606  * RPC boilerplate
607  */
608 static void
609 keyprogram(rqstp, transp)
610 	struct svc_req *rqstp;
611 	SVCXPRT *transp;
612 {
613 	union {
614 		keybuf key_set_1_arg;
615 		cryptkeyarg key_encrypt_1_arg;
616 		cryptkeyarg key_decrypt_1_arg;
617 		netnamestr key_getcred_1_arg;
618 		cryptkeyarg key_encrypt_2_arg;
619 		cryptkeyarg key_decrypt_2_arg;
620 		netnamestr key_getcred_2_arg;
621 		cryptkeyarg2 key_encrypt_pk_2_arg;
622 		cryptkeyarg2 key_decrypt_pk_2_arg;
623 		key_netstarg key_net_put_2_arg;
624 		netobj  key_get_conv_2_arg;
625 	} argument;
626 	char *result;
627 	bool_t(*xdr_argument)(), (*xdr_result)();
628 	char *(*local) ();
629 	uid_t uid = -1;
630 	int check_auth;
631 
632 	switch (rqstp->rq_proc) {
633 	case NULLPROC:
634 		svc_sendreply(transp, xdr_void, (char *)NULL);
635 		return;
636 
637 	case KEY_SET:
638 		xdr_argument = xdr_keybuf;
639 		xdr_result = xdr_int;
640 		local = (char *(*)()) key_set_1_svc_prog;
641 		check_auth = 1;
642 		break;
643 
644 	case KEY_ENCRYPT:
645 		xdr_argument = xdr_cryptkeyarg;
646 		xdr_result = xdr_cryptkeyres;
647 		local = (char *(*)()) key_encrypt_1_svc_prog;
648 		check_auth = 1;
649 		break;
650 
651 	case KEY_DECRYPT:
652 		xdr_argument = xdr_cryptkeyarg;
653 		xdr_result = xdr_cryptkeyres;
654 		local = (char *(*)()) key_decrypt_1_svc_prog;
655 		check_auth = 1;
656 		break;
657 
658 	case KEY_GEN:
659 		xdr_argument = xdr_void;
660 		xdr_result = xdr_des_block;
661 		local = (char *(*)()) key_gen_1_svc_prog;
662 		check_auth = 0;
663 		break;
664 
665 	case KEY_GETCRED:
666 		xdr_argument = xdr_netnamestr;
667 		xdr_result = xdr_getcredres;
668 		local = (char *(*)()) key_getcred_1_svc_prog;
669 		check_auth = 0;
670 		break;
671 
672 	case KEY_ENCRYPT_PK:
673 		xdr_argument = xdr_cryptkeyarg2;
674 		xdr_result = xdr_cryptkeyres;
675 		local = (char *(*)()) key_encrypt_pk_2_svc_prog;
676 		check_auth = 1;
677 		break;
678 
679 	case KEY_DECRYPT_PK:
680 		xdr_argument = xdr_cryptkeyarg2;
681 		xdr_result = xdr_cryptkeyres;
682 		local = (char *(*)()) key_decrypt_pk_2_svc_prog;
683 		check_auth = 1;
684 		break;
685 
686 
687 	case KEY_NET_PUT:
688 		xdr_argument = xdr_key_netstarg;
689 		xdr_result = xdr_keystatus;
690 		local = (char *(*)()) key_net_put_2_svc_prog;
691 		check_auth = 1;
692 		break;
693 
694 	case KEY_NET_GET:
695 		xdr_argument = (xdrproc_t) xdr_void;
696 		xdr_result = xdr_key_netstres;
697 		local = (char *(*)()) key_net_get_2_svc_prog;
698 		check_auth = 1;
699 		break;
700 
701 	case KEY_GET_CONV:
702 		xdr_argument = (xdrproc_t) xdr_keybuf;
703 		xdr_result = xdr_cryptkeyres;
704 		local = (char *(*)()) key_get_conv_2_svc_prog;
705 		check_auth = 1;
706 		break;
707 
708 	default:
709 		svcerr_noproc(transp);
710 		return;
711 	}
712 	if (check_auth) {
713 		if (root_auth(transp, rqstp) == 0) {
714 			if (debugging) {
715 				(void) fprintf(stderr,
716 				"not local privileged process\n");
717 			}
718 			svcerr_weakauth(transp);
719 			return;
720 		}
721 		if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
722 			if (debugging) {
723 				(void) fprintf(stderr,
724 				"not unix authentication\n");
725 			}
726 			svcerr_weakauth(transp);
727 			return;
728 		}
729 		uid = ((struct authsys_parms *)rqstp->rq_clntcred)->aup_uid;
730 	}
731 
732 	memset((char *) &argument, 0, sizeof (argument));
733 	if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
734 		svcerr_decode(transp);
735 		return;
736 	}
737 	result = (*local) (uid, &argument);
738 	if (!svc_sendreply(transp, xdr_result, (char *) result)) {
739 		if (debugging)
740 			(void) fprintf(stderr, "unable to reply\n");
741 		svcerr_systemerr(transp);
742 	}
743 	if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
744 		if (debugging)
745 			(void) fprintf(stderr,
746 			"unable to free arguments\n");
747 		exit(1);
748 	}
749 	return;
750 }
751 
752 static int
753 root_auth(trans, rqstp)
754 	SVCXPRT *trans;
755 	struct svc_req *rqstp;
756 {
757 	uid_t uid;
758 	struct sockaddr_in *remote;
759 
760 	remote = svc_getcaller(trans);
761 	if (remote->sin_family == AF_INET) {
762 		if (debugging)
763 			fprintf(stderr, "client didn't use AF_UNIX\n");
764 		return (0);
765 	}
766 
767 	if (__rpc_get_local_uid(&uid, trans) < 0) {
768 		if (debugging)
769 			fprintf(stderr, "__rpc_get_local_uid failed\n");
770 		return (0);
771 	}
772 
773 	if (debugging)
774 		fprintf(stderr, "local_uid  %ld\n", uid);
775 	if (uid == 0)
776 		return (1);
777 	if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
778 		if (((uid_t) ((struct authunix_parms *)
779 			rqstp->rq_clntcred)->aup_uid)
780 			== uid) {
781 			return (1);
782 		} else {
783 			if (debugging)
784 				fprintf(stderr,
785 			"local_uid  %ld mismatches auth %ld\n", uid,
786 ((uid_t) ((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid));
787 			return (0);
788 		}
789 	} else {
790 		if (debugging)
791 			fprintf(stderr, "Not auth sys\n");
792 		return (0);
793 	}
794 }
795 
796 static void
797 usage()
798 {
799 	(void) fprintf(stderr,
800 			"usage: keyserv [-n] [-D] [-d] [-v] [-p path]\n");
801 	(void) fprintf(stderr, "-d disables the use of default keys\n");
802 	exit(1);
803 }
804