xref: /freebsd/usr.sbin/keyserv/keyserv.c (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
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( des_block * );
76 static void usage( void );
77 static int getrootkey( des_block *, int );
78 static int root_auth( 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( uid_t, cryptkeyarg2 * );
106 cryptkeyres *key_decrypt_pk_2_svc_prog( uid_t, cryptkeyarg2 * );
107 des_block *key_gen_1_svc_prog( 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 	master->key.low = arc4random();
228 	master->key.high = arc4random();
229 }
230 
231 /*
232  * Try to get root's secret key, by prompting if terminal is a tty, else trying
233  * from standard input.
234  * Returns 1 on success.
235  */
236 static int
237 getrootkey(master, prompt)
238 	des_block *master;
239 	int prompt;
240 {
241 	char *passwd;
242 	char name[MAXNETNAMELEN + 1];
243 	char secret[HEXKEYBYTES];
244 	key_netstarg netstore;
245 	int fd;
246 
247 	if (!prompt) {
248 		/*
249 		 * Read secret key out of ROOTKEY
250 		 */
251 		fd = open(ROOTKEY, O_RDONLY, 0);
252 		if (fd < 0) {
253 			randomize(master);
254 			return (0);
255 		}
256 		if (read(fd, secret, HEXKEYBYTES) < HEXKEYBYTES) {
257 			warnx("the key read from %s was too short", ROOTKEY);
258 			(void) close(fd);
259 			return (0);
260 		}
261 		(void) close(fd);
262 		if (!getnetname(name)) {
263 		    warnx(
264 	"failed to generate host's netname when establishing root's key");
265 		    return (0);
266 		}
267 		memcpy(netstore.st_priv_key, secret, HEXKEYBYTES);
268 		memset(netstore.st_pub_key, 0, HEXKEYBYTES);
269 		netstore.st_netname = name;
270 		if (pk_netput(0, &netstore) != KEY_SUCCESS) {
271 		    warnx("could not set root's key and netname");
272 		    return (0);
273 		}
274 		return (1);
275 	}
276 	/*
277 	 * Decrypt yellow pages publickey entry to get secret key
278 	 */
279 	passwd = getpass("root password:");
280 	passwd2des(passwd, (char *)master);
281 	getnetname(name);
282 	if (!getsecretkey(name, secret, passwd)) {
283 		warnx("can't find %s's secret key", name);
284 		return (0);
285 	}
286 	if (secret[0] == 0) {
287 		warnx("password does not decrypt secret key for %s", name);
288 		return (0);
289 	}
290 	(void) pk_setkey(0, secret);
291 	/*
292 	 * Store it for future use in $ROOTKEY, if possible
293 	 */
294 	fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0);
295 	if (fd > 0) {
296 		char newline = '\n';
297 
298 		write(fd, secret, strlen(secret));
299 		write(fd, &newline, sizeof (newline));
300 		close(fd);
301 	}
302 	return (1);
303 }
304 
305 /*
306  * Procedures to implement RPC service
307  */
308 char *
309 strstatus(status)
310 	keystatus status;
311 {
312 	switch (status) {
313 	case KEY_SUCCESS:
314 		return ("KEY_SUCCESS");
315 	case KEY_NOSECRET:
316 		return ("KEY_NOSECRET");
317 	case KEY_UNKNOWN:
318 		return ("KEY_UNKNOWN");
319 	case KEY_SYSTEMERR:
320 		return ("KEY_SYSTEMERR");
321 	default:
322 		return ("(bad result code)");
323 	}
324 }
325 
326 keystatus *
327 key_set_1_svc_prog(uid, key)
328 	uid_t uid;
329 	keybuf key;
330 {
331 	static keystatus status;
332 
333 	if (debugging) {
334 		(void) fprintf(stderr, "set(%u, %.*s) = ", uid,
335 				(int) sizeof (keybuf), key);
336 	}
337 	status = pk_setkey(uid, key);
338 	if (debugging) {
339 		(void) fprintf(stderr, "%s\n", strstatus(status));
340 		(void) fflush(stderr);
341 	}
342 	return (&status);
343 }
344 
345 cryptkeyres *
346 key_encrypt_pk_2_svc_prog(uid, arg)
347 	uid_t uid;
348 	cryptkeyarg2 *arg;
349 {
350 	static cryptkeyres res;
351 
352 	if (debugging) {
353 		(void) fprintf(stderr, "encrypt(%u, %s, %08x%08x) = ", uid,
354 				arg->remotename, arg->deskey.key.high,
355 				arg->deskey.key.low);
356 	}
357 	res.cryptkeyres_u.deskey = arg->deskey;
358 	res.status = pk_encrypt(uid, arg->remotename, &(arg->remotekey),
359 				&res.cryptkeyres_u.deskey);
360 	if (debugging) {
361 		if (res.status == KEY_SUCCESS) {
362 			(void) fprintf(stderr, "%08x%08x\n",
363 					res.cryptkeyres_u.deskey.key.high,
364 					res.cryptkeyres_u.deskey.key.low);
365 		} else {
366 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
367 		}
368 		(void) fflush(stderr);
369 	}
370 	return (&res);
371 }
372 
373 cryptkeyres *
374 key_decrypt_pk_2_svc_prog(uid, arg)
375 	uid_t uid;
376 	cryptkeyarg2 *arg;
377 {
378 	static cryptkeyres res;
379 
380 	if (debugging) {
381 		(void) fprintf(stderr, "decrypt(%u, %s, %08x%08x) = ", uid,
382 				arg->remotename, arg->deskey.key.high,
383 				arg->deskey.key.low);
384 	}
385 	res.cryptkeyres_u.deskey = arg->deskey;
386 	res.status = pk_decrypt(uid, arg->remotename, &(arg->remotekey),
387 				&res.cryptkeyres_u.deskey);
388 	if (debugging) {
389 		if (res.status == KEY_SUCCESS) {
390 			(void) fprintf(stderr, "%08x%08x\n",
391 					res.cryptkeyres_u.deskey.key.high,
392 					res.cryptkeyres_u.deskey.key.low);
393 		} else {
394 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
395 		}
396 		(void) fflush(stderr);
397 	}
398 	return (&res);
399 }
400 
401 keystatus *
402 key_net_put_2_svc_prog(uid, arg)
403 	uid_t uid;
404 	key_netstarg *arg;
405 {
406 	static keystatus status;
407 
408 	if (debugging) {
409 		(void) fprintf(stderr, "net_put(%s, %.*s, %.*s) = ",
410 			arg->st_netname, (int)sizeof (arg->st_pub_key),
411 			arg->st_pub_key, (int)sizeof (arg->st_priv_key),
412 			arg->st_priv_key);
413 	}
414 
415 	status = pk_netput(uid, arg);
416 
417 	if (debugging) {
418 		(void) fprintf(stderr, "%s\n", strstatus(status));
419 		(void) fflush(stderr);
420 	}
421 
422 	return (&status);
423 }
424 
425 key_netstres *
426 key_net_get_2_svc_prog(uid, arg)
427 	uid_t uid;
428 	void *arg;
429 {
430 	static key_netstres keynetname;
431 
432 	if (debugging)
433 		(void) fprintf(stderr, "net_get(%u) = ", uid);
434 
435 	keynetname.status = pk_netget(uid, &keynetname.key_netstres_u.knet);
436 	if (debugging) {
437 		if (keynetname.status == KEY_SUCCESS) {
438 			fprintf(stderr, "<%s, %.*s, %.*s>\n",
439 			keynetname.key_netstres_u.knet.st_netname,
440 			(int)sizeof (keynetname.key_netstres_u.knet.st_pub_key),
441 			keynetname.key_netstres_u.knet.st_pub_key,
442 			(int)sizeof (keynetname.key_netstres_u.knet.st_priv_key),
443 			keynetname.key_netstres_u.knet.st_priv_key);
444 		} else {
445 			(void) fprintf(stderr, "NOT FOUND\n");
446 		}
447 		(void) fflush(stderr);
448 	}
449 
450 	return (&keynetname);
451 
452 }
453 
454 cryptkeyres *
455 key_get_conv_2_svc_prog(uid, arg)
456 	uid_t uid;
457 	keybuf arg;
458 {
459 	static cryptkeyres  res;
460 
461 	if (debugging)
462 		(void) fprintf(stderr, "get_conv(%u, %.*s) = ", uid,
463 			(int)sizeof (keybuf), arg);
464 
465 
466 	res.status = pk_get_conv_key(uid, arg, &res);
467 
468 	if (debugging) {
469 		if (res.status == KEY_SUCCESS) {
470 			(void) fprintf(stderr, "%08x%08x\n",
471 				res.cryptkeyres_u.deskey.key.high,
472 				res.cryptkeyres_u.deskey.key.low);
473 		} else {
474 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
475 		}
476 		(void) fflush(stderr);
477 	}
478 	return (&res);
479 }
480 
481 
482 cryptkeyres *
483 key_encrypt_1_svc_prog(uid, arg)
484 	uid_t uid;
485 	cryptkeyarg *arg;
486 {
487 	static cryptkeyres res;
488 
489 	if (debugging) {
490 		(void) fprintf(stderr, "encrypt(%u, %s, %08x%08x) = ", uid,
491 				arg->remotename, arg->deskey.key.high,
492 				arg->deskey.key.low);
493 	}
494 	res.cryptkeyres_u.deskey = arg->deskey;
495 	res.status = pk_encrypt(uid, arg->remotename, NULL,
496 				&res.cryptkeyres_u.deskey);
497 	if (debugging) {
498 		if (res.status == KEY_SUCCESS) {
499 			(void) fprintf(stderr, "%08x%08x\n",
500 					res.cryptkeyres_u.deskey.key.high,
501 					res.cryptkeyres_u.deskey.key.low);
502 		} else {
503 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
504 		}
505 		(void) fflush(stderr);
506 	}
507 	return (&res);
508 }
509 
510 cryptkeyres *
511 key_decrypt_1_svc_prog(uid, arg)
512 	uid_t uid;
513 	cryptkeyarg *arg;
514 {
515 	static cryptkeyres res;
516 
517 	if (debugging) {
518 		(void) fprintf(stderr, "decrypt(%u, %s, %08x%08x) = ", uid,
519 				arg->remotename, arg->deskey.key.high,
520 				arg->deskey.key.low);
521 	}
522 	res.cryptkeyres_u.deskey = arg->deskey;
523 	res.status = pk_decrypt(uid, arg->remotename, NULL,
524 				&res.cryptkeyres_u.deskey);
525 	if (debugging) {
526 		if (res.status == KEY_SUCCESS) {
527 			(void) fprintf(stderr, "%08x%08x\n",
528 					res.cryptkeyres_u.deskey.key.high,
529 					res.cryptkeyres_u.deskey.key.low);
530 		} else {
531 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
532 		}
533 		(void) fflush(stderr);
534 	}
535 	return (&res);
536 }
537 
538 /* ARGSUSED */
539 des_block *
540 key_gen_1_svc_prog(v, s)
541 	void	*v;
542 	struct svc_req	*s;
543 {
544 	struct timeval time;
545 	static des_block keygen;
546 	static des_block key;
547 
548 	(void)gettimeofday(&time, NULL);
549 	keygen.key.high += (time.tv_sec ^ time.tv_usec);
550 	keygen.key.low += (time.tv_sec ^ time.tv_usec);
551 	ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen),
552 		DES_ENCRYPT | DES_HW);
553 	key = keygen;
554 	des_setparity((char *)&key);
555 	if (debugging) {
556 		(void) fprintf(stderr, "gen() = %08x%08x\n", key.key.high,
557 					key.key.low);
558 		(void) fflush(stderr);
559 	}
560 	return (&key);
561 }
562 
563 getcredres *
564 key_getcred_1_svc_prog(uid, name)
565 	uid_t uid;
566 	netnamestr *name;
567 {
568 	static getcredres res;
569 	static u_int gids[NGROUPS];
570 	struct unixcred *cred;
571 
572 	cred = &res.getcredres_u.cred;
573 	cred->gids.gids_val = gids;
574 	if (!netname2user(*name, (uid_t *) &cred->uid, (gid_t *) &cred->gid,
575 			(int *)&cred->gids.gids_len, (gid_t *)gids)) {
576 		res.status = KEY_UNKNOWN;
577 	} else {
578 		res.status = KEY_SUCCESS;
579 	}
580 	if (debugging) {
581 		(void) fprintf(stderr, "getcred(%s) = ", *name);
582 		if (res.status == KEY_SUCCESS) {
583 			(void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n",
584 				cred->uid, cred->gid, cred->gids.gids_len);
585 		} else {
586 			(void) fprintf(stderr, "%s\n", strstatus(res.status));
587 		}
588 		(void) fflush(stderr);
589 	}
590 	return (&res);
591 }
592 
593 /*
594  * RPC boilerplate
595  */
596 static void
597 keyprogram(rqstp, transp)
598 	struct svc_req *rqstp;
599 	SVCXPRT *transp;
600 {
601 	union {
602 		keybuf key_set_1_arg;
603 		cryptkeyarg key_encrypt_1_arg;
604 		cryptkeyarg key_decrypt_1_arg;
605 		netnamestr key_getcred_1_arg;
606 		cryptkeyarg key_encrypt_2_arg;
607 		cryptkeyarg key_decrypt_2_arg;
608 		netnamestr key_getcred_2_arg;
609 		cryptkeyarg2 key_encrypt_pk_2_arg;
610 		cryptkeyarg2 key_decrypt_pk_2_arg;
611 		key_netstarg key_net_put_2_arg;
612 		netobj  key_get_conv_2_arg;
613 	} argument;
614 	char *result;
615 	xdrproc_t xdr_argument, xdr_result;
616 	char *(*local) ();
617 	uid_t uid = -1;
618 	int check_auth;
619 
620 	switch (rqstp->rq_proc) {
621 	case NULLPROC:
622 		svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
623 		return;
624 
625 	case KEY_SET:
626 		xdr_argument = (xdrproc_t)xdr_keybuf;
627 		xdr_result = (xdrproc_t)xdr_int;
628 		local = (char *(*)()) key_set_1_svc_prog;
629 		check_auth = 1;
630 		break;
631 
632 	case KEY_ENCRYPT:
633 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg;
634 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
635 		local = (char *(*)()) key_encrypt_1_svc_prog;
636 		check_auth = 1;
637 		break;
638 
639 	case KEY_DECRYPT:
640 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg;
641 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
642 		local = (char *(*)()) key_decrypt_1_svc_prog;
643 		check_auth = 1;
644 		break;
645 
646 	case KEY_GEN:
647 		xdr_argument = (xdrproc_t)xdr_void;
648 		xdr_result = (xdrproc_t)xdr_des_block;
649 		local = (char *(*)()) key_gen_1_svc_prog;
650 		check_auth = 0;
651 		break;
652 
653 	case KEY_GETCRED:
654 		xdr_argument = (xdrproc_t)xdr_netnamestr;
655 		xdr_result = (xdrproc_t)xdr_getcredres;
656 		local = (char *(*)()) key_getcred_1_svc_prog;
657 		check_auth = 0;
658 		break;
659 
660 	case KEY_ENCRYPT_PK:
661 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg2;
662 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
663 		local = (char *(*)()) key_encrypt_pk_2_svc_prog;
664 		check_auth = 1;
665 		break;
666 
667 	case KEY_DECRYPT_PK:
668 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg2;
669 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
670 		local = (char *(*)()) key_decrypt_pk_2_svc_prog;
671 		check_auth = 1;
672 		break;
673 
674 
675 	case KEY_NET_PUT:
676 		xdr_argument = (xdrproc_t)xdr_key_netstarg;
677 		xdr_result = (xdrproc_t)xdr_keystatus;
678 		local = (char *(*)()) key_net_put_2_svc_prog;
679 		check_auth = 1;
680 		break;
681 
682 	case KEY_NET_GET:
683 		xdr_argument = (xdrproc_t) xdr_void;
684 		xdr_result = (xdrproc_t)xdr_key_netstres;
685 		local = (char *(*)()) key_net_get_2_svc_prog;
686 		check_auth = 1;
687 		break;
688 
689 	case KEY_GET_CONV:
690 		xdr_argument = (xdrproc_t) xdr_keybuf;
691 		xdr_result = (xdrproc_t)xdr_cryptkeyres;
692 		local = (char *(*)()) key_get_conv_2_svc_prog;
693 		check_auth = 1;
694 		break;
695 
696 	default:
697 		svcerr_noproc(transp);
698 		return;
699 	}
700 	if (check_auth) {
701 		if (root_auth(transp, rqstp) == 0) {
702 			if (debugging) {
703 				(void) fprintf(stderr,
704 				"not local privileged process\n");
705 			}
706 			svcerr_weakauth(transp);
707 			return;
708 		}
709 		if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
710 			if (debugging) {
711 				(void) fprintf(stderr,
712 				"not unix authentication\n");
713 			}
714 			svcerr_weakauth(transp);
715 			return;
716 		}
717 		uid = ((struct authsys_parms *)rqstp->rq_clntcred)->aup_uid;
718 	}
719 
720 	memset(&argument, 0, sizeof (argument));
721 	if (!svc_getargs(transp, xdr_argument, &argument)) {
722 		svcerr_decode(transp);
723 		return;
724 	}
725 	result = (*local) (uid, &argument);
726 	if (!svc_sendreply(transp, xdr_result, result)) {
727 		if (debugging)
728 			(void) fprintf(stderr, "unable to reply\n");
729 		svcerr_systemerr(transp);
730 	}
731 	if (!svc_freeargs(transp, xdr_argument, &argument)) {
732 		if (debugging)
733 			(void) fprintf(stderr,
734 			"unable to free arguments\n");
735 		exit(1);
736 	}
737 	return;
738 }
739 
740 static int
741 root_auth(trans, rqstp)
742 	SVCXPRT *trans;
743 	struct svc_req *rqstp;
744 {
745 	uid_t uid;
746 	struct sockaddr *remote;
747 
748 	remote = svc_getrpccaller(trans)->buf;
749 	if (remote->sa_family != AF_UNIX) {
750 		if (debugging)
751 			fprintf(stderr, "client didn't use AF_UNIX\n");
752 		return (0);
753 	}
754 
755 	if (__rpc_get_local_uid(trans, &uid) < 0) {
756 		if (debugging)
757 			fprintf(stderr, "__rpc_get_local_uid failed\n");
758 		return (0);
759 	}
760 
761 	if (debugging)
762 		fprintf(stderr, "local_uid  %u\n", uid);
763 	if (uid == 0)
764 		return (1);
765 	if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
766 		if (((uid_t) ((struct authunix_parms *)
767 			rqstp->rq_clntcred)->aup_uid)
768 			== uid) {
769 			return (1);
770 		} else {
771 			if (debugging)
772 				fprintf(stderr,
773 			"local_uid  %u mismatches auth %u\n", uid,
774 ((uid_t) ((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid));
775 			return (0);
776 		}
777 	} else {
778 		if (debugging)
779 			fprintf(stderr, "Not auth sys\n");
780 		return (0);
781 	}
782 }
783 
784 static void
785 usage()
786 {
787 	(void) fprintf(stderr,
788 			"usage: keyserv [-n] [-D] [-d] [-v] [-p path]\n");
789 	(void) fprintf(stderr, "-d disables the use of default keys\n");
790 	exit(1);
791 }
792