xref: /illumos-gate/usr/src/cmd/keyserv/keyserv.c (revision 06e1a7147edd272b7296f208141627a5b1191731)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /*	All Rights Reserved   */
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /*
43  * keyserv - server for storing private encryption keys
44  *   keyserv(1M) performs multiple functions:  it stores secret keys per uid; it
45  *   performs public key encryption and decryption operations; and it generates
46  *   "random" keys.  keyserv(1M) will talk to no one but a local root process on
47  *   the local transport only.
48  */
49 
50 #include <stdio.h>
51 #include <stdio_ext.h>
52 #include <stdlib.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <sys/uio.h>
56 #include <unistd.h>
57 #include <string.h>
58 #include <deflt.h>
59 #include <rpc/rpc.h>
60 #include <sys/param.h>
61 #include <sys/file.h>
62 #include <sys/resource.h>
63 #include <pwd.h>
64 #include <rpc/des_crypt.h>
65 #include <rpc/key_prot.h>
66 #include <thread.h>
67 #include "rpc/svc_mt.h"
68 #include <rpcsvc/nis_dhext.h>
69 #include <syslog.h>
70 #include <libscf.h>
71 
72 #include "debug.h"
73 #include "keyserv_cache.h"
74 
75 #ifdef KEYSERV_RANDOM
76 extern long random();
77 #endif
78 
79 extern keystatus pk_setkey();
80 extern keystatus pk_encrypt();
81 extern keystatus pk_decrypt();
82 extern keystatus pk_netput();
83 extern keystatus pk_netget();
84 extern keystatus pk_get_conv_key();
85 extern bool_t svc_get_local_cred();
86 
87 extern keystatus pk_setkey3();
88 extern keystatus pk_encrypt3();
89 extern keystatus pk_decrypt3();
90 extern keystatus pk_netput3();
91 extern keystatus pk_netget3();
92 extern keystatus pk_get_conv_key3();
93 extern keystatus pk_clear3();
94 
95 extern int init_mechs();
96 extern int addmasterkey();
97 extern int storeotherrootkeys();
98 extern int setdeskeyarray();
99 
100 extern int getdomainname();
101 
102 static void randomize();
103 static void usage();
104 static void defaults();
105 static int getrootkey();
106 static int get_cache_size(char *);
107 static bool_t get_auth();
108 
109 #ifdef DEBUG
110 extern int test_debug();
111 extern int real_debug();
112 int debugging = 1;
113 #else
114 int debugging = 0;
115 #endif
116 
117 static void keyprogram();
118 static des_block masterkey;
119 char *getenv();
120 static char ROOTKEY[] = "/etc/.rootkey";
121 
122 static char *defaults_file = "/etc/default/keyserv";
123 static int use_nobody_keys = TRUE;
124 
125 /*
126  * Hack to allow the keyserver to use AUTH_DES (for authenticated
127  * NIS+ calls, for example).  The only functions that get called
128  * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
129  *
130  * The approach is to have the keyserver fill in pointers to local
131  * implementations of these functions, and to call those in key_call().
132  */
133 
134 bool_t __key_encrypt_pk_2_svc();
135 bool_t __key_decrypt_pk_2_svc();
136 bool_t __key_gen_1_svc();
137 
138 extern bool_t (*__key_encryptsession_pk_LOCAL)();
139 extern bool_t (*__key_decryptsession_pk_LOCAL)();
140 extern bool_t (*__key_gendes_LOCAL)();
141 
142 static int nthreads = 32;
143 
144 /* Disk caching of common keys on by default */
145 int disk_caching = 1;
146 
147 mechanism_t **mechs;
148 
149 /*
150  * The default size for all types of mech.
151  * positive integers denote multiples of 1MB
152  * negative integers denote number of entries
153  * same goes for non-null entries in cache_size
154  */
155 static int default_cache = 1;
156 
157 int *cache_size;
158 char **cache_options;
159 
160 int
161 main(int argc, char *argv[])
162 {
163 	int sflag = 0, s1flag = 0, s2flag = 0, nflag = 0, dflag = 0, eflag = 0;
164 	char *options, *value;
165 	extern char *optarg;
166 	extern int optind;
167 	int c, d;
168 	struct rlimit rl;
169 	int mode = RPC_SVC_MT_AUTO;
170 	int maxrecsz = RPC_MAXDATASIZE;
171 
172 	void detachfromtty(void);
173 	int setmodulus();
174 	int pk_nodefaultkeys();
175 	int svc_create_local_service();
176 
177 	char domainname[MAXNETNAMELEN + 1];
178 
179 	/*
180 	 * Set our allowed number of file descriptors to the max
181 	 * of what the system will allow, limited by FD_SETSIZE.
182 	 */
183 	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
184 		rlim_t limit;
185 
186 		if ((limit = rl.rlim_max) > FD_SETSIZE)
187 			limit = FD_SETSIZE;
188 		rl.rlim_cur = limit;
189 		(void) setrlimit(RLIMIT_NOFILE, &rl);
190 		(void) enable_extended_FILE_stdio(-1, -1);
191 	}
192 
193 	__key_encryptsession_pk_LOCAL = &__key_encrypt_pk_2_svc;
194 	__key_decryptsession_pk_LOCAL = &__key_decrypt_pk_2_svc;
195 	__key_gendes_LOCAL = &__key_gen_1_svc;
196 
197 	/*
198 	 * Pre-option initialisation
199 	 */
200 	(void) umask(066);	/* paranoia */
201 	if (geteuid() != 0) {
202 		(void) fprintf(stderr, "%s must be run as root\n", argv[0]);
203 		exit(1);
204 	}
205 	setmodulus(HEXMODULUS);
206 	openlog("keyserv", LOG_PID, LOG_DAEMON);
207 
208 	/*
209 	 * keyserv will not work with a null domainname.
210 	 */
211 	if (getdomainname(domainname, MAXNETNAMELEN+1) ||
212 	    (domainname[0] == '\0')) {
213 	    syslog(LOG_ERR, "could not get a valid domainname.\n");
214 	    exit(SMF_EXIT_ERR_CONFIG);
215 	}
216 
217 	/*
218 	 * Initialise security mechanisms
219 	 */
220 	cache_size = NULL;
221 	cache_options = NULL;
222 	if (init_mechs() == -1) {
223 		disk_caching = 0;
224 	}
225 
226 	defaults();
227 
228 	while ((c = getopt(argc, argv, "ndDet:cs:")) != -1)
229 		switch (c) {
230 		case 'n':
231 			nflag++;
232 			break;
233 		case 'd':
234 			dflag++;
235 			use_nobody_keys = FALSE;
236 			break;
237 		case 'e':
238 			eflag++;
239 			use_nobody_keys = TRUE;
240 			break;
241 		case 'D':
242 			debugging = 1;
243 			break;
244 		case 't':
245 			nthreads = atoi(optarg);
246 			break;
247 		case 'c':
248 			disk_caching = 0;
249 			break;
250 		case 's':
251 			if (!disk_caching) {
252 				fprintf(stderr, "missing configuration file");
253 				fprintf(stderr, " or -c option specified\n");
254 				usage();
255 			}
256 			sflag++;
257 			/*
258 			 * Which version of [-s] do we have...?
259 			 */
260 			if (strchr((const char *) optarg, '=') == NULL) {
261 				/*
262 				 * -s <size>
263 				 */
264 				if (s1flag) {
265 				    fprintf(stderr, "duplicate [-s <size>]\n");
266 					usage();
267 				}
268 				s1flag++;
269 				default_cache = get_cache_size(optarg);
270 				break;
271 			}
272 			/*
273 			 * -s <mechtype>=<size>[,...]
274 			 */
275 			s2flag++;
276 			options = optarg;
277 			while (*options != '\0') {
278 				d = getsubopt(&options, cache_options, &value);
279 				if (d == -1) {
280 					/* Ignore unknown mechtype */
281 					continue;
282 				}
283 				if (value == NULL) {
284 					fprintf(stderr,
285 					"missing cache size for mechtype %s\n",
286 					cache_options[d]);
287 					usage();
288 				}
289 				cache_size[d] = get_cache_size(value);
290 			}
291 			break;
292 		default:
293 			usage();
294 			break;
295 		}
296 
297 
298 	if (dflag && eflag) {
299 		(void) fprintf(stderr, "specify only one of -d and -e\n");
300 		usage();
301 	}
302 
303 	if (use_nobody_keys == FALSE) {
304 		pk_nodefaultkeys();
305 	}
306 
307 	if (optind != argc) {
308 		usage();
309 	}
310 
311 	if (!disk_caching && sflag) {
312 		fprintf(stderr, "missing configuration file");
313 		fprintf(stderr, " or -c option specified\n");
314 		usage();
315 	}
316 
317 	if (debugging) {
318 		if (disk_caching) {
319 			char **cpp = cache_options;
320 			int *ip = cache_size;
321 			(void) fprintf(stderr, "default disk cache size: ");
322 			if (default_cache < 0) {
323 				(void) fprintf(stderr, "%d entries\n",
324 					abs(default_cache));
325 			} else {
326 				(void) fprintf(stderr, "%dMB\n", default_cache);
327 			}
328 
329 			(void) fprintf(stderr, "supported mechanisms:\n");
330 			(void) fprintf(stderr, "\talias\t\tdisk cache size\n");
331 			(void) fprintf(stderr, "\t=====\t\t===============\n");
332 			while (*cpp != NULL) {
333 				(void) fprintf(stderr, "\t%s\t\t", *cpp++);
334 				if (*ip < 0) {
335 					(void) fprintf(stderr, "%d entries\n",
336 						abs(*ip));
337 				} else {
338 					(void) fprintf(stderr, "%dMB\n", *ip);
339 				}
340 				ip++;
341 			}
342 		} else {
343 			(void) fprintf(stderr,
344 				"common key disk caching disabled\n");
345 		}
346 	}
347 	/*
348 	 * Post-option initialisation
349 	 */
350 	if (disk_caching) {
351 		int i;
352 		for (i = 0; mechs[i]; i++) {
353 			if ((AUTH_DES_COMPAT_CHK(mechs[i])) ||
354 			    (mechs[i]->keylen < 0) || (mechs[i]->algtype < 0))
355 				continue;
356 			create_cache_file(mechs[i]->keylen, mechs[i]->algtype,
357 				cache_size[i] ? cache_size[i] : default_cache);
358 		}
359 	}
360 	getrootkey(&masterkey, nflag);
361 
362 	/*
363 	 * Set MT mode
364 	 */
365 	if (nthreads > 0) {
366 		(void) rpc_control(RPC_SVC_MTMODE_SET, &mode);
367 		(void) rpc_control(RPC_SVC_THRMAX_SET, &nthreads);
368 	}
369 
370 	/*
371 	 * Enable non-blocking mode and maximum record size checks for
372 	 * connection oriented transports.
373 	 */
374 	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
375 		syslog(LOG_INFO, "unable to set max RPC record size");
376 	}
377 
378 	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS,
379 		"netpath", "keyserv") == 0) {
380 		syslog(LOG_ERR,
381 			"%s: unable to create service for version %d\n",
382 			argv[0], KEY_VERS);
383 		exit(1);
384 	}
385 
386 	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS2,
387 		"netpath", "keyserv") == 0) {
388 		syslog(LOG_ERR,
389 			"%s: unable to create service for version %d\n",
390 			argv[0], KEY_VERS2);
391 		exit(1);
392 	}
393 
394 	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS3,
395 		"netpath", "keyserv") == 0) {
396 		syslog(LOG_ERR,
397 			"%s: unable to create service for version %d\n",
398 			argv[0], KEY_VERS3);
399 		exit(1);
400 	}
401 
402 	if (!debugging) {
403 		detachfromtty();
404 	}
405 
406 	if (svc_create(keyprogram, KEY_PROG, KEY_VERS, "door") == 0) {
407 		syslog(LOG_ERR,
408 		"%s: unable to create service over doors for version %d\n",
409 			argv[0], KEY_VERS);
410 		exit(1);
411 	}
412 
413 	if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, "door") == 0) {
414 		syslog(LOG_ERR,
415 		"%s: unable to create service over doors for version %d\n",
416 			argv[0], KEY_VERS2);
417 		exit(1);
418 	}
419 
420 	if (svc_create(keyprogram, KEY_PROG, KEY_VERS3, "door") == 0) {
421 		syslog(LOG_ERR,
422 		"%s: unable to create service over doors for version %d\n",
423 			argv[0], KEY_VERS3);
424 		exit(1);
425 	}
426 
427 	svc_run();
428 	abort();
429 	/* NOTREACHED */
430 	return (0);
431 }
432 
433 
434 /*
435  * In the event that we don't get a root password, we try to
436  * randomize the master key the best we can
437  */
438 static void
439 randomize(master)
440 	des_block *master;
441 {
442 	int i;
443 	int seed;
444 	struct timeval tv;
445 	int shift;
446 
447 	seed = 0;
448 	for (i = 0; i < 1024; i++) {
449 		(void) gettimeofday(&tv, (struct timezone *)NULL);
450 		shift = i % 8 * sizeof (int);
451 		seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift));
452 	}
453 #ifdef KEYSERV_RANDOM
454 	srandom(seed);
455 	master->key.low = random();
456 	master->key.high = random();
457 	srandom(seed);
458 #else
459 	/* use stupid dangerous bad rand() */
460 	srand(seed);
461 	master->key.low = rand();
462 	master->key.high = rand();
463 	srand(seed);
464 #endif
465 }
466 
467 static char *
468 fgets_ignorenul(char *s, int n, FILE *stream)
469 {
470 	int fildes = fileno(stream);
471 	int i = 0;
472 	int rs = 0;
473 	char c;
474 
475 	if (fildes < 0)
476 		return (NULL);
477 
478 	while (i < n - 1) {
479 		rs = read(fildes, &c, 1);
480 		switch (rs) {
481 		case 1:
482 			break;
483 		case 0:
484 			/* EOF */
485 			if (i > 0)
486 				s[i] = '\0';
487 			return (NULL);
488 			break;
489 		default:
490 			return (NULL);
491 		}
492 		switch (c) {
493 		case '\0':
494 			break;
495 		case '\n':
496 			s[i] = c;
497 			s[++i] = '\0';
498 			return (s);
499 		default:
500 		if (c != '\0')
501 			s[i++] = c;
502 		}
503 	}
504 	s[i] = '\0';
505 	return (s);
506 }
507 
508 /* Should last until 16384-bit DH keys */
509 #define	MAXROOTKEY_LINE_LEN	4224
510 #define	MAXROOTKEY_LEN		4096
511 #define	ROOTKEY_FILE		"/etc/.rootkey"
512 
513 static int
514 getotherrootkeys(char *name)
515 {
516 	FILE		*rootkey;
517 	char		line[MAXROOTKEY_LINE_LEN];
518 	char		key[MAXROOTKEY_LEN];
519 	algtype_t	algtype;
520 	int		count = 0;
521 
522 	if (!(rootkey = fopen(ROOTKEY, "r")))
523 		return (0);
524 
525 	while (fgets_ignorenul(line, MAXROOTKEY_LINE_LEN, rootkey)) {
526 		debug(KEYSERV_DEBUG0, ("ROOTKEY %d: %s\n", count, line));
527 		count++;
528 		if (sscanf(line, "%s %d", key, &algtype) < 2) {
529 			/*
530 			 * No encryption algorithm found in the file
531 			 * (algtype) so default to DES.
532 			 */
533 			algtype = AUTH_DES_ALGTYPE;
534 		}
535 		if (!strlen(key))
536 			continue;
537 		addmasterkey(key, name, algtype);
538 	}
539 	fclose(rootkey);
540 	return (1);
541 }
542 
543 /*
544  * Try to get root's secret key, by prompting if terminal is a tty, else trying
545  * from standard input.
546  * Returns 1 on success.
547  */
548 static int
549 getrootkey(master, prompt)
550 	des_block *master;
551 	int prompt;
552 {
553 	char *passwd;
554 	char name[MAXNETNAMELEN + 1];
555 	char secret[HEXKEYBYTES + 1];
556 	FILE *fp;
557 	int passwd2des();
558 	int retval;
559 
560 	randomize(master);
561 	if (!getnetname(name)) {
562 	    (void) fprintf(stderr, "keyserv: \
563 failed to generate host's netname when establishing root's key.\n");
564 	    return (0);
565 	}
566 	if (!prompt) {
567 		return (getotherrootkeys(name));
568 	}
569 	/*
570 	 * Decrypt yellow pages publickey entry to get secret key
571 	 */
572 	passwd = getpass("root password:");
573 	passwd2des(passwd, master);
574 	if (!getsecretkey(name, secret, passwd)) {
575 		(void) fprintf(stderr,
576 		"Can't find %s's secret key\n", name);
577 		return (0);
578 	}
579 	if (secret[0] == 0) {
580 		(void) fprintf(stderr,
581 	"Password does not decrypt secret key for %s\n", name);
582 		return (0);
583 	}
584 	if ((fp = fopen(ROOTKEY, "w")) == NULL) {
585 		(void) fprintf(stderr,
586 			"Cannot open %s for write\n", ROOTKEY);
587 		return (0);
588 	}
589 	retval = storeotherrootkeys(fp, name, passwd, secret);
590 	fclose(fp);
591 	return (retval);
592 }
593 
594 /*
595  * Procedures to implement RPC service.  These procedures are named
596  * differently from the definitions in key_prot.h (generated by rpcgen)
597  * because they take different arguments.
598  */
599 char *
600 strstatus(status)
601 	keystatus status;
602 {
603 	switch (status) {
604 	case KEY_SUCCESS:
605 		return ("KEY_SUCCESS");
606 	case KEY_NOSECRET:
607 		return ("KEY_NOSECRET");
608 	case KEY_UNKNOWN:
609 		return ("KEY_UNKNOWN");
610 	case KEY_SYSTEMERR:
611 		return ("KEY_SYSTEMERR");
612 	case KEY_BADALG:
613 		return ("KEY_BADALG");
614 	case KEY_BADLEN:
615 		return ("KEY_BADLEN");
616 	default:
617 		return ("(bad result code)");
618 	}
619 }
620 
621 bool_t
622 __key_set_1_svc(uid, key, status)
623 	uid_t uid;
624 	keybuf key;
625 	keystatus *status;
626 {
627 	if (debugging) {
628 		(void) fprintf(stderr, "set(%d, %.*s) = ", uid,
629 				sizeof (keybuf), key);
630 	}
631 	*status = pk_setkey(uid, key);
632 	if (debugging) {
633 		(void) fprintf(stderr, "%s\n", strstatus(*status));
634 		(void) fflush(stderr);
635 	}
636 	return (TRUE);
637 }
638 
639 bool_t
640 __key_encrypt_pk_2_svc(uid, arg, res)
641 	uid_t uid;
642 	cryptkeyarg2 *arg;
643 	cryptkeyres *res;
644 {
645 
646 	if (debugging) {
647 		(void) fprintf(stderr, "encrypt(%d, %s, %08x%08x) = ", uid,
648 				arg->remotename, arg->deskey.key.high,
649 				arg->deskey.key.low);
650 	}
651 	res->cryptkeyres_u.deskey = arg->deskey;
652 	res->status = pk_encrypt(uid, arg->remotename, &(arg->remotekey),
653 				&res->cryptkeyres_u.deskey);
654 	if (debugging) {
655 		if (res->status == KEY_SUCCESS) {
656 			(void) fprintf(stderr, "%08x%08x\n",
657 					res->cryptkeyres_u.deskey.key.high,
658 					res->cryptkeyres_u.deskey.key.low);
659 		} else {
660 			(void) fprintf(stderr, "%s\n", strstatus(res->status));
661 		}
662 		(void) fflush(stderr);
663 	}
664 	return (TRUE);
665 }
666 
667 bool_t
668 __key_decrypt_pk_2_svc(uid, arg, res)
669 	uid_t uid;
670 	cryptkeyarg2 *arg;
671 	cryptkeyres *res;
672 {
673 
674 	if (debugging) {
675 		(void) fprintf(stderr, "decrypt(%d, %s, %08x%08x) = ", uid,
676 				arg->remotename, arg->deskey.key.high,
677 				arg->deskey.key.low);
678 	}
679 	res->cryptkeyres_u.deskey = arg->deskey;
680 	res->status = pk_decrypt(uid, arg->remotename, &(arg->remotekey),
681 				&res->cryptkeyres_u.deskey);
682 	if (debugging) {
683 		if (res->status == KEY_SUCCESS) {
684 			(void) fprintf(stderr, "%08x%08x\n",
685 					res->cryptkeyres_u.deskey.key.high,
686 					res->cryptkeyres_u.deskey.key.low);
687 		} else {
688 			(void) fprintf(stderr, "%s\n", strstatus(res->status));
689 		}
690 		(void) fflush(stderr);
691 	}
692 	return (TRUE);
693 }
694 
695 bool_t
696 __key_net_put_2_svc(uid, arg, status)
697 	uid_t uid;
698 	key_netstarg *arg;
699 	keystatus *status;
700 {
701 
702 	if (debugging) {
703 		(void) fprintf(stderr, "net_put(%s, %.*s, %.*s) = ",
704 			arg->st_netname, sizeof (arg->st_pub_key),
705 			arg->st_pub_key, sizeof (arg->st_priv_key),
706 			arg->st_priv_key);
707 	};
708 
709 	*status = pk_netput(uid, arg);
710 
711 	if (debugging) {
712 		(void) fprintf(stderr, "%s\n", strstatus(*status));
713 		(void) fflush(stderr);
714 	}
715 
716 	return (TRUE);
717 }
718 
719 /* ARGSUSED */
720 bool_t
721 __key_net_get_2_svc(uid, arg, keynetname)
722 	uid_t uid;
723 	void *arg;
724 	key_netstres *keynetname;
725 {
726 
727 	if (debugging)
728 		(void) fprintf(stderr, "net_get(%d) = ", uid);
729 
730 	keynetname->status = pk_netget(uid, &keynetname->key_netstres_u.knet);
731 	if (debugging) {
732 		if (keynetname->status == KEY_SUCCESS) {
733 			fprintf(stderr, "<%s, %.*s, %.*s>\n",
734 			keynetname->key_netstres_u.knet.st_netname,
735 			sizeof (keynetname->key_netstres_u.knet.st_pub_key),
736 			keynetname->key_netstres_u.knet.st_pub_key,
737 			sizeof (keynetname->key_netstres_u.knet.st_priv_key),
738 			keynetname->key_netstres_u.knet.st_priv_key);
739 		} else {
740 			(void) fprintf(stderr, "NOT FOUND\n");
741 		}
742 		(void) fflush(stderr);
743 	}
744 
745 	return (TRUE);
746 
747 }
748 
749 bool_t
750 __key_get_conv_2_svc(uid, arg, res)
751 	uid_t uid;
752 	keybuf arg;
753 	cryptkeyres *res;
754 {
755 
756 	if (debugging)
757 		(void) fprintf(stderr, "get_conv(%d, %.*s) = ", uid,
758 			sizeof (arg), arg);
759 
760 
761 	res->status = pk_get_conv_key(uid, arg, res);
762 
763 	if (debugging) {
764 		if (res->status == KEY_SUCCESS) {
765 			(void) fprintf(stderr, "%08x%08x\n",
766 				res->cryptkeyres_u.deskey.key.high,
767 				res->cryptkeyres_u.deskey.key.low);
768 		} else {
769 			(void) fprintf(stderr, "%s\n", strstatus(res->status));
770 		}
771 		(void) fflush(stderr);
772 	}
773 	return (TRUE);
774 }
775 
776 
777 bool_t
778 __key_encrypt_1_svc(uid, arg, res)
779 	uid_t uid;
780 	cryptkeyarg *arg;
781 	cryptkeyres *res;
782 {
783 
784 	if (debugging) {
785 		(void) fprintf(stderr, "encrypt(%d, %s, %08x%08x) = ", uid,
786 				arg->remotename, arg->deskey.key.high,
787 				arg->deskey.key.low);
788 	}
789 	res->cryptkeyres_u.deskey = arg->deskey;
790 	res->status = pk_encrypt(uid, arg->remotename, NULL,
791 				&res->cryptkeyres_u.deskey);
792 	if (debugging) {
793 		if (res->status == KEY_SUCCESS) {
794 			(void) fprintf(stderr, "%08x%08x\n",
795 					res->cryptkeyres_u.deskey.key.high,
796 					res->cryptkeyres_u.deskey.key.low);
797 		} else {
798 			(void) fprintf(stderr, "%s\n", strstatus(res->status));
799 		}
800 		(void) fflush(stderr);
801 	}
802 	return (TRUE);
803 }
804 
805 bool_t
806 __key_decrypt_1_svc(uid, arg, res)
807 	uid_t uid;
808 	cryptkeyarg *arg;
809 	cryptkeyres *res;
810 {
811 	if (debugging) {
812 		(void) fprintf(stderr, "decrypt(%d, %s, %08x%08x) = ", uid,
813 				arg->remotename, arg->deskey.key.high,
814 				arg->deskey.key.low);
815 	}
816 	res->cryptkeyres_u.deskey = arg->deskey;
817 	res->status = pk_decrypt(uid, arg->remotename, NULL,
818 				&res->cryptkeyres_u.deskey);
819 	if (debugging) {
820 		if (res->status == KEY_SUCCESS) {
821 			(void) fprintf(stderr, "%08x%08x\n",
822 					res->cryptkeyres_u.deskey.key.high,
823 					res->cryptkeyres_u.deskey.key.low);
824 		} else {
825 			(void) fprintf(stderr, "%s\n", strstatus(res->status));
826 		}
827 		(void) fflush(stderr);
828 	}
829 	return (TRUE);
830 }
831 
832 /* ARGSUSED */
833 bool_t
834 __key_gen_1_svc(v, s, key)
835 	void *v;
836 	struct svc_req *s;
837 	des_block *key;
838 {
839 	struct timeval time;
840 	static des_block keygen;
841 	static mutex_t keygen_mutex = DEFAULTMUTEX;
842 	int r;
843 
844 	(void) gettimeofday(&time, (struct timezone *)NULL);
845 	(void) mutex_lock(&keygen_mutex);
846 	keygen.key.high += (time.tv_sec ^ time.tv_usec);
847 	keygen.key.low += (time.tv_sec ^ time.tv_usec);
848 	r = ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen),
849 		DES_ENCRYPT | DES_HW);
850 	if (r != DESERR_NONE && r != DESERR_NOHWDEVICE) {
851 		mutex_unlock(&keygen_mutex);
852 		return (FALSE);
853 	}
854 	*key = keygen;
855 	mutex_unlock(&keygen_mutex);
856 
857 	des_setparity_g(key);
858 	if (debugging) {
859 		(void) fprintf(stderr, "gen() = %08x%08x\n", key->key.high,
860 					key->key.low);
861 		(void) fflush(stderr);
862 	}
863 	return (TRUE);
864 }
865 
866 /* ARGSUSED */
867 bool_t
868 __key_getcred_1_svc(uid, name, res)
869 	uid_t uid;
870 	netnamestr *name;
871 	getcredres *res;
872 {
873 	struct unixcred *cred;
874 
875 	cred = &res->getcredres_u.cred;
876 	if (!netname2user(*name, (uid_t *)&cred->uid, (gid_t *)&cred->gid,
877 			(int *)&cred->gids.gids_len,
878 					(gid_t *)cred->gids.gids_val)) {
879 		res->status = KEY_UNKNOWN;
880 	} else {
881 		res->status = KEY_SUCCESS;
882 	}
883 	if (debugging) {
884 		(void) fprintf(stderr, "getcred(%s) = ", *name);
885 		if (res->status == KEY_SUCCESS) {
886 			(void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n",
887 				cred->uid, cred->gid, cred->gids.gids_len);
888 		} else {
889 			(void) fprintf(stderr, "%s\n", strstatus(res->status));
890 		}
891 		(void) fflush(stderr);
892 	}
893 	return (TRUE);
894 }
895 
896 /*
897  * Version 3 procedures follow...
898  */
899 
900 static bool_t
901 __key_set_3_svc(uid_t uid, setkeyarg3 *arg, keystatus *status)
902 {
903 	debug(KEYSERV_DEBUG, ("__key_set_3_svc(%d, %d, %d)",
904 		uid, arg->algtype, arg->keylen));
905 	*status = pk_setkey3(uid, arg);
906 	debug(KEYSERV_DEBUG, ("__key_set_3_svc %s", strstatus(*status)));
907 	return (TRUE);
908 }
909 
910 static bool_t
911 __key_encrypt_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res)
912 {
913 	int len, i;
914 	des_block *dp;
915 
916 	debug(KEYSERV_DEBUG, ("encrypt_3(%d %d %s)", uid,
917 		arg->deskey.deskeyarray_len, arg->remotename));
918 	res->status = pk_encrypt3(uid, arg, &res->cryptkeyres3_u.deskey);
919 	len = res->cryptkeyres3_u.deskey.deskeyarray_len;
920 	dp = res->cryptkeyres3_u.deskey.deskeyarray_val;
921 	for (i = 0; i < len; i++) {
922 		debug(KEYSERV_DEBUG0, ("encrypt_3 retval[%d] == (%x,%x)",
923 			i, dp->key.high, dp->key.low));
924 		dp++;
925 	}
926 	debug(KEYSERV_DEBUG, ("encrypt_3 returned %s", strstatus(res->status)));
927 	return (TRUE);
928 }
929 
930 static bool_t
931 __key_decrypt_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res)
932 {
933 	int len, i;
934 	des_block *dp;
935 
936 	debug(KEYSERV_DEBUG, ("decrypt_3(%d, %d, %s)", uid,
937 		arg->deskey.deskeyarray_len, arg->remotename));
938 	res->status = pk_decrypt3(uid, arg, &res->cryptkeyres3_u.deskey);
939 	len = res->cryptkeyres3_u.deskey.deskeyarray_len;
940 	dp = res->cryptkeyres3_u.deskey.deskeyarray_val;
941 	for (i = 0; i < len; i++) {
942 		debug(KEYSERV_DEBUG0, ("decrypt_3 retval[%d] == (%x,%x)",
943 			i, dp->key.high, dp->key.low));
944 		dp++;
945 	}
946 	debug(KEYSERV_DEBUG, ("decrypt_3 returned %s", strstatus(res->status)));
947 	return (TRUE);
948 }
949 
950 /* ARGSUSED */
951 static bool_t
952 __key_gen_3_svc(void *v, keynum_t *kp, deskeyarray *res)
953 {
954 	int i;
955 	keynum_t keynum = *kp;
956 
957 	debug(KEYSERV_DEBUG, ("gen_3(%d %x)", keynum, res));
958 	res->deskeyarray_val = 0;
959 	if (!setdeskeyarray(res, keynum)) {
960 		return (FALSE);
961 	}
962 	for (i = 0; i < keynum; i++) {
963 		debug(KEYSERV_DEBUG, ("gen_3 calling gen_1 %x",
964 			res->deskeyarray_val+i));
965 		__key_gen_1_svc((void *) NULL, (struct svc_req *)NULL,
966 			res->deskeyarray_val+i);
967 		debug(KEYSERV_DEBUG, ("gen_3 val %d %x",
968 			i, *(int *)(res->deskeyarray_val+i)));
969 	}
970 	return (TRUE);
971 }
972 
973 static void
974 __key_gen_3_svc_free(deskeyarray *dp)
975 {
976 	free(dp->deskeyarray_val);
977 }
978 
979 static bool_t
980 __key_getcred_3_svc(uid_t uid, netnamestr *name, getcredres3 *res)
981 {
982 	return (__key_getcred_1_svc(uid, name, (getcredres *)res));
983 }
984 
985 static bool_t
986 __key_encrypt_pk_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res)
987 {
988 	debug(KEYSERV_DEBUG, ("encrypt_pk_3(%d, %s)", uid, arg->remotename));
989 	res->status = pk_encrypt3(uid, arg, &res->cryptkeyres3_u.deskey);
990 	debug(KEYSERV_DEBUG, ("encrypt returned %s", strstatus(res->status)));
991 	return (TRUE);
992 }
993 
994 static void
995 __key_encrypt_pk_3_svc_free(cryptkeyres3 *res)
996 {
997 	if (res->status == KEY_SUCCESS) {
998 		free(res->cryptkeyres3_u.deskey.deskeyarray_val);
999 	}
1000 }
1001 
1002 static bool_t
1003 __key_decrypt_pk_3(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res)
1004 {
1005 	debug(KEYSERV_DEBUG, ("decrypt_pk_3(%d, %s)", uid, arg->remotename));
1006 	res->status = pk_decrypt3(uid, arg, &res->cryptkeyres3_u.deskey);
1007 	debug(KEYSERV_DEBUG, ("encrypt returned %s", strstatus(res->status)));
1008 	return (TRUE);
1009 }
1010 
1011 static void
1012 __key_decrypt_pk_3_free(cryptkeyres3 *res)
1013 {
1014 	if (res->status == KEY_SUCCESS) {
1015 		free(res->cryptkeyres3_u.deskey.deskeyarray_val);
1016 	}
1017 }
1018 
1019 static bool_t
1020 __key_net_put_3_svc(uid_t uid, key_netstarg3 *arg, keystatus *status)
1021 {
1022 	debug(KEYSERV_DEBUG, ("net_put_3 (%d, %x)", uid, arg));
1023 	*status = pk_netput3(uid, arg);
1024 	debug(KEYSERV_DEBUG, ("net_put_3 ret %s", strstatus(*status)));
1025 	return (TRUE);
1026 }
1027 
1028 static bool_t
1029 __key_net_get_3_svc(uid_t uid, mechtype *arg, key_netstres3 *keynetname)
1030 {
1031 	debug(KEYSERV_DEBUG, ("net_get_3 (%d, %x)", uid, arg));
1032 	keynetname->status = pk_netget3(uid,
1033 		arg, &keynetname->key_netstres3_u.knet);
1034 	debug(KEYSERV_DEBUG,
1035 		("net_get_3 ret %s", strstatus(keynetname->status)));
1036 	return (TRUE);
1037 }
1038 
1039 static void
1040 __key_net_get_3_svc_free(key_netstres3 *keynetname)
1041 {
1042 	if (keynetname->status == KEY_SUCCESS) {
1043 		free(keynetname->key_netstres3_u.knet.st_priv_key.keybuf3_val);
1044 		free(keynetname->key_netstres3_u.knet.st_pub_key.keybuf3_val);
1045 		free(keynetname->key_netstres3_u.knet.st_netname);
1046 	}
1047 }
1048 
1049 static bool_t
1050 __key_get_conv_3_svc(uid_t uid, deskeyarg3 *arg, cryptkeyres3 *res)
1051 {
1052 	debug(KEYSERV_DEBUG, ("get_conv_3(%d %x %x)", uid, arg, res));
1053 	res->status = pk_get_conv_key3(uid, arg, res);
1054 	debug(KEYSERV_DEBUG,
1055 		("get_conv_3 ret %s", strstatus(res->status)));
1056 	return (TRUE);
1057 }
1058 
1059 /* ARGSUSED */
1060 static bool_t
1061 __key_clear_3_svc(uid_t uid, void *arg, keystatus *status)
1062 {
1063 	debug(KEYSERV_DEBUG, ("clear_3(%d)", uid));
1064 	*status = pk_clear3(uid);
1065 	debug(KEYSERV_DEBUG, ("clear_3 ret %s", strstatus(*status)));
1066 	return (TRUE);
1067 }
1068 
1069 /*
1070  * RPC boilerplate
1071  */
1072 static void
1073 keyprogram(rqstp, transp)
1074 	struct svc_req *rqstp;
1075 	SVCXPRT *transp;
1076 {
1077 	union {
1078 		keybuf key_set_1_arg;
1079 		cryptkeyarg key_encrypt_1_arg;
1080 		cryptkeyarg key_decrypt_1_arg;
1081 		netnamestr key_getcred_1_arg;
1082 		cryptkeyarg key_encrypt_2_arg;
1083 		cryptkeyarg key_decrypt_2_arg;
1084 		netnamestr key_getcred_2_arg;
1085 		cryptkeyarg2 key_encrypt_pk_2_arg;
1086 		cryptkeyarg2 key_decrypt_pk_2_arg;
1087 		key_netstarg key_net_put_2_arg;
1088 		netobj  key_get_conv_2_arg;
1089 		keybuf3 key_set_3_arg;
1090 		cryptkeyarg3 key_encrypt_3_arg;
1091 		cryptkeyarg3 key_decrypt_3_arg;
1092 		cryptkeyarg3 key_encrypt_pk_3_arg;
1093 		cryptkeyarg3 key_decrypt_pk_3_arg;
1094 		keynum_t key_gen_3_arg;
1095 		netnamestr key_getcred_3_arg;
1096 		key_netstarg3 key_net_put_3_arg;
1097 		key_netstarg3 key_net_get_3_arg;
1098 		deskeyarg3 key_get_conv_3_arg;
1099 	} argument;
1100 	union {
1101 		keystatus status;
1102 		cryptkeyres cres;
1103 		des_block key;
1104 		getcredres gres;
1105 		key_netstres keynetname;
1106 		cryptkeyres3 cres3;
1107 		deskeyarray keyarray;
1108 		getcredres3 gres3;
1109 		key_netstres3 keynetname3;
1110 	} result;
1111 	uint_t gids[MAXGIDS];
1112 	char netname_str[MAXNETNAMELEN + 1];
1113 	bool_t (*xdr_argument)(), (*xdr_result)();
1114 	bool_t (*local)();
1115 	void (*local_free)() = NULL;
1116 	bool_t retval;
1117 	uid_t uid;
1118 	int check_auth;
1119 
1120 	switch (rqstp->rq_proc) {
1121 	case NULLPROC:
1122 		svc_sendreply(transp, xdr_void, (char *)NULL);
1123 		return;
1124 
1125 	case KEY_SET:
1126 		xdr_argument = xdr_keybuf;
1127 		xdr_result = xdr_int;
1128 		local = __key_set_1_svc;
1129 		check_auth = 1;
1130 		break;
1131 
1132 	case KEY_ENCRYPT:
1133 		xdr_argument = xdr_cryptkeyarg;
1134 		xdr_result = xdr_cryptkeyres;
1135 		local = __key_encrypt_1_svc;
1136 		check_auth = 1;
1137 		break;
1138 
1139 	case KEY_DECRYPT:
1140 		xdr_argument = xdr_cryptkeyarg;
1141 		xdr_result = xdr_cryptkeyres;
1142 		local = __key_decrypt_1_svc;
1143 		check_auth = 1;
1144 		break;
1145 
1146 	case KEY_GEN:
1147 		xdr_argument = xdr_void;
1148 		xdr_result = xdr_des_block;
1149 		local = __key_gen_1_svc;
1150 		check_auth = 0;
1151 		break;
1152 
1153 	case KEY_GETCRED:
1154 		xdr_argument = xdr_netnamestr;
1155 		xdr_result = xdr_getcredres;
1156 		local = __key_getcred_1_svc;
1157 		result.gres.getcredres_u.cred.gids.gids_val = gids;
1158 		check_auth = 0;
1159 		break;
1160 
1161 	case KEY_ENCRYPT_PK:
1162 		xdr_argument = xdr_cryptkeyarg2;
1163 		xdr_result = xdr_cryptkeyres;
1164 		local = __key_encrypt_pk_2_svc;
1165 		check_auth = 1;
1166 		break;
1167 
1168 	case KEY_DECRYPT_PK:
1169 		xdr_argument = xdr_cryptkeyarg2;
1170 		xdr_result = xdr_cryptkeyres;
1171 		local = __key_decrypt_pk_2_svc;
1172 		check_auth = 1;
1173 		break;
1174 
1175 
1176 	case KEY_NET_PUT:
1177 		xdr_argument = xdr_key_netstarg;
1178 		xdr_result = xdr_keystatus;
1179 		local = __key_net_put_2_svc;
1180 		check_auth = 1;
1181 		break;
1182 
1183 	case KEY_NET_GET:
1184 		xdr_argument = (xdrproc_t)xdr_void;
1185 		xdr_result = xdr_key_netstres;
1186 		local = __key_net_get_2_svc;
1187 		result.keynetname.key_netstres_u.knet.st_netname = netname_str;
1188 		check_auth = 1;
1189 		break;
1190 
1191 	case KEY_GET_CONV:
1192 		xdr_argument = (xdrproc_t)xdr_keybuf;
1193 		xdr_result = xdr_cryptkeyres;
1194 		local = __key_get_conv_2_svc;
1195 		check_auth = 1;
1196 		break;
1197 
1198 	/*
1199 	 * Version 3 procedures follow...
1200 	 */
1201 
1202 	case KEY_SET_3:
1203 		xdr_argument = (xdrproc_t)xdr_setkeyarg3;
1204 		xdr_result = xdr_keystatus;
1205 		local = __key_set_3_svc;
1206 		check_auth = 1;
1207 		break;
1208 
1209 	case KEY_ENCRYPT_3:
1210 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg3;
1211 		xdr_result = xdr_cryptkeyres3;
1212 		local = __key_encrypt_3_svc;
1213 		check_auth = 1;
1214 		break;
1215 
1216 	case KEY_DECRYPT_3:
1217 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg3;
1218 		xdr_result = xdr_cryptkeyres3;
1219 		local = __key_decrypt_3_svc;
1220 		check_auth = 1;
1221 		break;
1222 
1223 	case KEY_GEN_3:
1224 		xdr_argument = (xdrproc_t)xdr_keynum_t;
1225 		xdr_result = xdr_deskeyarray;
1226 		local = __key_gen_3_svc;
1227 		local_free = __key_gen_3_svc_free;
1228 		check_auth = 0;
1229 		break;
1230 
1231 	case KEY_GETCRED_3:
1232 		xdr_argument = (xdrproc_t)xdr_netnamestr;
1233 		xdr_result = xdr_getcredres3;
1234 		local = __key_getcred_3_svc;
1235 		check_auth = 0;
1236 		break;
1237 
1238 	case KEY_ENCRYPT_PK_3:
1239 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg3;
1240 		xdr_result = xdr_cryptkeyres3;
1241 		local = __key_encrypt_pk_3_svc;
1242 		local_free = __key_encrypt_pk_3_svc_free;
1243 		check_auth = 1;
1244 		break;
1245 
1246 	case KEY_DECRYPT_PK_3:
1247 		xdr_argument = (xdrproc_t)xdr_cryptkeyarg3;
1248 		xdr_result = xdr_cryptkeyres3;
1249 		local = __key_decrypt_pk_3;
1250 		local_free = __key_decrypt_pk_3_free;
1251 		check_auth = 1;
1252 		break;
1253 
1254 	case KEY_NET_PUT_3:
1255 		xdr_argument = (xdrproc_t)xdr_key_netstarg3;
1256 		xdr_result = xdr_keystatus;
1257 		local = __key_net_put_3_svc;
1258 		check_auth = 1;
1259 		break;
1260 
1261 	case KEY_NET_GET_3:
1262 		xdr_argument = (xdrproc_t)xdr_mechtype;
1263 		xdr_result = xdr_key_netstres3;
1264 		local = __key_net_get_3_svc;
1265 		local_free = __key_net_get_3_svc_free;
1266 		check_auth = 1;
1267 		break;
1268 
1269 	case KEY_GET_CONV_3:
1270 		xdr_argument = (xdrproc_t)xdr_deskeyarg3;
1271 		xdr_result = xdr_cryptkeyres3;
1272 		local = __key_get_conv_3_svc;
1273 		check_auth = 1;
1274 		break;
1275 
1276 	case KEY_CLEAR_3:
1277 		xdr_argument = (xdrproc_t)xdr_void;
1278 		xdr_result = xdr_keystatus;
1279 		local = __key_clear_3_svc;
1280 		check_auth = 1;
1281 		break;
1282 
1283 	default:
1284 		svcerr_noproc(transp);
1285 		return;
1286 	}
1287 	if (check_auth) {
1288 		if (!get_auth(transp, rqstp, &uid)) {
1289 			if (debugging) {
1290 				(void) fprintf(stderr,
1291 					"not local privileged process\n");
1292 			}
1293 			svcerr_weakauth(transp);
1294 			return;
1295 		}
1296 	}
1297 
1298 	memset((char *)&argument, 0, sizeof (argument));
1299 	if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
1300 		svcerr_decode(transp);
1301 		return;
1302 	}
1303 	retval = (*local)(uid, &argument, &result);
1304 	if (retval && !svc_sendreply(transp, xdr_result, (char *)&result)) {
1305 		if (debugging)
1306 			(void) fprintf(stderr, "unable to reply\n");
1307 		svcerr_systemerr(transp);
1308 	}
1309 	if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
1310 		if (debugging)
1311 			(void) fprintf(stderr,
1312 			"unable to free arguments\n");
1313 		exit(1);
1314 	}
1315 	if (local_free) {
1316 		(*local_free)(&result);
1317 	}
1318 }
1319 
1320 static bool_t
1321 get_auth(trans, rqstp, uid)
1322 	SVCXPRT *trans;
1323 	struct svc_req *rqstp;
1324 	uid_t *uid;
1325 {
1326 	svc_local_cred_t cred;
1327 
1328 	if (!svc_get_local_cred(trans, &cred)) {
1329 		if (debugging)
1330 			fprintf(stderr, "svc_get_local_cred failed %s %s\n",
1331 				trans->xp_netid, trans->xp_tp);
1332 		return (FALSE);
1333 	}
1334 	if (debugging)
1335 		fprintf(stderr, "local_uid  %d\n", cred.euid);
1336 	if (rqstp->rq_cred.oa_flavor == AUTH_SYS ||
1337 	    rqstp->rq_cred.oa_flavor == AUTH_LOOPBACK) {
1338 /* LINTED pointer alignment */
1339 		*uid = ((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid;
1340 		return (*uid == cred.euid || cred.euid == 0);
1341 	} else {
1342 		*uid = cred.euid;
1343 		return (TRUE);
1344 	}
1345 }
1346 
1347 static int
1348 get_cache_size(size)
1349 char *size;
1350 {
1351 	int csize, len;
1352 
1353 	len = (int)strlen(size);
1354 	if (len == 0) {
1355 		usage();
1356 	}
1357 
1358 	if (size[len-1] == 'M' || size[len-1] == 'm') {
1359 		/*
1360 		 * cache size in MB
1361 		 */
1362 		size[len-1] = '\0';
1363 		csize = atoi(size);
1364 	} else {
1365 		csize = atoi(size);
1366 		/*
1367 		 * negative size indicates number of entries in cache
1368 		 */
1369 		csize = 0 - csize;
1370 	}
1371 
1372 	if (csize == 0) {
1373 		(void) fprintf(stderr, "invalid cache size: %s\n", size);
1374 		usage();
1375 	}
1376 
1377 	return (csize);
1378 }
1379 
1380 static void
1381 usage()
1382 {
1383 	(void) fprintf(stderr, "usage: \n");
1384 	(void) fprintf(stderr, "keyserv [-c]|[-s ");
1385 	(void) fprintf(stderr, "<size>|<mechtype>=<size>[,...]] [-n] [-D] ");
1386 	(void) fprintf(stderr, "[-d | -e] ");
1387 	(void) fprintf(stderr, "[-t threads]\n");
1388 	(void) fprintf(stderr, "-d disables the use of default keys\n");
1389 	(void) fprintf(stderr, "-e enables the use of default keys\n");
1390 	exit(1);
1391 }
1392 
1393 static void
1394 defaults(void)
1395 {
1396 	register int  flags;
1397 	register char *ptr;
1398 
1399 	if (defopen(defaults_file) == 0) {
1400 		/*
1401 		 * ignore case
1402 		 */
1403 		flags = defcntl(DC_GETFLAGS, 0);
1404 		TURNOFF(flags, DC_CASE);
1405 		(void) defcntl(DC_SETFLAGS, flags);
1406 
1407 		if ((ptr = defread("ENABLE_NOBODY_KEYS=")) != NULL) {
1408 			if (strcasecmp(ptr, "NO") == 0) {
1409 				use_nobody_keys = FALSE;
1410 			}
1411 		}
1412 
1413 		(void) defopen((char *)NULL);
1414 	}
1415 }
1416