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
76extern long random();
77#endif
78
79extern keystatus pk_setkey();
80extern keystatus pk_encrypt();
81extern keystatus pk_decrypt();
82extern keystatus pk_netput();
83extern keystatus pk_netget();
84extern keystatus pk_get_conv_key();
85extern bool_t svc_get_local_cred();
86
87extern keystatus pk_setkey3();
88extern keystatus pk_encrypt3();
89extern keystatus pk_decrypt3();
90extern keystatus pk_netput3();
91extern keystatus pk_netget3();
92extern keystatus pk_get_conv_key3();
93extern keystatus pk_clear3();
94
95extern int init_mechs();
96extern int addmasterkey();
97extern int storeotherrootkeys();
98extern int setdeskeyarray();
99
100extern int getdomainname();
101
102static void randomize();
103static void usage();
104static void defaults();
105static int getrootkey();
106static int get_cache_size(char *);
107static bool_t get_auth();
108
109#ifdef DEBUG
110extern int test_debug();
111extern int real_debug();
112int debugging = 1;
113#else
114int debugging = 0;
115#endif
116
117static void keyprogram();
118static des_block masterkey;
119char *getenv();
120static char ROOTKEY[] = "/etc/.rootkey";
121
122static char *defaults_file = "/etc/default/keyserv";
123static 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
134bool_t __key_encrypt_pk_2_svc();
135bool_t __key_decrypt_pk_2_svc();
136bool_t __key_gen_1_svc();
137
138extern bool_t (*__key_encryptsession_pk_LOCAL)();
139extern bool_t (*__key_decryptsession_pk_LOCAL)();
140extern bool_t (*__key_gendes_LOCAL)();
141
142static int nthreads = 32;
143
144/* Disk caching of common keys on by default */
145int disk_caching = 1;
146
147mechanism_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 */
155static int default_cache = 1;
156
157int *cache_size;
158char **cache_options;
159
160int
161main(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 */
439static void
440randomize(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
468static char *
469fgets_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
514static int
515getotherrootkeys(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 */
549static int
550getrootkey(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: \
564failed 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 */
600char *
601strstatus(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
622bool_t
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
640bool_t
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
668bool_t
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
696bool_t
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 */
721bool_t
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
750bool_t
751__key_get_conv_2_svc(uid_t uid, keybuf arg, cryptkeyres *res)
752{
753
754	if (debugging)
755		(void) fprintf(stderr, "get_conv(%d, %.*s) = ", uid,
756		    sizeof (keybuf), arg);
757
758
759	res->status = pk_get_conv_key(uid, arg, res);
760
761	if (debugging) {
762		if (res->status == KEY_SUCCESS) {
763			(void) fprintf(stderr, "%08x%08x\n",
764				res->cryptkeyres_u.deskey.key.high,
765				res->cryptkeyres_u.deskey.key.low);
766		} else {
767			(void) fprintf(stderr, "%s\n", strstatus(res->status));
768		}
769		(void) fflush(stderr);
770	}
771	return (TRUE);
772}
773
774
775bool_t
776__key_encrypt_1_svc(uid, arg, res)
777	uid_t uid;
778	cryptkeyarg *arg;
779	cryptkeyres *res;
780{
781
782	if (debugging) {
783		(void) fprintf(stderr, "encrypt(%d, %s, %08x%08x) = ", uid,
784				arg->remotename, arg->deskey.key.high,
785				arg->deskey.key.low);
786	}
787	res->cryptkeyres_u.deskey = arg->deskey;
788	res->status = pk_encrypt(uid, arg->remotename, NULL,
789				&res->cryptkeyres_u.deskey);
790	if (debugging) {
791		if (res->status == KEY_SUCCESS) {
792			(void) fprintf(stderr, "%08x%08x\n",
793					res->cryptkeyres_u.deskey.key.high,
794					res->cryptkeyres_u.deskey.key.low);
795		} else {
796			(void) fprintf(stderr, "%s\n", strstatus(res->status));
797		}
798		(void) fflush(stderr);
799	}
800	return (TRUE);
801}
802
803bool_t
804__key_decrypt_1_svc(uid, arg, res)
805	uid_t uid;
806	cryptkeyarg *arg;
807	cryptkeyres *res;
808{
809	if (debugging) {
810		(void) fprintf(stderr, "decrypt(%d, %s, %08x%08x) = ", uid,
811				arg->remotename, arg->deskey.key.high,
812				arg->deskey.key.low);
813	}
814	res->cryptkeyres_u.deskey = arg->deskey;
815	res->status = pk_decrypt(uid, arg->remotename, NULL,
816				&res->cryptkeyres_u.deskey);
817	if (debugging) {
818		if (res->status == KEY_SUCCESS) {
819			(void) fprintf(stderr, "%08x%08x\n",
820					res->cryptkeyres_u.deskey.key.high,
821					res->cryptkeyres_u.deskey.key.low);
822		} else {
823			(void) fprintf(stderr, "%s\n", strstatus(res->status));
824		}
825		(void) fflush(stderr);
826	}
827	return (TRUE);
828}
829
830/* ARGSUSED */
831bool_t
832__key_gen_1_svc(v, s, key)
833	void *v;
834	struct svc_req *s;
835	des_block *key;
836{
837	struct timeval time;
838	static des_block keygen;
839	static mutex_t keygen_mutex = DEFAULTMUTEX;
840	int r;
841
842	(void) gettimeofday(&time, (struct timezone *)NULL);
843	(void) mutex_lock(&keygen_mutex);
844	keygen.key.high += (time.tv_sec ^ time.tv_usec);
845	keygen.key.low += (time.tv_sec ^ time.tv_usec);
846	r = ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen),
847		DES_ENCRYPT | DES_HW);
848	if (r != DESERR_NONE && r != DESERR_NOHWDEVICE) {
849		mutex_unlock(&keygen_mutex);
850		return (FALSE);
851	}
852	*key = keygen;
853	mutex_unlock(&keygen_mutex);
854
855	des_setparity_g(key);
856	if (debugging) {
857		(void) fprintf(stderr, "gen() = %08x%08x\n", key->key.high,
858					key->key.low);
859		(void) fflush(stderr);
860	}
861	return (TRUE);
862}
863
864/* ARGSUSED */
865bool_t
866__key_getcred_1_svc(uid, name, res)
867	uid_t uid;
868	netnamestr *name;
869	getcredres *res;
870{
871	struct unixcred *cred;
872
873	cred = &res->getcredres_u.cred;
874	if (!netname2user(*name, (uid_t *)&cred->uid, (gid_t *)&cred->gid,
875			(int *)&cred->gids.gids_len,
876					(gid_t *)cred->gids.gids_val)) {
877		res->status = KEY_UNKNOWN;
878	} else {
879		res->status = KEY_SUCCESS;
880	}
881	if (debugging) {
882		(void) fprintf(stderr, "getcred(%s) = ", *name);
883		if (res->status == KEY_SUCCESS) {
884			(void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n",
885				cred->uid, cred->gid, cred->gids.gids_len);
886		} else {
887			(void) fprintf(stderr, "%s\n", strstatus(res->status));
888		}
889		(void) fflush(stderr);
890	}
891	return (TRUE);
892}
893
894/*
895 * Version 3 procedures follow...
896 */
897
898static bool_t
899__key_set_3_svc(uid_t uid, setkeyarg3 *arg, keystatus *status)
900{
901	debug(KEYSERV_DEBUG, ("__key_set_3_svc(%d, %d, %d)",
902	    uid, arg->algtype, arg->keylen));
903	*status = pk_setkey3(uid, arg);
904	debug(KEYSERV_DEBUG, ("__key_set_3_svc %s", strstatus(*status)));
905	return (TRUE);
906}
907
908static bool_t
909__key_encrypt_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res)
910{
911	int len, i;
912	des_block *dp;
913
914	debug(KEYSERV_DEBUG, ("encrypt_3(%d %d %s)", uid,
915	    arg->deskey.deskeyarray_len, arg->remotename));
916	res->status = pk_encrypt3(uid, arg, &res->cryptkeyres3_u.deskey);
917	len = res->cryptkeyres3_u.deskey.deskeyarray_len;
918	dp = res->cryptkeyres3_u.deskey.deskeyarray_val;
919	for (i = 0; i < len; i++) {
920		debug(KEYSERV_DEBUG0, ("encrypt_3 retval[%d] == (%x,%x)",
921		    i, dp->key.high, dp->key.low));
922		dp++;
923	}
924	debug(KEYSERV_DEBUG, ("encrypt_3 returned %s", strstatus(res->status)));
925	return (TRUE);
926}
927
928static bool_t
929__key_decrypt_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res)
930{
931	int len, i;
932	des_block *dp;
933
934	debug(KEYSERV_DEBUG, ("decrypt_3(%d, %d, %s)", uid,
935	    arg->deskey.deskeyarray_len, arg->remotename));
936	res->status = pk_decrypt3(uid, arg, &res->cryptkeyres3_u.deskey);
937	len = res->cryptkeyres3_u.deskey.deskeyarray_len;
938	dp = res->cryptkeyres3_u.deskey.deskeyarray_val;
939	for (i = 0; i < len; i++) {
940		debug(KEYSERV_DEBUG0, ("decrypt_3 retval[%d] == (%x,%x)",
941		    i, dp->key.high, dp->key.low));
942		dp++;
943	}
944	debug(KEYSERV_DEBUG, ("decrypt_3 returned %s", strstatus(res->status)));
945	return (TRUE);
946}
947
948/* ARGSUSED */
949static bool_t
950__key_gen_3_svc(void *v, keynum_t *kp, deskeyarray *res)
951{
952	int i;
953	keynum_t keynum = *kp;
954
955	debug(KEYSERV_DEBUG, ("gen_3(%d %x)", keynum, res));
956	res->deskeyarray_val = 0;
957	if (!setdeskeyarray(res, keynum)) {
958		return (FALSE);
959	}
960	for (i = 0; i < keynum; i++) {
961		debug(KEYSERV_DEBUG, ("gen_3 calling gen_1 %x",
962		    res->deskeyarray_val+i));
963		__key_gen_1_svc((void *) NULL, (struct svc_req *)NULL,
964		    res->deskeyarray_val+i);
965		debug(KEYSERV_DEBUG, ("gen_3 val %d %x",
966		    i, *(int *)(res->deskeyarray_val+i)));
967	}
968	return (TRUE);
969}
970
971static void
972__key_gen_3_svc_free(deskeyarray *dp)
973{
974	free(dp->deskeyarray_val);
975}
976
977static bool_t
978__key_getcred_3_svc(uid_t uid, netnamestr *name, getcredres3 *res)
979{
980	return (__key_getcred_1_svc(uid, name, (getcredres *)res));
981}
982
983static bool_t
984__key_encrypt_pk_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res)
985{
986	debug(KEYSERV_DEBUG, ("encrypt_pk_3(%d, %s)", uid, arg->remotename));
987	res->status = pk_encrypt3(uid, arg, &res->cryptkeyres3_u.deskey);
988	debug(KEYSERV_DEBUG, ("encrypt returned %s", strstatus(res->status)));
989	return (TRUE);
990}
991
992static void
993__key_encrypt_pk_3_svc_free(cryptkeyres3 *res)
994{
995	if (res->status == KEY_SUCCESS) {
996		free(res->cryptkeyres3_u.deskey.deskeyarray_val);
997	}
998}
999
1000static bool_t
1001__key_decrypt_pk_3(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res)
1002{
1003	debug(KEYSERV_DEBUG, ("decrypt_pk_3(%d, %s)", uid, arg->remotename));
1004	res->status = pk_decrypt3(uid, arg, &res->cryptkeyres3_u.deskey);
1005	debug(KEYSERV_DEBUG, ("encrypt returned %s", strstatus(res->status)));
1006	return (TRUE);
1007}
1008
1009static void
1010__key_decrypt_pk_3_free(cryptkeyres3 *res)
1011{
1012	if (res->status == KEY_SUCCESS) {
1013		free(res->cryptkeyres3_u.deskey.deskeyarray_val);
1014	}
1015}
1016
1017static bool_t
1018__key_net_put_3_svc(uid_t uid, key_netstarg3 *arg, keystatus *status)
1019{
1020	debug(KEYSERV_DEBUG, ("net_put_3 (%d, %x)", uid, arg));
1021	*status = pk_netput3(uid, arg);
1022	debug(KEYSERV_DEBUG, ("net_put_3 ret %s", strstatus(*status)));
1023	return (TRUE);
1024}
1025
1026static bool_t
1027__key_net_get_3_svc(uid_t uid, mechtype *arg, key_netstres3 *keynetname)
1028{
1029	debug(KEYSERV_DEBUG, ("net_get_3 (%d, %x)", uid, arg));
1030	keynetname->status = pk_netget3(uid,
1031	    arg, &keynetname->key_netstres3_u.knet);
1032	debug(KEYSERV_DEBUG,
1033	    ("net_get_3 ret %s", strstatus(keynetname->status)));
1034	return (TRUE);
1035}
1036
1037static void
1038__key_net_get_3_svc_free(key_netstres3 *keynetname)
1039{
1040	if (keynetname->status == KEY_SUCCESS) {
1041		free(keynetname->key_netstres3_u.knet.st_priv_key.keybuf3_val);
1042		free(keynetname->key_netstres3_u.knet.st_pub_key.keybuf3_val);
1043		free(keynetname->key_netstres3_u.knet.st_netname);
1044	}
1045}
1046
1047static bool_t
1048__key_get_conv_3_svc(uid_t uid, deskeyarg3 *arg, cryptkeyres3 *res)
1049{
1050	debug(KEYSERV_DEBUG, ("get_conv_3(%d %x %x)", uid, arg, res));
1051	res->status = pk_get_conv_key3(uid, arg, res);
1052	debug(KEYSERV_DEBUG,
1053	    ("get_conv_3 ret %s", strstatus(res->status)));
1054	return (TRUE);
1055}
1056
1057/* ARGSUSED */
1058static bool_t
1059__key_clear_3_svc(uid_t uid, void *arg, keystatus *status)
1060{
1061	debug(KEYSERV_DEBUG, ("clear_3(%d)", uid));
1062	*status = pk_clear3(uid);
1063	debug(KEYSERV_DEBUG, ("clear_3 ret %s", strstatus(*status)));
1064	return (TRUE);
1065}
1066
1067/*
1068 * RPC boilerplate
1069 */
1070static void
1071keyprogram(rqstp, transp)
1072	struct svc_req *rqstp;
1073	SVCXPRT *transp;
1074{
1075	union {
1076		keybuf key_set_1_arg;
1077		cryptkeyarg key_encrypt_1_arg;
1078		cryptkeyarg key_decrypt_1_arg;
1079		netnamestr key_getcred_1_arg;
1080		cryptkeyarg key_encrypt_2_arg;
1081		cryptkeyarg key_decrypt_2_arg;
1082		netnamestr key_getcred_2_arg;
1083		cryptkeyarg2 key_encrypt_pk_2_arg;
1084		cryptkeyarg2 key_decrypt_pk_2_arg;
1085		key_netstarg key_net_put_2_arg;
1086		netobj  key_get_conv_2_arg;
1087		keybuf3 key_set_3_arg;
1088		cryptkeyarg3 key_encrypt_3_arg;
1089		cryptkeyarg3 key_decrypt_3_arg;
1090		cryptkeyarg3 key_encrypt_pk_3_arg;
1091		cryptkeyarg3 key_decrypt_pk_3_arg;
1092		keynum_t key_gen_3_arg;
1093		netnamestr key_getcred_3_arg;
1094		key_netstarg3 key_net_put_3_arg;
1095		key_netstarg3 key_net_get_3_arg;
1096		deskeyarg3 key_get_conv_3_arg;
1097	} argument;
1098	union {
1099		keystatus status;
1100		cryptkeyres cres;
1101		des_block key;
1102		getcredres gres;
1103		key_netstres keynetname;
1104		cryptkeyres3 cres3;
1105		deskeyarray keyarray;
1106		getcredres3 gres3;
1107		key_netstres3 keynetname3;
1108	} result;
1109	uint_t gids[MAXGIDS];
1110	char netname_str[MAXNETNAMELEN + 1];
1111	bool_t (*xdr_argument)(), (*xdr_result)();
1112	bool_t (*local)();
1113	void (*local_free)() = NULL;
1114	bool_t retval;
1115	uid_t uid;
1116	int check_auth;
1117
1118	switch (rqstp->rq_proc) {
1119	case NULLPROC:
1120		svc_sendreply(transp, xdr_void, (char *)NULL);
1121		return;
1122
1123	case KEY_SET:
1124		xdr_argument = xdr_keybuf;
1125		xdr_result = xdr_int;
1126		local = __key_set_1_svc;
1127		check_auth = 1;
1128		break;
1129
1130	case KEY_ENCRYPT:
1131		xdr_argument = xdr_cryptkeyarg;
1132		xdr_result = xdr_cryptkeyres;
1133		local = __key_encrypt_1_svc;
1134		check_auth = 1;
1135		break;
1136
1137	case KEY_DECRYPT:
1138		xdr_argument = xdr_cryptkeyarg;
1139		xdr_result = xdr_cryptkeyres;
1140		local = __key_decrypt_1_svc;
1141		check_auth = 1;
1142		break;
1143
1144	case KEY_GEN:
1145		xdr_argument = xdr_void;
1146		xdr_result = xdr_des_block;
1147		local = __key_gen_1_svc;
1148		check_auth = 0;
1149		break;
1150
1151	case KEY_GETCRED:
1152		xdr_argument = xdr_netnamestr;
1153		xdr_result = xdr_getcredres;
1154		local = __key_getcred_1_svc;
1155		result.gres.getcredres_u.cred.gids.gids_val = gids;
1156		check_auth = 0;
1157		break;
1158
1159	case KEY_ENCRYPT_PK:
1160		xdr_argument = xdr_cryptkeyarg2;
1161		xdr_result = xdr_cryptkeyres;
1162		local = __key_encrypt_pk_2_svc;
1163		check_auth = 1;
1164		break;
1165
1166	case KEY_DECRYPT_PK:
1167		xdr_argument = xdr_cryptkeyarg2;
1168		xdr_result = xdr_cryptkeyres;
1169		local = __key_decrypt_pk_2_svc;
1170		check_auth = 1;
1171		break;
1172
1173
1174	case KEY_NET_PUT:
1175		xdr_argument = xdr_key_netstarg;
1176		xdr_result = xdr_keystatus;
1177		local = __key_net_put_2_svc;
1178		check_auth = 1;
1179		break;
1180
1181	case KEY_NET_GET:
1182		xdr_argument = (xdrproc_t)xdr_void;
1183		xdr_result = xdr_key_netstres;
1184		local = __key_net_get_2_svc;
1185		result.keynetname.key_netstres_u.knet.st_netname = netname_str;
1186		check_auth = 1;
1187		break;
1188
1189	case KEY_GET_CONV:
1190		xdr_argument = (xdrproc_t)xdr_keybuf;
1191		xdr_result = xdr_cryptkeyres;
1192		local = __key_get_conv_2_svc;
1193		check_auth = 1;
1194		break;
1195
1196	/*
1197	 * Version 3 procedures follow...
1198	 */
1199
1200	case KEY_SET_3:
1201		xdr_argument = (xdrproc_t)xdr_setkeyarg3;
1202		xdr_result = xdr_keystatus;
1203		local = __key_set_3_svc;
1204		check_auth = 1;
1205		break;
1206
1207	case KEY_ENCRYPT_3:
1208		xdr_argument = (xdrproc_t)xdr_cryptkeyarg3;
1209		xdr_result = xdr_cryptkeyres3;
1210		local = __key_encrypt_3_svc;
1211		check_auth = 1;
1212		break;
1213
1214	case KEY_DECRYPT_3:
1215		xdr_argument = (xdrproc_t)xdr_cryptkeyarg3;
1216		xdr_result = xdr_cryptkeyres3;
1217		local = __key_decrypt_3_svc;
1218		check_auth = 1;
1219		break;
1220
1221	case KEY_GEN_3:
1222		xdr_argument = (xdrproc_t)xdr_keynum_t;
1223		xdr_result = xdr_deskeyarray;
1224		local = __key_gen_3_svc;
1225		local_free = __key_gen_3_svc_free;
1226		check_auth = 0;
1227		break;
1228
1229	case KEY_GETCRED_3:
1230		xdr_argument = (xdrproc_t)xdr_netnamestr;
1231		xdr_result = xdr_getcredres3;
1232		local = __key_getcred_3_svc;
1233		check_auth = 0;
1234		break;
1235
1236	case KEY_ENCRYPT_PK_3:
1237		xdr_argument = (xdrproc_t)xdr_cryptkeyarg3;
1238		xdr_result = xdr_cryptkeyres3;
1239		local = __key_encrypt_pk_3_svc;
1240		local_free = __key_encrypt_pk_3_svc_free;
1241		check_auth = 1;
1242		break;
1243
1244	case KEY_DECRYPT_PK_3:
1245		xdr_argument = (xdrproc_t)xdr_cryptkeyarg3;
1246		xdr_result = xdr_cryptkeyres3;
1247		local = __key_decrypt_pk_3;
1248		local_free = __key_decrypt_pk_3_free;
1249		check_auth = 1;
1250		break;
1251
1252	case KEY_NET_PUT_3:
1253		xdr_argument = (xdrproc_t)xdr_key_netstarg3;
1254		xdr_result = xdr_keystatus;
1255		local = __key_net_put_3_svc;
1256		check_auth = 1;
1257		break;
1258
1259	case KEY_NET_GET_3:
1260		xdr_argument = (xdrproc_t)xdr_mechtype;
1261		xdr_result = xdr_key_netstres3;
1262		local = __key_net_get_3_svc;
1263		local_free = __key_net_get_3_svc_free;
1264		check_auth = 1;
1265		break;
1266
1267	case KEY_GET_CONV_3:
1268		xdr_argument = (xdrproc_t)xdr_deskeyarg3;
1269		xdr_result = xdr_cryptkeyres3;
1270		local = __key_get_conv_3_svc;
1271		check_auth = 1;
1272		break;
1273
1274	case KEY_CLEAR_3:
1275		xdr_argument = (xdrproc_t)xdr_void;
1276		xdr_result = xdr_keystatus;
1277		local = __key_clear_3_svc;
1278		check_auth = 1;
1279		break;
1280
1281	default:
1282		svcerr_noproc(transp);
1283		return;
1284	}
1285	if (check_auth) {
1286		if (!get_auth(transp, rqstp, &uid)) {
1287			if (debugging) {
1288				(void) fprintf(stderr,
1289					"not local privileged process\n");
1290			}
1291			svcerr_weakauth(transp);
1292			return;
1293		}
1294	}
1295
1296	memset((char *)&argument, 0, sizeof (argument));
1297	if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
1298		svcerr_decode(transp);
1299		return;
1300	}
1301	retval = (*local)(uid, &argument, &result);
1302	if (retval && !svc_sendreply(transp, xdr_result, (char *)&result)) {
1303		if (debugging)
1304			(void) fprintf(stderr, "unable to reply\n");
1305		svcerr_systemerr(transp);
1306	}
1307	if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
1308		if (debugging)
1309			(void) fprintf(stderr,
1310			"unable to free arguments\n");
1311		exit(1);
1312	}
1313	if (local_free) {
1314		(*local_free)(&result);
1315	}
1316}
1317
1318static bool_t
1319get_auth(trans, rqstp, uid)
1320	SVCXPRT *trans;
1321	struct svc_req *rqstp;
1322	uid_t *uid;
1323{
1324	svc_local_cred_t cred;
1325
1326	if (!svc_get_local_cred(trans, &cred)) {
1327		if (debugging)
1328			fprintf(stderr, "svc_get_local_cred failed %s %s\n",
1329				trans->xp_netid, trans->xp_tp);
1330		return (FALSE);
1331	}
1332	if (debugging)
1333		fprintf(stderr, "local_uid  %d\n", cred.euid);
1334	if (rqstp->rq_cred.oa_flavor == AUTH_SYS ||
1335	    rqstp->rq_cred.oa_flavor == AUTH_LOOPBACK) {
1336		CTASSERT(sizeof (struct authunix_parms) <= RQCRED_SIZE);
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
1346static int
1347get_cache_size(size)
1348char *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
1379static void
1380usage()
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
1392static void
1393defaults(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