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