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