summaryrefslogtreecommitdiffstats
path: root/lib/librpc/secure_rpc/keyserv/keyserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/librpc/secure_rpc/keyserv/keyserv.c')
-rw-r--r--lib/librpc/secure_rpc/keyserv/keyserv.c458
1 files changed, 458 insertions, 0 deletions
diff --git a/lib/librpc/secure_rpc/keyserv/keyserv.c b/lib/librpc/secure_rpc/keyserv/keyserv.c
new file mode 100644
index 0000000..d82dc12
--- /dev/null
+++ b/lib/librpc/secure_rpc/keyserv/keyserv.c
@@ -0,0 +1,458 @@
+#ifndef lint
+static char sccsid[] = "@(#)keyserv.c 2.4 88/08/15 4.0 RPCSRC Copyr 1988 Sun Micro";
+#endif
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+/*
+ * Keyserver
+ * Store secret keys per uid. Do public key encryption and decryption
+ * operations. Generate "random" keys. Do not talk to anything but a local root
+ * process (by checking that the source port < IPPORT_RESERVED and by binding
+ * to the loopback address).
+ */
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <pwd.h>
+#include <des_crypt.h>
+#include <rpc/key_prot.h>
+
+
+char ROOTKEY[] = "/etc/.rootkey";
+
+extern long random();
+
+extern keystatus pk_setkey();
+extern keystatus pk_encrypt();
+extern keystatus pk_decrypt();
+
+
+#ifdef DEBUG
+int debugging = 1;
+#else
+int debugging = 0;
+#endif
+
+static void keyprogram();
+des_block masterkey;
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+
+{
+ SVCXPRT *transp;
+ int nflag;
+
+ nflag = (argc == 2) && (strcmp(argv[1], "-n") == 0);
+ if (!(argc == 1 || nflag)) {
+ (void) fprintf(stderr, "usage: %s [-n]\n", argv[0]);
+ exit(1);
+ }
+ /*
+ * Initialize
+ */
+ (void) umask(066); /* paranoia */
+ if (geteuid() != 0) {
+ (void) fprintf(stderr, "%s must be run as root\n", argv[0]);
+ exit(1);
+ }
+ setmodulus(HEXMODULUS);
+ openstore();
+ getrootkey(&masterkey, nflag);
+ readkeys();
+
+ /*
+ * create the service, register it, and run
+ */
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL) {
+ (void) fprintf(stderr,
+ "%s: unable to create udp service\n", argv[0]);
+ exit(1);
+ }
+ pmap_unset(KEY_PROG, KEY_VERS);
+ if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram,
+ IPPROTO_UDP)) {
+ (void) fprintf(stderr, "%s: unable to register service\n",
+ argv[0]);
+ exit(1);
+ }
+ /*
+ * run
+ */
+ if (!debugging) {
+ detachfromtty();
+ }
+ svc_run();
+ abort();
+}
+
+/*
+ * In the event that we don't get a root password, we try to randomize the
+ * master key the best we can
+ */
+randomize(master)
+ des_block *master;
+{
+ int i;
+ int seed;
+ struct timeval tv;
+ int shift;
+
+ seed = 0;
+ for (i = 0; i < 1024; i++) {
+ (void) gettimeofday(&tv, (struct timezone *) NULL);
+ shift = i % 8 * sizeof(int);
+ seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift));
+ }
+ srandom(seed);
+ master->key.low = random();
+ master->key.high = random();
+ srandom(seed);
+}
+
+
+
+/*
+ * Try to get root's secret key, by prompting if terminal is a tty, else trying
+ * from standard input.
+ */
+getrootkey(master, prompt)
+ des_block *master;
+ int prompt;
+{
+ char *getpass();
+ char *passwd;
+ char name[MAXNETNAMELEN + 1];
+ char secret[HEXKEYBYTES + 1];
+ char *crypt();
+ int fd;
+
+ if (!prompt) {
+ /*
+ * Read secret key out of $ROOTKEY
+ */
+ fd = open(ROOTKEY, O_RDONLY, 0);
+ if (fd < 0) {
+ randomize(master);
+ return (0);
+ }
+ if (read(fd, secret, HEXKEYBYTES) < 0) {
+ (void) fprintf(stderr, "Invalid %s\n", ROOTKEY);
+ (void) close(fd);
+ return (0);
+ }
+ (void) close(fd);
+ secret[HEXKEYBYTES] = 0;
+ } else {
+ /*
+ * Decrypt yellow pages entry to get secret key
+ */
+ passwd = getpass("root password:");
+ passwd2des(passwd, master);
+ getnetname(name);
+ if (!getsecretkey(name, secret, passwd)) {
+ (void) fprintf(stderr,
+ "Can't find %s's secret key\n", name);
+ return (0);
+ }
+ if (secret[0] == 0) {
+ (void) fprintf(stderr,
+ "Invalid password for %s\n", name);
+ return (0);
+ }
+ }
+ (void) pk_setkey(0, secret);
+ return (1);
+}
+
+
+/*
+ * Procedures to implement RPC service
+ */
+
+char *
+strstatus(status)
+ keystatus status;
+{
+ switch (status) {
+ case KEY_SUCCESS:
+ return ("KEY_SUCCESS");
+ case KEY_NOSECRET:
+ return ("KEY_NOSECRET");
+ case KEY_UNKNOWN:
+ return ("KEY_UNKNOWN");
+ case KEY_SYSTEMERR:
+ return ("KEY_SYSTEMERR");
+ default:
+ return ("(bad result code)");
+ }
+}
+
+keystatus *
+key_set_1(uid, key)
+ short uid;
+ keybuf key;
+{
+ static keystatus status;
+
+ if (debugging) {
+ (void) fprintf(stderr, "set(%d, %.*s) = ", uid,
+ sizeof(keybuf), key);
+ }
+ status = pk_setkey(uid, key);
+ if (debugging) {
+ (void) fprintf(stderr, "%s\n", strstatus(status));
+ (void) fflush(stderr);
+ }
+ return (&status);
+}
+
+
+
+cryptkeyres *
+key_encrypt_1(uid, arg)
+ short uid;
+ cryptkeyarg *arg;
+{
+ static cryptkeyres res;
+
+ if (debugging) {
+ (void) fprintf(stderr, "encrypt(%d, %s, %08x%08x) = ", uid,
+ arg->remotename, arg->deskey.key.high,
+ arg->deskey.key.low);
+ }
+ res.cryptkeyres_u.deskey = arg->deskey;
+ res.status = pk_encrypt(uid, arg->remotename, &res.cryptkeyres_u.deskey);
+ if (debugging) {
+ if (res.status == KEY_SUCCESS) {
+ (void) fprintf(stderr, "%08x%08x\n",
+ res.cryptkeyres_u.deskey.key.high,
+ res.cryptkeyres_u.deskey.key.low);
+ } else {
+ (void) fprintf(stderr,
+ "%s\n", strstatus(res.status));
+ }
+ (void) fflush(stderr);
+ }
+ return (&res);
+}
+
+cryptkeyres *
+key_decrypt_1(uid, arg)
+ short uid;
+ cryptkeyarg *arg;
+{
+ static cryptkeyres res;
+
+ if (debugging) {
+ (void) fprintf(stderr, "decrypt(%d, %s, %08x%08x) = ", uid,
+ arg->remotename, arg->deskey.key.high,
+ arg->deskey.key.low);
+ }
+ res.cryptkeyres_u.deskey = arg->deskey;
+ res.status = pk_decrypt(uid, arg->remotename,
+ &res.cryptkeyres_u.deskey);
+ if (debugging) {
+ if (res.status == KEY_SUCCESS) {
+ (void) fprintf(stderr, "%08x%08x\n",
+ res.cryptkeyres_u.deskey.key.high,
+ res.cryptkeyres_u.deskey.key.low);
+ } else {
+ (void) fprintf(stderr, "%s\n", strstatus(res.status));
+ }
+ (void) fflush(stderr);
+ }
+ return (&res);
+}
+
+des_block *
+key_gen_1()
+{
+ struct timeval time;
+ static des_block keygen;
+ static des_block key;
+
+ (void) gettimeofday(&time, (struct timezone *) NULL);
+ keygen.key.high += (time.tv_sec ^ time.tv_usec);
+ keygen.key.low += (time.tv_sec ^ time.tv_usec);
+ ecb_crypt(&masterkey, &keygen, sizeof(keygen), DES_ENCRYPT | DES_HW);
+ key = keygen;
+ des_setparity(&key);
+ if (debugging) {
+ (void) fprintf(stderr, "gen() = %08x%08x\n", key.key.high,
+ key.key.low);
+ (void) fflush(stderr);
+ }
+ return (&key);
+}
+
+/* ARGSUSED */
+getcredres *
+key_getcred_1(uid, name)
+ short uid;
+ netnamestr *name;
+{
+ static getcredres res;
+ static int gids[NGROUPS];
+ struct unixcred *cred;
+
+ cred = &res.getcredres_u.cred;
+ cred->gids.gids_val = gids;
+ if (!netname2user(*name, &cred->uid, &cred->gid,
+ &cred->gids.gids_len, gids)) {
+ res.status = KEY_UNKNOWN;
+ } else {
+ res.status = KEY_SUCCESS;
+ }
+ if (debugging) {
+ (void) fprintf(stderr, "getcred(%s) = ", *name);
+ if (res.status == KEY_SUCCESS) {
+ (void) fprintf(stderr, "uid=%d,gid=%d,grouplen=%d\n",
+ cred->uid, cred->gid, cred->gids.gids_len);
+ } else {
+ (void) fprintf(stderr, "%s\n", strstatus(res.status));
+ }
+ (void) fflush(stderr);
+ }
+ return (&res);
+}
+
+
+/*
+ * RPC boilerplate
+ */
+static void
+keyprogram(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ union {
+ keybuf key_set_1_arg;
+ cryptkeyarg key_encrypt_1_arg;
+ cryptkeyarg key_decrypt_1_arg;
+ des_block key_gen_1_arg;
+ } argument;
+ char *result;
+
+ bool_t(*xdr_argument) (), (*xdr_result) ();
+ char *(*local) ();
+ struct sockaddr_in remote;
+ int uid;
+ int check_auth;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ svc_sendreply(transp, xdr_void, (char *) NULL);
+ return;
+
+ case KEY_SET:
+ xdr_argument = xdr_keybuf;
+ xdr_result = xdr_int;
+ local = (char *(*)()) key_set_1;
+ check_auth = 1;
+ break;
+
+ case KEY_ENCRYPT:
+ xdr_argument = xdr_cryptkeyarg;
+ xdr_result = xdr_cryptkeyres;
+ local = (char *(*)()) key_encrypt_1;
+ check_auth = 1;
+ break;
+
+ case KEY_DECRYPT:
+ xdr_argument = xdr_cryptkeyarg;
+ xdr_result = xdr_cryptkeyres;
+ local = (char *(*)()) key_decrypt_1;
+ check_auth = 1;
+ break;
+
+ case KEY_GEN:
+ xdr_argument = xdr_void;
+ xdr_result = xdr_des_block;
+ local = (char *(*)()) key_gen_1;
+ check_auth = 0;
+ break;
+
+ case KEY_GETCRED:
+ xdr_argument = xdr_netnamestr;
+ xdr_result = xdr_getcredres;
+ local = (char *(*)()) key_getcred_1;
+ check_auth = 0;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ if (check_auth) {
+ remote = *svc_getcaller(transp);
+ if (ntohs(remote.sin_port) >= IPPORT_RESERVED ||
+ ntohl(remote.sin_addr.s_addr) != INADDR_LOOPBACK) {
+ if (debugging) {
+ (void) fprintf(stderr,
+ "not local privileged process\n");
+ }
+ svcerr_weakauth(transp);
+ return;
+ }
+ if (rqstp->rq_cred.oa_flavor != AUTH_UNIX) {
+ if (debugging) {
+ (void) fprintf(stderr,
+ "not unix authentication\n");
+ }
+ svcerr_weakauth(transp);
+ return;
+ }
+ uid = ((struct authunix_parms *) rqstp->rq_clntcred)->aup_uid;
+ }
+ bzero((char *) &argument, sizeof(argument));
+ if (!svc_getargs(transp, xdr_argument, &argument)) {
+ svcerr_decode(transp);
+ return;
+ }
+ result = (*local) (uid, &argument);
+ if (!svc_sendreply(transp, xdr_result, (char *) result)) {
+ (void) fprintf(stderr, "unable to reply\n");
+ svcerr_systemerr(transp);
+ }
+ if (!svc_freeargs(transp, xdr_argument, &argument)) {
+ (void) fprintf(stderr, "unable to free arguments\n");
+ exit(1);
+ }
+}
OpenPOWER on IntegriCloud