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