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