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