xref: /freebsd/usr.sbin/keyserv/keyserv.c (revision ebbd4fa8c8427d3dd847ba33c45c996e0500e6ff)
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 <sys/param.h>
60 #include <sys/file.h>
61 #include <rpc/des_crypt.h>
62 #include <rpc/des.h>
63 #include <rpc/key_prot.h>
64 #include <rpcsvc/crypt.h>
65 #include "keyserv.h"
66 
67 #ifndef NGROUPS
68 #define	NGROUPS 16
69 #endif
70 
71 #ifndef KEYSERVSOCK
72 #define KEYSERVSOCK "/var/run/keyservsock"
73 #endif
74 
75 static void randomize __P(( des_block * ));
76 static void usage __P(( void ));
77 static int getrootkey __P(( des_block *, int ));
78 static int root_auth __P(( SVCXPRT *, struct svc_req * ));
79 
80 #ifdef DEBUG
81 static int debugging = 1;
82 #else
83 static int debugging = 0;
84 #endif
85 
86 static void keyprogram();
87 static des_block masterkey;
88 char *getenv();
89 static char ROOTKEY[] = "/etc/.rootkey";
90 
91 /*
92  * Hack to allow the keyserver to use AUTH_DES (for authenticated
93  * NIS+ calls, for example).  The only functions that get called
94  * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
95  *
96  * The approach is to have the keyserver fill in pointers to local
97  * implementations of these functions, and to call those in key_call().
98  */
99 
100 extern cryptkeyres *(*__key_encryptsession_pk_LOCAL)();
101 extern cryptkeyres *(*__key_decryptsession_pk_LOCAL)();
102 extern des_block *(*__key_gendes_LOCAL)();
103 extern int (*__des_crypt_LOCAL)();
104 
105 cryptkeyres *key_encrypt_pk_2_svc_prog __P(( uid_t, cryptkeyarg2 * ));
106 cryptkeyres *key_decrypt_pk_2_svc_prog __P(( uid_t, cryptkeyarg2 * ));
107 des_block *key_gen_1_svc_prog __P(( void *, struct svc_req * ));
108 
109 int
110 main(argc, argv)
111 	int argc;
112 	char *argv[];
113 {
114 	int nflag = 0;
115 	int c;
116 	int warn = 0;
117 	char *path = NULL;
118 	void *localhandle;
119 	register SVCXPRT *transp;
120 	struct netconfig *nconf = 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(S_IXUSR|S_IXGRP|S_IXOTH);
160 	if (geteuid() != 0)
161 		errx(1, "keyserv must be run as root");
162 	setmodulus(HEXMODULUS);
163 	getrootkey(&masterkey, nflag);
164 
165 	rpcb_unset(KEY_PROG, KEY_VERS, NULL);
166 	rpcb_unset(KEY_PROG, KEY_VERS2, NULL);
167 
168 	if (svc_create(keyprogram, KEY_PROG, KEY_VERS,
169 		"netpath") == 0) {
170 		(void) fprintf(stderr,
171 			"%s: unable to create service\n", argv[0]);
172 		exit(1);
173 	}
174 
175 	if (svc_create(keyprogram, KEY_PROG, KEY_VERS2,
176 	"netpath") == 0) {
177 		(void) fprintf(stderr,
178 			"%s: unable to create service\n", argv[0]);
179 		exit(1);
180 	}
181 
182 	localhandle = setnetconfig();
183 	while ((nconf = getnetconfig(localhandle)) != NULL) {
184 		if (nconf->nc_protofmly != NULL &&
185 		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
186 			break;
187 	}
188 
189 	if (nconf == NULL)
190 		errx(1, "getnetconfig: %s", nc_sperror());
191 
192 	unlink(KEYSERVSOCK);
193 	rpcb_unset(CRYPT_PROG, CRYPT_VERS, nconf);
194 	transp = svcunix_create(RPC_ANYSOCK, 0, 0, KEYSERVSOCK);
195 	if (transp == NULL)
196 		errx(1, "cannot create AF_LOCAL service");
197 	if (!svc_reg(transp, KEY_PROG, KEY_VERS, keyprogram, nconf))
198 		errx(1, "unable to register (KEY_PROG, KEY_VERS, unix)");
199 	if (!svc_reg(transp, KEY_PROG, KEY_VERS2, keyprogram, nconf))
200 		errx(1, "unable to register (KEY_PROG, KEY_VERS2, unix)");
201 	if (!svc_reg(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, nconf))
202 		errx(1, "unable to register (CRYPT_PROG, CRYPT_VERS, unix)");
203 
204 	endnetconfig(localhandle);
205 
206 	(void) umask(066);	/* paranoia */
207 
208 	if (!debugging) {
209 		daemon(0,0);
210 	}
211 
212 	signal(SIGPIPE, SIG_IGN);
213 
214 	svc_run();
215 	abort();
216 	/* NOTREACHED */
217 }
218 
219 /*
220  * In the event that we don't get a root password, we try to
221  * randomize the master key the best we can
222  */
223 static void
224 randomize(master)
225 	des_block *master;
226 {
227 	int i;
228 	int seed;
229 	struct timeval tv;
230 	int shift;
231 
232 	seed = 0;
233 	for (i = 0; i < 1024; i++) {
234 		(void) gettimeofday(&tv, (struct timezone *) NULL);
235 		shift = i % 8 * sizeof (int);
236 		seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift));
237 	}
238 #ifdef KEYSERV_RANDOM
239 	srandom(seed);
240 	master->key.low = random();
241 	master->key.high = random();
242 	srandom(seed);
243 #else
244 	/* use stupid dangerous bad rand() */
245 	srand(seed);
246 	master->key.low = rand();
247 	master->key.high = rand();
248 	srand(seed);
249 #endif
250 }
251 
252 /*
253  * Try to get root's secret key, by prompting if terminal is a tty, else trying
254  * from standard input.
255  * Returns 1 on success.
256  */
257 static int
258 getrootkey(master, prompt)
259 	des_block *master;
260 	int prompt;
261 {
262 	char *passwd;
263 	char name[MAXNETNAMELEN + 1];
264 	char secret[HEXKEYBYTES];
265 	key_netstarg netstore;
266 	int fd;
267 
268 	if (!prompt) {
269 		/*
270 		 * Read secret key out of ROOTKEY
271 		 */
272 		fd = open(ROOTKEY, O_RDONLY, 0);
273 		if (fd < 0) {
274 			randomize(master);
275 			return (0);
276 		}
277 		if (read(fd, secret, HEXKEYBYTES) < HEXKEYBYTES) {
278 			warnx("the key read from %s was too short", ROOTKEY);
279 			(void) close(fd);
280 			return (0);
281 		}
282 		(void) close(fd);
283 		if (!getnetname(name)) {
284 		    warnx(
285 	"failed to generate host's netname when establishing root's key");
286 		    return (0);
287 		}
288 		memcpy(netstore.st_priv_key, secret, HEXKEYBYTES);
289 		memset(netstore.st_pub_key, 0, HEXKEYBYTES);
290 		netstore.st_netname = name;
291 		if (pk_netput(0, &netstore) != KEY_SUCCESS) {
292 		    warnx("could not set root's key and netname");
293 		    return (0);
294 		}
295 		return (1);
296 	}
297 	/*
298 	 * Decrypt yellow pages publickey entry to get secret key
299 	 */
300 	passwd = getpass("root password:");
301 	passwd2des(passwd, (char *)master);
302 	getnetname(name);
303 	if (!getsecretkey(name, secret, passwd)) {
304 		warnx("can't find %s's secret key", name);
305 		return (0);
306 	}
307 	if (secret[0] == 0) {
308 		warnx("password does not decrypt secret key for %s", name);
309 		return (0);
310 	}
311 	(void) pk_setkey(0, secret);
312 	/*
313 	 * Store it for future use in $ROOTKEY, if possible
314 	 */
315 	fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0);
316 	if (fd > 0) {
317 		char newline = '\n';
318 
319 		write(fd, secret, strlen(secret));
320 		write(fd, &newline, sizeof (newline));
321 		close(fd);
322 	}
323 	return (1);
324 }
325 
326 /*
327  * Procedures to implement RPC service
328  */
329 char *
330 strstatus(status)
331 	keystatus status;
332 {
333 	switch (status) {
334 	case KEY_SUCCESS:
335 		return ("KEY_SUCCESS");
336 	case KEY_NOSECRET:
337 		return ("KEY_NOSECRET");
338 	case KEY_UNKNOWN:
339 		return ("KEY_UNKNOWN");
340 	case KEY_SYSTEMERR:
341 		return ("KEY_SYSTEMERR");
342 	default:
343 		return ("(bad result code)");
344 	}
345 }
346 
347 keystatus *
348 key_set_1_svc_prog(uid, key)
349 	uid_t uid;
350 	keybuf key;
351 {
352 	static keystatus status;
353 
354 	if (debugging) {
355 		(void) fprintf(stderr, "set(%ld, %.*s) = ", uid,
356 				(int) sizeof (keybuf), key);
357 	}
358 	status = pk_setkey(uid, key);
359 	if (debugging) {
360 		(void) fprintf(stderr, "%s\n", strstatus(status));
361 		(void) fflush(stderr);
362 	}
363 	return (&status);
364 }
365 
366 cryptkeyres *
367 key_encrypt_pk_2_svc_prog(uid, arg)
368 	uid_t uid;
369 	cryptkeyarg2 *arg;
370 {
371 	static cryptkeyres res;
372 
373 	if (debugging) {
374 		(void) fprintf(stderr, "encrypt(%ld, %s, %08x%08x) = ", uid,
375 				arg->remotename, arg->deskey.key.high,
376 				arg->deskey.key.low);
377 	}
378 	res.cryptkeyres_u.deskey = arg->deskey;
379 	res.status = pk_encrypt(uid, arg->remotename, &(arg->remotekey),
380 				&res.cryptkeyres_u.deskey);
381 	if (debugging) {
382 		if (res.status == KEY_SUCCESS) {
383 			(void) fprintf(stderr, "%08x%08x\n",
384 					res.cryptkeyres_u.deskey.key.high,
385 					res.cryptkeyres_u.deskey.key.low);
386 		} else {
387 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
388 		}
389 		(void) fflush(stderr);
390 	}
391 	return (&res);
392 }
393 
394 cryptkeyres *
395 key_decrypt_pk_2_svc_prog(uid, arg)
396 	uid_t uid;
397 	cryptkeyarg2 *arg;
398 {
399 	static cryptkeyres res;
400 
401 	if (debugging) {
402 		(void) fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid,
403 				arg->remotename, arg->deskey.key.high,
404 				arg->deskey.key.low);
405 	}
406 	res.cryptkeyres_u.deskey = arg->deskey;
407 	res.status = pk_decrypt(uid, arg->remotename, &(arg->remotekey),
408 				&res.cryptkeyres_u.deskey);
409 	if (debugging) {
410 		if (res.status == KEY_SUCCESS) {
411 			(void) fprintf(stderr, "%08x%08x\n",
412 					res.cryptkeyres_u.deskey.key.high,
413 					res.cryptkeyres_u.deskey.key.low);
414 		} else {
415 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
416 		}
417 		(void) fflush(stderr);
418 	}
419 	return (&res);
420 }
421 
422 keystatus *
423 key_net_put_2_svc_prog(uid, arg)
424 	uid_t uid;
425 	key_netstarg *arg;
426 {
427 	static keystatus status;
428 
429 	if (debugging) {
430 		(void) fprintf(stderr, "net_put(%s, %.*s, %.*s) = ",
431 			arg->st_netname, (int)sizeof (arg->st_pub_key),
432 			arg->st_pub_key, (int)sizeof (arg->st_priv_key),
433 			arg->st_priv_key);
434 	};
435 
436 	status = pk_netput(uid, arg);
437 
438 	if (debugging) {
439 		(void) fprintf(stderr, "%s\n", strstatus(status));
440 		(void) fflush(stderr);
441 	}
442 
443 	return (&status);
444 }
445 
446 key_netstres *
447 key_net_get_2_svc_prog(uid, arg)
448 	uid_t uid;
449 	void *arg;
450 {
451 	static key_netstres keynetname;
452 
453 	if (debugging)
454 		(void) fprintf(stderr, "net_get(%ld) = ", uid);
455 
456 	keynetname.status = pk_netget(uid, &keynetname.key_netstres_u.knet);
457 	if (debugging) {
458 		if (keynetname.status == KEY_SUCCESS) {
459 			fprintf(stderr, "<%s, %.*s, %.*s>\n",
460 			keynetname.key_netstres_u.knet.st_netname,
461 			(int)sizeof (keynetname.key_netstres_u.knet.st_pub_key),
462 			keynetname.key_netstres_u.knet.st_pub_key,
463 			(int)sizeof (keynetname.key_netstres_u.knet.st_priv_key),
464 			keynetname.key_netstres_u.knet.st_priv_key);
465 		} else {
466 			(void) fprintf(stderr, "NOT FOUND\n");
467 		}
468 		(void) fflush(stderr);
469 	}
470 
471 	return (&keynetname);
472 
473 }
474 
475 cryptkeyres *
476 key_get_conv_2_svc_prog(uid, arg)
477 	uid_t uid;
478 	keybuf arg;
479 {
480 	static cryptkeyres  res;
481 
482 	if (debugging)
483 		(void) fprintf(stderr, "get_conv(%ld, %.*s) = ", uid,
484 			(int)sizeof (arg), arg);
485 
486 
487 	res.status = pk_get_conv_key(uid, arg, &res);
488 
489 	if (debugging) {
490 		if (res.status == KEY_SUCCESS) {
491 			(void) fprintf(stderr, "%08x%08x\n",
492 				res.cryptkeyres_u.deskey.key.high,
493 				res.cryptkeyres_u.deskey.key.low);
494 		} else {
495 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
496 		}
497 		(void) fflush(stderr);
498 	}
499 	return (&res);
500 }
501 
502 
503 cryptkeyres *
504 key_encrypt_1_svc_prog(uid, arg)
505 	uid_t uid;
506 	cryptkeyarg *arg;
507 {
508 	static cryptkeyres res;
509 
510 	if (debugging) {
511 		(void) fprintf(stderr, "encrypt(%ld, %s, %08x%08x) = ", uid,
512 				arg->remotename, arg->deskey.key.high,
513 				arg->deskey.key.low);
514 	}
515 	res.cryptkeyres_u.deskey = arg->deskey;
516 	res.status = pk_encrypt(uid, arg->remotename, NULL,
517 				&res.cryptkeyres_u.deskey);
518 	if (debugging) {
519 		if (res.status == KEY_SUCCESS) {
520 			(void) fprintf(stderr, "%08x%08x\n",
521 					res.cryptkeyres_u.deskey.key.high,
522 					res.cryptkeyres_u.deskey.key.low);
523 		} else {
524 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
525 		}
526 		(void) fflush(stderr);
527 	}
528 	return (&res);
529 }
530 
531 cryptkeyres *
532 key_decrypt_1_svc_prog(uid, arg)
533 	uid_t uid;
534 	cryptkeyarg *arg;
535 {
536 	static cryptkeyres res;
537 
538 	if (debugging) {
539 		(void) fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid,
540 				arg->remotename, arg->deskey.key.high,
541 				arg->deskey.key.low);
542 	}
543 	res.cryptkeyres_u.deskey = arg->deskey;
544 	res.status = pk_decrypt(uid, arg->remotename, NULL,
545 				&res.cryptkeyres_u.deskey);
546 	if (debugging) {
547 		if (res.status == KEY_SUCCESS) {
548 			(void) fprintf(stderr, "%08x%08x\n",
549 					res.cryptkeyres_u.deskey.key.high,
550 					res.cryptkeyres_u.deskey.key.low);
551 		} else {
552 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
553 		}
554 		(void) fflush(stderr);
555 	}
556 	return (&res);
557 }
558 
559 /* ARGSUSED */
560 des_block *
561 key_gen_1_svc_prog(v, s)
562 	void	*v;
563 	struct svc_req	*s;
564 {
565 	struct timeval time;
566 	static des_block keygen;
567 	static des_block key;
568 
569 	(void) gettimeofday(&time, (struct timezone *) NULL);
570 	keygen.key.high += (time.tv_sec ^ time.tv_usec);
571 	keygen.key.low += (time.tv_sec ^ time.tv_usec);
572 	ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen),
573 		DES_ENCRYPT | DES_HW);
574 	key = keygen;
575 	des_setparity((char *)&key);
576 	if (debugging) {
577 		(void) fprintf(stderr, "gen() = %08x%08x\n", key.key.high,
578 					key.key.low);
579 		(void) fflush(stderr);
580 	}
581 	return (&key);
582 }
583 
584 getcredres *
585 key_getcred_1_svc_prog(uid, name)
586 	uid_t uid;
587 	netnamestr *name;
588 {
589 	static getcredres res;
590 	static u_int gids[NGROUPS];
591 	struct unixcred *cred;
592 
593 	cred = &res.getcredres_u.cred;
594 	cred->gids.gids_val = gids;
595 	if (!netname2user(*name, (uid_t *) &cred->uid, (gid_t *) &cred->gid,
596 			(int *)&cred->gids.gids_len, (gid_t *)gids)) {
597 		res.status = KEY_UNKNOWN;
598 	} else {
599 		res.status = KEY_SUCCESS;
600 	}
601 	if (debugging) {
602 		(void) fprintf(stderr, "getcred(%s) = ", *name);
603 		if (res.status == KEY_SUCCESS) {
604 			(void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n",
605 				cred->uid, cred->gid, cred->gids.gids_len);
606 		} else {
607 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
608 		}
609 		(void) fflush(stderr);
610 	}
611 	return (&res);
612 }
613 
614 /*
615  * RPC boilerplate
616  */
617 static void
618 keyprogram(rqstp, transp)
619 	struct svc_req *rqstp;
620 	SVCXPRT *transp;
621 {
622 	union {
623 		keybuf key_set_1_arg;
624 		cryptkeyarg key_encrypt_1_arg;
625 		cryptkeyarg key_decrypt_1_arg;
626 		netnamestr key_getcred_1_arg;
627 		cryptkeyarg key_encrypt_2_arg;
628 		cryptkeyarg key_decrypt_2_arg;
629 		netnamestr key_getcred_2_arg;
630 		cryptkeyarg2 key_encrypt_pk_2_arg;
631 		cryptkeyarg2 key_decrypt_pk_2_arg;
632 		key_netstarg key_net_put_2_arg;
633 		netobj  key_get_conv_2_arg;
634 	} argument;
635 	char *result;
636 	xdrproc_t xdr_argument, xdr_result;
637 	char *(*local) ();
638 	uid_t uid = -1;
639 	int check_auth;
640 
641 	switch (rqstp->rq_proc) {
642 	case NULLPROC:
643 		svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
644 		return;
645 
646 	case KEY_SET:
647 		xdr_argument = (xdrproc_t)xdr_keybuf;
648 		xdr_result = (xdrproc_t)xdr_int;
649 		local = (char *(*)()) key_set_1_svc_prog;
650 		check_auth = 1;
651 		break;
652 
653 	case KEY_ENCRYPT:
654 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg;
655 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
656 		local = (char *(*)()) key_encrypt_1_svc_prog;
657 		check_auth = 1;
658 		break;
659 
660 	case KEY_DECRYPT:
661 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg;
662 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
663 		local = (char *(*)()) key_decrypt_1_svc_prog;
664 		check_auth = 1;
665 		break;
666 
667 	case KEY_GEN:
668 		xdr_argument = (xdrproc_t)xdr_void;
669 		xdr_result = (xdrproc_t)xdr_des_block;
670 		local = (char *(*)()) key_gen_1_svc_prog;
671 		check_auth = 0;
672 		break;
673 
674 	case KEY_GETCRED:
675 		xdr_argument = (xdrproc_t)xdr_netnamestr;
676 		xdr_result = (xdrproc_t)xdr_getcredres;
677 		local = (char *(*)()) key_getcred_1_svc_prog;
678 		check_auth = 0;
679 		break;
680 
681 	case KEY_ENCRYPT_PK:
682 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg2;
683 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
684 		local = (char *(*)()) key_encrypt_pk_2_svc_prog;
685 		check_auth = 1;
686 		break;
687 
688 	case KEY_DECRYPT_PK:
689 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg2;
690 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
691 		local = (char *(*)()) key_decrypt_pk_2_svc_prog;
692 		check_auth = 1;
693 		break;
694 
695 
696 	case KEY_NET_PUT:
697 		xdr_argument = (xdrproc_t)xdr_key_netstarg;
698 		xdr_result = (xdrproc_t)xdr_keystatus;
699 		local = (char *(*)()) key_net_put_2_svc_prog;
700 		check_auth = 1;
701 		break;
702 
703 	case KEY_NET_GET:
704 		xdr_argument = (xdrproc_t) xdr_void;
705 		xdr_result = (xdrproc_t)xdr_key_netstres;
706 		local = (char *(*)()) key_net_get_2_svc_prog;
707 		check_auth = 1;
708 		break;
709 
710 	case KEY_GET_CONV:
711 		xdr_argument = (xdrproc_t) xdr_keybuf;
712 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
713 		local = (char *(*)()) key_get_conv_2_svc_prog;
714 		check_auth = 1;
715 		break;
716 
717 	default:
718 		svcerr_noproc(transp);
719 		return;
720 	}
721 	if (check_auth) {
722 		if (root_auth(transp, rqstp) == 0) {
723 			if (debugging) {
724 				(void) fprintf(stderr,
725 				"not local privileged process\n");
726 			}
727 			svcerr_weakauth(transp);
728 			return;
729 		}
730 		if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
731 			if (debugging) {
732 				(void) fprintf(stderr,
733 				"not unix authentication\n");
734 			}
735 			svcerr_weakauth(transp);
736 			return;
737 		}
738 		uid = ((struct authsys_parms *)rqstp->rq_clntcred)->aup_uid;
739 	}
740 
741 	memset(&argument, 0, sizeof (argument));
742 	if (!svc_getargs(transp, xdr_argument, &argument)) {
743 		svcerr_decode(transp);
744 		return;
745 	}
746 	result = (*local) (uid, &argument);
747 	if (!svc_sendreply(transp, xdr_result, result)) {
748 		if (debugging)
749 			(void) fprintf(stderr, "unable to reply\n");
750 		svcerr_systemerr(transp);
751 	}
752 	if (!svc_freeargs(transp, xdr_argument, &argument)) {
753 		if (debugging)
754 			(void) fprintf(stderr,
755 			"unable to free arguments\n");
756 		exit(1);
757 	}
758 	return;
759 }
760 
761 static int
762 root_auth(trans, rqstp)
763 	SVCXPRT *trans;
764 	struct svc_req *rqstp;
765 {
766 	uid_t uid;
767 	struct sockaddr *remote;
768 
769 	remote = svc_getrpccaller(trans)->buf;
770 	if (remote->sa_family != AF_UNIX) {
771 		if (debugging)
772 			fprintf(stderr, "client didn't use AF_UNIX\n");
773 		return (0);
774 	}
775 
776 	if (__rpc_get_local_uid(trans, &uid) < 0) {
777 		if (debugging)
778 			fprintf(stderr, "__rpc_get_local_uid failed\n");
779 		return (0);
780 	}
781 
782 	if (debugging)
783 		fprintf(stderr, "local_uid  %ld\n", uid);
784 	if (uid == 0)
785 		return (1);
786 	if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
787 		if (((uid_t) ((struct authunix_parms *)
788 			rqstp->rq_clntcred)->aup_uid)
789 			== uid) {
790 			return (1);
791 		} else {
792 			if (debugging)
793 				fprintf(stderr,
794 			"local_uid  %ld mismatches auth %ld\n", uid,
795 ((uid_t) ((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid));
796 			return (0);
797 		}
798 	} else {
799 		if (debugging)
800 			fprintf(stderr, "Not auth sys\n");
801 		return (0);
802 	}
803 }
804 
805 static void
806 usage()
807 {
808 	(void) fprintf(stderr,
809 			"usage: keyserv [-n] [-D] [-d] [-v] [-p path]\n");
810 	(void) fprintf(stderr, "-d disables the use of default keys\n");
811 	exit(1);
812 }
813