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