summaryrefslogtreecommitdiffstats
path: root/lib/librpc/secure_rpc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/librpc/secure_rpc')
-rw-r--r--lib/librpc/secure_rpc/README92
-rw-r--r--lib/librpc/secure_rpc/bin/Makefile50
-rw-r--r--lib/librpc/secure_rpc/bin/chkey.c302
-rw-r--r--lib/librpc/secure_rpc/bin/keylogin.c66
-rw-r--r--lib/librpc/secure_rpc/demo/Makefile28
-rw-r--r--lib/librpc/secure_rpc/demo/rme.c96
-rw-r--r--lib/librpc/secure_rpc/demo/whoami.x33
-rw-r--r--lib/librpc/secure_rpc/demo/whoami_proc.c95
-rw-r--r--lib/librpc/secure_rpc/des/des.h68
-rw-r--r--lib/librpc/secure_rpc/des/des_crypt.c138
-rw-r--r--lib/librpc/secure_rpc/des/des_crypt.h101
-rw-r--r--lib/librpc/secure_rpc/des/des_soft.c67
-rw-r--r--lib/librpc/secure_rpc/doc/Makefile40
-rw-r--r--lib/librpc/secure_rpc/doc/nfs.secure.ms934
-rw-r--r--lib/librpc/secure_rpc/keyserv/Makefile49
-rw-r--r--lib/librpc/secure_rpc/keyserv/detach.c69
-rw-r--r--lib/librpc/secure_rpc/keyserv/keyenvoy.c213
-rw-r--r--lib/librpc/secure_rpc/keyserv/keyserv.c458
-rw-r--r--lib/librpc/secure_rpc/keyserv/mp.c145
-rw-r--r--lib/librpc/secure_rpc/keyserv/setkey.c514
-rw-r--r--lib/librpc/secure_rpc/man/chkey.119
-rw-r--r--lib/librpc/secure_rpc/man/des_crypt.3126
-rw-r--r--lib/librpc/secure_rpc/man/keyenvoy.8c22
-rw-r--r--lib/librpc/secure_rpc/man/keylogin.132
-rw-r--r--lib/librpc/secure_rpc/man/keyserv.8c52
-rw-r--r--lib/librpc/secure_rpc/man/publickey.3r44
-rw-r--r--lib/librpc/secure_rpc/man/publickey.537
-rw-r--r--lib/librpc/secure_rpc/man/rpc_secure.3n330
-rw-r--r--lib/librpc/secure_rpc/man/rtime.3n43
-rw-r--r--lib/librpc/secure_rpc/rpc/Makefile109
-rw-r--r--lib/librpc/secure_rpc/rpc/auth_des.c411
-rw-r--r--lib/librpc/secure_rpc/rpc/auth_des.h105
-rw-r--r--lib/librpc/secure_rpc/rpc/authdes_prot.c82
-rw-r--r--lib/librpc/secure_rpc/rpc/key_call.c228
-rw-r--r--lib/librpc/secure_rpc/rpc/key_prot.c165
-rw-r--r--lib/librpc/secure_rpc/rpc/key_prot.h114
-rw-r--r--lib/librpc/secure_rpc/rpc/key_prot.x151
-rw-r--r--lib/librpc/secure_rpc/rpc/netname.c239
-rw-r--r--lib/librpc/secure_rpc/rpc/openchild.c133
-rw-r--r--lib/librpc/secure_rpc/rpc/publickey.c129
-rw-r--r--lib/librpc/secure_rpc/rpc/rtime.c141
-rw-r--r--lib/librpc/secure_rpc/rpc/svc_auth.c116
-rw-r--r--lib/librpc/secure_rpc/rpc/svcauth_des.c519
-rw-r--r--lib/librpc/secure_rpc/rpc/xcrypt.c183
44 files changed, 7088 insertions, 0 deletions
diff --git a/lib/librpc/secure_rpc/README b/lib/librpc/secure_rpc/README
new file mode 100644
index 0000000..b8a860e
--- /dev/null
+++ b/lib/librpc/secure_rpc/README
@@ -0,0 +1,92 @@
+Export restriction prohibit us from including DES encryption routines in RPCSRC
+4.0. The main RPCSRC 4.0 hierarchy does not include DES Authentication,
+however this directory contains the documentation and code used to build secure
+rpc. THIS DISTRIBUTION OF SECURE RPC NEEDS EXTENSIVE WORK BEFORE IT CAN BE
+USED. PLEASE READ THE PORTING GUIDLINES BELOW.
+
+HIERARCHY
+
+bin/
+
+ This directory contains chkey and keylogin. These are user programs
+ used to establish the credentials of an RPC user.
+
+demo/
+ The 'whoami' service is found here. It can be used to test secure RPC.
+ rpcgen is used to build the client and server.
+
+des/
+
+ des_crypt.h defines the interfaces to cbc_crypt() and ecb_crypt(),
+ the DES routines used by DES Authentication.
+ des.h defines the desparams structure that is used internally by
+ these routines. Secure RPC expects it to be installed in
+ /usr/include/sys.
+ des_crypt.c defines the cbc_crypt() and ecb_crypt() routines. These
+ eventually call the routine _des_crypt(), which is *not* provided.
+ des_soft.c contains the des_setparity() routine.
+
+doc/
+
+ The document "nfs.secure.ms" is found here. It describes Secure
+ RPC and Secure NFS.
+
+keyserv/
+
+ This is an RPC based program that stores the private keys for
+ users that are using secure RPC.
+
+man/
+
+ Manual pages for the programs and library routines are found here.
+
+rpc/
+
+ The routines in this directory should be integrated with the
+ default rpc directory to make a single RPC library. The Makefile
+ found in this directory replaces the one in ../rpc. Note: the file
+ svc_auth.c in this directory replaces the one in ../rpc. Also, the
+ file ../rpc/rpc.h should be edited to include the file <rpc/des_auth.h>
+ (it presently is commented out).
+
+PORTING GUIDELINES
+
+You will need to provide a DES encryption routine. man/des_crypt.3 describes
+the interface to ecb_crypt() and cbc_crypt() (secure RPC uses both modes). The
+des/ directory has the "front-end" for these routines in the des_crypt.c file.
+
+Since public key authentication systems require a network global data lookup
+facility, this implementation uses Sun's Yellow Pages. If your site does not
+have Yellow Pages, you will have to modify the routines in rpc/publickey.c and
+bin/chkey.c. One possible approach is to replace the YP calls with code to
+read the file /etc/publickey; this file would presumably be shared by all
+secure RPC sites via NFS or some equivalent file sharing facility. If you wish
+to implement YP yourself, the RPCL (.x) protocol description file can be found
+in ../rpcsvc/yp.x.
+
+The routines in rpc/ and keyserv/ assume that the file des/des_crypt.h
+is installed in /usr/include (they include <des_crypt.h>). The file
+des/des_crypt.c assumes that des.h is installed in /usr/include/sys (it
+include <sys/des.h>). The des/ directory does not have a Makefile that
+would install these header files, so you will either have to do this
+by hand, or modify the routines to include the header files in a way suitable
+for your site.
+
+While the programs in bin/ and keyserv/ can be built in place (assuming
+the header files they include and the RPC library are available), the files
+in rpc/ must be moved into ../rpc/, the main RPC library. The Makefile and
+svc_auth.c found in rpc/ will replace those found in ../rpc/. You must also
+edit ../rpc/rpc.h to include <rpc/des_auth.h>.
+
+OPERATION
+
+Please read the documentation and manual pages for information on how to
+administer secure RPC.
+
+In the demo/ directory you'll find the 'whoami' service. This service uses DES
+Authentication, and can be used to check out secure RPC. The client program,
+'rme' takes a host as an argument. This host must be running the keyserv
+daemon and the 'whoami_svc' server. The service returns the identity of the
+client-user as known to the system on which the server is running. This
+information is only returned, however, if the client request has proper DES
+credentials.
diff --git a/lib/librpc/secure_rpc/bin/Makefile b/lib/librpc/secure_rpc/bin/Makefile
new file mode 100644
index 0000000..9d08018
--- /dev/null
+++ b/lib/librpc/secure_rpc/bin/Makefile
@@ -0,0 +1,50 @@
+#
+# @(#)Makefile 2.1 88/08/10 4.0 RPCSRC
+#
+DESTDIR=
+CFLAGS= -O
+RPCLIB= -lrpclib
+
+# C programs that live in the current directory and need explicit make lines.
+# (make depend has special rules for these files)
+#
+NSTD= chkey keylogin
+
+all: ${NSTD}
+
+chkey: chkey.c
+ ${CC} ${CFLAGS} -o chkey chkey.c -lrpcsvc -lmp ${RPCLIB}
+
+keylogin: keylogin.c
+ ${CC} ${CFLAGS} -o keylogin keylogin.c -lrpcsvc ${RPCLIB}
+
+install:
+ -for i in ${NSTD}; do \
+ (install -s $$i ${DESTDIR}/usr/bin/$$i); done
+
+clean:
+ rm -f a.out core *.s *.o
+ rm -f ${NSTD}
+
+depend:
+ for i in ${NSTD}; do \
+ cc -M ${INCPATH} $$i.c | sed 's/\.o//' | \
+ awk ' { if ($$1 != prev) \
+ { if (rec != "") print rec; rec = $$0; prev = $$1; } \
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
+ else rec = rec " " $$2 } } \
+ END { print rec } ' >> makedep; done
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile < eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
+ echo '# see make depend above' >> Makefile
+
+# Files listed in ${NSTD} have explicit make lines given below.
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
diff --git a/lib/librpc/secure_rpc/bin/chkey.c b/lib/librpc/secure_rpc/bin/chkey.c
new file mode 100644
index 0000000..eefb34e
--- /dev/null
+++ b/lib/librpc/secure_rpc/bin/chkey.c
@@ -0,0 +1,302 @@
+#ifndef lint
+static char sccsid[] = "@(#)chkey.c 2.3 88/08/15 4.0 RPCSRC";
+#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) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * Command to change one's public key in the public key database
+ */
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <sys/file.h>
+#include <pwd.h>
+#include <mp.h>
+
+extern char *getpass();
+extern char *index();
+extern char *crypt();
+extern char *sprintf();
+extern long random();
+
+static char PKMAP[] = "publickey.byname";
+static char *domain;
+struct passwd *ypgetpwuid();
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char name[MAXNETNAMELEN+1];
+ char public[HEXKEYBYTES + 1];
+ char secret[HEXKEYBYTES + 1];
+ char crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
+ char crypt2[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
+ int status;
+ char *pass;
+ struct passwd *pw;
+ char *master;
+ int euid;
+ int fd;
+ int force;
+ char *self;
+
+ self = argv[0];
+ force = 0;
+ for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
+ if (argv[0][2] != 0) {
+ usage(self);
+ }
+ switch (argv[0][1]) {
+ case 'f':
+ force = 1;
+ break;
+ default:
+ usage(self);
+ }
+ }
+ if (argc != 0) {
+ usage(self);
+ }
+
+ (void)yp_get_default_domain(&domain);
+ if (yp_master(domain, PKMAP, &master) != 0) {
+ (void)fprintf(stderr,
+ "can't find master of publickey database\n");
+ exit(1);
+ }
+
+ getnetname(name);
+ (void)printf("Generating new key for %s.\n", name);
+
+ euid = geteuid();
+ if (euid != 0) {
+ pw = ypgetpwuid(euid);
+ if (pw == NULL) {
+ (void)fprintf(stderr,
+ "No yp password found: can't change key.\n");
+ exit(1);
+ }
+ } else {
+ pw = getpwuid(0);
+ if (pw == NULL) {
+ (void)fprintf(stderr,
+ "No password found: can't change key.\n");
+ exit(1);
+ }
+ }
+ pass = getpass("Password:");
+ if (!force) {
+ if (strcmp(crypt(pass, pw->pw_passwd), pw->pw_passwd) != 0) {
+ (void)fprintf(stderr, "Invalid password.\n");
+ exit(1);
+ }
+ }
+
+ genkeys(public, secret, pass);
+
+ bcopy(secret, crypt1, HEXKEYBYTES);
+ bcopy(secret, crypt1 + HEXKEYBYTES, KEYCHECKSUMSIZE);
+ crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
+ xencrypt(crypt1, pass);
+
+ if (force) {
+ bcopy(crypt1, crypt2, HEXKEYBYTES + KEYCHECKSUMSIZE + 1);
+ xdecrypt(crypt2, getpass("Retype password:"));
+ if (bcmp(crypt2, crypt2 + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0 ||
+ bcmp(crypt2, secret, HEXKEYBYTES) != 0) {
+ (void)fprintf(stderr, "Password incorrect.\n");
+ exit(1);
+ }
+ }
+
+ (void)printf("Sending key change request to %s...\n", master);
+ status = setpublicmap(name, public, crypt1);
+ if (status != 0) {
+ (void)printf("%s: unable to update yp database (%u): %s\n",
+ self, status, yperr_string(status));
+ (void)printf("Perhaps %s is down?\n", master);
+ exit(1);
+ }
+ (void)printf("Done.\n");
+
+ if (key_setsecret(secret) < 0) {
+ (void)printf("Unable to login with new secret key.\n");
+ exit(1);
+ }
+}
+
+usage(name)
+ char *name;
+{
+ (void)fprintf(stderr, "usage: %s [-f]\n", name);
+ exit(1);
+}
+
+
+/*
+ * Generate a seed
+ */
+getseed(seed, seedsize, pass)
+ char *seed;
+ int seedsize;
+ unsigned char *pass;
+{
+ int i;
+ int rseed;
+ struct timeval tv;
+
+ (void)gettimeofday(&tv, (struct timezone *)NULL);
+ rseed = tv.tv_sec + tv.tv_usec;
+ for (i = 0; i < 8; i++) {
+ rseed ^= (rseed << 8) | pass[i];
+ }
+ srandom(rseed);
+
+ for (i = 0; i < seedsize; i++) {
+ seed[i] = (random() & 0xff) ^ pass[i % 8];
+ }
+}
+
+
+/*
+ * Generate a random public/secret key pair
+ */
+genkeys(public, secret, pass)
+ char *public;
+ char *secret;
+ char *pass;
+{
+ int i;
+
+#define BASEBITS (8*sizeof(short) - 1)
+#define BASE (1 << BASEBITS)
+
+ MINT *pk = itom(0);
+ MINT *sk = itom(0);
+ MINT *tmp;
+ MINT *base = itom(BASE);
+ MINT *root = itom(PROOT);
+ MINT *modulus = xtom(HEXMODULUS);
+ short r;
+ unsigned short seed[KEYSIZE/BASEBITS + 1];
+ char *xkey;
+
+ getseed((char *)seed, sizeof(seed), (unsigned char *)pass);
+ for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
+ r = seed[i] % BASE;
+ tmp = itom(r);
+ mult(sk, base, sk);
+ madd(sk, tmp, sk);
+ mfree(tmp);
+ }
+ tmp = itom(0);
+ mdiv(sk, modulus, tmp, sk);
+ mfree(tmp);
+ pow(root, sk, modulus, pk);
+ xkey = mtox(sk);
+ adjust(secret, xkey);
+ xkey = mtox(pk);
+ adjust(public, xkey);
+ mfree(sk);
+ mfree(base);
+ mfree(pk);
+ mfree(root);
+ mfree(modulus);
+}
+
+/*
+ * Adjust the input key so that it is 0-filled on the left
+ */
+adjust(keyout, keyin)
+ char keyout[HEXKEYBYTES+1];
+ char *keyin;
+{
+ char *p;
+ char *s;
+
+ for (p = keyin; *p; p++)
+ ;
+ for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
+ *s = *p;
+ }
+ while (s >= keyout) {
+ *s-- = '0';
+ }
+}
+
+/*
+ * Set the entry in the public key map
+ */
+setpublicmap(name, public, secret)
+ char *name;
+ char *public;
+ char *secret;
+{
+ char pkent[1024];
+ u_int rslt;
+
+ (void)sprintf(pkent,"%s:%s", public, secret);
+ rslt = yp_update(domain, PKMAP, YPOP_STORE,
+ name, strlen(name), pkent, strlen(pkent));
+ return (rslt);
+}
+
+struct passwd *
+ypgetpwuid(uid)
+ int uid;
+{
+ char uidstr[10];
+ char *val;
+ int vallen;
+ static struct passwd pw;
+ char *p;
+
+ (void)sprintf(uidstr, "%d", uid);
+ if (yp_match(domain, "passwd.byuid", uidstr, strlen(uidstr),
+ &val, &vallen) != 0) {
+ return (NULL);
+ }
+ p = index(val, ':');
+ if (p == NULL) {
+ return (NULL);
+ }
+ pw.pw_passwd = p + 1;
+ p = index(pw.pw_passwd, ':');
+ if (p == NULL) {
+ return (NULL);
+ }
+ *p = 0;
+ return (&pw);
+}
diff --git a/lib/librpc/secure_rpc/bin/keylogin.c b/lib/librpc/secure_rpc/bin/keylogin.c
new file mode 100644
index 0000000..0643f07
--- /dev/null
+++ b/lib/librpc/secure_rpc/bin/keylogin.c
@@ -0,0 +1,66 @@
+#ifndef lint
+static char sccsid[] = "@(#)keylogin.c 2.2 88/08/10 4.0 RPCSRC";
+#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) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * Set secret key on local machine
+ */
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+
+main(argc,argv)
+ int argc;
+ char *argv[];
+{
+ char fullname[MAXNETNAMELEN + 1];
+ char secret[HEXKEYBYTES + 1];
+ char *getpass();
+
+ getnetname(fullname);
+ if (! getsecretkey(fullname, secret, getpass("Password:"))) {
+ fprintf(stderr, "Can't find %s's secret key\n", fullname);
+ exit(1);
+ }
+ if (secret[0] == 0) {
+ fprintf(stderr, "Password incorrect for %s\n", fullname);
+ exit(1);
+ }
+ if (key_setsecret(secret) < 0) {
+ fprintf(stderr, "Could not set %s's secret key\n", fullname);
+ fprintf(stderr, "Maybe the keyserver is down?\n");
+ exit(1);
+ }
+ exit(0);
+}
diff --git a/lib/librpc/secure_rpc/demo/Makefile b/lib/librpc/secure_rpc/demo/Makefile
new file mode 100644
index 0000000..f1e62a7
--- /dev/null
+++ b/lib/librpc/secure_rpc/demo/Makefile
@@ -0,0 +1,28 @@
+#
+# @(#)Makefile 2.2 88/08/15 4.0 RPCSRC
+#
+BIN = whoami_svc rme
+GEN = whoami_clnt.c whoami_svc.c whoami_xdr.c whoami.h
+LIB = -lrpclib
+#use this line on SunOS or NFSSRC-based systems.
+#LIB = -lrpcsvc
+RPCCOM = rpcgen
+
+all: $(BIN)
+
+$(GEN): whoami.x
+ $(RPCCOM) whoami.x
+
+whoami_svc: whoami_proc.o whoami_svc.o whoami_xdr.o
+ $(CC) -o $@ whoami_proc.o whoami_svc.o whoami_xdr.o $(LIB)
+
+rme: rme.o whoami_clnt.o whoami_xdr.o
+ $(CC) -o $@ rme.o whoami_clnt.o whoami_xdr.o $(LIB)
+
+rme.o: rme.c whoami.h
+
+whoami_proc.o: whoami_proc.c whoami.h
+
+clean cleanup:
+ rm -f $(GEN) *.o $(BIN)
+
diff --git a/lib/librpc/secure_rpc/demo/rme.c b/lib/librpc/secure_rpc/demo/rme.c
new file mode 100644
index 0000000..773eafa
--- /dev/null
+++ b/lib/librpc/secure_rpc/demo/rme.c
@@ -0,0 +1,96 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rme.c 2.3 88/09/09 4.0 RPCSRC";
+#endif
+/*
+ * rme.c: secure identity verifier and reporter: client side
+ */
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include "whoami.h"
+
+/*
+ * Before running this program, the user must have a key in the publickey
+ * database, and must have logged in with a password (or used keylogin).
+ * The user's machine and the server's machine must both be running keyserv.
+ */
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ CLIENT *cl;
+ char *server;
+ remote_identity *remote_me;
+ name *servername;
+ void *nullp;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s host\n", argv[0]);
+ exit(1);
+ }
+
+ /*
+ * Remember what our command line argument refers to
+ */
+ server = argv[1];
+
+ /*
+ * Create client "handle" used for calling WHOAMI on the
+ * server designated on the command line. We tell the rpc package
+ * to use the "udp" protocol when contacting the server.
+ */
+ cl = clnt_create(server, WHOAMI, WHOAMI_V1, "udp");
+ if (cl == NULL) {
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+ /*
+ * Get network identifier for server machine.
+ */
+ servername = whoami_whoru_1(nullp, cl);
+ if (servername == NULL)
+ {
+ fprintf(stderr, "Trouble communicating with %s\n",
+ clnt_sperror(cl, server));
+ exit(1);
+ }
+ else if (*servername[0] == '\0')
+ {
+ fprintf(stderr, "Could not determine netname of WHOAMI server.\n");
+ exit(1);
+ }
+ printf("Server's netname is: %s\n", *servername);
+
+ /*
+ * A wide window and no synchronization is used. Client and server
+ * clock must be with five minutes of each other.
+ */
+ if ((cl->cl_auth = authdes_create(*servername, 300, NULL, NULL)) == NULL)
+ {
+ fprintf(stderr, "Could not establish DES credentials of netname %s\n",
+ servername);
+ exit(1);
+ }
+
+ /*
+ * Find out who I am, in the server's point of view.
+ */
+ remote_me = whoami_iask_1(nullp, cl);
+ if (remote_me == NULL)
+ {
+ fprintf(stderr, "Trouble getting my identity from %s\n",
+ clnt_sperror(cl, server));
+ exit(1);
+ }
+ /*
+ * Print out my identity.
+ */
+ printf("My remote user name: %s\n", remote_me->remote_username);
+ printf("My remote real name: %s\n", remote_me->remote_realname);
+
+ exit(0);
+}
diff --git a/lib/librpc/secure_rpc/demo/whoami.x b/lib/librpc/secure_rpc/demo/whoami.x
new file mode 100644
index 0000000..041cd0a
--- /dev/null
+++ b/lib/librpc/secure_rpc/demo/whoami.x
@@ -0,0 +1,33 @@
+/* @(#)whoami.x 2.2 88/08/22 4.0 RPCSRC */
+
+const WHOAMI_NGROUPS = 16;
+
+typedef string name<MAXNETNAMELEN>;
+
+struct remote_identity {
+ bool authenticated; /* TRUE if the server authenticates us */
+ name remote_username; /* login name */
+ name remote_realname; /* gcos-field name (long name) */
+ int uid;
+ int gid;
+ int gids<WHOAMI_NGROUPS>;
+};
+
+program WHOAMI {
+ version WHOAMI_V1 {
+ /*
+ * Report on the server's notion of the client's identity.
+ * Will respond to AUTH_DES only.
+ */
+ remote_identity
+ WHOAMI_IASK(void) = 1;
+ /*
+ * Return server's netname. AUTH_NONE is okay.
+ * This routine allows this server to be started under any uid,
+ * and the client can ask it its netname for use in authdes_create().
+ */
+ name
+ WHOAMI_WHORU(void) = 2;
+
+ } = 1;
+} = 80955;
diff --git a/lib/librpc/secure_rpc/demo/whoami_proc.c b/lib/librpc/secure_rpc/demo/whoami_proc.c
new file mode 100644
index 0000000..231d322
--- /dev/null
+++ b/lib/librpc/secure_rpc/demo/whoami_proc.c
@@ -0,0 +1,95 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)whoami_proc.c 2.3 89/07/11 4.0 RPCSRC";
+#endif
+/*
+ * whoami_proc.c: secure identity verifier and reporter: server proc
+ */
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+#include <pwd.h>
+#include "whoami.h"
+
+extern char *strcpy();
+
+/*
+ * Report on the server's notion of the client's identity.
+ */
+remote_identity *
+whoami_iask_1(nullarg, rqstp)
+ void *nullarg;
+ struct svc_req *rqstp;
+{
+static remote_identity whoisthem;
+static char username[MAXNETNAMELEN+1];
+static char realname[MAXNETNAMELEN+1]; /* really gecos field */
+static int grouplist[NGROUPS];
+ char publickey[HEXKEYBYTES+1];
+
+ struct authdes_cred *des_cred;
+ struct passwd *pwdent;
+
+ switch (rqstp->rq_cred.oa_flavor)
+ {
+ case AUTH_DES:
+ whoisthem.remote_username = username;
+ whoisthem.remote_realname = realname;
+ whoisthem.gids.gids_val = grouplist;
+ des_cred = (struct authdes_cred *) rqstp->rq_clntcred;
+ /*
+ * Check to see if the netname being used is in the public key
+ * database (if not, reject this (potential) imposter).
+ */
+ if (! getpublickey(des_cred->adc_fullname.name, publickey))
+ {
+ svcerr_weakauth(rqstp->rq_xprt);
+ return(NULL);
+ }
+ /*
+ * Get the info that the client wants.
+ */
+ if (! netname2user(des_cred->adc_fullname.name, &whoisthem.uid,
+ &whoisthem.gid, &whoisthem.gids.gids_len,
+ whoisthem.gids.gids_val))
+ { /* netname not found */
+ whoisthem.authenticated = FALSE;
+ strcpy(whoisthem.remote_username, "nobody");
+ strcpy(whoisthem.remote_realname, "INTERLOPER!");
+ whoisthem.uid = -2;
+ whoisthem.gid = -2;
+ whoisthem.gids.gids_len = 0;
+ return(&whoisthem);
+ }
+ /* else we found the netname */
+ whoisthem.authenticated = TRUE;
+ pwdent = getpwuid(whoisthem.uid);
+ strcpy(whoisthem.remote_username, pwdent->pw_name);
+ strcpy(whoisthem.remote_realname, pwdent->pw_gecos);
+ return(&whoisthem);
+ break;
+ case AUTH_UNIX:
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(rqstp->rq_xprt);
+ return(NULL);
+ }
+}
+
+/*
+ * Return server's netname. AUTH_NONE is valid.
+ * This routine allows this server to be started under any uid,
+ * and the client can ask us our netname for use in authdes_create().
+ */
+name *
+whoami_whoru_1(nullarg, rqstp)
+ void *nullarg;
+ struct svc_req *rqstp;
+{
+static name whoru;
+static char servername[MAXNETNAMELEN+1];
+
+ whoru = servername;
+ getnetname(servername);
+
+ return(&whoru);
+}
diff --git a/lib/librpc/secure_rpc/des/des.h b/lib/librpc/secure_rpc/des/des.h
new file mode 100644
index 0000000..c237f23
--- /dev/null
+++ b/lib/librpc/secure_rpc/des/des.h
@@ -0,0 +1,68 @@
+/* @(#)des.h 2.2 88/08/10 4.0 RPCSRC; from 2.7 88/02/08 SMI */
+/*
+ * 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
+ */
+/*
+ * Generic DES driver interface
+ * Keep this file hardware independent!
+ * Copyright (c) 1986 by Sun Microsystems, Inc.
+ */
+
+#define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */
+#define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */
+
+enum desdir { ENCRYPT, DECRYPT };
+enum desmode { CBC, ECB };
+
+/*
+ * parameters to ioctl call
+ */
+struct desparams {
+ u_char des_key[8]; /* key (with low bit parity) */
+ enum desdir des_dir; /* direction */
+ enum desmode des_mode; /* mode */
+ u_char des_ivec[8]; /* input vector */
+ unsigned des_len; /* number of bytes to crypt */
+ union {
+ u_char UDES_data[DES_QUICKLEN];
+ u_char *UDES_buf;
+ } UDES;
+# define des_data UDES.UDES_data /* direct data here if quick */
+# define des_buf UDES.UDES_buf /* otherwise, pointer to data */
+};
+
+/*
+ * Encrypt an arbitrary sized buffer
+ */
+#define DESIOCBLOCK _IOWR(d, 6, struct desparams)
+
+/*
+ * Encrypt of small amount of data, quickly
+ */
+#define DESIOCQUICK _IOWR(d, 7, struct desparams)
+
diff --git a/lib/librpc/secure_rpc/des/des_crypt.c b/lib/librpc/secure_rpc/des/des_crypt.c
new file mode 100644
index 0000000..57a9e71
--- /dev/null
+++ b/lib/librpc/secure_rpc/des/des_crypt.c
@@ -0,0 +1,138 @@
+#ifndef lint
+static char sccsid[] = "@(#)des_crypt.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#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
+ */
+/*
+ * des_crypt.c, DES encryption library routines
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+#include <des_crypt.h>
+#include <sys/des.h>
+
+/*
+ * To see if chip is installed
+ */
+#define UNOPENED (-2)
+static int g_desfd = UNOPENED;
+
+
+/*
+ * Copy 8 bytes
+ */
+#define COPY8(src, dst) { \
+ register char *a = (char *) dst; \
+ register char *b = (char *) src; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+}
+
+/*
+ * Copy multiple of 8 bytes
+ */
+#define DESCOPY(src, dst, len) { \
+ register char *a = (char *) dst; \
+ register char *b = (char *) src; \
+ register int i; \
+ for (i = (int) len; i > 0; i -= 8) { \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ } \
+}
+
+/*
+ * CBC mode encryption
+ */
+cbc_crypt(key, buf, len, mode, ivec)
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+ char *ivec;
+{
+ int err;
+ struct desparams dp;
+
+ dp.des_mode = CBC;
+ COPY8(ivec, dp.des_ivec);
+ err = common_crypt(key, buf, len, mode, &dp);
+ COPY8(dp.des_ivec, ivec);
+ return(err);
+}
+
+
+/*
+ * ECB mode encryption
+ */
+ecb_crypt(key, buf, len, mode)
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+{
+ struct desparams dp;
+
+ dp.des_mode = ECB;
+ return(common_crypt(key, buf, len, mode, &dp));
+}
+
+
+
+/*
+ * Common code to cbc_crypt() & ecb_crypt()
+ */
+static
+common_crypt(key, buf, len, mode, desp)
+ char *key;
+ char *buf;
+ register unsigned len;
+ unsigned mode;
+ register struct desparams *desp;
+{
+ register int desdev;
+ register int res;
+
+ if ((len % 8) != 0 || len > DES_MAXDATA) {
+ return(DESERR_BADPARAM);
+ }
+ desp->des_dir =
+ ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT;
+
+ desdev = mode & DES_DEVMASK;
+ COPY8(key, desp->des_key);
+ /*
+ * software
+ */
+ if (!_des_crypt(buf, len, desp)) {
+ return (DESERR_HWERROR);
+ }
+ return(desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE);
+}
diff --git a/lib/librpc/secure_rpc/des/des_crypt.h b/lib/librpc/secure_rpc/des/des_crypt.h
new file mode 100644
index 0000000..d21d095
--- /dev/null
+++ b/lib/librpc/secure_rpc/des/des_crypt.h
@@ -0,0 +1,101 @@
+/*
+ * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC; from 1.4 88/02/08 (C) 1986 SMI
+ *
+ * des_crypt.h, des library routine interface
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+/*
+ * 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
+ */
+#define DES_MAXDATA 8192 /* max bytes encrypted in one call */
+#define DES_DIRMASK (1 << 0)
+#define DES_ENCRYPT (0*DES_DIRMASK) /* Encrypt */
+#define DES_DECRYPT (1*DES_DIRMASK) /* Decrypt */
+
+
+#define DES_DEVMASK (1 << 1)
+#define DES_HW (0*DES_DEVMASK) /* Use hardware device */
+#define DES_SW (1*DES_DEVMASK) /* Use software device */
+
+
+#define DESERR_NONE 0 /* succeeded */
+#define DESERR_NOHWDEVICE 1 /* succeeded, but hw device not available */
+#define DESERR_HWERROR 2 /* failed, hardware/driver error */
+#define DESERR_BADPARAM 3 /* failed, bad parameter to call */
+
+#define DES_FAILED(err) \
+ ((err) > DESERR_NOHWDEVICE)
+
+/*
+ * cbc_crypt()
+ * ecb_crypt()
+ *
+ * Encrypt (or decrypt) len bytes of a buffer buf.
+ * The length must be a multiple of eight.
+ * The key should have odd parity in the low bit of each byte.
+ * ivec is the input vector, and is updated to the new one (cbc only).
+ * The mode is created by oring together the appropriate parameters.
+ * DESERR_NOHWDEVICE is returned if DES_HW was specified but
+ * there was no hardware to do it on (the data will still be
+ * encrypted though, in software).
+ */
+
+
+/*
+ * Cipher Block Chaining mode
+ */
+cbc_crypt(/* key, buf, len, mode, ivec */); /*
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+ char *ivec;
+*/
+
+
+/*
+ * Electronic Code Book mode
+ */
+ecb_crypt(/* key, buf, len, mode */); /*
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+*/
+
+
+#ifndef KERNEL
+/*
+ * Set des parity for a key.
+ * DES parity is odd and in the low bit of each byte
+ */
+void
+des_setparity(/* key */); /*
+ char *key;
+*/
+#endif
diff --git a/lib/librpc/secure_rpc/des/des_soft.c b/lib/librpc/secure_rpc/des/des_soft.c
new file mode 100644
index 0000000..01dd7f2
--- /dev/null
+++ b/lib/librpc/secure_rpc/des/des_soft.c
@@ -0,0 +1,67 @@
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)des_soft.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#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
+ */
+/*
+ * Table giving odd parity in the low bit for ASCII characters
+ */
+static char partab[128] = {
+ 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07,
+ 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e,
+ 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
+ 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f,
+ 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26,
+ 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f,
+ 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37,
+ 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e,
+ 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
+ 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f,
+ 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57,
+ 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e,
+ 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67,
+ 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e,
+ 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
+ 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f,
+};
+
+/*
+ * Add odd parity to low bit of 8 byte key
+ */
+void
+des_setparity(p)
+ char *p;
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ *p = partab[*p & 0x7f];
+ p++;
+ }
+}
diff --git a/lib/librpc/secure_rpc/doc/Makefile b/lib/librpc/secure_rpc/doc/Makefile
new file mode 100644
index 0000000..3cfbe9e
--- /dev/null
+++ b/lib/librpc/secure_rpc/doc/Makefile
@@ -0,0 +1,40 @@
+#
+# @(#)Makefile 2.1 88/08/10 4.0 RPCSRC
+#
+#
+TROFF= ditroff
+TOPTS= -t
+NROFF= nroff
+NOPTS=
+PIC= pic
+TBL= tbl
+EQN= eqn
+
+SRC= nfs.secure.ms
+
+all default: all.nroff
+
+install: all.nroff
+ @echo "Nothing installed."
+
+all.nroff: ${SRC}
+ ${TBL} ${SRC} | ${EQN} | ${NROFF} ${NOPTS} -ms >all.nroff
+
+all.troff: ${SRC}
+ ${TBL} ${SRC} | ${PIC} | ${EQN} | ${TROFF} ${TOPTS} -ms >all.troff
+
+#
+
+nfs.secure.nroff: nfs.secure.ms
+ ${TBL} nfs.secure.ms | ${EQN} | ${NROFF} ${NOPTS} -ms >nfs.secure.nroff
+
+nfs.secure.troff: nfs.secure.ms
+ ${TBL} nfs.secure.ms|${PIC}|${EQN}| ${TROFF} ${TOPTS} -ms >nfs.secure.troff
+
+clean:
+ rm -f *.nroff *.troff
+
+spell: ${SRC}
+ @for i in ${SRC}; do \
+ echo $$i; spell $$i | sort | comm -23 - spell.ok > $$i.spell; \
+ done
diff --git a/lib/librpc/secure_rpc/doc/nfs.secure.ms b/lib/librpc/secure_rpc/doc/nfs.secure.ms
new file mode 100644
index 0000000..2476790
--- /dev/null
+++ b/lib/librpc/secure_rpc/doc/nfs.secure.ms
@@ -0,0 +1,934 @@
+.\" Must use -- pic tbl eqn -- with this one.
+.\"
+.\" @(#)nfs.secure.ms 2.2 88/08/09 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Secure Networking''Page %'
+.EH 'Page %''Secure Networking'
+.if \\n%=1 .bp
+.EQ
+delim $$
+gsize 11
+.EN
+.SH
+\&Secure Networking
+.nr OF 1
+.IX "security" "of networks" "" "" PAGE START
+.IX "network security" "" "" "" PAGE START
+.IX "NFS security" "" "" "" PAGE START
+.LP
+RPCSRC 4.0 includes an authentication system
+that greatly improves the security of network environments.
+The system is general enough to be used by other
+.UX
+and non-UNIX systems.
+The system uses DES encryption and public key cryptography
+to authenticate both users and machines in the network.
+(DES stands for Data Encryption Standard.)
+.LP
+Public key cryptography is a cipher system that involves two keys:
+one public and the other private.
+The public key is published, while the private key is not;
+the private (or secret) key is used to encrypt and decrypt data.
+Sun's system differs from some other public key cryptography systems
+in that the public and secret keys are used to generate a common key,
+which is used in turn to create a DES key.
+DES is relatively fast,
+and on Sun Workstations,
+optional hardware is available to make it even faster.
+.#
+.NH 0
+\&Administering Secure RPC
+.IX "administering secure RPC"
+.IX "security" "RPC administration"
+.LP
+This section describes what the system administrator must do
+in order to use secure networking.
+.IP 1
+RPCSRC now includes the
+.I /etc/publickey
+.IX "etc/publickey" "" "\&\fI/etc/publickey\fP"
+database, which should contain three fields for each user:
+the user's netname, a public key, and an encrypted secret key.
+The corresponding Yellow Pages map is available to YP clients as
+.I publickey.byname
+but the database should reside only on the YP master. Make sure
+.I /etc/netid
+exists on the YP master server.
+As normally installed, the only user is
+.I nobody .
+This is convenient administratively,
+because users can establish their own public keys using
+.I chkey (1)
+.IX "chkey command" "" "\&\fIchkey\fP command"
+without administrator intervention.
+For even greater security,
+the administrator can establish public keys for everyone using
+.I newkey (8).
+.IX "newkey command" "" "\&\fInewkey\fP command"
+Note that the Yellow Pages take time to propagate a new map,
+so it's a good idea for users to run
+.I chkey ,
+or for the administrator to run
+.I newkey ,
+just before going home for the night.
+.IP 2
+Verify that the
+.I keyserv (8c)
+.IX "keyserv daemon" "" "\&\fIkeyserv\fP daemon"
+daemon was started by
+.I /etc/rc.local
+and is still running.
+This daemon performs public key encryption
+and stores the private key (encrypted, of course) in
+.I /etc/keystore :
+.DS
+% \fBps aux | grep keyserv\fP
+root 1354 0.0 4.1 128 296 p0 I Oct 15 0:13 keyserv
+.DE
+When users log in with
+.I login
+.IX "login command" "" "\&\fIlogin\fP command"
+or remote log in with
+.I rlogin ,
+these programs use the typed password to decrypt the secret key stored in
+.I /etc/publickey .
+This becomes the private key, and gets passed to the
+.I keyserv
+daemon.
+If users don't type a password for
+.I login
+or
+.I rlogin ,
+either because their password field is empty
+or because their machine is in the
+.I hosts\fR.\fPequiv
+.IX "etc/hosts.equiv" "" "\&\fI/etc/hosts.equiv\fP"
+file of the remote host,
+they can still place a private key in
+.I /etc/keystore
+by invoking the
+.I keylogin (1)
+.IX "keylogin command" "" "\&\fIkeylogin\fP command"
+program.
+Administrators should take care not to delete
+.I /etc/keystore
+and
+.I /etc/.rootkey
+(the latter file contains the private key for
+.I root ).
+.IP 3
+When you reinstall, move, or upgrade a machine, save
+.I /etc/keystore
+and
+.I /etc/.rootkey
+along with everything else you normally save.
+.LP
+.LP
+Note that if you
+.I login ,
+.I rlogin ,
+or
+.I telnet
+to another machine, are asked for your password, and type it correctly,
+you've given away access to your own account.
+This is because your secret key is now stored in
+.I /etc/keystore
+on that remote machine.
+This is only a concern if you don't trust the remote machine.
+If this is the case,
+don't ever log in to a remote machine if it asks for your password.
+Instead, use NFS to remote mount the files you're looking for.
+At this point there is no
+.I keylogout
+command, even though there should be.
+.LP
+The remainder of this chapter discusses the theory of secure networking,
+and is useful as a background for both users and administrators.
+.#
+.NH 1
+\&Security Shortcomings of NFS
+.IX "security" "shortcomings of NFS"
+.LP
+Sun's Remote Procedure Call (RPC) mechanism has proved to be a very
+powerful primitive for building network services.
+The most well-known of these services is the Network File System (NFS),
+a service that provides transparent file-sharing
+between heterogeneous machine architectures and operating systems.
+The NFS is not without its shortcomings, however.
+Currently, an NFS server authenticates a file request by authenticating the
+machine making the request, but not the user.
+On NFS-based filesystems, it is a simple matter of running
+.I su
+.IX "su command" "" "\&\fIsu\fP command"
+to impersonate the rightful owner of a file.
+But the security weaknesses of the NFS are nothing new.
+The familiar command
+.I rlogin
+is subject to exactly the same attacks as the NFS
+because it uses the same kind of authentication.
+.LP
+A common solution to network security problems
+is to leave the solution to each application.
+A far better solution is to put authentication at the RPC level.
+The result is a standard authentication system
+that covers all RPC-based applications,
+such as the NFS and the Yellow Pages (a name-lookup service).
+Our system allows the authentication of users as well as machines.
+The advantage of this is that it makes a network environment
+more like the older time-sharing environment.
+Users can log in on any machine,
+just as they could log in on any terminal.
+Their login password is their passport to network security.
+No knowledge of the underlying authentication system is required.
+Our goal was a system that is as secure and easy to use
+as a time-sharing system.
+.LP
+Several remarks are in order. Given
+.I root
+access and a good knowledge of network programming,
+anyone is capable of injecting arbitrary data into the network,
+and picking up any data from the network.
+However, on a local area network, no machine is capable of packet smashing \(en
+capturing packets before they reach their destination, changing the contents,
+then sending packets back on their original course \(en
+because packets reach all machines, including the server, at the same time.
+Packet smashing is possible on a gateway, though,
+so make sure you trust all gateways on the network.
+The most dangerous attacks are those involving the injection of data,
+such as impersonating a user by generating the right packets,
+or recording conversations and replaying them later.
+These attacks affect data integrity.
+Attacks involving passive eavesdropping \(en
+merely listening to network traffic without impersonating anybody \(en
+are not as dangerous, since data integrity had not been compromised.
+Users can protect the privacy of sensitive information
+by encrypting data that goes over the network.
+It's not easy to make sense of network traffic, anyway.
+.#
+.NH 1
+\&RPC Authentication
+.IX "RPC authentication"
+.IX "authentication" "RPC"
+.LP
+RPC is at the core of the new network security system.
+To understand the big picture,
+it's necessary to understand how authentication works in RPC.
+RPC's authentication is open-ended:
+a variety of authentication systems may be plugged into it
+and may coexist on the network.
+Currently, we have two: UNIX and DES.
+UNIX authentication is the older, weaker system;
+DES authentication is the new system discussed in this chapter.
+Two terms are important for any RPC authentication system:
+.I credentials
+and
+.I verifiers .
+Using ID badges as an example, the credential is what identifies a person:
+a name, address, birth date, etc.
+The verifier is the photo attached to the badge:
+you can be sure the badge has not been stolen by checking the photo
+on the badge against the person carrying it.
+In RPC, things are similar.
+The client process sends both a credential and a verifier
+to the server with each RPC request.
+The server sends back only a verifier,
+since the client already knows the server's credentials.
+.#
+.NH 2
+\&UNIX Authentication
+.IX "UNIX authentication"
+.IX "authentication" "UNIX"
+.LP
+UNIX authentication was used by most of Sun's original network services.
+The credentials contain the client's machine-name,
+.I uid ,
+.I gid ,
+and group-access-list.
+The verifier contains \fBnothing\fP!
+There are two problems with this system.
+The glaring problem is the empty verifier,
+which makes it easy to cook up the right credential using
+.I hostname
+.IX "hostname command" "" "\&\fIhostname\fP command"
+and
+.I su .
+.IX "su command" "" "\&\fIsu\fP command"
+If you trust all root users in the network, this is not really a problem.
+But many networks \(en especially at universities \(en are not this secure.
+The NFS tries to combat deficiencies in UNIX authentication
+by checking the source Internet address of
+.I mount
+requests as a verifier of the
+.I hostname
+field, and accepting requests only from privileged Internet ports.
+Still, it is not difficult to circumvent these measures,
+and NFS really has no way to verify the user-ID.
+.LP
+The other problem with UNIX authentication appears in the name UNIX.
+It is unrealistic to assume that all machines on a network
+will be UNIX machines.
+The NFS works with MS-DOS and VMS machines,
+but UNIX authentication breaks down when applied to them.
+For instance, MS-DOS doesn't even have a notion of different user IDs.
+.LP
+Given these shortcomings,
+it is clear what is needed in a new authentication system:
+operating system independent credentials, and secure verifiers.
+This is the essence of DES authentication discussed below.
+.#
+.NH 2
+\&DES Authentication
+.IX "DES authentication"
+.IX "authentication" "DES"
+.LP
+The security of DES authentication is based on
+a sender's ability to encrypt the current time,
+which the receiver can then decrypt and check against its own clock.
+The timestamp is encrypted with DES.
+Two things are necessary for this scheme to work:
+1) the two agents must agree on what the current time is, and
+2) the sender and receiver must be using the same encryption key.
+.LP
+If a network has time synchronization (Berkeley's TEMPO for example),
+then client/server time synchronization is performed automatically.
+However, if this is not available,
+timestamps can be computed using the server's time instead of network time.
+In order to do this, the client asks the server what time it is,
+before starting the RPC session,
+then computes the time difference between its own clock and the server's.
+This difference is used to offset the client's clock when computing timestamps.
+If the client and server clocks get out of sync
+to the point where the server begins rejecting the client's requests,
+the DES authentication system just resynchronizes with the server.
+.LP
+Here's how the client and server arrive at the same encryption key.
+When a client wishes to talk to a server, it generates at random
+a key to be used for encrypting the timestamps (among other things).
+This key is known as the
+.I "conversation key, CK."
+The client encrypts the conversation key using a public key scheme,
+and sends it to the server in its first transaction.
+This key is the only thing that is ever encrypted with public key cryptography.
+The particular scheme used is described further on in this chapter.
+For now, suffice to say that for any two agents A and B,
+there is a DES key $K sub AB$ that only A and B can deduce.
+This key is known as the
+.I "common key,"
+$K sub AB$.
+.EQ
+gsize 10
+.EN
+.ne 1i
+.PS
+.in +.7i
+circlerad=.4
+boxht=.2
+boxwid=1.3
+circle "\s+9A\s-9" "(client)" at 0,1.2
+circle "\s+9B\s-9" "(server)" at 5.1,1.2
+line invis at .5,2 ; box invis "\fBCredential\fP"; line invis;
+ box invis "\fBVerifier\fP"
+arrow at .5,1.7; box "$A, K sub AB (CK), CK(win)$"; arrow;
+ box "$CK(t sub 1 ), CK(win + 1)$"; arrow
+arrow <- at .5,1.4; line right 1.3; line;
+ box "$CK(t sub 1 - 1), ID$"; arrow <-
+arrow at .5,1; box "ID"; arrow;
+ box "$CK(t sub 2 )$"; arrow
+arrow <- at .5,.7; line right 1.3; line;
+ box "$CK(t sub 2 - 1), ID$"; arrow <-
+arrow at .5,.3; box "ID"; arrow;
+ box "$CK(t sub n )$"; arrow
+arrow <- at .5,0; line right 1.3; line;
+ box "$CK(t sub n - 1), ID$"; arrow <-
+.PE
+.EQ
+gsize 11
+.EN
+.in -.7i
+.LP
+The figure above illustrates the authentication protocol in more detail,
+describing client A talking to server B.
+A term of the form $K(x)$ means $x$ encrypted with the DES key $K$.
+Examining the figure, you can see that for its first request,
+the client's credential contains three things:
+its name $A$, the conversation key $CK$ encrypted with the common key
+$K sub AB$, and a thing called $win$ (window) encrypted with $CK$.
+What the window says to the server, in effect, is this:
+.LP
+.I
+I will be sending you many credentials in the future,
+but there may be crackers sending them too,
+trying to impersonate me with bogus timestamps.
+When you receive a timestamp, check to see if your current time
+is somewhere between the timestamp and the timestamp plus the window.
+If it's not, please reject the credential.
+.LP
+For secure NFS filesystems, the window currently defaults to 30 minutes.
+The client's verifier in the first request contains the encrypted timestamp
+and an encrypted verifier of the specified window, $win + 1$.
+The reason this exists is the following.
+Suppose somebody wanted to impersonate A by writing a program
+that instead of filling in the encrypted fields of the credential and verifier,
+just stuffs in random bits.
+The server will decrypt CK into some random DES key,
+and use it to decrypt the window and the timestamp.
+These will just end up as random numbers.
+After a few thousand trials, there is a good chance
+that the random window/timestamp pair will pass the authentication system.
+The window verifier makes guessing the right credential much more difficult.
+.LP
+After authenticating the client,
+the server stores four things into a credential table:
+the client's name A, the conversation key $CK$, the window, and the timestamp.
+The reason the server stores the first three things should be clear:
+it needs them for future use.
+The reason for storing the timestamp is to protect against replays.
+The server will only accept timestamps
+that are chronologically greater than the last one seen,
+so any replayed transactions are guaranteed to be rejected.
+The server returns to the client in its verifier an index ID
+into its credential table, plus the client's timestamp minus one,
+encrypted by $CK$.
+The client knows that only the server could have sent such a verifier,
+since only the server knows what timestamp the client sent.
+The reason for subtracting one from it is to insure that it is invalid
+and cannot be reused as a client verifier.
+.LP
+The first transaction is rather complicated,
+but after this things go very smoothly.
+The client just sends its ID and an encrypted timestamp to the server,
+and the server sends back the client's timestamp minus one,
+encrypted by $CK$.
+.#
+.NH 1
+\&Public Key Encryption
+.IX "public key encryption"
+.LP
+The particular public key encryption scheme Sun uses
+is the Diffie-Hellman method.
+The way this algorithm works is to generate a
+.I "secret key"
+$SK sub A$ at random
+and compute a
+.I "public key"
+$PK sub A$ using the following formula
+($PK$ and $SK$ are 192 bit numbers and \(*a is a well-known constant):
+.EQ
+PK sub A ~ = ~ alpha sup {SK sub A}
+.EN
+Public key $PK sub A$ is stored in a public directory,
+but secret key $SK sub A$ is kept private.
+Next, $PK sub B$ is generated from $SK sub B$ in the same manner as above.
+Now common key $K sub AB$ can be derived as follows:
+.EQ
+K sub AB ~ = ~ PK sub B sup {SK sub A} ~ = ~
+( alpha sup {SK sub B} ) sup {SK sub A} ~ = ~
+alpha sup {( SK sub A SK sub B )}
+.EN
+Without knowing the client's secret key,
+the server can calculate the same common key $K sub AB$
+in a different way, as follows:
+.EQ
+K sub AB ~ = ~ PK sub A sup {SK sub B} ~ = ~
+( alpha sup {SK sub A} ) sup {SK sub B} ~ = ~
+alpha sup {( SK sub A SK sub B )}
+.EN
+Notice that nobody else but the server and client can calculate $K sub AB$,
+since doing so requires knowing either one secret key or the other.
+All of this arithmetic is actually computed modulo $M$,
+which is another well-known constant.
+It would seem at first that somebody could guess your secret key
+by taking the logarithm of your public one,
+but $M$ is so large that this is a computationally infeasible task.
+To be secure, $K sub AB$ has too many bits to be used as a DES key,
+so 56 bits are extracted from it to form the DES key.
+.LP
+Both the public and the secret keys
+are stored indexed by netname in the Yellow Pages map
+.I publickey.byname
+the secret key is DES-encrypted with your login password.
+When you log in to a machine, the
+.I login
+program grabs your encrypted secret key,
+decrypts it with your login password,
+and gives it to a secure local keyserver to save
+for use in future RPC transactions.
+Note that ordinary users do not have to be aware of
+their public and secret keys.
+In addition to changing your login password, the
+.I yppasswd
+.IX "yppasswd command" "" "\&\fIyppasswd\fP command"
+program randomly generates a new public/secret key pair as well.
+.LP
+The keyserver
+.I keyserv (8c)
+.IX "keyserv daemon" "" "\&\fIkeyserv\fP daemon"
+is an RPC service local to each machine
+that performs all of the public key operations,
+of which there are only three. They are:
+.DS
+setsecretkey(secretkey)
+encryptsessionkey(servername, des_key)
+decryptsessionkey(clientname, des_key)
+.DE
+.I setsecretkey()
+tells the keyserver to store away your secret key $SK sub A$ for future use;
+it is normally called by
+.I login .
+The client program calls
+.I encryptsessionkey()
+to generate the encrypted conversation key
+that is passed in the first RPC transaction to a server.
+The keyserver looks up
+.I servername 's
+public key and combines it with the client's secret key (set up by a previous
+.I setsecretkey()
+call) to generate the key that encrypts
+.I des_key .
+The server asks the keyserver to decrypt the conversation key by calling
+.I decryptsessionkey().
+Note that implicit in these procedures is the name of caller,
+who must be authenticated in some manner.
+The keyserver cannot use DES authentication to do this,
+since it would create deadlock.
+The keyserver solves this problem by storing the secret keys by
+.I uid ,
+and only granting requests to local root processes.
+The client process then executes a
+.I setuid
+process, owned by root, which makes the request on the part of the client,
+telling the keyserver the real
+.I uid
+of the client. Ideally, the three operations described above
+would be system calls, and the kernel would talk to the keyserver directly,
+instead of executing the
+.I setuid
+program.
+.#
+.NH 1
+\&Naming of Network Entities
+.IX "naming of network entities"
+.IX "network naming"
+.LP
+The old UNIX authentication system has a few problems when it comes to naming.
+Recall that with UNIX authentication,
+the name of a network entity is basically the
+.I uid .
+These
+.I uid s
+are assigned per Yellow Pages naming domain,
+which typically spans several machines.
+We have already stated one problem with this system,
+that it is too UNIX system oriented,
+but there are two other problems as well.
+One is the problem of
+.I uid
+clashes when domains are linked together.
+The other problem is that the super-user (with
+.I uid
+of 0) should not be assigned on a per-domain basis,
+but rather on a per-machine basis.
+By default, the NFS deals with this latter problem in a severe manner:
+it does not allow root access across the network by
+.I uid
+0 at all.
+.LP
+DES authentication corrects these problems
+by basing naming upon new names that we call
+.I netnames.
+Simply put, a netname is just a string of printable characters,
+and fundamentally, it is really these netnames that we authenticate.
+The public and secret keys are stored on a per-netname,
+rather than per-username, basis.
+The Yellow Pages map
+.I netid.byname
+maps the netname into a local
+.I uid
+and group-access-list,
+though non-Sun environments may map the netname into something else.
+.LP
+We solve the Internet naming problem by choosing globally unique netnames.
+This is far easier then choosing globally unique user IDs.
+In the Sun environment, user names are unique within each Yellow Page domain.
+Netnames are assigned by concatenating the operating system and user ID
+with the Yellow Pages and ARPA domain names.
+For example, a UNIX system user with a user ID of 508 in the domain
+.I eng.sun.COM
+would be assigned the following netname:
+.I unix.508@eng.sun.COM .
+A good convention for naming domains is to append
+the ARPA domain name (COM, EDU, GOV, MIL) to the local domain name.
+Thus, the Yellow Pages domain
+.I eng
+within the ARPA domain
+.I sun.COM
+becomes
+.I eng.sun.COM .
+.LP
+We solve the problem of multiple super-users per domain
+by assigning netnames to machines as well as to users.
+A machine's netname is formed much like a user's.
+For example, a UNIX machine named
+.I hal
+in the same domain as before has the netname
+.I unix.hal@eng.sun.COM .
+Proper authentication of machines is very important for diskless machines
+that need full access to their home directories over the net.
+.LP
+Non-Sun environments will have other ways of generating netnames,
+but this does not preclude them from accessing
+the secure network services of the Sun environment.
+To authenticate users from any remote domain,
+all that has to be done is make entries for them in two Yellow Pages databases.
+One is an entry for their public and secret keys,
+the other is for their local
+.I uid
+and group-access-list mapping.
+Upon doing this, users in the remote domain
+will be able access all of the local network services,
+such as the NFS and remote logins.
+.#
+.NH 1
+\&Applications of DES Authentication
+.IX "applications of DES authentication"
+.IX "authentication" "DES"
+.LP
+The first application of DES authentication
+is a generalized Yellow Pages update service.
+This service allows users to update private fields in Yellow Page databases.
+So far the Yellow Pages maps
+.I hosts,
+.I ethers,
+.I bootparams
+and
+.I publickey
+employ the DES-based update service.
+Before the advent of an update service for mail aliases,
+Sun had to hire a full-time person just to update mail aliases.
+.LP
+The second application of DES authentication is the most important:
+a more secure Network File System.
+There are three security problems with the
+old NFS using UNIX authentication.
+The first is that verification of credentials occurs only at mount time
+when the client gets from the server a piece of information
+that is its key to all further requests: the
+.I "file handle" .
+Security can be broken if one can figure out a file handle
+without contacting the server, perhaps by tapping into the net or by guessing.
+After an NFS file system has been mounted,
+there is no checking of credentials during file requests,
+which brings up the second problem.
+If a file system has been mounted from a server that serves multiple clients
+(as is typically the case), there is no protection
+against someone who has root permission on their machine using
+.I su
+(or some other means of changing
+.I uid )
+gaining unauthorized access to other people's files.
+The third problem with the NFS is the severe method it uses to circumvent
+the problem of not being able to authenticate remote client super-users:
+denying them super-user access altogether.
+.LP
+The new authentication system corrects all of these problems.
+Guessing file handles is no longer a problem since in order to gain
+unauthorized access, the miscreant will also have to guess the right
+encrypted timestamp to place in the credential,
+which is a virtually impossible task.
+The problem of authenticating root users is solved,
+since the new system can authenticate machines.
+At this point, however,
+secure NFS is not used for root filesystems.
+Root users of nonsecure filesystems are identified by IP address.
+.LP
+Actually, the level of security associated with each filesystem
+may be altered by the administrator. The file
+.I /etc/exports
+.IX "etc/exports" "" "\&\fI/etc/exports\fP"
+contains a list of filesystems and which machines may mount them.
+By default, filesystems are exported with UNIX authentication,
+but the administrator can have them exported with DES authentication
+by specifying
+.I -secure
+on any line in the
+.I /etc/exports
+file. Associated with DES authentication is a parameter:
+the maximum window size that the server is willing to accept.
+.#
+.NH 1
+\&Security Issues Remaining
+.IX "security" "issues remaining"
+.IX "remaining security issues"
+.LP
+There are several ways to break DES authentication, but using
+.I su
+is not one of them. In order to be authenticated,
+your secret key must be stored by your workstation.
+This usually occurs when you login, with the
+.I login
+program decrypting your secret key with your login password,
+and storing it away for you.
+If somebody tries to use
+.I su
+to impersonate you, it won't work,
+because they won't be able to decrypt your secret key. Editing
+.I /etc/passwd
+isn't going to help them either, because the thing they need to edit,
+your encrypted secret key, is stored in the Yellow Pages.
+If you log into somebody else's workstation and type in your password,
+then your secret key would be stored in their workstation and they could use
+.I su
+to impersonate you. But this is not a problem since you should not
+be giving away your password to a machine you don't trust anyway.
+Someone on that machine could just as easily change
+.I login
+to save all the passwords it sees into a file.
+.LP
+Not having
+.I su
+to employ any more, how can nefarious users impersonate others now?
+Probably the easiest way is to guess somebody's password,
+since most people don't choose very secure passwords.
+We offer no protection against this;
+it's up to each user to choose a secure password.
+.LP
+The next best attack would be to attempt replays.
+For example, let's say I have been squirreling away
+all of your NFS transactions with a particular server.
+As long as the server remains up,
+I won't succeed by replaying them since the server always demands timestamps
+that are greater than the previous ones seen.
+But suppose I go and pull the plug on your server, causing it to crash.
+As it reboots, its credential table will be clean,
+so it has lost all track of previously seen timestamps,
+and now I am free to replay your transactions.
+There are few things to be said about this.
+First of all, servers should be kept in a secure place
+so that no one can go and pull the plug on them.
+But even if they are physically secure,
+servers occasionally crash without any help.
+Replaying transactions is not a very big security problem,
+but even so, there is protection against it.
+If a client specifies a window size that is smaller than the time it takes
+a server to reboot (5 to 10 minutes), the server will reject
+any replayed transactions because they will have expired.
+.LP
+There are other ways to break DES authentication,
+but they are much more difficult.
+These methods involve breaking the DES key itself,
+or computing the logarithm of the public key,
+both of which would would take months of compute time on a supercomputer.
+But it is important to keep our goals in mind.
+Sun did not aim for super-secure network computing.
+What we wanted was something as secure as a good time-sharing system,
+and in that we have been successful.
+.LP
+There is another security issue that DES authentication does not address,
+and that is tapping of the net.
+Even with DES authentication in place,
+there is no protection against somebody watching what goes across the net.
+This is not a big problem for most things,
+such as the NFS, since very few files are not publically readable, and besides,
+trying to make sense of all the bits flying over the net is not a trivial task.
+For logins, this is a bit of a problem because you wouldn't
+want somebody to pick up your password over the net.
+As we mentioned before,
+a side effect of the authentication system is a key exchange,
+so that the network tapping problem can be tackled on a per-application basis.
+.#
+.NH 1
+\&Performance
+.IX "performance of DES authentication"
+.IX "authentication" "performance"
+.LP
+Public key systems are known to be slow,
+but there is not much actual public key encryption going on in Sun's system.
+Public key encryption only occurs in the first transaction with a service,
+and even then, there is caching that speeds things up considerably.
+The first time a client program contacts a server,
+both it and the server will have to calculate the common key.
+The time it takes to compute the common key is basically the time it takes
+to compute an exponential modulo $M$.
+On a Sun-3 using a 192-bit modulus, this takes roughly 1 second,
+which means it takes 2 seconds just to get things started,
+since both client and server have to perform this operation.
+This is a long time,
+but you have to wait only the first time you contact a machine.
+Since the keyserver caches the results of previous computations,
+it does not have to recompute the exponential every time.
+.LP
+The most important service in terms of performance is the secure NFS,
+which is acceptably fast.
+The extra overhead that DES authentication requires versus UNIX authentication
+is the encryption.
+A timestamp is a 64-bit quantity,
+which also happens to be the DES block size.
+Four encryption operations take place in an average RPC transaction:
+the client encrypts the request timestamp, the server decrypts it,
+the server encrypts the reply timestamp, and the client decrypts it.
+On a Sun-3, the time it takes to encrypt one block is about
+half a millisecond if performed by hardware,
+and 1.2 milliseconds if performed by software.
+So, the extra time added to the round trip time is about
+2 milliseconds for hardware encryption and 5 for software.
+The round trip time for the average NFS request is about 20 milliseconds,
+resulting in a performance hit of 10 percent if one has encryption hardware,
+and 25 percent if not.
+Remember that this is the impact on network performance.
+The fact is that not all file operations go over the wire,
+so the impact on total system performance will actually be lower than this.
+It is also important to remember that security is optional,
+so environments that require higher performance can turn it off.
+.#
+.NH 1
+\&Problems with Booting and \&\fBsetuid\fP Programs
+.IX "problems with booting and \&\fIsetuid\fP programs"
+.IX "booting and \&\fIsetuid\fP problems"
+.LP
+Consider the problem of a machine rebooting,
+say after a power failure at some strange hour when nobody is around.
+All of the secret keys that were stored get wiped out,
+and now no process will be able to access secure network services,
+such as mounting an NFS filesystem.
+The important processes at this time are usually root processes,
+so things would work OK if root's secret key were stored away,
+but nobody is around to type the password that decrypts it.
+The solution to this problem is to store root's decrypted secret key in a file,
+which the keyserver can read.
+This works well for diskful machines that can store the secret key
+on a physically secure local disk,
+but not so well for diskless machines,
+whose secret key must be stored across the network.
+If you tap the net when a diskless machine is booting,
+you will find the decrypted key.
+This is not very easy to accomplish, though.
+.LP
+Another booting problem is the single-user boot.
+There is a mode of booting known as single-user mode, where a
+.I root
+login shell appears on the console.
+The problem here is that a password is not required for this.
+With C2 security installed,
+a password is required in order to boot single-user.
+Without C2 security installed,
+machines can still be booted single-user without a password,
+as long as the entry for
+.I console
+in the
+.I /etc/ttytab
+.IX "etc/ttytab" "" "\&\fI/etc/ttytab\fP"
+file is labeled as physically
+.I secure
+(this is the default).
+.LP
+Yet another problem is that diskless machine booting is not totally secure.
+It is possible for somebody to impersonate the boot-server,
+and boot a devious kernel that, for example,
+makes a record of your secret key on a remote machine.
+The problem is that our system is set up to provide protection
+only after the kernel and the keyserver are running.
+Before that, there is no way to authenticate
+the replies given by the boot server.
+We don't consider this a serious problem,
+because it is highly unlikely that somebody would be able to write
+this funny kernel without source code.
+Also, the crime is not without evidence.
+If you polled the net for boot-servers,
+you would discover the devious boot-server's location.
+.LP
+Not all
+.I setuid
+programs will behave as they should.
+For example, if a
+.I setuid
+program is owned by
+.I dave ,
+who has not logged into the machine since it booted,
+then the program will not be able to access any secure network services as
+.I dave .
+The good news is that most
+.I setuid
+programs are owned by root,
+and since root's secret key is always stored at boot time,
+these programs will behave as they always have.
+.#
+.NH 1
+\&Conclusion
+.IX "network security" "summary"
+.LP
+Our goal was to build a system as secure as a time-shared system.
+This goal has been met.
+The way you are authenticated in a time-sharing system
+is by knowing your password.
+With DES authentication, the same is true.
+In time-sharing the person you trust is your system administrator,
+who has an ethical obligation
+not to change your password in order to impersonate you.
+In Sun's system, you trust your network administrator,
+who does not alter your entry in the public key database.
+In one sense, our system is even more secure than time-sharing,
+because it is useless to place a tap on the network
+in hopes of catching a password or encryption key,
+since these are encrypted.
+Most time-sharing environments do not encrypt data emanating from the terminal;
+users must trust that nobody is tapping their terminal lines.
+.LP
+DES authentication is perhaps not the ultimate authentication system.
+In the future it is likely there will be sufficient advances
+in algorithms and hardware to render the public key system
+as we have defined it useless.
+But at least DES authentication offers a smooth migration path for the future.
+Syntactically speaking,
+nothing in the protocol requires the encryption of the conversation
+key to be Diffie-Hellman, or even public key encryption in general.
+To make the authentication stronger in the future,
+all that needs to be done is to strengthen the way
+the conversation key is encrypted.
+Semantically, this will be a different protocol,
+but the beauty of RPC is that it can be plugged in
+and live peacefully with any authentication system.
+.LP
+For the present at least, DES authentication satisfies our requirements
+for a secure networking environment.
+From it we built a system secure enough for use in unfriendly networks,
+such as a student-run university workstation environment.
+The price for this security is not high.
+Nobody has to carry around a magnetic card or remember
+any hundred digit numbers.
+You use your login password to authenticate yourself, just as before.
+There is a small impact on performance,
+but if this worries you and you have a friendly net,
+you can turn authentication off.
+.#
+.NH 1
+\&References
+.IX "references on network security"
+.LP
+Diffie and Hellman, ``New Directions in Cryptography,''
+\fIIEEE Transactions on Information Theory IT-22,\fP
+November 1976.
+.LP
+Gusella & Zatti, ``TEMPO: A Network Time Controller
+for a Distributed Berkeley UNIX System,''
+\fIUSENIX 1984 Summer Conference Proceedings,\fP
+June 1984.
+.LP
+National Bureau of Standards, ``Data Encryption Standard,''
+\fIFederal Information Processing Standards Publication 46,\fP
+January 15, 1977.
+.LP
+Needham & Schroeder, ``Using Encryption for Authentication
+in Large Networks of Computers,''
+\fIXerox Corporation CSL-78-4,\fP
+September 1978.
+.EQ
+delim off
+.EN
+.IX "security" "of networks" "" "" PAGE END
+.IX "network security" "" "" "" PAGE END
+.IX "NFS security" "" "" "" PAGE END
diff --git a/lib/librpc/secure_rpc/keyserv/Makefile b/lib/librpc/secure_rpc/keyserv/Makefile
new file mode 100644
index 0000000..de6771e
--- /dev/null
+++ b/lib/librpc/secure_rpc/keyserv/Makefile
@@ -0,0 +1,49 @@
+#
+# @(#)Makefile 2.4 88/08/15 4.0 RPCSRC; from 1.9 87/11/29 SMI
+#
+CFLAGS= -O
+RPCLIB= -lrpclib
+#RPCLIB= -lrpcsvc
+
+KEYSERV_OBJS = keyserv.o setkey.o detach.o mp.o
+KEYENVOY_OBJS = keyenvoy.o
+SRCS = keyserv.c setkey.c detach.c keyenvoy.c mp.c
+
+ALL= keyserv keyenvoy
+
+all: $(ALL)
+
+keyserv: $(KEYSERV_OBJS)
+ $(CC) $(CFLAGS) $(KEYSERV_OBJS) -lmp $(LIBC) $(RPCLIB) -o $@
+
+keyenvoy: $(KEYENVOY_OBJS)
+ $(CC) $(CFLAGS) $(KEYENVOY_OBJS) $(LIBC) $(RPCLIB) -o $@
+
+clean:
+ rm -f $(ALL) $(KEYSERV_OBJS) $(KEYENVOY_OBJS)
+
+install: $(ALL)
+ install -s -m 755 keyserv $(DESTDIR)/usr/etc
+ install -s -m 4755 keyenvoy $(DESTDIR)/usr/etc
+
+depend:
+ rm -f makedep
+ for i in ${SRCS}; do \
+ ${CC} -M ${INCPATH} $$i | \
+ awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
+ else rec = rec " " $$2 } } \
+ END { print rec } ' >> makedep; done
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile < eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
+ echo '# see make depend above' >> Makefile
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+
diff --git a/lib/librpc/secure_rpc/keyserv/detach.c b/lib/librpc/secure_rpc/keyserv/detach.c
new file mode 100644
index 0000000..ff1fac3
--- /dev/null
+++ b/lib/librpc/secure_rpc/keyserv/detach.c
@@ -0,0 +1,69 @@
+#ifndef lint
+static char sccsid[] = "@(#)detach.c 2.2 88/08/10 4.0 RPCSRC";
+#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.
+ */
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+/*
+ * detach from tty
+ */
+detachfromtty()
+{
+ int tt;
+
+ close(0);
+ close(1);
+ close(2);
+ switch (fork()) {
+ case -1:
+ perror("fork");
+ break;
+ case 0:
+ break;
+ default:
+ exit(0);
+ }
+ tt = open("/dev/tty", O_RDWR);
+ if (tt > 0) {
+ ioctl(tt, TIOCNOTTY, 0);
+ close(tt);
+ }
+ (void)open("/dev/null", O_RDWR, 0);
+ dup(0);
+ dup(0);
+}
+
+
diff --git a/lib/librpc/secure_rpc/keyserv/keyenvoy.c b/lib/librpc/secure_rpc/keyserv/keyenvoy.c
new file mode 100644
index 0000000..5379651
--- /dev/null
+++ b/lib/librpc/secure_rpc/keyserv/keyenvoy.c
@@ -0,0 +1,213 @@
+#ifndef lint
+static char sccsid[] = "@(#)keyenvoy.c 2.2 88/08/10 4.0 RPCSRC";
+#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.
+ */
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+/*
+ * Talk to the keyserver on a privileged port on the part of a calling program.
+ *
+ * Protocol is for caller to send through stdin the procedure number
+ * to call followed by the argument data. We call the keyserver, and
+ * send the results back to the caller through stdout.
+ * Non-zero exit status means something went wrong.
+ */
+
+#ifndef DEBUG
+#define debug(msg)
+#endif
+
+#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */
+#define TOTAL_TRIES 10 /* Number of tries */
+
+/*
+ * Opaque data that we send and receive
+ */
+#define MAXOPAQUE 256
+struct opaqn {
+ u_int len;
+ u_int data[MAXOPAQUE];
+};
+bool_t xdr_opaqn();
+
+
+main(argc,argv)
+ int argc;
+ char *argv[];
+{
+ XDR xdrs_args;
+ XDR xdrs_rslt;
+ int proc;
+ struct opaqn args, rslt;
+
+
+ if (isatty(0)) {
+ fprintf(stderr,
+ "This program cannot be used interactively.\n");
+ exit(1);
+ }
+
+#ifdef DEBUG
+ close(2);
+ open("/dev/console", O_WRONLY, 0);
+#endif
+
+ xdrstdio_create(&xdrs_args, stdin, XDR_DECODE);
+ xdrstdio_create(&xdrs_rslt, stdout, XDR_ENCODE);
+
+ if ( ! xdr_u_long(&xdrs_args, &proc)) {
+ debug("no proc");
+ exit(1);
+ }
+ if (! xdr_opaqn(&xdrs_args, &args)) {
+ debug("recving args failed");
+ exit(1);
+ }
+ if (! callkeyserver(proc, xdr_opaqn, &args, xdr_opaqn, &rslt)) {
+ debug("rpc_call failed");
+ exit(1);
+ }
+ if (! xdr_opaqn(&xdrs_rslt, &rslt)) {
+ debug("sending args failed");
+ exit(1);
+ }
+ exit(0);
+}
+
+
+
+callkeyserver(proc, xdr_args, args, xdr_rslt, rslt)
+ u_long proc;
+ bool_t (*xdr_args)();
+ void *args;
+ bool_t (*xdr_rslt)();
+ void *rslt;
+
+{
+ struct sockaddr_in remote;
+ int port;
+ struct timeval wait;
+ enum clnt_stat stat;
+ CLIENT *client;
+ int sd;
+
+ /*
+ * set up the remote address
+ * and create client
+ */
+ remote.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ remote.sin_family = AF_INET;
+ remote.sin_port = 0;
+ wait.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; wait.tv_usec = 0;
+ sd = RPC_ANYSOCK;
+ client = clntudp_create(&remote, KEY_PROG, KEY_VERS, wait, &sd);
+ if (client == NULL) {
+ debug("no client");
+ return (0);
+ }
+
+ /*
+ * Check that server is bound to a reserved port, so
+ * that noone can masquerade as the keyserver.
+ */
+ if (ntohs(remote.sin_port) >= IPPORT_RESERVED) {
+ debug("insecure port");
+ return (0);
+ }
+
+ /*
+ * Create authentication
+ * All we care about really is sending the real uid
+ */
+ client->cl_auth = authunix_create("", getuid(), 0, 0, NULL);
+ if (client->cl_auth == NULL) {
+ debug("no auth");
+ return (0);
+ }
+ wait.tv_sec = TOTAL_TIMEOUT; wait.tv_usec = 0;
+ stat = clnt_call(client, proc, xdr_args, args, xdr_rslt, rslt, wait);
+ if (stat != RPC_SUCCESS) {
+ debug("clnt_call failed");
+ }
+ return (stat == RPC_SUCCESS);
+}
+
+
+/*
+ * XDR opaque data
+ * Don't know the length on decode, so just keep receiving until failure.
+ */
+bool_t
+xdr_opaqn(xdrs, objp)
+ XDR *xdrs;
+ struct opaqn *objp;
+{
+ int i;
+
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ break;
+ case XDR_DECODE:
+ for (i = 0; i < MAXOPAQUE && xdr_int(xdrs, &objp->data[i]); i++) {
+ }
+ if (i == MAXOPAQUE) {
+ return (FALSE);
+ }
+ objp->len = i;
+ break;
+ case XDR_ENCODE:
+ for (i = 0; i < objp->len; i++) {
+ if (! xdr_int(xdrs, &objp->data[i])) {
+ return (FALSE);
+ }
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
+#ifdef DEBUG
+debug(msg)
+ char *msg;
+{
+ fprintf(stderr, "%s\n", msg);
+}
+#endif
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);
+ }
+}
diff --git a/lib/librpc/secure_rpc/keyserv/mp.c b/lib/librpc/secure_rpc/keyserv/mp.c
new file mode 100644
index 0000000..97c85b0
--- /dev/null
+++ b/lib/librpc/secure_rpc/keyserv/mp.c
@@ -0,0 +1,145 @@
+#ifndef lint
+static char sccsid[] = "@(#)mp.c 2.1 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
+ */
+
+/*
+ * These routines add hexadecimal functionality to the multiple-precision
+ * library.
+ */
+#include <stdio.h>
+#include <mp.h>
+
+void mfree();
+
+/*
+ * Convert hex digit to binary value
+ */
+static int
+xtoi(c)
+ char c;
+{
+ if (c >= '0' && c <= '9') {
+ return(c - '0');
+ } else if (c >= 'a' && c <= 'f') {
+ return(c - 'a' + 10);
+ } else {
+ return(-1);
+ }
+}
+
+/*
+ * Convert hex key to MINT key
+ */
+MINT *
+xtom(key)
+ char *key;
+{
+ int digit;
+ MINT *m = itom(0);
+ MINT *d;
+ MINT *sixteen;
+ sixteen = itom(16);
+ for (; *key; key++) {
+ digit = xtoi(*key);
+ if (digit < 0) {
+ return(NULL);
+ }
+ d = itom(digit);
+ mult(m,sixteen,m);
+ madd(m,d,m);
+ mfree(d);
+ }
+ mfree(sixteen);
+ return(m);
+}
+static char
+itox(d)
+ short d;
+{
+ d &= 15;
+ if (d < 10) {
+ return('0' + d);
+ } else {
+ return('a' - 10 + d);
+ }
+}
+/*
+ * Convert MINT key to hex key
+ */
+char *
+mtox(key)
+ MINT *key;
+{
+ MINT *m = itom(0);
+ MINT *zero = itom(0);
+ short r;
+ char *p;
+ char c;
+ char *s;
+ char *hex;
+ int size;
+#define BASEBITS (8*sizeof(short) - 1)
+ if (key->len >= 0) {
+ size = key->len;
+ } else {
+ size = -key->len;
+ }
+ hex = malloc((unsigned) ((size * BASEBITS + 3)) / 4 + 1);
+ if (hex == NULL) {
+ return(NULL);
+ }
+ move(key,m);
+ p = hex;
+ do {
+ sdiv(m,16,m,&r);
+ *p++ = itox(r);
+ } while (mcmp(m,zero) != 0);
+ mfree(m);
+ mfree(zero);
+ *p = 0;
+ for (p--, s = hex; s < p; s++, p--) {
+ c = *p;
+ *p = *s;
+ *s = c;
+ }
+ return(hex);
+}
+/*
+ * Deallocate a multiple precision integer
+ */
+void
+mfree(a)
+ MINT *a;
+{
+ xfree(a);
+ free((char *)a);
+}
+
diff --git a/lib/librpc/secure_rpc/keyserv/setkey.c b/lib/librpc/secure_rpc/keyserv/setkey.c
new file mode 100644
index 0000000..d62dc9c
--- /dev/null
+++ b/lib/librpc/secure_rpc/keyserv/setkey.c
@@ -0,0 +1,514 @@
+#ifndef lint
+static char sccsid[] = "@(#)setkey.c 2.2 88/08/10 4.0 RPCSRC; from 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.
+ */
+
+/*
+ * Do the real work of the keyserver .
+ * Store secret keys. Compute common keys,
+ * and use them to decrypt and encrypt DES keys .
+ * Cache the common keys, so the
+ * expensive computation is avoided.
+ */
+#include <stdio.h>
+#include <sys/file.h>
+#include <mp.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+#include <des_crypt.h>
+#include <sys/errno.h>
+
+extern char *malloc();
+extern char ROOTKEY[];
+
+static MINT *MODULUS;
+static char *fetchsecretkey();
+static keystatus pk_crypt();
+
+
+/*
+ * Set the modulus for all our Diffie-Hellman operations
+ */
+setmodulus(modx)
+ char *modx;
+{
+ MODULUS = xtom(modx);
+}
+
+
+/*
+ * Set the secretkey key for this uid
+ */
+keystatus
+pk_setkey(uid, skey)
+ short uid;
+ keybuf skey;
+{
+ if (!storesecretkey(uid, skey)) {
+ return (KEY_SYSTEMERR);
+ }
+ return (KEY_SUCCESS);
+}
+
+
+/*
+ * Encrypt the key using the public key associated with remote_name and the
+ * secret key associated with uid.
+ */
+keystatus
+pk_encrypt(uid, remote_name, key)
+ short uid;
+ char *remote_name;
+ des_block *key;
+{
+ return (pk_crypt(uid, remote_name, key, DES_ENCRYPT));
+}
+
+
+/*
+ * Decrypt the key using the public key associated with remote_name and the
+ * secret key associated with uid.
+ */
+keystatus
+pk_decrypt(uid, remote_name, key)
+ short uid;
+ char *remote_name;
+ des_block *key;
+{
+ return (pk_crypt(uid, remote_name, key, DES_DECRYPT));
+}
+
+
+/*
+ * Do the work of pk_encrypt && pk_decrypt
+ */
+static keystatus
+pk_crypt(uid, remote_name, key, mode)
+ short uid;
+ char *remote_name;
+ des_block *key;
+ int mode;
+{
+ char *xsecret;
+ char xpublic[HEXKEYBYTES + 1];
+ char xsecret_hold[HEXKEYBYTES + 1];
+ des_block deskey;
+ int err;
+ MINT *public;
+ MINT *secret;
+ MINT *common;
+ char zero[8];
+
+ xsecret = fetchsecretkey(uid);
+ if (xsecret == NULL) {
+ bzero(zero, sizeof(zero));
+ xsecret = xsecret_hold;
+ if (!getsecretkey("nobody", xsecret, zero) ||
+ xsecret[0] == 0) {
+ return (KEY_NOSECRET);
+ }
+ }
+ if (!getpublickey(remote_name, xpublic) &&
+ !getpublickey("nobody", xpublic)) {
+ return (KEY_UNKNOWN);
+ }
+ if (!readcache(xpublic, xsecret, &deskey)) {
+ public = xtom(xpublic);
+ secret = xtom(xsecret);
+ common = itom(0);
+ pow(public, secret, MODULUS, common);
+ extractdeskey(common, &deskey);
+ writecache(xpublic, xsecret, &deskey);
+ mfree(secret);
+ mfree(public);
+ mfree(common);
+ }
+ err = ecb_crypt(&deskey, key, sizeof(des_block), DES_HW | mode);
+ if (DES_FAILED(err)) {
+ return (KEY_SYSTEMERR);
+ }
+ return (KEY_SUCCESS);
+}
+
+
+/*
+ * Choose middle 64 bits of the common key to use as our des key, possibly
+ * overwriting the lower order bits by setting parity.
+ */
+static
+extractdeskey(ck, deskey)
+ MINT *ck;
+ des_block *deskey;
+{
+ MINT *a;
+ short r;
+ int i;
+ short base = (1 << 8);
+ char *k;
+
+
+ a = itom(0);
+ move(ck, a);
+ for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
+ sdiv(a, base, a, &r);
+ }
+ k = deskey->c;
+ for (i = 0; i < 8; i++) {
+ sdiv(a, base, a, &r);
+ *k++ = r;
+ }
+ mfree(a);
+ des_setparity(deskey);
+}
+
+
+/*
+ * Key storage management
+ */
+
+struct secretkey_list {
+ short uid;
+ char secretkey[HEXKEYBYTES+1];
+ struct secretkey_list *next;
+};
+
+static struct secretkey_list *g_secretkeys;
+
+/*
+ * Fetch the secret key for this uid
+ */
+static char *
+fetchsecretkey(uid)
+ short uid;
+{
+ struct secretkey_list *l;
+
+ for (l = g_secretkeys; l != NULL; l = l->next) {
+ if (l->uid == uid) {
+ return (l->secretkey);
+ }
+ }
+ return (NULL);
+}
+
+/*
+ * Store the secretkey for this uid
+ */
+storesecretkey(uid, key)
+ short uid;
+ keybuf key;
+{
+ struct secretkey_list *new;
+ struct secretkey_list **l;
+ int nitems;
+
+
+ nitems = 0;
+ for (l = &g_secretkeys; *l != NULL && (*l)->uid != uid;
+ l = &(*l)->next) {
+ nitems++;
+ }
+ if (*l == NULL) {
+ new = (struct secretkey_list *)malloc(sizeof(*new));
+ if (new == NULL) {
+ return (0);
+ }
+ new->uid = uid;
+ new->next = NULL;
+ *l = new;
+ } else {
+ new = *l;
+ }
+ bcopy(key, new->secretkey, HEXKEYBYTES);
+ new->secretkey[HEXKEYBYTES] = 0;
+ seekitem(nitems);
+ writeitem(uid, new->secretkey);
+ return (1);
+}
+
+
+hexdigit(val)
+ int val;
+{
+ return ("0123456789abcdef"[val]);
+
+}
+bin2hex(bin, hex, size)
+ unsigned char *bin;
+ unsigned char *hex;
+ int size;
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ *hex++ = hexdigit(*bin >> 4);
+ *hex++ = hexdigit(*bin++ & 0xf);
+ }
+}
+
+hexval(dig)
+ char dig;
+{
+ if ('0' <= dig && dig <= '9') {
+ return (dig - '0');
+ } else if ('a' <= dig && dig <= 'f') {
+ return (dig - 'a' + 10);
+ } else if ('A' <= dig && dig <= 'F') {
+ return (dig - 'A' + 10);
+ } else {
+ return (-1);
+ }
+}
+
+hex2bin(hex, bin, size)
+ unsigned char *hex;
+ unsigned char *bin;
+ int size;
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ *bin = hexval(*hex++) << 4;
+ *bin++ |= hexval(*hex++);
+ }
+}
+
+static char KEYSTORE[] = "/etc/keystore";
+FILE *kf;
+
+openstore()
+{
+ kf = fopen(KEYSTORE, "r+");
+ if (kf == NULL) {
+ kf = fopen(KEYSTORE, "w+");
+ if (kf == NULL) {
+ return (0);
+ }
+ }
+ setbuf(kf, NULL);
+ return (1);
+}
+
+static char rootkey[KEYBYTES];
+static int haverootkey;
+struct storedkey {
+ short uid;
+ char crypt[KEYBYTES];
+};
+
+readkeys()
+{
+ struct secretkey_list *node;
+ struct secretkey_list **l;
+ int uid;
+ char secretkey[HEXKEYBYTES+1];
+
+ if (kf == NULL) {
+ return;
+ }
+ l = &g_secretkeys;
+ seekitem(0);
+ while (readitem(&uid, secretkey)) {
+ node = (struct secretkey_list *)malloc(sizeof(*node));
+ if (node == NULL) {
+ return;
+ }
+ node->uid = uid;
+ bcopy(secretkey, node->secretkey, HEXKEYBYTES + 1);
+ node->next = NULL;
+ *l = node;
+ l = &node->next;
+ }
+}
+
+writekeys()
+{
+ struct secretkey_list *k;
+
+ seekitem(0);
+ for (k = g_secretkeys; k != NULL; k = k->next) {
+ writeitem(k->uid, k->secretkey);
+ }
+}
+
+seekitem(item)
+ int item;
+{
+ if (kf != NULL) {
+ fseek(kf, item * sizeof(struct storedkey), 0);
+ }
+}
+
+writeitem(uid, key)
+ int uid;
+ char *key;
+{
+ struct storedkey item;
+ char rootkey_tmp[KEYBYTES];
+ int reencrypt;
+
+ if (kf == NULL) {
+ return (1);
+ }
+ if (uid == 0) {
+ writerootkey(key);
+ hex2bin(key, rootkey_tmp, KEYBYTES);
+ reencrypt = (haverootkey &&
+ bcmp(rootkey, rootkey_tmp, KEYBYTES) != 0);
+ bcopy(rootkey_tmp, rootkey, KEYBYTES);
+ haverootkey = 1;
+ if (reencrypt) {
+ writekeys();
+ return (1);
+ }
+ }
+ if (!haverootkey) {
+ return (1);
+ }
+ item.uid = uid;
+ hex2bin(key, item.crypt, KEYBYTES);
+ ecb_crypt(rootkey, item.crypt, KEYBYTES, DES_ENCRYPT|DES_HW);
+ return (fwrite(&item, sizeof(item), 1, kf) >= 0);
+}
+
+
+readitem(uidp, key)
+ int *uidp;
+ char *key;
+{
+ struct storedkey item;
+
+ if (!haverootkey || kf == NULL) {
+ return (0);
+ }
+ if (fread(&item, sizeof(item), 1, kf) != 1) {
+ return (0);
+ }
+ *uidp = item.uid;
+ ecb_crypt(rootkey, item.crypt, KEYBYTES, DES_DECRYPT|DES_HW);
+ bin2hex(item.crypt, key, KEYBYTES);
+ key[HEXKEYBYTES] = 0;
+ return (1);
+}
+
+/*
+ * Root users store their key in /etc/$ROOTKEY so
+ * that they can auto reboot without having to be
+ * around to type a password. Storing this in a file
+ * is rather dubious: it should really be in the EEPROM
+ * so it does not go over the net for diskless machines.
+ */
+writerootkey(secret)
+ char *secret;
+{
+ char newline = '\n';
+ int fd;
+
+ fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0);
+ if (fd < 0) {
+ perror(ROOTKEY);
+ } else {
+ if (write(fd, secret, strlen(secret)) < 0 ||
+ write(fd, &newline, sizeof(newline)) < 0) {
+ (void)fprintf(stderr, "%s: ", ROOTKEY);
+ perror("write");
+ }
+ close(fd);
+ }
+}
+
+
+/*
+ * Exponential caching management
+ */
+struct cachekey_list {
+ keybuf secret;
+ keybuf public;
+ des_block deskey;
+ struct cachekey_list *next;
+};
+static struct cachekey_list *g_cachedkeys;
+
+
+/*
+ * cache result of expensive multiple precision exponential operation
+ */
+static
+writecache(pub, sec, deskey)
+ char *pub;
+ char *sec;
+ des_block *deskey;
+{
+ struct cachekey_list *new;
+
+ new = (struct cachekey_list *) malloc(sizeof(struct cachekey_list));
+ if (new == NULL) {
+ return;
+ }
+ bcopy(pub, new->public, sizeof(keybuf));
+ bcopy(sec, new->secret, sizeof(keybuf));
+ new->deskey = *deskey;
+ new->next = g_cachedkeys;
+ g_cachedkeys = new;
+}
+
+/*
+ * Try to find the common key in the cache
+ */
+static
+readcache(pub, sec, deskey)
+ char *pub;
+ char *sec;
+ des_block *deskey;
+{
+ struct cachekey_list *found;
+ register struct cachekey_list **l;
+
+#define cachehit(pub, sec, list) \
+ (bcmp(pub, (list)->public, sizeof(keybuf)) == 0 && \
+ bcmp(sec, (list)->secret, sizeof(keybuf)) == 0)
+
+ for (l = &g_cachedkeys;
+ (*l) != NULL && !cachehit(pub, sec, *l);
+ l = &(*l)->next);
+ if ((*l) == NULL) {
+ return (0);
+ }
+ found = *l;
+ (*l) = (*l)->next;
+ found->next = g_cachedkeys;
+ g_cachedkeys = found;
+ *deskey = found->deskey;
+ return (1);
+}
diff --git a/lib/librpc/secure_rpc/man/chkey.1 b/lib/librpc/secure_rpc/man/chkey.1
new file mode 100644
index 0000000..fbf1fcd
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/chkey.1
@@ -0,0 +1,19 @@
+.\" @(#)chkey.1 2.1 88/08/10 4.0 RPCSRC; from 1.6 88/02/29 SMI;
+.TH CHKEY 1 "9 September 1987"
+.SH NAME
+chkey \- change your encryption key
+.SH SYNOPSIS
+.B chkey
+.SH DESCRIPTION
+.IX "chkey command" "" "\fLchkey\fP command"
+.IX "encryption key, change, \fLchkey\fR command"
+.B chkey
+prompts the user for their login password, and uses it to encrypt
+a new encryption key for the user to be stored in the
+.BR publickey (5)
+database.
+.SH "SEE ALSO"
+.BR keylogin (1),
+.BR publickey (5),
+.BR keyserv (8C),
+.BR newkey (8)
diff --git a/lib/librpc/secure_rpc/man/des_crypt.3 b/lib/librpc/secure_rpc/man/des_crypt.3
new file mode 100644
index 0000000..ca0a33e
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/des_crypt.3
@@ -0,0 +1,126 @@
+.\" @(#)des_crypt.3 2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI;
+.TH DES_CRYPT 3 "6 October 1987"
+.SH NAME
+des_crypt, ecb_crypt, cbc_crypt, des_setparity \- fast DES encryption
+.SH SYNOPSIS
+.nf
+.B #include <des_crypt.h>
+.LP
+.B int ecb_crypt(key, data, datalen, mode)
+.B char *key;
+.B char *data;
+.B unsigned datalen;
+.B unsigned mode;
+.LP
+.B int cbc_crypt(key, data, datalen, mode, ivec)
+.B char *key;
+.B char *data;
+.B unsigned datalen;
+.B unsigned mode;
+.B char *ivec;
+.LP
+.B void des_setparity(key)
+.B char *key;
+.fi
+.SH DESCRIPTION
+.IX encryption cbc_crypt "" \fLcbc_crypt\fP
+.IX "des encryption" cbc_crypt "DES encryption" \fLcbc_crypt\fP
+.IX encryption des_setparity "" \fLdes_setparity\fP
+.IX "des encryption" des_setparity "DES encryption" \fLdes_setparity\fP
+.B ecb_crypt(\|)
+and
+.B cbc_crypt(\|)
+implement the
+.SM NBS
+.SM DES
+(Data Encryption Standard).
+These routines are faster and more general purpose than
+.BR crypt (3).
+They also are able to utilize
+.SM DES
+hardware if it is available.
+.B ecb_crypt(\|)
+encrypts in
+.SM ECB
+(Electronic Code Book)
+mode, which encrypts blocks of data independently.
+.B cbc_crypt(\|)
+encrypts in
+.SM CBC
+(Cipher Block Chaining)
+mode, which chains together
+successive blocks.
+.SM CBC
+mode protects against insertions, deletions and
+substitutions of blocks. Also, regularities in the clear text will
+not appear in the cipher text.
+.LP
+Here is how to use these routines. The first parameter,
+.IR key ,
+is the 8-byte encryption key with parity.
+To set the key's parity, which for
+.SM DES
+is in the low bit of each byte, use
+.IR des_setparity .
+The second parameter,
+.IR data ,
+contains the data to be encrypted or decrypted. The
+third parameter,
+.IR datalen ,
+is the length in bytes of
+.IR data ,
+which must be a multiple of 8. The fourth parameter,
+.IR mode ,
+is formed by
+.SM OR\s0'ing
+together some things. For the encryption direction 'or' in either
+.SM DES_ENCRYPT
+or
+.SM DES_DECRYPT\s0.
+For software versus hardware
+encryption, 'or' in either
+.SM DES_HW
+or
+.SM DES_SW\s0.
+If
+.SM DES_HW
+is specified, and there is no hardware, then the encryption is performed
+in software and the routine returns
+.SM DESERR_NOHWDEVICE\s0.
+For
+.IR cbc_crypt ,
+the parameter
+.I ivec
+is the the 8-byte initialization
+vector for the chaining. It is updated to the next initialization
+vector upon return.
+.LP
+.SH "SEE ALSO"
+.BR des (1),
+.BR crypt (3)
+.SH DIAGNOSTICS
+.PD 0
+.TP 20
+.SM DESERR_NONE
+No error.
+.TP
+.SM DESERR_NOHWDEVICE
+Encryption succeeded, but done in software instead of the requested hardware.
+.TP
+.SM DESERR_HWERR
+An error occurred in the hardware or driver.
+.TP
+.SM DESERR_BADPARAM
+Bad parameter to routine.
+.PD
+.LP
+Given a result status
+.IR stat ,
+the macro
+.SM DES_FAILED\c
+.BR ( stat )
+is false only for the first two statuses.
+.SH RESTRICTIONS
+These routines are not available in RPCSRC 4.0.
+This information is provided to describe the DES interface expected by
+Secure RPC.
diff --git a/lib/librpc/secure_rpc/man/keyenvoy.8c b/lib/librpc/secure_rpc/man/keyenvoy.8c
new file mode 100644
index 0000000..8cf7bc3
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/keyenvoy.8c
@@ -0,0 +1,22 @@
+.\" @(#)keyenvoy.8c 2.1 88/08/10 4.0 RPCSRC; from 1.5 88/03/01 SMI;
+.TH KEYENVOY 8C "9 September 1987"
+.SH NAME
+keyenvoy \- talk to keyserver
+.SH SYNOPSIS
+.B keyenvoy
+.SH DESCRIPTION
+.IX "keyenvoy command" "" "\fLkeyenvoy\fP command"
+.B keyenvoy
+is used by some
+.SM RPC
+programs to talk to the key server,
+.BR keyserv (8C).
+The key server will not talk to anything but a root process, and
+.B keyenvoy
+is a set-uid root process that acts as an intermediary between a user
+process that wishes to talk to the
+key server and the key server itself.
+.LP
+This program cannot be run interactively.
+.SH "SEE ALSO"
+.BR keyserv (8C)
diff --git a/lib/librpc/secure_rpc/man/keylogin.1 b/lib/librpc/secure_rpc/man/keylogin.1
new file mode 100644
index 0000000..516d9de
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/keylogin.1
@@ -0,0 +1,32 @@
+.\" @(#)keylogin.1 2.1 88/08/10 4.0 RPCSRC; from 1.6 88/02/29 SMI;
+.TH KEYLOGIN 1 "9 September 1987"
+.SH NAME
+keylogin \- decrypt and store secret key
+.SH SYNOPSIS
+.B keylogin
+.SH DESCRIPTION
+.IX "keylogin command" "" "\fLkeylogin\fR command"
+.LP
+.B keylogin
+prompts the user for their login password, and uses it do decrypt
+the user's secret key stored in the
+.BR publickey (5)
+database. Once decrypted, the user's key is stored by the local
+key server process
+.BR keyserv (8C)
+to be used by any secure network services, such as
+.SM NFS\s0.
+.LP
+Normally,
+.BR login (1)
+does this work when the user logs onto the system, but running
+.B keylogin
+may be necessary if
+the user did not type a password to
+.BR login (1).
+.SH "SEE ALSO"
+.BR chkey (1),
+.BR login (1),
+.BR publickey (5),
+.BR keyserv (8C),
+.BR newkey (8)
diff --git a/lib/librpc/secure_rpc/man/keyserv.8c b/lib/librpc/secure_rpc/man/keyserv.8c
new file mode 100644
index 0000000..aa153ed
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/keyserv.8c
@@ -0,0 +1,52 @@
+.\" @(#)keyserv.8c 2.1 88/08/10 4.0 RPCSRC; from 1.6 88/03/01 SMI;
+.TH KEYSERV 8C "9 September 1987"
+.SH NAME
+keyserv \- server for storing public and private keys
+.SH SYNOPSIS
+.B keyserv
+[
+.B \-n
+]
+.SH DESCRIPTION
+.IX "keyenvoy server" "" "\fLkeyenvoy\fP server"
+.B keyserv
+is a daemon that is used for storing the
+private encryption keys of each
+user logged into the system. These encryption
+keys are using for accessing
+secure network services such as secure
+.SM NFS\s0.
+When a user logs in to the system, the
+.BR login(1)
+program uses the login password to decrypt
+the user's encryption key stored
+in the Yellow Pages, and then gives the decrypted key to the
+.B keyserv
+daemon to store away.
+.LP
+Normally, root's key is read from the file
+.B /etc/.rootkey
+when the daemon starts up. This is useful during power-fail reboots
+when no one is around to type a password, yet you still want the
+secure network services to operate normally.
+.SH OPTIONS
+.TP
+.B \-n
+Do not read root's key from
+.BR /etc/.rootkey .
+Instead, prompt the user for the password to decrypt
+.B root 's
+key stored in the Yellow Pages and then store the decrypted key in
+.B /etc/.rootkey
+for future use.
+This option is useful if the
+.B /etc/.rootkey
+file ever gets out of date or corrupted.
+.SH FILES
+.PD 0
+.TP 20
+.B /etc/.rootkey
+.PD
+.SH "SEE ALSO"
+.BR login (1),
+.BR publickey (5)
diff --git a/lib/librpc/secure_rpc/man/publickey.3r b/lib/librpc/secure_rpc/man/publickey.3r
new file mode 100644
index 0000000..7063e8a
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/publickey.3r
@@ -0,0 +1,44 @@
+.\" @(#)publickey.3r 2.1 88/08/07 4.0 RPCSRC
+.TH PUBLICKEY 3R "6 October 1987"
+.SH NAME
+publickey, getpublickey, getsecretkey \- get public or secret key
+.SH SYNOPSIS
+.nf
+.B #include <rpc/rpc.h>
+.B #include <rpc/key_prot.h>
+.LP
+.B getpublickey(netname, publickey)
+.B char netname[\s-1MAXNETNAMELEN\s0+1];
+.B char publickey[\s-1HEXKEYBYTES\s0+1];
+.LP
+.B getsecretkey(netname, secretkey, passwd)
+.B char netname[\s-1MAXNETNAMELEN\s0+1];
+.B char secretkey[\s-1HEXKEYBYTES\s0+1];
+.B char *passwd;
+.fi
+.SH DESCRIPTION
+.IX "getpublickey function" "" "\fLgetpublickey()\fP function"
+.IX "getsecretkey function" "" "\fLgetsecretkey()\fP function"
+These routines are used to get public and secret keys from the
+.SM YP
+database.
+.B getsecretkey(\|)
+has an extra argument,
+.IR passwd ,
+which is used to decrypt the encrypted secret key stored in the database.
+Both routines return 1 if they are successful in finding the key, 0 otherwise.
+The keys are returned as
+.SM NULL\s0-terminated,
+hexadecimal strings. If the password supplied to
+.B getsecretkey(\|)
+fails to decrypt the secret key, the routine will return 1 but the
+.I secretkey
+argument will be a
+.SM NULL
+string (``'').
+.SH "SEE ALSO"
+.BR publickey (5)
+.LP
+.I \s-1RPC\s0 Programmer's Manual
+in
+.TX NETP
diff --git a/lib/librpc/secure_rpc/man/publickey.5 b/lib/librpc/secure_rpc/man/publickey.5
new file mode 100644
index 0000000..de3c1e9
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/publickey.5
@@ -0,0 +1,37 @@
+.\" @(#)publickey.5 2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI;
+.TH PUBLICKEY 5 "19 October 1987"
+.SH NAME
+publickey \- public key database
+.SH SYNOPSIS
+.B /etc/publickey
+.SH DESCRIPTION
+.LP
+.B /etc/publickey
+is the public key database used for secure
+networking. Each entry in
+the database consists of a network user
+name (which may either refer to
+a user or a hostname), followed by the user's
+public key (in hex
+notation), a colon, and then the user's
+secret key encrypted with
+its login password (also in hex notation).
+.LP
+This file is altered either by the user through the
+.BR chkey (1)
+command or by the system administrator through the
+.BR newkey (8)
+command.
+The file
+.B /etc/publickey
+should only contain data on the Yellow
+Pages master machine, where it
+is converted into the
+.SM YP
+database
+.BR publickey.byname .
+.SH SEE ALSO
+.BR chkey (1),
+.BR publickey (3R),
+.BR newkey (8),
+.BR ypupdated (8C)
diff --git a/lib/librpc/secure_rpc/man/rpc_secure.3n b/lib/librpc/secure_rpc/man/rpc_secure.3n
new file mode 100644
index 0000000..6e9a2ee
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/rpc_secure.3n
@@ -0,0 +1,330 @@
+.\" @(#)rpc_secure.3n 2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.TH RPC 3N "16 February 1988"
+.SH NAME
+rpc_secure \- library routines for secure remote procedure calls
+.SH SYNOPSIS AND DESCRIPTION
+These routines are part of the RPC library. They implement DES
+Authentication. See
+.BR rpc (3N)
+for further details about RPC.
+.LP
+.ft B
+.nf
+.sp .5
+#include <rpc/rpc.h>
+.fi
+.ft R
+.br
+.if t .ne 22
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authdes_create(name, window, syncaddr, ckey)
+char *name;
+unsigned window;
+struct sockaddr_in *addr;
+des_block *ckey;
+.fi
+.ft R
+.IP
+.B authdes_create(\|)
+is the first of two routines which interface to the
+.SM RPC
+secure authentication system, known as
+.SM DES
+authentication.
+The second is
+.BR authdes_getucred(\|) ,
+below. Note: the keyserver daemon
+.BR keyserv (8C)
+must be running for the
+.SM DES
+authentication system to work.
+.IP
+.BR authdes_create(\|) ,
+used on the client side, returns an authentication handle that
+will enable the use of the secure authentication system.
+The first parameter
+.I name
+is the network name, or
+.IR netname ,
+of the owner of the server process. This field usually
+represents a
+.I hostname
+derived from the utility routine
+.BR host2netname ,
+but could also represent a user name using
+.BR user2netname .
+The second field is window on the validity of
+the client credential, given in seconds. A small
+window is more secure than a large one, but choosing
+too small of a window will increase the frequency of
+resynchronizations because of clock drift. The third
+parameter
+.I syncaddr
+is optional. If it is
+.SM NULL\s0,
+then the authentication system will assume
+that the local clock is always in sync with the server's
+clock, and will not attempt resynchronizations. If an address
+is supplied, however, then the system will use the address
+for consulting the remote time service whenever
+resynchronization
+is required. This parameter is usually the
+address of the
+.SM RPC
+server itself. The final parameter
+.I ckey
+is also optional. If it is
+.SM NULL\s0,
+then the authentication system will
+generate a random
+.SM DES
+key to be used for the encryption of credentials.
+If it is supplied, however, then it will be used instead.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+authdes_getucred(adc, uid, gid, grouplen, groups)
+struct authdes_cred *adc;
+short *uid;
+short *gid;
+short *grouplen;
+int *groups;
+.fi
+.ft R
+.IP
+.BR authdes_getucred(\|) ,
+the second of the two
+.SM DES
+authentication routines,
+is used on the server side for converting a
+.SM DES
+credential, which is
+operating system independent, into a
+.UX
+credential. This routine differs from utility routine
+.B netname2user
+in that
+.B authdes_getucred(\|)
+pulls its information from a cache, and does not have to do a
+Yellow Pages lookup every time it is called to get its information.
+.br
+.ft .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+host2netname(name, host, domain)
+char *name;
+char *host;
+char *domain;
+.fi
+.ft R
+.IP
+Convert from a domain-specific hostname to an
+operating-system independent netname. Return
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails. Inverse of
+.BR netname2host(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+key_decryptsession(remotename, deskey)
+char *remotename;
+des_block *deskey;
+.fi
+.ft R
+.IP
+.B key_decryptsession(\|)
+is an interface to the keyserver daemon, which is associated
+with
+.SM RPC\s0's
+secure authentication system (\s-1DES\s0
+authentication).
+User programs rarely need to call it, or its associated routines
+.BR key_encryptsession(\|) ,
+.B key_gendes(\|)
+and
+.BR key_setsecret(\|) .
+System commands such as
+.B login
+and the
+.SM RPC
+library are the main clients of these four routines.
+.IP
+.B key_decryptsession(\|)
+takes a server netname and a des key, and decrypts the key by
+using the the public key of the the server and the secret key
+associated with the effective uid of the calling process. It
+is the inverse of
+.BR key_encryptsession(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+key_encryptsession(remotename, deskey)
+char *remotename;
+des_block *deskey;
+.fi
+.ft R
+.IP
+.B key_encryptsession(\|)
+is a keyserver interface routine. It
+takes a server netname and a des key, and encrypts
+it using the public key of the the server and the secret key
+associated with the effective uid of the calling process. It
+is the inverse of
+.BR key_decryptsession(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+key_gendes(deskey)
+des_block *deskey;
+.fi
+.ft R
+.IP
+.B key_gendes(\|)
+is a keyserver interface routine. It
+is used to ask the keyserver for a secure conversation key.
+Choosing one at \(lqrandom\(rq is usually not good enough,
+because
+the common ways of choosing random numbers, such as using the
+current time, are very easy to guess.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+key_setsecret(key)
+char *key;
+.fi
+.ft R
+.IP
+.B key_setsecret(\|)
+is a keyserver interface routine. It is used to set the key for
+the effective
+.I uid
+of the calling process.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+getnetname(name)
+char name[\s-1MAXNETNAMELEN\s0];
+.fi
+.ft R
+.IP
+.B getnetname(\|)
+installs the unique, operating-system independent netname of
+the
+caller in the fixed-length array
+.IR name .
+Returns
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+netname2host(name, host, hostlen)
+char *name;
+char *host;
+int hostlen;
+.fi
+.ft R
+.IP
+Convert from an operating-system independent netname to a
+domain-specific hostname. Returns
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails. Inverse of
+.BR host2netname(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+netname2user(name, uidp, gidp, gidlenp, gidlist)
+char *name;
+int *uidp;
+int *gidp;
+int *gidlenp;
+int *gidlist;
+.fi
+.ft R
+.IP
+Convert from an operating-system independent netname to a
+domain-specific user
+.SM ID.
+Returns
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails. Inverse of
+.BR user2netname(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+user2netname(name, uid, domain)
+char *name;
+int uid;
+char *domain;
+.fi
+.ft R
+.IP
+Convert from a domain-specific username to an operating-system
+independent netname. Returns
+.SM TRUE
+if it succeeds and
+.SM FALSE
+if it fails. Inverse of
+.BR netname2user(\|) .
+.br
+.SH SEE ALSO
+.BR xdr (3N),
+.BR keyserv (8C),
+.BR rpc (3N)
+.br
+The following manuals:
+.RS
+.ft I
+Remote Procedure Calls: Protocol Specification
+.br
+Remote Procedure Call Programming Guide
+.br
+rpcgen Programming Guide
+.br
+.ft R
+.RE
+.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" ,
+.SM RFC1050, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
+
diff --git a/lib/librpc/secure_rpc/man/rtime.3n b/lib/librpc/secure_rpc/man/rtime.3n
new file mode 100644
index 0000000..af0c1ca
--- /dev/null
+++ b/lib/librpc/secure_rpc/man/rtime.3n
@@ -0,0 +1,43 @@
+.\" @(#)rtime.3n 2.1 88/08/08 4.0 RPCSRC; from 1.5 88/02/08 SMI
+.TH RTIME 3 "22 November 1987"
+.SH NAME
+rtime \- get remote time
+.SH SYNOPSIS
+.nf
+.B #include <sys/types.h>
+.B #include <sys/time.h>
+.B #include <netinet/in.h>
+.LP
+.B int rtime(addrp, timep, timeout)
+.B struct sockaddr_in \(**addrp;
+.B struct timeval \(**timep;
+.B struct timeval \(**timeout;
+.fi
+.SH DESCRIPTION
+.B rtime(\|)
+consults the Internet Time Server at the address pointed to by
+.I addrp
+and returns the remote time in the
+.B timeval
+struct pointed to by
+.IR timep .
+Normally, the
+.SM UDP
+protocol is used when consulting the Time Server. The
+.I timeout
+parameter specifies how long the
+routine should wait before giving
+up when waiting for a reply. If
+.I timeout
+is specified as
+.SM NULL\s0,
+however, the routine will instead use
+.SM TCP
+and block until a reply is received from the time server.
+.LP
+The routine returns 0 if it is successful. Otherwise,
+it returns \-1 and
+.B errno
+is set to reflect the cause of the error.
+.SH "SEE ALSO"
+.BR timed (8c)
diff --git a/lib/librpc/secure_rpc/rpc/Makefile b/lib/librpc/secure_rpc/rpc/Makefile
new file mode 100644
index 0000000..88b242f
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/Makefile
@@ -0,0 +1,109 @@
+#
+# @(#)Makefile 2.3 88/08/15 4.0 RPCSRC
+#
+#
+# Copyright (c) 1987 by Sun Microsystems, Inc.
+#
+
+DESTDIR=
+
+CFLAGS = -I..
+
+SRCS = auth_des.c authdes_prot.c key_call.c key_prot.c netname.c svcauth_des.c \
+ openchild.c rtime.c publickey.c xcrypt.c \
+ auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
+ clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
+ clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \
+ pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
+ pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \
+ svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \
+ svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_float.c xdr_mem.c \
+ xdr_rec.c xdr_reference.c xdr_stdio.c
+
+OBJS = auth_des.o authdes_prot.o key_call.o key_prot.o netname.o svcauth_des.o \
+ openchild.o rtime.o publickey.o xcrypt.o \
+ auth_none.o auth_unix.o authunix_prot.o bindresvport.o \
+ clnt_generic.o clnt_perror.o clnt_raw.o clnt_simple.o clnt_tcp.o \
+ clnt_udp.o rpc_dtablesize.o get_myaddress.o getrpcent.o getrpcport.o \
+ pmap_clnt.o pmap_getmaps.o pmap_getport.o pmap_prot.o \
+ pmap_prot2.o pmap_rmt.o rpc_prot.o rpc_commondata.o rpc_callmsg.o \
+ svc.o svc_auth.o svc_auth_unix.o svc_raw.o svc_run.o svc_simple.o \
+ svc_tcp.o svc_udp.o xdr.o xdr_array.o xdr_float.o xdr_mem.o \
+ xdr_rec.o xdr_reference.o xdr_stdio.o
+
+HDRS = key_prot.h \
+ auth.h auth_unix.h auth_des.h clnt.h netdb.h pmap_clnt.h \
+ pmap_prot.h pmap_rmt.h rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h
+
+XFILES= key_prot.x
+
+all rpclib: librpclib.a
+
+librpclib.a: ${OBJS}
+ @echo "building librpclib.a"
+ @ar cru librpclib.a ${OBJS}
+
+install: $(HDRS) librpclib.a
+ @echo "Creating RPC header directory"
+ -mkdir ${DESTDIR}/usr/include/rpc && \
+ chown bin ${DESTDIR}/usr/include/rpc && \
+ chmod 755 ${DESTDIR}/usr/include/rpc
+ @echo "Installing RPC header files"
+ -set -x;for i in $(HDRS) $(XFILES) ; do \
+ (install -c -m 644 $$i ${DESTDIR}/usr/include/rpc) done
+ @echo "Installing RPC library"
+ install -c -m 644 librpclib.a ${DESTDIR}/usr/lib
+ ranlib ${DESTDIR}/usr/lib/librpclib.a
+
+tags: $(SRCS) $(HDRS)
+ ctags -tw $(SRCS) $(HDRS)
+
+ref: tags
+ sed 's, /.*,,' tags | \
+ awk ' { printf("%-26s%-16s%s\n", $$1, $$2, $$3) }' > ref
+
+lint: $(SRCS) $(HDRS)
+ $(LINT.c) $(SRCS)
+
+clean: rm -f *.o rpclib.a
+
+.SUFFIXES: .x .x~
+
+.x.c:
+ rpcgen -c $< | \
+ sed 's/^#include \"$*\.h\"/#include <rpc\/$*\.h>/' > $@
+
+.x.h:
+ rpcgen -h $< > $@
+
+depend: $(SRCS) $(HDRS)
+ @${CC} ${CFLAGS} -M ${SRCS} > makedep
+ @echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep
+ @echo '$$r makedep' >>eddep
+ @echo 'w' >>eddep
+ @cp Makefile makefile.bak
+ @ed - Makefile < eddep
+ @rm eddep makedep makefile.bak
+
+depend.42BSD depend.42bsd:
+ cp /dev/null x.c
+ for i in $(SRCS) ; do \
+ (/bin/grep '^#[ ]*include' x.c $$i | sed \
+ -e '/\.\.\/h/d' \
+ -e '/\.\.\/ufs/d' \
+ -e 's,<\(.*\)>,"/usr/include/\1",' \
+ -e 's/:[^"]*"\([^"]*\)".*/: \1/' \
+ -e 's/\.c/\.o/' >>makedep); done
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile < eddep
+ rm eddep makedep x.c
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
+ echo '# see make depend above' >> Makefile
+
+# DO NOT DELETE THIS LINE
+
+
diff --git a/lib/librpc/secure_rpc/rpc/auth_des.c b/lib/librpc/secure_rpc/rpc/auth_des.c
new file mode 100644
index 0000000..a757c49
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/auth_des.c
@@ -0,0 +1,411 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI";
+#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) 1988 by Sun Microsystems, Inc.
+ */
+/*
+ * auth_des.c, client-side implementation of DES authentication
+ */
+
+#include <des_crypt.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h> /* XXX: just to get htonl() and ntohl() */
+#include <sys/socket.h>
+
+#define MILLION 1000000L
+#define RTIME_TIMEOUT 5 /* seconds to wait for sync */
+
+#define AUTH_PRIVATE(auth) (struct ad_private *) auth->ah_private
+#define ALLOC(object_type) (object_type *) mem_alloc(sizeof(object_type))
+#define FREE(ptr, size) mem_free((char *)(ptr), (int) size)
+#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
+
+#define debug(msg) /*printf("%s\n", msg) */
+
+/*
+ * DES authenticator operations vector
+ */
+static void authdes_nextverf();
+static bool_t authdes_marshal();
+static bool_t authdes_validate();
+static bool_t authdes_refresh();
+static void authdes_destroy();
+static struct auth_ops authdes_ops = {
+ authdes_nextverf,
+ authdes_marshal,
+ authdes_validate,
+ authdes_refresh,
+ authdes_destroy
+};
+
+
+/*
+ * This struct is pointed to by the ah_private field of an "AUTH *"
+ */
+struct ad_private {
+ char *ad_fullname; /* client's full name */
+ u_int ad_fullnamelen; /* length of name, rounded up */
+ char *ad_servername; /* server's full name */
+ u_int ad_servernamelen; /* length of name, rounded up */
+ u_int ad_window; /* client specified window */
+ bool_t ad_dosync; /* synchronize? */
+ struct sockaddr ad_syncaddr; /* remote host to synch with */
+ struct timeval ad_timediff; /* server's time - client's time */
+ u_long ad_nickname; /* server's nickname for client */
+ struct authdes_cred ad_cred; /* storage for credential */
+ struct authdes_verf ad_verf; /* storage for verifier */
+ struct timeval ad_timestamp; /* timestamp sent */
+ des_block ad_xkey; /* encrypted conversation key */
+};
+
+
+/*
+ * Create the client des authentication object
+ */
+AUTH *
+authdes_create(servername, window, syncaddr, ckey)
+ char *servername; /* network name of server */
+ u_int window; /* time to live */
+ struct sockaddr *syncaddr; /* optional addr of host to sync with */
+ des_block *ckey; /* optional conversation key to use*/
+{
+
+ AUTH *auth;
+ struct ad_private *ad;
+ char namebuf[MAXNETNAMELEN+1];
+
+ /*
+ * Allocate everything now
+ */
+ auth = ALLOC(AUTH);
+ ad = ALLOC(struct ad_private);
+ (void) getnetname(namebuf);
+
+ ad->ad_fullnamelen = RNDUP(strlen(namebuf));
+ ad->ad_fullname = mem_alloc(ad->ad_fullnamelen + 1);
+
+ ad->ad_servernamelen = strlen(servername);
+ ad->ad_servername = mem_alloc(ad->ad_servernamelen + 1);
+
+ if (auth == NULL || ad == NULL || ad->ad_fullname == NULL ||
+ ad->ad_servername == NULL) {
+ debug("authdes_create: out of memory");
+ goto failed;
+ }
+
+ /*
+ * Set up private data
+ */
+ bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1);
+ bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1);
+ if (syncaddr != NULL) {
+ ad->ad_syncaddr = *syncaddr;
+ ad->ad_dosync = TRUE;
+ } else {
+ ad->ad_dosync = FALSE;
+ }
+ ad->ad_window = window;
+ if (ckey == NULL) {
+ if (key_gendes(&auth->ah_key) < 0) {
+ debug("authdes_create: unable to gen conversation key");
+ return (NULL);
+ }
+ } else {
+ auth->ah_key = *ckey;
+ }
+
+ /*
+ * Set up auth handle
+ */
+ auth->ah_cred.oa_flavor = AUTH_DES;
+ auth->ah_verf.oa_flavor = AUTH_DES;
+ auth->ah_ops = &authdes_ops;
+ auth->ah_private = (caddr_t)ad;
+
+ if (!authdes_refresh(auth)) {
+ goto failed;
+ }
+ return (auth);
+
+failed:
+ if (auth != NULL)
+ FREE(auth, sizeof(AUTH));
+ if (ad != NULL)
+ FREE(ad, sizeof(struct ad_private));
+ if (ad->ad_fullname != NULL)
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ if (ad->ad_servername != NULL)
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ return (NULL);
+}
+
+/*
+ * Implement the five authentication operations
+ */
+
+
+/*
+ * 1. Next Verifier
+ */
+/*ARGSUSED*/
+static void
+authdes_nextverf(auth)
+ AUTH *auth;
+{
+ /* what the heck am I supposed to do??? */
+}
+
+
+
+/*
+ * 2. Marshal
+ */
+static bool_t
+authdes_marshal(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_cred *cred = &ad->ad_cred;
+ struct authdes_verf *verf = &ad->ad_verf;
+ des_block cryptbuf[2];
+ des_block ivec;
+ int status;
+ int len;
+ register long *ixdr;
+
+ /*
+ * Figure out the "time", accounting for any time difference
+ * with the server if necessary.
+ */
+ (void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL);
+ ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
+ ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
+ if (ad->ad_timestamp.tv_usec >= MILLION) {
+ ad->ad_timestamp.tv_usec -= MILLION;
+ ad->ad_timestamp.tv_sec += 1;
+ }
+
+ /*
+ * XDR the timestamp and possibly some other things, then
+ * encrypt them.
+ */
+ ixdr = (long *)cryptbuf;
+ IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_sec);
+ IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_usec);
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ IXDR_PUT_U_LONG(ixdr, ad->ad_window);
+ IXDR_PUT_U_LONG(ixdr, ad->ad_window - 1);
+ ivec.key.high = ivec.key.low = 0;
+ status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
+ 2*sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec);
+ } else {
+ status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
+ sizeof(des_block), DES_ENCRYPT | DES_HW);
+ }
+ if (DES_FAILED(status)) {
+ debug("authdes_marshal: DES encryption failure");
+ return (FALSE);
+ }
+ ad->ad_verf.adv_xtimestamp = cryptbuf[0];
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
+ ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
+ } else {
+ ad->ad_cred.adc_nickname = ad->ad_nickname;
+ ad->ad_verf.adv_winverf = 0;
+ }
+
+ /*
+ * Serialize the credential and verifier into opaque
+ * authentication data.
+ */
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
+ } else {
+ len = (1 + 1)*BYTES_PER_XDR_UNIT;
+ }
+
+ if (ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT)) {
+ IXDR_PUT_LONG(ixdr, AUTH_DES);
+ IXDR_PUT_LONG(ixdr, len);
+ } else {
+ ATTEMPT(xdr_putlong(xdrs, &auth->ah_cred.oa_flavor));
+ ATTEMPT(xdr_putlong(xdrs, &len));
+ }
+ ATTEMPT(xdr_authdes_cred(xdrs, cred));
+
+ len = (2 + 1)*BYTES_PER_XDR_UNIT;
+ if (ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT)) {
+ IXDR_PUT_LONG(ixdr, AUTH_DES);
+ IXDR_PUT_LONG(ixdr, len);
+ } else {
+ ATTEMPT(xdr_putlong(xdrs, &auth->ah_verf.oa_flavor));
+ ATTEMPT(xdr_putlong(xdrs, &len));
+ }
+ ATTEMPT(xdr_authdes_verf(xdrs, verf));
+ return (TRUE);
+}
+
+
+/*
+ * 3. Validate
+ */
+static bool_t
+authdes_validate(auth, rverf)
+ AUTH *auth;
+ struct opaque_auth *rverf;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_verf verf;
+ int status;
+ register u_long *ixdr;
+
+ if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
+ return (FALSE);
+ }
+ ixdr = (u_long *)rverf->oa_base;
+ verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
+ verf.adv_xtimestamp.key.low = (u_long)*ixdr++;
+ verf.adv_int_u = (u_long)*ixdr++; /* nickname not XDR'd ! */
+
+ /*
+ * Decrypt the timestamp
+ */
+ status = ecb_crypt((char *)&auth->ah_key, (char *)&verf.adv_xtimestamp,
+ sizeof(des_block), DES_DECRYPT | DES_HW);
+
+ if (DES_FAILED(status)) {
+ debug("authdes_validate: DES decryption failure");
+ return (FALSE);
+ }
+
+ /*
+ * xdr the decrypted timestamp
+ */
+ ixdr = (u_long *)verf.adv_xtimestamp.c;
+ verf.adv_timestamp.tv_sec = IXDR_GET_LONG(ixdr) + 1;
+ verf.adv_timestamp.tv_usec = IXDR_GET_LONG(ixdr);
+
+ /*
+ * validate
+ */
+ if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
+ sizeof(struct timeval)) != 0) {
+ debug("authdes_validate: verifier mismatch\n");
+ return (FALSE);
+ }
+
+ /*
+ * We have a nickname now, let's use it
+ */
+ ad->ad_nickname = verf.adv_nickname;
+ ad->ad_cred.adc_namekind = ADN_NICKNAME;
+ return (TRUE);
+}
+
+/*
+ * 4. Refresh
+ */
+static bool_t
+authdes_refresh(auth)
+ AUTH *auth;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_cred *cred = &ad->ad_cred;
+
+ if (ad->ad_dosync &&
+ !synchronize(&ad->ad_syncaddr, &ad->ad_timediff)) {
+ /*
+ * Hope the clocks are synced!
+ */
+ ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0;
+ debug("authdes_refresh: unable to synchronize with server");
+ }
+ ad->ad_xkey = auth->ah_key;
+ if (key_encryptsession(ad->ad_servername, &ad->ad_xkey) < 0) {
+ debug("authdes_create: unable to encrypt conversation key");
+ return (FALSE);
+ }
+ cred->adc_fullname.key = ad->ad_xkey;
+ cred->adc_namekind = ADN_FULLNAME;
+ cred->adc_fullname.name = ad->ad_fullname;
+ return (TRUE);
+}
+
+
+/*
+ * 5. Destroy
+ */
+static void
+authdes_destroy(auth)
+ AUTH *auth;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ FREE(ad, sizeof(struct ad_private));
+ FREE(auth, sizeof(AUTH));
+}
+
+
+
+/*
+ * Synchronize with the server at the given address, that is,
+ * adjust timep to reflect the delta between our clocks
+ */
+static bool_t
+synchronize(syncaddr, timep)
+ struct sockaddr *syncaddr;
+ struct timeval *timep;
+{
+ struct timeval mytime;
+ struct timeval timeout;
+
+ timeout.tv_sec = RTIME_TIMEOUT;
+ timeout.tv_usec = 0;
+ if (rtime((struct sockaddr_in *)syncaddr, timep, &timeout) < 0) {
+ return (FALSE);
+ }
+ (void) gettimeofday(&mytime, (struct timezone *)NULL);
+ timep->tv_sec -= mytime.tv_sec;
+ if (mytime.tv_usec > timep->tv_usec) {
+ timep->tv_sec -= 1;
+ timep->tv_usec += MILLION;
+ }
+ timep->tv_usec -= mytime.tv_usec;
+ return (TRUE);
+}
diff --git a/lib/librpc/secure_rpc/rpc/auth_des.h b/lib/librpc/secure_rpc/rpc/auth_des.h
new file mode 100644
index 0000000..4ae4761
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/auth_des.h
@@ -0,0 +1,105 @@
+/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */
+/*
+ * 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) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * auth_des.h, Protocol for DES style authentication for RPC
+ */
+
+#ifndef _AUTH_DES_
+#define _AUTH_DES_
+
+/*
+ * There are two kinds of "names": fullnames and nicknames
+ */
+enum authdes_namekind {
+ ADN_FULLNAME,
+ ADN_NICKNAME
+};
+
+/*
+ * A fullname contains the network name of the client,
+ * a conversation key and the window
+ */
+struct authdes_fullname {
+ char *name; /* network name of client, up to MAXNETNAMELEN */
+ des_block key; /* conversation key */
+ u_long window; /* associated window */
+};
+
+
+/*
+ * A credential
+ */
+struct authdes_cred {
+ enum authdes_namekind adc_namekind;
+ struct authdes_fullname adc_fullname;
+ u_long adc_nickname;
+};
+
+
+
+/*
+ * A des authentication verifier
+ */
+struct authdes_verf {
+ union {
+ struct timeval adv_ctime; /* clear time */
+ des_block adv_xtime; /* crypt time */
+ } adv_time_u;
+ u_long adv_int_u;
+};
+
+/*
+ * des authentication verifier: client variety
+ *
+ * adv_timestamp is the current time.
+ * adv_winverf is the credential window + 1.
+ * Both are encrypted using the conversation key.
+ */
+#define adv_timestamp adv_time_u.adv_ctime
+#define adv_xtimestamp adv_time_u.adv_xtime
+#define adv_winverf adv_int_u
+
+/*
+ * des authentication verifier: server variety
+ *
+ * adv_timeverf is the client's timestamp + client's window
+ * adv_nickname is the server's nickname for the client.
+ * adv_timeverf is encrypted using the conversation key.
+ */
+#define adv_timeverf adv_time_u.adv_ctime
+#define adv_xtimeverf adv_time_u.adv_xtime
+#define adv_nickname adv_int_u
+
+#endif /* ndef _AUTH_DES_ */
diff --git a/lib/librpc/secure_rpc/rpc/authdes_prot.c b/lib/librpc/secure_rpc/rpc/authdes_prot.c
new file mode 100644
index 0000000..14679c0
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/authdes_prot.c
@@ -0,0 +1,82 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI";
+#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) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * authdes_prot.c, XDR routines for DES authentication
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+
+#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
+
+bool_t
+xdr_authdes_cred(xdrs, cred)
+ XDR *xdrs;
+ struct authdes_cred *cred;
+{
+ /*
+ * Unrolled xdr
+ */
+ ATTEMPT(xdr_enum(xdrs, (enum_t *)&cred->adc_namekind));
+ switch (cred->adc_namekind) {
+ case ADN_FULLNAME:
+ ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name, MAXNETNAMELEN));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key, sizeof(des_block)));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window, sizeof(cred->adc_fullname.window)));
+ return (TRUE);
+ case ADN_NICKNAME:
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname, sizeof(cred->adc_nickname)));
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+}
+
+
+bool_t
+xdr_authdes_verf(xdrs, verf)
+ register XDR *xdrs;
+ register struct authdes_verf *verf;
+{
+ /*
+ * Unrolled xdr
+ */
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp, sizeof(des_block)));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u, sizeof(verf->adv_int_u)));
+ return (TRUE);
+}
diff --git a/lib/librpc/secure_rpc/rpc/key_call.c b/lib/librpc/secure_rpc/rpc/key_call.c
new file mode 100644
index 0000000..c2fd335
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/key_call.c
@@ -0,0 +1,228 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)key_call.c 2.2 88/08/15 4.0 RPCSRC; from 1.11 88/02/08 SMI";
+#endif
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+/*
+ * 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
+ */
+
+/*
+ * key_call.c, Interface to keyserver
+ *
+ * setsecretkey(key) - set your secret key
+ * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent
+ * decryptsessionkey(agent, deskey) - decrypt ditto
+ * gendeskey(deskey) - generate a secure des key
+ * netname2user(...) - get unix credential for given name (kernel only)
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+
+#define KEY_TIMEOUT 5 /* per-try timeout in seconds */
+#define KEY_NRETRY 12 /* number of retries */
+
+#define debug(msg) /* turn off debugging */
+
+static struct timeval trytimeout = { KEY_TIMEOUT, 0 };
+static struct timeval tottimeout = { KEY_TIMEOUT * KEY_NRETRY, 0 };
+
+key_setsecret(secretkey)
+ char *secretkey;
+{
+ keystatus status;
+
+ if (!key_call((u_long)KEY_SET, xdr_keybuf, secretkey, xdr_keystatus,
+ (char*)&status))
+ {
+ return (-1);
+ }
+ if (status != KEY_SUCCESS) {
+ debug("set status is nonzero");
+ return (-1);
+ }
+ return (0);
+}
+
+
+key_encryptsession(remotename, deskey)
+ char *remotename;
+ des_block *deskey;
+{
+ cryptkeyarg arg;
+ cryptkeyres res;
+
+ arg.remotename = remotename;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_ENCRYPT,
+ xdr_cryptkeyarg, (char *)&arg, xdr_cryptkeyres, (char *)&res))
+ {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("encrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+
+key_decryptsession(remotename, deskey)
+ char *remotename;
+ des_block *deskey;
+{
+ cryptkeyarg arg;
+ cryptkeyres res;
+
+ arg.remotename = remotename;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_DECRYPT,
+ xdr_cryptkeyarg, (char *)&arg, xdr_cryptkeyres, (char *)&res))
+ {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("decrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+key_gendes(key)
+ des_block *key;
+{
+ struct sockaddr_in sin;
+ CLIENT *client;
+ int socket;
+ enum clnt_stat stat;
+
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = 0;
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ bzero(sin.sin_zero, sizeof(sin.sin_zero));
+ socket = RPC_ANYSOCK;
+ client = clntudp_bufcreate(&sin, (u_long)KEY_PROG, (u_long)KEY_VERS,
+ trytimeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if (client == NULL) {
+ return (-1);
+ }
+ stat = clnt_call(client, KEY_GEN, xdr_void, NULL,
+ xdr_des_block, key, tottimeout);
+ clnt_destroy(client);
+ (void) close(socket);
+ if (stat != RPC_SUCCESS) {
+ return (-1);
+ }
+ return (0);
+}
+
+
+#include <stdio.h>
+#include <sys/wait.h>
+
+
+static
+key_call(proc, xdr_arg, arg, xdr_rslt, rslt)
+ u_long proc;
+ bool_t (*xdr_arg)();
+ char *arg;
+ bool_t (*xdr_rslt)();
+ char *rslt;
+{
+ XDR xdrargs;
+ XDR xdrrslt;
+ FILE *fargs;
+ FILE *frslt;
+ int (*osigchild)();
+ union wait status;
+ int pid;
+ int success;
+ int ruid;
+ int euid;
+ static char MESSENGER[] = "/usr/etc/keyenvoy";
+
+ success = 1;
+ osigchild = signal(SIGCHLD, SIG_IGN);
+
+ /*
+ * We are going to exec a set-uid program which makes our effective uid
+ * zero, and authenticates us with our real uid. We need to make the
+ * effective uid be the real uid for the setuid program, and
+ * the real uid be the effective uid so that we can change things back.
+ */
+ euid = geteuid();
+ ruid = getuid();
+ (void) setreuid(euid, ruid);
+ pid = _openchild(MESSENGER, &fargs, &frslt);
+ (void) setreuid(ruid, euid);
+ if (pid < 0) {
+ debug("open_streams");
+ return (0);
+ }
+ xdrstdio_create(&xdrargs, fargs, XDR_ENCODE);
+ xdrstdio_create(&xdrrslt, frslt, XDR_DECODE);
+
+ if (!xdr_u_long(&xdrargs, &proc) || !(*xdr_arg)(&xdrargs, arg)) {
+ debug("xdr args");
+ success = 0;
+ }
+ (void) fclose(fargs);
+
+ if (success && !(*xdr_rslt)(&xdrrslt, rslt)) {
+ debug("xdr rslt");
+ success = 0;
+ }
+
+#ifdef NOTDEF
+ /*
+ * WARNING! XXX
+ * The original code appears first. wait4 returns only after the process
+ * with the requested pid terminates. The effect of using wait() instead
+ * has not been determined.
+ */
+ (void) fclose(frslt);
+ if (wait4(pid, &status, 0, NULL) < 0 || status.w_retcode != 0) {
+ debug("wait4");
+ success = 0;
+ }
+#endif /* def NOTDEF */
+ if (wait(&status) < 0 || status.w_retcode != 0) {
+ debug("wait");
+ success = 0;
+ }
+ (void)signal(SIGCHLD, osigchild);
+
+ return (success);
+}
+
diff --git a/lib/librpc/secure_rpc/rpc/key_prot.c b/lib/librpc/secure_rpc/rpc/key_prot.c
new file mode 100644
index 0000000..a93f543
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/key_prot.c
@@ -0,0 +1,165 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)key_prot.c 2.1 88/08/07 4.0 RPCSRC; from 1.4 88/02/08 SMI";
+#endif
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+/*
+ * 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
+ */
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+
+
+/*
+ * Compiled from key_prot.x using rpcgen.
+ * DO NOT EDIT THIS FILE!
+ * This is NOT source code!
+ */
+
+
+bool_t
+xdr_keystatus(xdrs, objp)
+ XDR *xdrs;
+ keystatus *objp;
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_keybuf(xdrs, objp)
+ XDR *xdrs;
+ keybuf objp;
+{
+ if (!xdr_opaque(xdrs, objp, HEXKEYBYTES)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_netnamestr(xdrs, objp)
+ XDR *xdrs;
+ netnamestr *objp;
+{
+ if (!xdr_string(xdrs, objp, MAXNETNAMELEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_cryptkeyarg(xdrs, objp)
+ XDR *xdrs;
+ cryptkeyarg *objp;
+{
+ if (!xdr_netnamestr(xdrs, &objp->remotename)) {
+ return (FALSE);
+ }
+ if (!xdr_des_block(xdrs, &objp->deskey)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_cryptkeyres(xdrs, objp)
+ XDR *xdrs;
+ cryptkeyres *objp;
+{
+ if (!xdr_keystatus(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case KEY_SUCCESS:
+ if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_unixcred(xdrs, objp)
+ XDR *xdrs;
+ unixcred *objp;
+{
+ if (!xdr_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_array(xdrs, (char **)&objp->gids.gids_val, (u_int *)&objp->gids.gids_len, MAXGIDS, sizeof(int), xdr_int)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_getcredres(xdrs, objp)
+ XDR *xdrs;
+ getcredres *objp;
+{
+ if (!xdr_keystatus(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case KEY_SUCCESS:
+ if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+
diff --git a/lib/librpc/secure_rpc/rpc/key_prot.h b/lib/librpc/secure_rpc/rpc/key_prot.h
new file mode 100644
index 0000000..277e4b8
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/key_prot.h
@@ -0,0 +1,114 @@
+/* @(#)key_prot.h 2.1 88/08/07 4.0 RPCSRC; from 1.4 87/03/10 Copyr 1986 Sun Micro */
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+/*
+ * 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
+ */
+
+
+/*
+ * Compiled from key_prot.x using rpcgen.
+ * DO NOT EDIT THIS FILE!
+ * This is NOT source code!
+ */
+
+#define KEY_PROG 100029
+#define KEY_VERS 1
+#define KEY_SET 1
+#define KEY_ENCRYPT 2
+#define KEY_DECRYPT 3
+#define KEY_GEN 4
+#define KEY_GETCRED 5
+
+#define PROOT 3
+#define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"
+#define HEXKEYBYTES 48
+#define KEYSIZE 192
+#define KEYBYTES 24
+#define KEYCHECKSUMSIZE 16
+
+enum keystatus {
+ KEY_SUCCESS = 0,
+ KEY_NOSECRET = 1,
+ KEY_UNKNOWN = 2,
+ KEY_SYSTEMERR = 3,
+};
+typedef enum keystatus keystatus;
+bool_t xdr_keystatus();
+
+
+typedef char keybuf[HEXKEYBYTES];
+bool_t xdr_keybuf();
+
+
+typedef char *netnamestr;
+bool_t xdr_netnamestr();
+
+
+struct cryptkeyarg {
+ netnamestr remotename;
+ des_block deskey;
+};
+typedef struct cryptkeyarg cryptkeyarg;
+bool_t xdr_cryptkeyarg();
+
+
+struct cryptkeyres {
+ keystatus status;
+ union {
+ des_block deskey;
+ } cryptkeyres_u;
+};
+typedef struct cryptkeyres cryptkeyres;
+bool_t xdr_cryptkeyres();
+
+#define MAXGIDS 16
+
+struct unixcred {
+ int uid;
+ int gid;
+ struct {
+ u_int gids_len;
+ int *gids_val;
+ } gids;
+};
+typedef struct unixcred unixcred;
+bool_t xdr_unixcred();
+
+
+struct getcredres {
+ keystatus status;
+ union {
+ unixcred cred;
+ } getcredres_u;
+};
+typedef struct getcredres getcredres;
+bool_t xdr_getcredres();
+
diff --git a/lib/librpc/secure_rpc/rpc/key_prot.x b/lib/librpc/secure_rpc/rpc/key_prot.x
new file mode 100644
index 0000000..2f6ebdb
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/key_prot.x
@@ -0,0 +1,151 @@
+%/* @(#)key_prot.x 2.1 88/08/07 4.0 RPCSRC; from 1.7 88/02/08 SMI */
+%
+%/*
+% * Copyright (c) 1988 by Sun Microsystems, Inc.
+% */
+%
+%/*
+% * Compiled from key_prot.x using rpcgen.
+% * DO NOT EDIT THIS FILE!
+% * This is NOT source code!
+% */
+
+/*
+ * Key server protocol definition
+ * Copyright (C) 1987 Sun Microsystems, Inc.
+ *
+ * The keyserver is a public key storage/encryption/decryption service
+ * The encryption method used is Diffie-Hellman with 128 bit keys.
+ *
+ * The key server is local to each machine, akin to the portmapper.
+ * Only privileged processes may talk to the key server, so
+ * user processes must communicate through a privileged dispatcher (such
+ * as the kernel or a set-uid-root process).
+ */
+program KEY_PROG {
+ version KEY_VERS {
+ /*
+ * This is my secret key.
+ * Store it for me.
+ */
+ int
+ KEY_SET(keybuf) = 1;
+
+ /*
+ * I want to talk to X.
+ * Encrypt a conversation key for me.
+ */
+ cryptkeyres
+ KEY_ENCRYPT(cryptkeyarg) = 2;
+
+ /*
+ * X just sent me a message.
+ * Decrypt the conversation key for me.
+ */
+ cryptkeyres
+ KEY_DECRYPT(cryptkeyarg) = 3;
+
+ /*
+ * Generate a secure conversation key for me
+ */
+ des_block
+ KEY_GEN(void) = 4;
+
+ /*
+ * Get me the uid, gid and group-access-list associated
+ * with this netname (for kernel which cannot use yp)
+ */
+ getcredres
+ KEY_GETCRED(netnamestr) = 5;
+ } = 1;
+} = 100029;
+
+
+/*
+ * PROOT and MODULUS define the way the Diffie-Hellman key is generated.
+ *
+ * MODULUS should be chosen as a prime of the form: MODULUS == 2*p + 1,
+ * where p is also prime.
+ *
+ * PROOT satisfies the following two conditions:
+ * (1) (PROOT ** 2) % MODULUS != 1
+ * (2) (PROOT ** p) % MODULUS != 1
+ *
+ */
+
+const PROOT = 3;
+const HEXMODULUS = "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b";
+
+const HEXKEYBYTES = 48; /* HEXKEYBYTES == strlen(HEXMODULUS) */
+const KEYSIZE = 192; /* KEYSIZE == bit length of key */
+const KEYBYTES = 24; /* byte length of key */
+
+/*
+ * The first 16 hex digits of the encrypted secret key are used as
+ * a checksum in the database.
+ */
+const KEYCHECKSUMSIZE = 16;
+
+/*
+ * status of operation
+ */
+enum keystatus {
+ KEY_SUCCESS, /* no problems */
+ KEY_NOSECRET, /* no secret key stored */
+ KEY_UNKNOWN, /* unknown netname */
+ KEY_SYSTEMERR /* system error (out of memory, encryption failure) */
+};
+
+/*
+ * The kernel doesn't use keybuf, so we insure that it
+ * is ifdef'd out in the output files. The proper way to do
+ * this is to #ifndef KERNEL it here, and have the kernel build
+ * use rpcgen, but config doesn't understand rpcgen files so
+ * it is done this way.
+ */
+#ifndef RPC_SVC
+%#ifndef KERNEL
+typedef opaque keybuf[HEXKEYBYTES]; /* store key in hex */
+%#endif
+#endif
+
+typedef string netnamestr<MAXNETNAMELEN>;
+
+/*
+ * Argument to ENCRYPT or DECRYPT
+ */
+struct cryptkeyarg {
+ netnamestr remotename;
+ des_block deskey;
+};
+
+/*
+ * Result of ENCRYPT or DECRYPT
+ */
+union cryptkeyres switch (keystatus status) {
+case KEY_SUCCESS:
+ des_block deskey;
+default:
+ void;
+};
+
+const MAXGIDS = 16; /* max number of gids in gid list */
+
+/*
+ * Unix credential
+ */
+struct unixcred {
+ int uid;
+ int gid;
+ int gids<MAXGIDS>;
+};
+
+/*
+ * Result returned from GETCRED
+ */
+union getcredres switch (keystatus status) {
+case KEY_SUCCESS:
+ unixcred cred;
+default:
+ void;
+};
diff --git a/lib/librpc/secure_rpc/rpc/netname.c b/lib/librpc/secure_rpc/rpc/netname.c
new file mode 100644
index 0000000..21e2491
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/netname.c
@@ -0,0 +1,239 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)netname.c 2.2 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI";
+#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) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * netname utility routines
+ * convert from unix names to network names and vice-versa
+ * This module is operating system dependent!
+ * What we define here will work with any unix system that has adopted
+ * the sun yp domain architecture.
+ */
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <ctype.h>
+
+extern char *sprintf();
+extern char *strncpy();
+
+static char OPSYS[] = "unix";
+static char NETID[] = "netid.byname";
+
+/*
+ * Convert network-name into unix credential
+ */
+netname2user(netname, uidp, gidp, gidlenp, gidlist)
+ char netname[MAXNETNAMELEN+1];
+ int *uidp;
+ int *gidp;
+ int *gidlenp;
+ int *gidlist;
+{
+ int stat;
+ char *val;
+ char *p;
+ int vallen;
+ char *domain;
+ int gidlen;
+
+ stat = yp_get_default_domain(&domain);
+ if (stat != 0) {
+ return (0);
+ }
+ stat = yp_match(domain, NETID, netname, strlen(netname), &val, &vallen);
+ if (stat != 0) {
+ return (0);
+ }
+ val[vallen] = 0;
+ p = val;
+ *uidp = atois(&p);
+ if (p == NULL || *p++ != ':') {
+ free(val);
+ return (0);
+ }
+ *gidp = atois(&p);
+ if (p == NULL) {
+ free(val);
+ return (0);
+ }
+ gidlen = 0;
+ for (gidlen = 0; gidlen < NGROUPS; gidlen++) {
+ if (*p++ != ',') {
+ break;
+ }
+ gidlist[gidlen] = atois(&p);
+ if (p == NULL) {
+ free(val);
+ return (0);
+ }
+ }
+ *gidlenp = gidlen;
+ free(val);
+ return (1);
+}
+
+/*
+ * Convert network-name to hostname
+ */
+netname2host(netname, hostname, hostlen)
+ char netname[MAXNETNAMELEN+1];
+ char *hostname;
+ int hostlen;
+{
+ int stat;
+ char *val;
+ int vallen;
+ char *domain;
+
+ stat = yp_get_default_domain(&domain);
+ if (stat != 0) {
+ return (0);
+ }
+ stat = yp_match(domain, NETID, netname, strlen(netname), &val, &vallen);
+ if (stat != 0) {
+ return (0);
+ }
+ val[vallen] = 0;
+ if (*val != '0') {
+ free(val);
+ return (0);
+ }
+ if (val[1] != ':') {
+ free(val);
+ return (0);
+ }
+ (void) strncpy(hostname, val + 2, hostlen);
+ free(val);
+ return (1);
+}
+
+
+/*
+ * Figure out my fully qualified network name
+ */
+getnetname(name)
+ char name[MAXNETNAMELEN+1];
+{
+ int uid;
+
+ uid = geteuid();
+ if (uid == 0) {
+ return (host2netname(name, (char *) NULL, (char *) NULL));
+ } else {
+ return (user2netname(name, uid, (char *) NULL));
+ }
+}
+
+
+/*
+ * Convert unix cred to network-name
+ */
+user2netname(netname, uid, domain)
+ char netname[MAXNETNAMELEN + 1];
+ int uid;
+ char *domain;
+{
+ char *dfltdom;
+
+#define MAXIPRINT (11) /* max length of printed integer */
+
+ if (domain == NULL) {
+ if (yp_get_default_domain(&dfltdom) != 0) {
+ return (0);
+ }
+ domain = dfltdom;
+ }
+ if (strlen(domain) + 1 + MAXIPRINT > MAXNETNAMELEN) {
+ return (0);
+ }
+ (void) sprintf(netname, "%s.%d@%s", OPSYS, uid, domain);
+ return (1);
+}
+
+
+/*
+ * Convert host to network-name
+ */
+host2netname(netname, host, domain)
+ char netname[MAXNETNAMELEN + 1];
+ char *host;
+ char *domain;
+{
+ char *dfltdom;
+ char hostname[MAXHOSTNAMELEN+1];
+
+ if (domain == NULL) {
+ if (yp_get_default_domain(&dfltdom) != 0) {
+ return (0);
+ }
+ domain = dfltdom;
+ }
+ if (host == NULL) {
+ (void) gethostname(hostname, sizeof(hostname));
+ host = hostname;
+ }
+ if (strlen(domain) + 1 + strlen(host) > MAXNETNAMELEN) {
+ return (0);
+ }
+ (void) sprintf(netname, "%s.%s@%s", OPSYS, host, domain);
+ return (1);
+}
+
+
+static
+atois(str)
+ char **str;
+{
+ char *p;
+ int n;
+ int sign;
+
+ if (**str == '-') {
+ sign = -1;
+ (*str)++;
+ } else {
+ sign = 1;
+ }
+ n = 0;
+ for (p = *str; isdigit(*p); p++) {
+ n = (10 * n) + (*p - '0');
+ }
+ if (p == *str) {
+ *str = NULL;
+ return (0);
+ }
+ *str = p;
+ return (n * sign);
+}
diff --git a/lib/librpc/secure_rpc/rpc/openchild.c b/lib/librpc/secure_rpc/rpc/openchild.c
new file mode 100644
index 0000000..b30e615
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/openchild.c
@@ -0,0 +1,133 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)openchild.c 2.3 88/08/15 4.0 RPCSRC; from 1.7 88/02/08 SMI";
+#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) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * Open two pipes to a child process, one for reading, one for writing.
+ * The pipes are accessed by FILE pointers. This is NOT a public
+ * interface, but for internal use only!
+ */
+#include <stdio.h>
+
+extern char *malloc();
+extern char *rindex();
+extern char *sprintf();
+
+static char *basename();
+static char SHELL[] = "/bin/sh";
+
+
+/*
+ * returns pid, or -1 for failure
+ */
+_openchild(command, fto, ffrom)
+ char *command;
+ FILE **fto;
+ FILE **ffrom;
+{
+ int i;
+ int pid;
+ int pdto[2];
+ int pdfrom[2];
+ char *com;
+
+
+ if (pipe(pdto) < 0) {
+ goto error1;
+ }
+ if (pipe(pdfrom) < 0) {
+ goto error2;
+ }
+ switch (pid = vfork()) {
+ case -1:
+ goto error3;
+
+ case 0:
+ /*
+ * child: read from pdto[0], write into pdfrom[1]
+ */
+ (void) close(0);
+ (void) dup(pdto[0]);
+ (void) close(1);
+ (void) dup(pdfrom[1]);
+ for (i = _rpc_dtablesize() - 1; i >= 3; i--) {
+ (void) close(i);
+ }
+ com = malloc((unsigned) strlen(command) + 6);
+ if (com == NULL) {
+ _exit(~0);
+ }
+ (void) sprintf(com, "exec %s", command);
+ execl(SHELL, basename(SHELL), "-c", com, NULL);
+ _exit(~0);
+
+ default:
+ /*
+ * parent: write into pdto[1], read from pdfrom[0]
+ */
+ *fto = fdopen(pdto[1], "w");
+ (void) close(pdto[0]);
+ *ffrom = fdopen(pdfrom[0], "r");
+ (void) close(pdfrom[1]);
+ break;
+ }
+ return (pid);
+
+ /*
+ * error cleanup and return
+ */
+error3:
+ (void) close(pdfrom[0]);
+ (void) close(pdfrom[1]);
+error2:
+ (void) close(pdto[0]);
+ (void) close(pdto[1]);
+error1:
+ return (-1);
+}
+
+static char *
+basename(path)
+ char *path;
+{
+ char *p;
+
+ p = rindex(path, '/');
+ if (p == NULL) {
+ return (path);
+ } else {
+ return (p + 1);
+ }
+}
diff --git a/lib/librpc/secure_rpc/rpc/publickey.c b/lib/librpc/secure_rpc/rpc/publickey.c
new file mode 100644
index 0000000..d403b63
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/publickey.c
@@ -0,0 +1,129 @@
+#ifndef lint
+static char sccsid[] = "@(#)publickey.c 2.3 88/08/15 4.0 RPCSRC";
+#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) 1988 by Sun Microsystems, Inc.
+ * @(#) from SUN 1.3
+ */
+
+/*
+ * Public key lookup routines
+ */
+#include <stdio.h>
+#include <pwd.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+
+
+extern char *index();
+extern char *strcpy();
+
+static char PKMAP[] = "publickey.byname";
+
+/*
+ * Get somebody's encrypted secret key from the database, using
+ * the given passwd to decrypt it.
+ */
+getsecretkey(netname, secretkey, passwd)
+ char *netname;
+ char *secretkey;
+ char *passwd;
+{
+ char *domain;
+ int len;
+ char *lookup;
+ int err;
+ char *p;
+
+
+ err = yp_get_default_domain(&domain);
+ if (err) {
+ return(0);
+ }
+ err = yp_match(domain, PKMAP, netname, strlen(netname), &lookup, &len);
+ if (err) {
+ return(0);
+ }
+ lookup[len] = 0;
+ p = index(lookup,':');
+ if (p == NULL) {
+ free(lookup);
+ return(0);
+ }
+ p++;
+ if (!xdecrypt(p, passwd)) {
+ free(lookup);
+ return(0);
+ }
+ if (bcmp(p, p + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0) {
+ secretkey[0] = 0;
+ free(lookup);
+ return(1);
+ }
+ p[HEXKEYBYTES] = 0;
+ (void) strcpy(secretkey, p);
+ free(lookup);
+ return(1);
+}
+
+
+
+/*
+ * Get somebody's public key
+ */
+getpublickey(netname, publickey)
+ char *netname;
+ char *publickey;
+{
+ char *domain;
+ int len;
+ char *lookup;
+ int err;
+ char *p;
+
+ err = yp_get_default_domain(&domain);
+ if (err) {
+ return(0);
+ }
+ err = yp_match(domain, PKMAP, netname, strlen(netname), &lookup, &len);
+ if (err) {
+ return(0);
+ }
+ p = index(lookup, ':');
+ if (p == NULL) {
+ free(lookup);
+ return(0);
+ }
+ *p = 0;
+ (void) strcpy(publickey, lookup);
+ return(1);
+}
diff --git a/lib/librpc/secure_rpc/rpc/rtime.c b/lib/librpc/secure_rpc/rpc/rtime.c
new file mode 100644
index 0000000..725995c
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/rtime.c
@@ -0,0 +1,141 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI";
+#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) 1988 by Sun Microsystems, Inc.
+
+ */
+
+/*
+ * rtime - get time from remote machine
+ *
+ * gets time, obtaining value from host
+ * on the udp/time socket. Since timeserver returns
+ * with time of day in seconds since Jan 1, 1900, must
+ * subtract seconds before Jan 1, 1970 to get
+ * what unix uses.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <netinet/in.h>
+#include <stdio.h>
+
+#define NYEARS (1970 - 1900)
+#define TOFFSET (60*60*24*(365*NYEARS + (NYEARS/4)))
+extern errno;
+
+static void do_close();
+
+rtime(addrp, timep, timeout)
+ struct sockaddr_in *addrp;
+ struct timeval *timep;
+ struct timeval *timeout;
+{
+ int s;
+ fd_set readfds;
+ int res;
+ unsigned long thetime;
+ struct sockaddr_in from;
+ int fromlen;
+ int type;
+
+ if (timeout == NULL) {
+ type = SOCK_STREAM;
+ } else {
+ type = SOCK_DGRAM;
+ }
+ s = socket(AF_INET, type, 0);
+ if (s < 0) {
+ return(-1);
+ }
+ addrp->sin_family = AF_INET;
+ addrp->sin_port = htons(IPPORT_TIMESERVER);
+ if (type == SOCK_DGRAM) {
+ res = sendto(s, (char *)&thetime, sizeof(thetime), 0,
+ (struct sockaddr *)addrp, sizeof(*addrp));
+ if (res < 0) {
+ do_close(s);
+ return(-1);
+ }
+ do {
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+ res = select(_rpc_dtablesize(), &readfds, (int *)NULL,
+ (int *)NULL, timeout);
+ } while (res < 0 && errno == EINTR);
+ if (res <= 0) {
+ if (res == 0) {
+ errno = ETIMEDOUT;
+ }
+ do_close(s);
+ return(-1);
+ }
+ fromlen = sizeof(from);
+ res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
+ (struct sockaddr *)&from, &fromlen);
+ do_close(s);
+ if (res < 0) {
+ return(-1);
+ }
+ } else {
+ if (connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) {
+ do_close(s);
+ return(-1);
+ }
+ res = read(s, (char *)&thetime, sizeof(thetime));
+ do_close(s);
+ if (res < 0) {
+ return(-1);
+ }
+ }
+ if (res != sizeof(thetime)) {
+ errno = EIO;
+ return(-1);
+ }
+ thetime = ntohl(thetime);
+ timep->tv_sec = thetime - TOFFSET;
+ timep->tv_usec = 0;
+ return(0);
+}
+
+static void
+do_close(s)
+ int s;
+{
+ int save;
+
+ save = errno;
+ (void) close(s);
+ errno = save;
+}
diff --git a/lib/librpc/secure_rpc/rpc/svc_auth.c b/lib/librpc/secure_rpc/rpc/svc_auth.c
new file mode 100644
index 0000000..7ad47ca
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/svc_auth.c
@@ -0,0 +1,116 @@
+/* @(#)svc_auth.c 2.4 88/08/15 4.0 RPCSRC */
+/*
+ * 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
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_auth.c, Server-side rpc authenticator interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+
+/*
+ * svcauthsw is the bdevsw of server side authentication.
+ *
+ * Server side authenticators are called from authenticate by
+ * using the client auth struct flavor field to index into svcauthsw.
+ * The server auth flavors must implement a routine that looks
+ * like:
+ *
+ * enum auth_stat
+ * flavorx_auth(rqst, msg)
+ * register struct svc_req *rqst;
+ * register struct rpc_msg *msg;
+ *
+ */
+
+enum auth_stat _svcauth_null(); /* no authentication */
+enum auth_stat _svcauth_unix(); /* unix style (uid, gids) */
+enum auth_stat _svcauth_short(); /* short hand unix style */
+enum auth_stat _svcauth_des(); /* des style */
+
+static struct {
+ enum auth_stat (*authenticator)();
+} svcauthsw[] = {
+ _svcauth_null, /* AUTH_NULL */
+ _svcauth_unix, /* AUTH_UNIX */
+ _svcauth_short, /* AUTH_SHORT */
+ _svcauth_des /* AUTH_DES */
+};
+#define AUTH_MAX 3 /* HIGHEST AUTH NUMBER */
+
+
+/*
+ * The call rpc message, msg has been obtained from the wire. The msg contains
+ * the raw form of credentials and verifiers. authenticate returns AUTH_OK
+ * if the msg is successfully authenticated. If AUTH_OK then the routine also
+ * does the following things:
+ * set rqst->rq_xprt->verf to the appropriate response verifier;
+ * sets rqst->rq_client_cred to the "cooked" form of the credentials.
+ *
+ * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
+ * its length is set appropriately.
+ *
+ * The caller still owns and is responsible for msg->u.cmb.cred and
+ * msg->u.cmb.verf. The authentication system retains ownership of
+ * rqst->rq_client_cred, the cooked credentials.
+ *
+ * There is an assumption that any flavour less than AUTH_NULL is
+ * invalid.
+ */
+enum auth_stat
+_authenticate(rqst, msg)
+ register struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ register int cred_flavor;
+
+ rqst->rq_cred = msg->rm_call.cb_cred;
+ rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
+ rqst->rq_xprt->xp_verf.oa_length = 0;
+ cred_flavor = rqst->rq_cred.oa_flavor;
+ if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) {
+ return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg));
+ }
+
+ return (AUTH_REJECTEDCRED);
+}
+
+enum auth_stat
+_svcauth_null(/*rqst, msg*/)
+ /*struct svc_req *rqst;
+ struct rpc_msg *msg;*/
+{
+
+ return (AUTH_OK);
+}
diff --git a/lib/librpc/secure_rpc/rpc/svcauth_des.c b/lib/librpc/secure_rpc/rpc/svcauth_des.c
new file mode 100644
index 0000000..0129bef
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/svcauth_des.c
@@ -0,0 +1,519 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)svcauth_des.c 2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI";
+#endif
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * 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
+ */
+
+/*
+ * svcauth_des.c, server-side des authentication
+ *
+ * We insure for the service the following:
+ * (1) The timestamp microseconds do not exceed 1 million.
+ * (2) The timestamp plus the window is less than the current time.
+ * (3) The timestamp is not less than the one previously
+ * seen in the current session.
+ *
+ * It is up to the server to determine if the window size is
+ * too small .
+ *
+ */
+
+#include <des_crypt.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <rpc/svc_auth.h>
+#include <rpc/svc.h>
+#include <rpc/rpc_msg.h>
+
+
+#define debug(msg) /*printf("svcauth_des: %s\n", msg)*/
+
+extern char *strcpy();
+
+#define USEC_PER_SEC ((u_long) 1000000L)
+#define BEFORE(t1, t2) timercmp(t1, t2, <)
+
+/*
+ * LRU cache of conversation keys and some other useful items.
+ */
+#define AUTHDES_CACHESZ 64
+struct cache_entry {
+ des_block key; /* conversation key */
+ char *rname; /* client's name */
+ u_int window; /* credential lifetime window */
+ struct timeval laststamp; /* detect replays of creds */
+ char *localcred; /* generic local credential */
+};
+static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */;
+static short *authdes_lru/* [AUTHDES_CACHESZ] */;
+
+static void cache_init(); /* initialize the cache */
+static short cache_spot(); /* find an entry in the cache */
+static void cache_ref(/*short sid*/); /* note that sid was ref'd */
+
+static void invalidate(); /* invalidate entry in cache */
+
+/*
+ * cache statistics
+ */
+struct {
+ u_long ncachehits; /* times cache hit, and is not replay */
+ u_long ncachereplays; /* times cache hit, and is replay */
+ u_long ncachemisses; /* times cache missed */
+} svcauthdes_stats;
+
+/*
+ * Service side authenticator for AUTH_DES
+ */
+enum auth_stat
+_svcauth_des(rqst, msg)
+ register struct svc_req *rqst;
+ register struct rpc_msg *msg;
+{
+
+ register long *ixdr;
+ des_block cryptbuf[2];
+ register struct authdes_cred *cred;
+ struct authdes_verf verf;
+ int status;
+ register struct cache_entry *entry;
+ short sid;
+ des_block *sessionkey;
+ des_block ivec;
+ u_int window;
+ struct timeval timestamp;
+ u_long namelen;
+ struct area {
+ struct authdes_cred area_cred;
+ char area_netname[MAXNETNAMELEN+1];
+ } *area;
+
+ if (authdes_cache == NULL) {
+ cache_init();
+ }
+
+ area = (struct area *)rqst->rq_clntcred;
+ cred = (struct authdes_cred *)&area->area_cred;
+
+ /*
+ * Get the credential
+ */
+ ixdr = (long *)msg->rm_call.cb_cred.oa_base;
+ cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind);
+ switch (cred->adc_namekind) {
+ case ADN_FULLNAME:
+ namelen = IXDR_GET_U_LONG(ixdr);
+ if (namelen > MAXNETNAMELEN) {
+ return (AUTH_BADCRED);
+ }
+ cred->adc_fullname.name = area->area_netname;
+ bcopy((char *)ixdr, cred->adc_fullname.name,
+ (u_int)namelen);
+ cred->adc_fullname.name[namelen] = 0;
+ ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT);
+ cred->adc_fullname.key.key.high = (u_long)*ixdr++;
+ cred->adc_fullname.key.key.low = (u_long)*ixdr++;
+ cred->adc_fullname.window = (u_long)*ixdr++;
+ break;
+ case ADN_NICKNAME:
+ cred->adc_nickname = (u_long)*ixdr++;
+ break;
+ default:
+ return (AUTH_BADCRED);
+ }
+
+ /*
+ * Get the verifier
+ */
+ ixdr = (long *)msg->rm_call.cb_verf.oa_base;
+ verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
+ verf.adv_xtimestamp.key.low = (u_long)*ixdr++;
+ verf.adv_int_u = (u_long)*ixdr++;
+
+
+ /*
+ * Get the conversation key
+ */
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ sessionkey = &cred->adc_fullname.key;
+ if (key_decryptsession(cred->adc_fullname.name,
+ sessionkey) < 0) {
+ debug("decryptsessionkey");
+ return (AUTH_BADCRED); /* key not found */
+ }
+ } else { /* ADN_NICKNAME */
+ sid = (short)cred->adc_nickname;
+ if (sid >= AUTHDES_CACHESZ) {
+ debug("bad nickname");
+ return (AUTH_BADCRED); /* garbled credential */
+ }
+ sessionkey = &authdes_cache[sid].key;
+ }
+
+
+ /*
+ * Decrypt the timestamp
+ */
+ cryptbuf[0] = verf.adv_xtimestamp;
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ cryptbuf[1].key.high = cred->adc_fullname.window;
+ cryptbuf[1].key.low = verf.adv_winverf;
+ ivec.key.high = ivec.key.low = 0;
+ status = cbc_crypt((char *)sessionkey, (char *)cryptbuf,
+ 2*sizeof(des_block), DES_DECRYPT | DES_HW,
+ (char *)&ivec);
+ } else {
+ status = ecb_crypt((char *)sessionkey, (char *)cryptbuf,
+ sizeof(des_block), DES_DECRYPT | DES_HW);
+ }
+ if (DES_FAILED(status)) {
+ debug("decryption failure");
+ return (AUTH_FAILED); /* system error */
+ }
+
+ /*
+ * XDR the decrypted timestamp
+ */
+ ixdr = (long *)cryptbuf;
+ timestamp.tv_sec = IXDR_GET_LONG(ixdr);
+ timestamp.tv_usec = IXDR_GET_LONG(ixdr);
+
+ /*
+ * Check for valid credentials and verifiers.
+ * They could be invalid because the key was flushed
+ * out of the cache, and so a new session should begin.
+ * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case.
+ */
+ {
+ struct timeval current;
+ int nick;
+ int winverf;
+
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ window = IXDR_GET_U_LONG(ixdr);
+ winverf = IXDR_GET_U_LONG(ixdr);
+ if (winverf != window - 1) {
+ debug("window verifier mismatch");
+ return (AUTH_BADCRED); /* garbled credential */
+ }
+ sid = cache_spot(sessionkey, cred->adc_fullname.name,
+ &timestamp);
+ if (sid < 0) {
+ debug("replayed credential");
+ return (AUTH_REJECTEDCRED); /* replay */
+ }
+ nick = 0;
+ } else { /* ADN_NICKNAME */
+ window = authdes_cache[sid].window;
+ nick = 1;
+ }
+
+ if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) {
+ debug("invalid usecs");
+ /* cached out (bad key), or garbled verifier */
+ return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF);
+ }
+ if (nick && BEFORE(&timestamp,
+ &authdes_cache[sid].laststamp)) {
+ debug("timestamp before last seen");
+ return (AUTH_REJECTEDVERF); /* replay */
+ }
+ (void) gettimeofday(&current, (struct timezone *)NULL);
+ current.tv_sec -= window; /* allow for expiration */
+ if (!BEFORE(&current, &timestamp)) {
+ debug("timestamp expired");
+ /* replay, or garbled credential */
+ return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED);
+ }
+ }
+
+ /*
+ * Set up the reply verifier
+ */
+ verf.adv_nickname = (u_long)sid;
+
+ /*
+ * xdr the timestamp before encrypting
+ */
+ ixdr = (long *)cryptbuf;
+ IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1);
+ IXDR_PUT_LONG(ixdr, timestamp.tv_usec);
+
+ /*
+ * encrypt the timestamp
+ */
+ status = ecb_crypt((char *)sessionkey, (char *)cryptbuf,
+ sizeof(des_block), DES_ENCRYPT | DES_HW);
+ if (DES_FAILED(status)) {
+ debug("encryption failure");
+ return (AUTH_FAILED); /* system error */
+ }
+ verf.adv_xtimestamp = cryptbuf[0];
+
+ /*
+ * Serialize the reply verifier, and update rqst
+ */
+ ixdr = (long *)msg->rm_call.cb_verf.oa_base;
+ *ixdr++ = (long)verf.adv_xtimestamp.key.high;
+ *ixdr++ = (long)verf.adv_xtimestamp.key.low;
+ *ixdr++ = (long)verf.adv_int_u;
+
+ rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES;
+ rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base;
+ rqst->rq_xprt->xp_verf.oa_length =
+ (char *)ixdr - msg->rm_call.cb_verf.oa_base;
+
+ /*
+ * We succeeded, commit the data to the cache now and
+ * finish cooking the credential.
+ */
+ entry = &authdes_cache[sid];
+ entry->laststamp = timestamp;
+ cache_ref(sid);
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ cred->adc_fullname.window = window;
+ cred->adc_nickname = (u_long)sid; /* save nickname */
+ if (entry->rname != NULL) {
+ mem_free(entry->rname, strlen(entry->rname) + 1);
+ }
+ entry->rname = mem_alloc((u_int)strlen(cred->adc_fullname.name)
+ + 1);
+ if (entry->rname != NULL) {
+ (void) strcpy(entry->rname, cred->adc_fullname.name);
+ } else {
+ debug("out of memory");
+ }
+ entry->key = *sessionkey;
+ entry->window = window;
+ invalidate(entry->localcred); /* mark any cached cred invalid */
+ } else { /* ADN_NICKNAME */
+ /*
+ * nicknames are cooked into fullnames
+ */
+ cred->adc_namekind = ADN_FULLNAME;
+ cred->adc_fullname.name = entry->rname;
+ cred->adc_fullname.key = entry->key;
+ cred->adc_fullname.window = entry->window;
+ }
+ return (AUTH_OK); /* we made it!*/
+}
+
+
+/*
+ * Initialize the cache
+ */
+static void
+cache_init()
+{
+ register int i;
+
+ authdes_cache = (struct cache_entry *)
+ mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ);
+ bzero((char *)authdes_cache,
+ sizeof(struct cache_entry) * AUTHDES_CACHESZ);
+
+ authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ);
+ /*
+ * Initialize the lru list
+ */
+ for (i = 0; i < AUTHDES_CACHESZ; i++) {
+ authdes_lru[i] = i;
+ }
+}
+
+
+/*
+ * Find the lru victim
+ */
+static short
+cache_victim()
+{
+ return (authdes_lru[AUTHDES_CACHESZ-1]);
+}
+
+/*
+ * Note that sid was referenced
+ */
+static void
+cache_ref(sid)
+ register short sid;
+{
+ register int i;
+ register short curr;
+ register short prev;
+
+ prev = authdes_lru[0];
+ authdes_lru[0] = sid;
+ for (i = 1; prev != sid; i++) {
+ curr = authdes_lru[i];
+ authdes_lru[i] = prev;
+ prev = curr;
+ }
+}
+
+
+/*
+ * Find a spot in the cache for a credential containing
+ * the items given. Return -1 if a replay is detected, otherwise
+ * return the spot in the cache.
+ */
+static short
+cache_spot(key, name, timestamp)
+ register des_block *key;
+ char *name;
+ struct timeval *timestamp;
+{
+ register struct cache_entry *cp;
+ register int i;
+ register u_long hi;
+
+ hi = key->key.high;
+ for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) {
+ if (cp->key.key.high == hi &&
+ cp->key.key.low == key->key.low &&
+ cp->rname != NULL &&
+ bcmp(cp->rname, name, strlen(name) + 1) == 0) {
+ if (BEFORE(timestamp, &cp->laststamp)) {
+ svcauthdes_stats.ncachereplays++;
+ return (-1); /* replay */
+ }
+ svcauthdes_stats.ncachehits++;
+ return (i); /* refresh */
+ }
+ }
+ svcauthdes_stats.ncachemisses++;
+ return (cache_victim()); /* new credential */
+}
+
+
+#if (defined(sun) || defined(vax))
+/*
+ * Local credential handling stuff.
+ * NOTE: bsd unix dependent.
+ * Other operating systems should put something else here.
+ */
+#define UNKNOWN -2 /* grouplen, if cached cred is unknown user */
+#define INVALID -1 /* grouplen, if cache entry is invalid */
+
+struct bsdcred {
+ short uid; /* cached uid */
+ short gid; /* cached gid */
+ short grouplen; /* length of cached groups */
+ short groups[NGROUPS]; /* cached groups */
+};
+
+/*
+ * Map a des credential into a unix cred.
+ * We cache the credential here so the application does
+ * not have to make an rpc call every time to interpret
+ * the credential.
+ */
+authdes_getucred(adc, uid, gid, grouplen, groups)
+ struct authdes_cred *adc;
+ short *uid;
+ short *gid;
+ short *grouplen;
+ register int *groups;
+{
+ unsigned sid;
+ register int i;
+ int i_uid;
+ int i_gid;
+ int i_grouplen;
+ struct bsdcred *cred;
+
+ sid = adc->adc_nickname;
+ if (sid >= AUTHDES_CACHESZ) {
+ debug("invalid nickname");
+ return (0);
+ }
+ cred = (struct bsdcred *)authdes_cache[sid].localcred;
+ if (cred == NULL) {
+ cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred));
+ authdes_cache[sid].localcred = (char *)cred;
+ cred->grouplen = INVALID;
+ }
+ if (cred->grouplen == INVALID) {
+ /*
+ * not in cache: lookup
+ */
+ if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid,
+ &i_grouplen, groups))
+ {
+ debug("unknown netname");
+ cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */
+ return (0);
+ }
+ debug("missed ucred cache");
+ *uid = cred->uid = i_uid;
+ *gid = cred->gid = i_gid;
+ *grouplen = cred->grouplen = i_grouplen;
+ for (i = i_grouplen - 1; i >= 0; i--) {
+ cred->groups[i] = groups[i]; /* int to short */
+ }
+ return (1);
+ } else if (cred->grouplen == UNKNOWN) {
+ /*
+ * Already lookup up, but no match found
+ */
+ return (0);
+ }
+
+ /*
+ * cached credentials
+ */
+ *uid = cred->uid;
+ *gid = cred->gid;
+ *grouplen = cred->grouplen;
+ for (i = cred->grouplen - 1; i >= 0; i--) {
+ groups[i] = cred->groups[i]; /* short to int */
+ }
+ return (1);
+}
+
+static void
+invalidate(cred)
+ char *cred;
+{
+ if (cred == NULL) {
+ return;
+ }
+ ((struct bsdcred *)cred)->grouplen = INVALID;
+}
+#endif
+
diff --git a/lib/librpc/secure_rpc/rpc/xcrypt.c b/lib/librpc/secure_rpc/rpc/xcrypt.c
new file mode 100644
index 0000000..215fda6
--- /dev/null
+++ b/lib/librpc/secure_rpc/rpc/xcrypt.c
@@ -0,0 +1,183 @@
+#ifndef lint
+static char sccsid[] = "@(#)xcrypt.c 2.2 88/08/10 4.0 RPCSRC";
+#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
+ */
+/*
+ * Hex encryption/decryption and utility routines
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <des_crypt.h>
+
+extern char *malloc();
+
+extern char hex[]; /* forward */
+static char hexval();
+
+/*
+ * Encrypt a secret key given passwd
+ * The secret key is passed and returned in hex notation.
+ * Its length must be a multiple of 16 hex digits (64 bits).
+ */
+xencrypt(secret, passwd)
+ char *secret;
+ char *passwd;
+{
+ char key[8];
+ char ivec[8];
+ char *buf;
+ int err;
+ int len;
+
+ len = strlen(secret) / 2;
+ buf = malloc((unsigned)len);
+
+ hex2bin(len, secret, buf);
+ passwd2des(passwd, key);
+ bzero(ivec, 8);
+
+ err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec);
+ if (DES_FAILED(err)) {
+ free(buf);
+ return (0);
+ }
+ bin2hex(len, (unsigned char *) buf, secret);
+ free(buf);
+ return (1);
+}
+
+/*
+ * Decrypt secret key using passwd
+ * The secret key is passed and returned in hex notation.
+ * Once again, the length is a multiple of 16 hex digits
+ */
+xdecrypt(secret, passwd)
+ char *secret;
+ char *passwd;
+{
+ char key[8];
+ char ivec[8];
+ char *buf;
+ int err;
+ int len;
+
+ len = strlen(secret) / 2;
+ buf = malloc((unsigned)len);
+
+ hex2bin(len, secret, buf);
+ passwd2des(passwd, key);
+ bzero(ivec, 8);
+
+ err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec);
+ if (DES_FAILED(err)) {
+ free(buf);
+ return (0);
+ }
+ bin2hex(len, (unsigned char *) buf, secret);
+ free(buf);
+ return (1);
+}
+
+
+/*
+ * Turn password into DES key
+ */
+passwd2des(pw, key)
+ char *pw;
+ char *key;
+{
+ int i;
+
+ bzero(key, 8);
+ for (i = 0; *pw; i = (i+1)%8) {
+ key[i] ^= *pw++ << 1;
+ }
+ des_setparity(key);
+}
+
+
+
+/*
+ * Hex to binary conversion
+ */
+static
+hex2bin(len, hexnum, binnum)
+ int len;
+ char *hexnum;
+ char *binnum;
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ *binnum++ = 16 * hexval(hexnum[2*i]) + hexval(hexnum[2*i+1]);
+ }
+}
+
+/*
+ * Binary to hex conversion
+ */
+static
+bin2hex(len, binnum, hexnum)
+ int len;
+ unsigned char *binnum;
+ char *hexnum;
+{
+ int i;
+ unsigned val;
+
+ for (i = 0; i < len; i++) {
+ val = binnum[i];
+ hexnum[i*2] = hex[val >> 4];
+ hexnum[i*2+1] = hex[val & 0xf];
+ }
+ hexnum[len*2] = 0;
+}
+
+static char hex[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
+};
+
+static char
+hexval(c)
+ char c;
+{
+ if (c >= '0' && c <= '9') {
+ return (c - '0');
+ } else if (c >= 'a' && c <= 'z') {
+ return (c - 'a' + 10);
+ } else if (c >= 'A' && c <= 'Z') {
+ return (c - 'A' + 10);
+ } else {
+ return (-1);
+ }
+}
OpenPOWER on IntegriCloud