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