126234Swpaul/*
226234Swpaul * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
326234Swpaul * unrestricted use provided that this legend is included on all tape
426234Swpaul * media and as a part of the software program in whole or part.  Users
526234Swpaul * may copy or modify Sun RPC without charge, but are not authorized
626234Swpaul * to license or distribute it to anyone else except as part of a product or
726234Swpaul * program developed by the user.
826234Swpaul *
926234Swpaul * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1026234Swpaul * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1126234Swpaul * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1226234Swpaul *
1326234Swpaul * Sun RPC is provided with no support and without any obligation on the
1426234Swpaul * part of Sun Microsystems, Inc. to assist in its use, correction,
1526234Swpaul * modification or enhancement.
1626234Swpaul *
1726234Swpaul * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
1826234Swpaul * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
1926234Swpaul * OR ANY PART THEREOF.
2026234Swpaul *
2126234Swpaul * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2226234Swpaul * or profits or other special, indirect and consequential damages, even if
2326234Swpaul * Sun has been advised of the possibility of such damages.
2426234Swpaul *
2526234Swpaul * Sun Microsystems, Inc.
2626234Swpaul * 2550 Garcia Avenue
2726234Swpaul * Mountain View, California  94043
2826234Swpaul */
2926234Swpaul
3029735Scharnier#ifndef lint
3129735Scharnier#if 0
3229735Scharnierstatic char sccsid[] = "@(#)keyserv.c	1.15	94/04/25 SMI";
3329735Scharnier#endif
3429735Scharnierstatic const char rcsid[] =
3550479Speter  "$FreeBSD$";
3629735Scharnier#endif /* not lint */
3726234Swpaul
3826234Swpaul/*
3926234Swpaul * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
4026234Swpaul */
4126234Swpaul
4226234Swpaul/*
4326234Swpaul * Keyserver
4426234Swpaul * Store secret keys per uid. Do public key encryption and decryption
4526234Swpaul * operations. Generate "random" keys.
4626234Swpaul * Do not talk to anything but a local root
4726234Swpaul * process on the local transport only
4826234Swpaul */
4926234Swpaul
5029735Scharnier#include <err.h>
5129735Scharnier#include <pwd.h>
5226234Swpaul#include <stdio.h>
5326234Swpaul#include <stdlib.h>
5429735Scharnier#include <string.h>
5526234Swpaul#include <unistd.h>
5626234Swpaul#include <sys/stat.h>
5726234Swpaul#include <sys/types.h>
5826234Swpaul#include <rpc/rpc.h>
5926234Swpaul#include <sys/param.h>
6026234Swpaul#include <sys/file.h>
6126234Swpaul#include <rpc/des_crypt.h>
6226234Swpaul#include <rpc/des.h>
6326234Swpaul#include <rpc/key_prot.h>
6426234Swpaul#include <rpcsvc/crypt.h>
6526234Swpaul#include "keyserv.h"
6626234Swpaul
6726234Swpaul#ifndef NGROUPS
6826234Swpaul#define	NGROUPS 16
6926234Swpaul#endif
7026234Swpaul
7126234Swpaul#ifndef KEYSERVSOCK
7226234Swpaul#define KEYSERVSOCK "/var/run/keyservsock"
7326234Swpaul#endif
7426234Swpaul
75173412Skevlostatic void randomize( des_block * );
76173412Skevlostatic void usage( void );
77173412Skevlostatic int getrootkey( des_block *, int );
78173412Skevlostatic int root_auth( SVCXPRT *, struct svc_req * );
7926234Swpaul
8026234Swpaul#ifdef DEBUG
8126234Swpaulstatic int debugging = 1;
8226234Swpaul#else
8326234Swpaulstatic int debugging = 0;
8426234Swpaul#endif
8526234Swpaul
8626234Swpaulstatic void keyprogram();
8726234Swpaulstatic des_block masterkey;
8826234Swpaulchar *getenv();
8926234Swpaulstatic char ROOTKEY[] = "/etc/.rootkey";
9026234Swpaul
9126234Swpaul/*
9226234Swpaul * Hack to allow the keyserver to use AUTH_DES (for authenticated
9326234Swpaul * NIS+ calls, for example).  The only functions that get called
9426234Swpaul * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
9526234Swpaul *
9626234Swpaul * The approach is to have the keyserver fill in pointers to local
9726234Swpaul * implementations of these functions, and to call those in key_call().
9826234Swpaul */
9926234Swpaul
10026234Swpaulextern cryptkeyres *(*__key_encryptsession_pk_LOCAL)();
10126234Swpaulextern cryptkeyres *(*__key_decryptsession_pk_LOCAL)();
10226234Swpaulextern des_block *(*__key_gendes_LOCAL)();
10326234Swpaulextern int (*__des_crypt_LOCAL)();
10426234Swpaul
105173412Skevlocryptkeyres *key_encrypt_pk_2_svc_prog( uid_t, cryptkeyarg2 * );
106173412Skevlocryptkeyres *key_decrypt_pk_2_svc_prog( uid_t, cryptkeyarg2 * );
107173412Skevlodes_block *key_gen_1_svc_prog( void *, struct svc_req * );
10826234Swpaul
10926234Swpaulint
11026234Swpaulmain(argc, argv)
11126234Swpaul	int argc;
11226234Swpaul	char *argv[];
11326234Swpaul{
11426234Swpaul	int nflag = 0;
11526234Swpaul	int c;
11626234Swpaul	int warn = 0;
11726234Swpaul	char *path = NULL;
11890317Salfred	void *localhandle;
11990317Salfred	register SVCXPRT *transp;
12090317Salfred	struct netconfig *nconf = NULL;
12126234Swpaul
12226234Swpaul	__key_encryptsession_pk_LOCAL = &key_encrypt_pk_2_svc_prog;
12326234Swpaul	__key_decryptsession_pk_LOCAL = &key_decrypt_pk_2_svc_prog;
12426234Swpaul	__key_gendes_LOCAL = &key_gen_1_svc_prog;
12526234Swpaul
12626234Swpaul	while ((c = getopt(argc, argv, "ndDvp:")) != -1)
12726234Swpaul		switch (c) {
12826234Swpaul		case 'n':
12926234Swpaul			nflag++;
13026234Swpaul			break;
13126234Swpaul		case 'd':
13226234Swpaul			pk_nodefaultkeys();
13326234Swpaul			break;
13426234Swpaul		case 'D':
13526234Swpaul			debugging = 1;
13626234Swpaul			break;
13726234Swpaul		case 'v':
13826234Swpaul			warn = 1;
13926234Swpaul			break;
14026234Swpaul		case 'p':
14126234Swpaul			path = optarg;
14226234Swpaul			break;
14326234Swpaul		default:
14426234Swpaul			usage();
14526234Swpaul		}
14626234Swpaul
14726234Swpaul	load_des(warn, path);
14826234Swpaul	__des_crypt_LOCAL = _my_crypt;
14929735Scharnier	if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1)
15029735Scharnier		errx(1, "failed to register AUTH_DES authenticator");
15126234Swpaul
15226234Swpaul	if (optind != argc) {
15326234Swpaul		usage();
15426234Swpaul	}
15526234Swpaul
15626234Swpaul	/*
15726234Swpaul	 * Initialize
15826234Swpaul	 */
15990317Salfred	(void) umask(S_IXUSR|S_IXGRP|S_IXOTH);
16029735Scharnier	if (geteuid() != 0)
16129735Scharnier		errx(1, "keyserv must be run as root");
16226234Swpaul	setmodulus(HEXMODULUS);
16326234Swpaul	getrootkey(&masterkey, nflag);
16426234Swpaul
16590317Salfred	rpcb_unset(KEY_PROG, KEY_VERS, NULL);
16690317Salfred	rpcb_unset(KEY_PROG, KEY_VERS2, NULL);
16790317Salfred
16874462Salfred	if (svc_create(keyprogram, KEY_PROG, KEY_VERS,
16974462Salfred		"netpath") == 0) {
17074462Salfred		(void) fprintf(stderr,
17174462Salfred			"%s: unable to create service\n", argv[0]);
17274462Salfred		exit(1);
17374462Salfred	}
17474462Salfred
17574462Salfred	if (svc_create(keyprogram, KEY_PROG, KEY_VERS2,
17674462Salfred	"netpath") == 0) {
17774462Salfred		(void) fprintf(stderr,
17874462Salfred			"%s: unable to create service\n", argv[0]);
17974462Salfred		exit(1);
18074462Salfred	}
18126234Swpaul
18290317Salfred	localhandle = setnetconfig();
18390317Salfred	while ((nconf = getnetconfig(localhandle)) != NULL) {
18490317Salfred		if (nconf->nc_protofmly != NULL &&
18590317Salfred		    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
18690317Salfred			break;
18790317Salfred	}
18890317Salfred
18990317Salfred	if (nconf == NULL)
19090317Salfred		errx(1, "getnetconfig: %s", nc_sperror());
19190317Salfred
19290317Salfred	unlink(KEYSERVSOCK);
19390317Salfred	rpcb_unset(CRYPT_PROG, CRYPT_VERS, nconf);
19490317Salfred	transp = svcunix_create(RPC_ANYSOCK, 0, 0, KEYSERVSOCK);
19590317Salfred	if (transp == NULL)
19690317Salfred		errx(1, "cannot create AF_LOCAL service");
19790317Salfred	if (!svc_reg(transp, KEY_PROG, KEY_VERS, keyprogram, nconf))
19890317Salfred		errx(1, "unable to register (KEY_PROG, KEY_VERS, unix)");
19990317Salfred	if (!svc_reg(transp, KEY_PROG, KEY_VERS2, keyprogram, nconf))
20090317Salfred		errx(1, "unable to register (KEY_PROG, KEY_VERS2, unix)");
20190317Salfred	if (!svc_reg(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, nconf))
20290317Salfred		errx(1, "unable to register (CRYPT_PROG, CRYPT_VERS, unix)");
20390317Salfred
20490317Salfred	endnetconfig(localhandle);
20590317Salfred
20690317Salfred	(void) umask(066);	/* paranoia */
20790317Salfred
20826234Swpaul	if (!debugging) {
20926234Swpaul		daemon(0,0);
21026234Swpaul	}
21126234Swpaul
21290317Salfred	signal(SIGPIPE, SIG_IGN);
21390317Salfred
21426234Swpaul	svc_run();
21526234Swpaul	abort();
21626234Swpaul	/* NOTREACHED */
21726234Swpaul}
21826234Swpaul
21926234Swpaul/*
22026234Swpaul * In the event that we don't get a root password, we try to
22126234Swpaul * randomize the master key the best we can
22226234Swpaul */
22326234Swpaulstatic void
22426234Swpaulrandomize(master)
22526234Swpaul	des_block *master;
22626234Swpaul{
227110665Sache#ifndef __FreeBSD__
22826234Swpaul	int i;
22926234Swpaul	int seed;
23026234Swpaul	struct timeval tv;
23126234Swpaul	int shift;
23226234Swpaul
23326234Swpaul	seed = 0;
23426234Swpaul	for (i = 0; i < 1024; i++) {
235239991Sed		(void)gettimeofday(&tv, NULL);
23626234Swpaul		shift = i % 8 * sizeof (int);
23726234Swpaul		seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift));
23826234Swpaul	}
239110665Sache#endif
24026234Swpaul#ifdef KEYSERV_RANDOM
241110665Sache#ifdef __FreeBSD__
242111062Skris	master->key.low = arc4random();
243111062Skris	master->key.high = arc4random();
244110665Sache#else
24526234Swpaul	srandom(seed);
24626234Swpaul	master->key.low = random();
24726234Swpaul	master->key.high = random();
248111062Skris#endif
24926234Swpaul#else
25026234Swpaul	/* use stupid dangerous bad rand() */
251110665Sache#ifdef __FreeBSD__
252110665Sache	sranddev();
253110665Sache#else
25426234Swpaul	srand(seed);
255110665Sache#endif
25626234Swpaul	master->key.low = rand();
25726234Swpaul	master->key.high = rand();
25826234Swpaul#endif
25926234Swpaul}
26026234Swpaul
26126234Swpaul/*
26226234Swpaul * Try to get root's secret key, by prompting if terminal is a tty, else trying
26326234Swpaul * from standard input.
26426234Swpaul * Returns 1 on success.
26526234Swpaul */
26626234Swpaulstatic int
26726234Swpaulgetrootkey(master, prompt)
26826234Swpaul	des_block *master;
26926234Swpaul	int prompt;
27026234Swpaul{
27126234Swpaul	char *passwd;
27226234Swpaul	char name[MAXNETNAMELEN + 1];
27326234Swpaul	char secret[HEXKEYBYTES];
27426234Swpaul	key_netstarg netstore;
27526234Swpaul	int fd;
27626234Swpaul
27726234Swpaul	if (!prompt) {
27826234Swpaul		/*
27926234Swpaul		 * Read secret key out of ROOTKEY
28026234Swpaul		 */
28126234Swpaul		fd = open(ROOTKEY, O_RDONLY, 0);
28226234Swpaul		if (fd < 0) {
28326234Swpaul			randomize(master);
28426234Swpaul			return (0);
28526234Swpaul		}
28626234Swpaul		if (read(fd, secret, HEXKEYBYTES) < HEXKEYBYTES) {
28729735Scharnier			warnx("the key read from %s was too short", ROOTKEY);
28826234Swpaul			(void) close(fd);
28926234Swpaul			return (0);
29026234Swpaul		}
29126234Swpaul		(void) close(fd);
29226234Swpaul		if (!getnetname(name)) {
29329735Scharnier		    warnx(
29429735Scharnier	"failed to generate host's netname when establishing root's key");
29526234Swpaul		    return (0);
29626234Swpaul		}
29726234Swpaul		memcpy(netstore.st_priv_key, secret, HEXKEYBYTES);
29826234Swpaul		memset(netstore.st_pub_key, 0, HEXKEYBYTES);
29926234Swpaul		netstore.st_netname = name;
30026234Swpaul		if (pk_netput(0, &netstore) != KEY_SUCCESS) {
30129735Scharnier		    warnx("could not set root's key and netname");
30226234Swpaul		    return (0);
30326234Swpaul		}
30426234Swpaul		return (1);
30526234Swpaul	}
30626234Swpaul	/*
30726234Swpaul	 * Decrypt yellow pages publickey entry to get secret key
30826234Swpaul	 */
30926234Swpaul	passwd = getpass("root password:");
31026234Swpaul	passwd2des(passwd, (char *)master);
31126234Swpaul	getnetname(name);
31226234Swpaul	if (!getsecretkey(name, secret, passwd)) {
31329735Scharnier		warnx("can't find %s's secret key", name);
31426234Swpaul		return (0);
31526234Swpaul	}
31626234Swpaul	if (secret[0] == 0) {
31729735Scharnier		warnx("password does not decrypt secret key for %s", name);
31826234Swpaul		return (0);
31926234Swpaul	}
32026234Swpaul	(void) pk_setkey(0, secret);
32126234Swpaul	/*
32226234Swpaul	 * Store it for future use in $ROOTKEY, if possible
32326234Swpaul	 */
32426234Swpaul	fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0);
32526234Swpaul	if (fd > 0) {
32626234Swpaul		char newline = '\n';
32726234Swpaul
32826234Swpaul		write(fd, secret, strlen(secret));
32926234Swpaul		write(fd, &newline, sizeof (newline));
33026234Swpaul		close(fd);
33126234Swpaul	}
33226234Swpaul	return (1);
33326234Swpaul}
33426234Swpaul
33526234Swpaul/*
33626234Swpaul * Procedures to implement RPC service
33726234Swpaul */
33826234Swpaulchar *
33926234Swpaulstrstatus(status)
34026234Swpaul	keystatus status;
34126234Swpaul{
34226234Swpaul	switch (status) {
34326234Swpaul	case KEY_SUCCESS:
34426234Swpaul		return ("KEY_SUCCESS");
34526234Swpaul	case KEY_NOSECRET:
34626234Swpaul		return ("KEY_NOSECRET");
34726234Swpaul	case KEY_UNKNOWN:
34826234Swpaul		return ("KEY_UNKNOWN");
34926234Swpaul	case KEY_SYSTEMERR:
35026234Swpaul		return ("KEY_SYSTEMERR");
35126234Swpaul	default:
35226234Swpaul		return ("(bad result code)");
35326234Swpaul	}
35426234Swpaul}
35526234Swpaul
35626234Swpaulkeystatus *
35726234Swpaulkey_set_1_svc_prog(uid, key)
35826234Swpaul	uid_t uid;
35926234Swpaul	keybuf key;
36026234Swpaul{
36126234Swpaul	static keystatus status;
36226234Swpaul
36326234Swpaul	if (debugging) {
364228662Sdim		(void) fprintf(stderr, "set(%u, %.*s) = ", uid,
36526234Swpaul				(int) sizeof (keybuf), key);
36626234Swpaul	}
36726234Swpaul	status = pk_setkey(uid, key);
36826234Swpaul	if (debugging) {
36926234Swpaul		(void) fprintf(stderr, "%s\n", strstatus(status));
37026234Swpaul		(void) fflush(stderr);
37126234Swpaul	}
37226234Swpaul	return (&status);
37326234Swpaul}
37426234Swpaul
37526234Swpaulcryptkeyres *
37626234Swpaulkey_encrypt_pk_2_svc_prog(uid, arg)
37726234Swpaul	uid_t uid;
37826234Swpaul	cryptkeyarg2 *arg;
37926234Swpaul{
38026234Swpaul	static cryptkeyres res;
38126234Swpaul
38226234Swpaul	if (debugging) {
383228662Sdim		(void) fprintf(stderr, "encrypt(%u, %s, %08x%08x) = ", uid,
38426234Swpaul				arg->remotename, arg->deskey.key.high,
38526234Swpaul				arg->deskey.key.low);
38626234Swpaul	}
38726234Swpaul	res.cryptkeyres_u.deskey = arg->deskey;
38826234Swpaul	res.status = pk_encrypt(uid, arg->remotename, &(arg->remotekey),
38926234Swpaul				&res.cryptkeyres_u.deskey);
39026234Swpaul	if (debugging) {
39126234Swpaul		if (res.status == KEY_SUCCESS) {
39226234Swpaul			(void) fprintf(stderr, "%08x%08x\n",
39326234Swpaul					res.cryptkeyres_u.deskey.key.high,
39426234Swpaul					res.cryptkeyres_u.deskey.key.low);
39526234Swpaul		} else {
39626234Swpaul			(void) fprintf(stderr, "%s\n", strstatus(res.status));
39726234Swpaul		}
39826234Swpaul		(void) fflush(stderr);
39926234Swpaul	}
40026234Swpaul	return (&res);
40126234Swpaul}
40226234Swpaul
40326234Swpaulcryptkeyres *
40426234Swpaulkey_decrypt_pk_2_svc_prog(uid, arg)
40526234Swpaul	uid_t uid;
40626234Swpaul	cryptkeyarg2 *arg;
40726234Swpaul{
40826234Swpaul	static cryptkeyres res;
40926234Swpaul
41026234Swpaul	if (debugging) {
411228662Sdim		(void) fprintf(stderr, "decrypt(%u, %s, %08x%08x) = ", uid,
41226234Swpaul				arg->remotename, arg->deskey.key.high,
41326234Swpaul				arg->deskey.key.low);
41426234Swpaul	}
41526234Swpaul	res.cryptkeyres_u.deskey = arg->deskey;
41626234Swpaul	res.status = pk_decrypt(uid, arg->remotename, &(arg->remotekey),
41726234Swpaul				&res.cryptkeyres_u.deskey);
41826234Swpaul	if (debugging) {
41926234Swpaul		if (res.status == KEY_SUCCESS) {
42026234Swpaul			(void) fprintf(stderr, "%08x%08x\n",
42126234Swpaul					res.cryptkeyres_u.deskey.key.high,
42226234Swpaul					res.cryptkeyres_u.deskey.key.low);
42326234Swpaul		} else {
42426234Swpaul			(void) fprintf(stderr, "%s\n", strstatus(res.status));
42526234Swpaul		}
42626234Swpaul		(void) fflush(stderr);
42726234Swpaul	}
42826234Swpaul	return (&res);
42926234Swpaul}
43026234Swpaul
43126234Swpaulkeystatus *
43226234Swpaulkey_net_put_2_svc_prog(uid, arg)
43326234Swpaul	uid_t uid;
43426234Swpaul	key_netstarg *arg;
43526234Swpaul{
43626234Swpaul	static keystatus status;
43726234Swpaul
43826234Swpaul	if (debugging) {
43926234Swpaul		(void) fprintf(stderr, "net_put(%s, %.*s, %.*s) = ",
44026234Swpaul			arg->st_netname, (int)sizeof (arg->st_pub_key),
44126234Swpaul			arg->st_pub_key, (int)sizeof (arg->st_priv_key),
44226234Swpaul			arg->st_priv_key);
44326234Swpaul	};
44426234Swpaul
44526234Swpaul	status = pk_netput(uid, arg);
44626234Swpaul
44726234Swpaul	if (debugging) {
44826234Swpaul		(void) fprintf(stderr, "%s\n", strstatus(status));
44926234Swpaul		(void) fflush(stderr);
45026234Swpaul	}
45126234Swpaul
45226234Swpaul	return (&status);
45326234Swpaul}
45426234Swpaul
45526234Swpaulkey_netstres *
45626234Swpaulkey_net_get_2_svc_prog(uid, arg)
45726234Swpaul	uid_t uid;
45826234Swpaul	void *arg;
45926234Swpaul{
46026234Swpaul	static key_netstres keynetname;
46126234Swpaul
46226234Swpaul	if (debugging)
463228662Sdim		(void) fprintf(stderr, "net_get(%u) = ", uid);
46426234Swpaul
46526234Swpaul	keynetname.status = pk_netget(uid, &keynetname.key_netstres_u.knet);
46626234Swpaul	if (debugging) {
46726234Swpaul		if (keynetname.status == KEY_SUCCESS) {
46826234Swpaul			fprintf(stderr, "<%s, %.*s, %.*s>\n",
46926234Swpaul			keynetname.key_netstres_u.knet.st_netname,
47026234Swpaul			(int)sizeof (keynetname.key_netstres_u.knet.st_pub_key),
47126234Swpaul			keynetname.key_netstres_u.knet.st_pub_key,
47226234Swpaul			(int)sizeof (keynetname.key_netstres_u.knet.st_priv_key),
47326234Swpaul			keynetname.key_netstres_u.knet.st_priv_key);
47426234Swpaul		} else {
47526234Swpaul			(void) fprintf(stderr, "NOT FOUND\n");
47626234Swpaul		}
47726234Swpaul		(void) fflush(stderr);
47826234Swpaul	}
47926234Swpaul
48026234Swpaul	return (&keynetname);
48126234Swpaul
48226234Swpaul}
48326234Swpaul
48426234Swpaulcryptkeyres *
48526234Swpaulkey_get_conv_2_svc_prog(uid, arg)
48626234Swpaul	uid_t uid;
48726234Swpaul	keybuf arg;
48826234Swpaul{
48926234Swpaul	static cryptkeyres  res;
49026234Swpaul
49126234Swpaul	if (debugging)
492228662Sdim		(void) fprintf(stderr, "get_conv(%u, %.*s) = ", uid,
493228662Sdim			(int)sizeof (keybuf), arg);
49426234Swpaul
49526234Swpaul
49626234Swpaul	res.status = pk_get_conv_key(uid, arg, &res);
49726234Swpaul
49826234Swpaul	if (debugging) {
49926234Swpaul		if (res.status == KEY_SUCCESS) {
50026234Swpaul			(void) fprintf(stderr, "%08x%08x\n",
50126234Swpaul				res.cryptkeyres_u.deskey.key.high,
50226234Swpaul				res.cryptkeyres_u.deskey.key.low);
50326234Swpaul		} else {
50426234Swpaul			(void) fprintf(stderr, "%s\n", strstatus(res.status));
50526234Swpaul		}
50626234Swpaul		(void) fflush(stderr);
50726234Swpaul	}
50826234Swpaul	return (&res);
50926234Swpaul}
51026234Swpaul
51126234Swpaul
51226234Swpaulcryptkeyres *
51326234Swpaulkey_encrypt_1_svc_prog(uid, arg)
51426234Swpaul	uid_t uid;
51526234Swpaul	cryptkeyarg *arg;
51626234Swpaul{
51726234Swpaul	static cryptkeyres res;
51826234Swpaul
51926234Swpaul	if (debugging) {
520228662Sdim		(void) fprintf(stderr, "encrypt(%u, %s, %08x%08x) = ", uid,
52126234Swpaul				arg->remotename, arg->deskey.key.high,
52226234Swpaul				arg->deskey.key.low);
52326234Swpaul	}
52426234Swpaul	res.cryptkeyres_u.deskey = arg->deskey;
52526234Swpaul	res.status = pk_encrypt(uid, arg->remotename, NULL,
52626234Swpaul				&res.cryptkeyres_u.deskey);
52726234Swpaul	if (debugging) {
52826234Swpaul		if (res.status == KEY_SUCCESS) {
52926234Swpaul			(void) fprintf(stderr, "%08x%08x\n",
53026234Swpaul					res.cryptkeyres_u.deskey.key.high,
53126234Swpaul					res.cryptkeyres_u.deskey.key.low);
53226234Swpaul		} else {
53326234Swpaul			(void) fprintf(stderr, "%s\n", strstatus(res.status));
53426234Swpaul		}
53526234Swpaul		(void) fflush(stderr);
53626234Swpaul	}
53726234Swpaul	return (&res);
53826234Swpaul}
53926234Swpaul
54026234Swpaulcryptkeyres *
54126234Swpaulkey_decrypt_1_svc_prog(uid, arg)
54226234Swpaul	uid_t uid;
54326234Swpaul	cryptkeyarg *arg;
54426234Swpaul{
54526234Swpaul	static cryptkeyres res;
54626234Swpaul
54726234Swpaul	if (debugging) {
548228662Sdim		(void) fprintf(stderr, "decrypt(%u, %s, %08x%08x) = ", uid,
54926234Swpaul				arg->remotename, arg->deskey.key.high,
55026234Swpaul				arg->deskey.key.low);
55126234Swpaul	}
55226234Swpaul	res.cryptkeyres_u.deskey = arg->deskey;
55326234Swpaul	res.status = pk_decrypt(uid, arg->remotename, NULL,
55426234Swpaul				&res.cryptkeyres_u.deskey);
55526234Swpaul	if (debugging) {
55626234Swpaul		if (res.status == KEY_SUCCESS) {
55726234Swpaul			(void) fprintf(stderr, "%08x%08x\n",
55826234Swpaul					res.cryptkeyres_u.deskey.key.high,
55926234Swpaul					res.cryptkeyres_u.deskey.key.low);
56026234Swpaul		} else {
56126234Swpaul			(void) fprintf(stderr, "%s\n", strstatus(res.status));
56226234Swpaul		}
56326234Swpaul		(void) fflush(stderr);
56426234Swpaul	}
56526234Swpaul	return (&res);
56626234Swpaul}
56726234Swpaul
56826234Swpaul/* ARGSUSED */
56926234Swpauldes_block *
57026234Swpaulkey_gen_1_svc_prog(v, s)
57126234Swpaul	void	*v;
57226234Swpaul	struct svc_req	*s;
57326234Swpaul{
57426234Swpaul	struct timeval time;
57526234Swpaul	static des_block keygen;
57626234Swpaul	static des_block key;
57726234Swpaul
578239991Sed	(void)gettimeofday(&time, NULL);
57926234Swpaul	keygen.key.high += (time.tv_sec ^ time.tv_usec);
58026234Swpaul	keygen.key.low += (time.tv_sec ^ time.tv_usec);
58126234Swpaul	ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen),
58226234Swpaul		DES_ENCRYPT | DES_HW);
58326234Swpaul	key = keygen;
58426234Swpaul	des_setparity((char *)&key);
58526234Swpaul	if (debugging) {
58626234Swpaul		(void) fprintf(stderr, "gen() = %08x%08x\n", key.key.high,
58726234Swpaul					key.key.low);
58826234Swpaul		(void) fflush(stderr);
58926234Swpaul	}
59026234Swpaul	return (&key);
59126234Swpaul}
59226234Swpaul
59326234Swpaulgetcredres *
59426234Swpaulkey_getcred_1_svc_prog(uid, name)
59526234Swpaul	uid_t uid;
59626234Swpaul	netnamestr *name;
59726234Swpaul{
59826234Swpaul	static getcredres res;
59926234Swpaul	static u_int gids[NGROUPS];
60026234Swpaul	struct unixcred *cred;
60126234Swpaul
60226234Swpaul	cred = &res.getcredres_u.cred;
60326234Swpaul	cred->gids.gids_val = gids;
60426234Swpaul	if (!netname2user(*name, (uid_t *) &cred->uid, (gid_t *) &cred->gid,
60526234Swpaul			(int *)&cred->gids.gids_len, (gid_t *)gids)) {
60626234Swpaul		res.status = KEY_UNKNOWN;
60726234Swpaul	} else {
60826234Swpaul		res.status = KEY_SUCCESS;
60926234Swpaul	}
61026234Swpaul	if (debugging) {
61126234Swpaul		(void) fprintf(stderr, "getcred(%s) = ", *name);
61226234Swpaul		if (res.status == KEY_SUCCESS) {
61326234Swpaul			(void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n",
61426234Swpaul				cred->uid, cred->gid, cred->gids.gids_len);
61526234Swpaul		} else {
61626234Swpaul			(void) fprintf(stderr, "%s\n", strstatus(res.status));
61726234Swpaul		}
61826234Swpaul		(void) fflush(stderr);
61926234Swpaul	}
62026234Swpaul	return (&res);
62126234Swpaul}
62226234Swpaul
62326234Swpaul/*
62426234Swpaul * RPC boilerplate
62526234Swpaul */
62626234Swpaulstatic void
62726234Swpaulkeyprogram(rqstp, transp)
62826234Swpaul	struct svc_req *rqstp;
62926234Swpaul	SVCXPRT *transp;
63026234Swpaul{
63126234Swpaul	union {
63226234Swpaul		keybuf key_set_1_arg;
63326234Swpaul		cryptkeyarg key_encrypt_1_arg;
63426234Swpaul		cryptkeyarg key_decrypt_1_arg;
63526234Swpaul		netnamestr key_getcred_1_arg;
63626234Swpaul		cryptkeyarg key_encrypt_2_arg;
63726234Swpaul		cryptkeyarg key_decrypt_2_arg;
63826234Swpaul		netnamestr key_getcred_2_arg;
63926234Swpaul		cryptkeyarg2 key_encrypt_pk_2_arg;
64026234Swpaul		cryptkeyarg2 key_decrypt_pk_2_arg;
64126234Swpaul		key_netstarg key_net_put_2_arg;
64226234Swpaul		netobj  key_get_conv_2_arg;
64326234Swpaul	} argument;
64426234Swpaul	char *result;
64595658Sdes	xdrproc_t xdr_argument, xdr_result;
64626234Swpaul	char *(*local) ();
64726234Swpaul	uid_t uid = -1;
64826234Swpaul	int check_auth;
64926234Swpaul
65026234Swpaul	switch (rqstp->rq_proc) {
65126234Swpaul	case NULLPROC:
65295658Sdes		svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
65326234Swpaul		return;
65426234Swpaul
65526234Swpaul	case KEY_SET:
65695658Sdes		xdr_argument = (xdrproc_t)xdr_keybuf;
65795658Sdes		xdr_result = (xdrproc_t)xdr_int;
65826234Swpaul		local = (char *(*)()) key_set_1_svc_prog;
65926234Swpaul		check_auth = 1;
66026234Swpaul		break;
66126234Swpaul
66226234Swpaul	case KEY_ENCRYPT:
66395658Sdes		xdr_argument = (xdrproc_t)xdr_cryptkeyarg;
66495658Sdes		xdr_result = (xdrproc_t)xdr_cryptkeyres;
66526234Swpaul		local = (char *(*)()) key_encrypt_1_svc_prog;
66626234Swpaul		check_auth = 1;
66726234Swpaul		break;
66826234Swpaul
66926234Swpaul	case KEY_DECRYPT:
67095658Sdes		xdr_argument = (xdrproc_t)xdr_cryptkeyarg;
67195658Sdes		xdr_result = (xdrproc_t)xdr_cryptkeyres;
67226234Swpaul		local = (char *(*)()) key_decrypt_1_svc_prog;
67326234Swpaul		check_auth = 1;
67426234Swpaul		break;
67526234Swpaul
67626234Swpaul	case KEY_GEN:
67795658Sdes		xdr_argument = (xdrproc_t)xdr_void;
67895658Sdes		xdr_result = (xdrproc_t)xdr_des_block;
67926234Swpaul		local = (char *(*)()) key_gen_1_svc_prog;
68026234Swpaul		check_auth = 0;
68126234Swpaul		break;
68226234Swpaul
68326234Swpaul	case KEY_GETCRED:
68495658Sdes		xdr_argument = (xdrproc_t)xdr_netnamestr;
68595658Sdes		xdr_result = (xdrproc_t)xdr_getcredres;
68626234Swpaul		local = (char *(*)()) key_getcred_1_svc_prog;
68726234Swpaul		check_auth = 0;
68826234Swpaul		break;
68926234Swpaul
69026234Swpaul	case KEY_ENCRYPT_PK:
69195658Sdes		xdr_argument = (xdrproc_t)xdr_cryptkeyarg2;
69295658Sdes		xdr_result = (xdrproc_t)xdr_cryptkeyres;
69326234Swpaul		local = (char *(*)()) key_encrypt_pk_2_svc_prog;
69426234Swpaul		check_auth = 1;
69526234Swpaul		break;
69626234Swpaul
69726234Swpaul	case KEY_DECRYPT_PK:
69895658Sdes		xdr_argument = (xdrproc_t)xdr_cryptkeyarg2;
69995658Sdes		xdr_result = (xdrproc_t)xdr_cryptkeyres;
70026234Swpaul		local = (char *(*)()) key_decrypt_pk_2_svc_prog;
70126234Swpaul		check_auth = 1;
70226234Swpaul		break;
70326234Swpaul
70426234Swpaul
70526234Swpaul	case KEY_NET_PUT:
70695658Sdes		xdr_argument = (xdrproc_t)xdr_key_netstarg;
70795658Sdes		xdr_result = (xdrproc_t)xdr_keystatus;
70826234Swpaul		local = (char *(*)()) key_net_put_2_svc_prog;
70926234Swpaul		check_auth = 1;
71026234Swpaul		break;
71126234Swpaul
71226234Swpaul	case KEY_NET_GET:
71326234Swpaul		xdr_argument = (xdrproc_t) xdr_void;
71495658Sdes		xdr_result = (xdrproc_t)xdr_key_netstres;
71526234Swpaul		local = (char *(*)()) key_net_get_2_svc_prog;
71626234Swpaul		check_auth = 1;
71726234Swpaul		break;
71826234Swpaul
71926234Swpaul	case KEY_GET_CONV:
72026234Swpaul		xdr_argument = (xdrproc_t) xdr_keybuf;
72195658Sdes		xdr_result = (xdrproc_t)xdr_cryptkeyres;
72226234Swpaul		local = (char *(*)()) key_get_conv_2_svc_prog;
72326234Swpaul		check_auth = 1;
72426234Swpaul		break;
72526234Swpaul
72626234Swpaul	default:
72726234Swpaul		svcerr_noproc(transp);
72826234Swpaul		return;
72926234Swpaul	}
73026234Swpaul	if (check_auth) {
73126234Swpaul		if (root_auth(transp, rqstp) == 0) {
73226234Swpaul			if (debugging) {
73326234Swpaul				(void) fprintf(stderr,
73426234Swpaul				"not local privileged process\n");
73526234Swpaul			}
73626234Swpaul			svcerr_weakauth(transp);
73726234Swpaul			return;
73826234Swpaul		}
73926234Swpaul		if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
74026234Swpaul			if (debugging) {
74126234Swpaul				(void) fprintf(stderr,
74226234Swpaul				"not unix authentication\n");
74326234Swpaul			}
74426234Swpaul			svcerr_weakauth(transp);
74526234Swpaul			return;
74626234Swpaul		}
74726234Swpaul		uid = ((struct authsys_parms *)rqstp->rq_clntcred)->aup_uid;
74826234Swpaul	}
74926234Swpaul
75095658Sdes	memset(&argument, 0, sizeof (argument));
75195658Sdes	if (!svc_getargs(transp, xdr_argument, &argument)) {
75226234Swpaul		svcerr_decode(transp);
75326234Swpaul		return;
75426234Swpaul	}
75526234Swpaul	result = (*local) (uid, &argument);
75695658Sdes	if (!svc_sendreply(transp, xdr_result, result)) {
75726234Swpaul		if (debugging)
75826234Swpaul			(void) fprintf(stderr, "unable to reply\n");
75926234Swpaul		svcerr_systemerr(transp);
76026234Swpaul	}
76195658Sdes	if (!svc_freeargs(transp, xdr_argument, &argument)) {
76226234Swpaul		if (debugging)
76326234Swpaul			(void) fprintf(stderr,
76426234Swpaul			"unable to free arguments\n");
76526234Swpaul		exit(1);
76626234Swpaul	}
76726234Swpaul	return;
76826234Swpaul}
76926234Swpaul
77026234Swpaulstatic int
77126234Swpaulroot_auth(trans, rqstp)
77226234Swpaul	SVCXPRT *trans;
77326234Swpaul	struct svc_req *rqstp;
77426234Swpaul{
77526234Swpaul	uid_t uid;
776100120Salfred	struct sockaddr *remote;
77726234Swpaul
778100120Salfred	remote = svc_getrpccaller(trans)->buf;
779100120Salfred	if (remote->sa_family != AF_UNIX) {
78026234Swpaul		if (debugging)
78126234Swpaul			fprintf(stderr, "client didn't use AF_UNIX\n");
78226234Swpaul		return (0);
78326234Swpaul	}
78426234Swpaul
78574627Salfred	if (__rpc_get_local_uid(trans, &uid) < 0) {
78626234Swpaul		if (debugging)
78726234Swpaul			fprintf(stderr, "__rpc_get_local_uid failed\n");
78826234Swpaul		return (0);
78926234Swpaul	}
79026234Swpaul
79126234Swpaul	if (debugging)
792228662Sdim		fprintf(stderr, "local_uid  %u\n", uid);
79326234Swpaul	if (uid == 0)
79426234Swpaul		return (1);
79526234Swpaul	if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
79626234Swpaul		if (((uid_t) ((struct authunix_parms *)
79726234Swpaul			rqstp->rq_clntcred)->aup_uid)
79826234Swpaul			== uid) {
79926234Swpaul			return (1);
80026234Swpaul		} else {
80126234Swpaul			if (debugging)
80226234Swpaul				fprintf(stderr,
803228662Sdim			"local_uid  %u mismatches auth %u\n", uid,
80426234Swpaul((uid_t) ((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid));
80526234Swpaul			return (0);
80626234Swpaul		}
80726234Swpaul	} else {
80826234Swpaul		if (debugging)
80926234Swpaul			fprintf(stderr, "Not auth sys\n");
81026234Swpaul		return (0);
81126234Swpaul	}
81226234Swpaul}
81326234Swpaul
81426234Swpaulstatic void
81526234Swpaulusage()
81626234Swpaul{
81726234Swpaul	(void) fprintf(stderr,
81826234Swpaul			"usage: keyserv [-n] [-D] [-d] [-v] [-p path]\n");
81926234Swpaul	(void) fprintf(stderr, "-d disables the use of default keys\n");
82026234Swpaul	exit(1);
82126234Swpaul}
822