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