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