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