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