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