about summary refs log tree commit diff
path: root/sunrpc
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-08-29 21:01:47 +0000
committerUlrich Drepper <drepper@redhat.com>1997-08-29 21:01:47 +0000
commit800d775e426b9c0af63f711b79b09bf540c97456 (patch)
treeff7858571c81f2e6077c5e35b465494052984876 /sunrpc
parent39e16978c3b4ac8eaf2201fac56316623910d9da (diff)
downloadglibc-800d775e426b9c0af63f711b79b09bf540c97456.tar.gz
glibc-800d775e426b9c0af63f711b79b09bf540c97456.tar.xz
glibc-800d775e426b9c0af63f711b79b09bf540c97456.zip
1997-08-29 21:45  Ulrich Drepper  <drepper@cygnus.com>

	* sunrpc/auth_des.c: New file.  Copied from former secure_rpc add-on.
	* sunrpc/authdes_prot.c: New file.  Likewise.
	* sunrpc/des.h: New file.  Likewise.
	* sunrpc/des_crypt.c: New file.  Likewise.
	* sunrpc/des_soft.c: New file.  Likewise.
	* sunrpc/key_call.c: New file.  Likewise.
	* sunrpc/key_prot.c: New file.  Likewise.
	* sunrpc/netname.c: New file.  Likewise.
	* sunrpc/openchild.c: New file.  Likewise.
	* sunrpc/rtime.c: New file.  Likewise.
	* sunrpc/svc_auth.c: New file.  Likewise.
	* sunrpc/svcauth_des.c: New file.  Likewise.
	* sunrpc/xcrypt.c: New file.  Likewise.
	* sunrpc/rpc/auth.h: New file.  Likewise.
	* sunrpc/rpc/auth_des.h: New file.  Likewise.
	* sunrpc/rpc/des_crypt.h: New file.  Likewise.
	* sunrpc/rpc/key_prot.h: New file.  Likewise.
	* sunrpc/rpcsvc/key_prot.x: New file.  Likewise.
	* sysdeps/generic/svc_auth.h: Removed.
	* sysdeps/generic/rpc/auth.h: Removed.
	* sysdeps/generic/rpc/auth_des.h: Removed.
	* sysdeps/stub/des_impl.c: New file.  Stub version for DES.
	* sunrpc/Makefile (rpcsvc): Add keyprot.x.
	(headers): Add des_crypt.h and key_prot.h.
	(routines): Add auth_des, authdes_prot, des_crypt, des_impl, des_soft,
	key_call, key_prot, netname, openchild, rtime, svcauth_des, xcrypt.
	(distribute): Add des.h.

	* db2/Makefile: Add all headers and other files to distribute.
	(others): Add db_printlog.

	* sysdeps/mach/hurd/Dist: Add net/* headers.
	* sysdeps/mach/hurd/mips/Dist: New file.
	* sysdeps/powerpc/Dist: Add fe_nomask.c and t_sqrt.c.
	* sysdeps/sparc/Dist: Add sys/trap.h.
	* sysdeps/sparc/sparc32/Dist: Remove sys/trap.h.
	* sysdeps/sparc/sparc32/sparcv8/Dist: New file.
	* sysdeps/unix/sysv/linux/mips/Dist: Add sgidefs.h.
	* sysdeps/unix/sysv/linux/sparc/Dist: Add sys/trap.h.
	* sysdeps/unix/sysv/linux/sparc/sparc32/Dist: Remove sys/trap.h.

	Add previously missing assembler files for PPC.
	* sysdeps/powerpc/add_n.s: New file.
	* sysdeps/powerpc/addmul_1.s: New file.
	* sysdeps/powerpc/lshift.s: New file.
	* sysdeps/powerpc/memset.s: New file.
	* sysdeps/powerpc/mul_1.s: New file.
	* sysdeps/powerpc/rshift.s: New file.
	* sysdeps/powerpc/strchr.s: New file.
	* sysdeps/powerpc/strcmp.s: New file.
	* sysdeps/powerpc/sub_n.s: New file.
	* sysdeps/powerpc/submul_1.s: New file.

1997-08-28 18:42  Thorsten Kukuk  <kukuk@uni-paderborn.de>

	* nis/nis_server.c: Rewritten to fix a lot of bugs.

1997-08-28  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* md5-crypt/Makefile (LDFLAGS-md5crypt.so, libmd5crypt-map): New
	variables.

	in NLSPATH environment variable.  Patch by HJ Lu <hjl@gnu.ai.mit.edu>.
Diffstat (limited to 'sunrpc')
-rw-r--r--sunrpc/Makefile11
-rw-r--r--sunrpc/auth_des.c459
-rw-r--r--sunrpc/authdes_prot.c81
-rw-r--r--sunrpc/des.h83
-rw-r--r--sunrpc/des_crypt.c120
-rw-r--r--sunrpc/des_soft.c68
-rw-r--r--sunrpc/key_call.c363
-rw-r--r--sunrpc/key_prot.c161
-rw-r--r--sunrpc/netname.c201
-rw-r--r--sunrpc/openchild.c112
-rw-r--r--sunrpc/rpc/auth.h210
-rw-r--r--sunrpc/rpc/auth_des.h104
-rw-r--r--sunrpc/rpc/des_crypt.h97
-rw-r--r--sunrpc/rpc/key_prot.h345
-rw-r--r--sunrpc/rpcsvc/key_prot.x284
-rw-r--r--sunrpc/rtime.c146
-rw-r--r--sunrpc/svc_auth.c119
-rw-r--r--sunrpc/svcauth_des.c548
-rw-r--r--sunrpc/xcrypt.c180
19 files changed, 3688 insertions, 4 deletions
diff --git a/sunrpc/Makefile b/sunrpc/Makefile
index b7c86d4f84..baee72e85b 100644
--- a/sunrpc/Makefile
+++ b/sunrpc/Makefile
@@ -47,10 +47,11 @@ subdir	:= sunrpc
 
 rpcsvc = bootparam.x nlm_prot.x rstat.x \
 	 yppasswd.x klm_prot.x rex.x sm_inter.x mount.x \
-	 rusers.x spray.x nfs_prot.x rquota.x
+	 rusers.x spray.x nfs_prot.x rquota.x key_prot.x
 headers = $(addprefix rpc/,auth.h auth_unix.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 auth_des.h) \
+			   svc_auth.h types.h xdr.h auth_des.h \
+			   des_crypt.h key_prot.h) \
 	  $(rpcsvc:%=rpcsvc/%)
 install-others = $(inst_sysconfdir)/rpc
 generated = $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) \
@@ -64,7 +65,9 @@ routines := auth_none auth_unix authuxprot bindrsvprt \
 	    pmap_prot2 pmap_rmt rpc_prot rpc_common rpc_cmsg \
 	    svc svc_auth svc_authux svc_raw svc_run svc_simple \
 	    svc_tcp svc_udp xdr xdr_array xdr_float xdr_mem \
-	    xdr_rec xdr_ref xdr_stdio publickey xdr_sizeof
+	    xdr_rec xdr_ref xdr_stdio publickey xdr_sizeof \
+	    auth_des authdes_prot des_crypt des_impl des_soft \
+	    key_call key_prot netname openchild rtime svcauth_des xcrypt
 
 others := rpcinfo
 install-bin := rpcgen
@@ -73,7 +76,7 @@ rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \
 	      rpc_scan.o rpc_util.o rpc_svcout.o rpc_clntout.o \
 	      rpc_tblout.o rpc_sample.o
 # These headers are part of rpcgen.
-distribute := proto.h rpc_util.h rpc_parse.h rpc_scan.h \
+distribute := proto.h rpc_util.h rpc_parse.h rpc_scan.h des.h \
 	      $(rpcgen-objs:.o=.c) etc.rpc
 extra-objs = $(rpcgen-objs)
 
diff --git a/sunrpc/auth_des.c b/sunrpc/auth_des.c
new file mode 100644
index 0000000000..4ea6391c6e
--- /dev/null
+++ b/sunrpc/auth_des.c
@@ -0,0 +1,459 @@
+#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 <string.h>
+#include <rpc/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) */
+
+extern int rtime (struct sockaddr_in *, struct timeval *, struct timeval *);
+extern bool_t xdr_authdes_cred (XDR *, struct authdes_cred *);
+extern bool_t xdr_authdes_verf (XDR *, struct authdes_verf *);
+
+/*
+ * DES authenticator operations vector
+ */
+AUTH *authdes_create (const char *, u_int, struct sockaddr *,
+		      des_block *);
+AUTH *authdes_pk_create (const char *, netobj *, u_int,
+			 struct sockaddr *, des_block *);
+static void authdes_nextverf (AUTH *);
+static bool_t authdes_marshal (AUTH *, XDR *);
+static bool_t authdes_validate (AUTH *, struct opaque_auth *);
+static bool_t authdes_refresh (AUTH *);
+static void authdes_destroy (AUTH *);
+static bool_t synchronize (struct sockaddr *, struct timeval *);
+
+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 */
+    u_char ad_pkey[1024];	/* Servers actual public key */
+  };
+
+
+/*
+ * Create the client des authentication object
+ */
+AUTH *
+authdes_create (const char *servername, u_int window, 
+		struct sockaddr *syncaddr, des_block * ckey)
+  /* servername - network name of server */
+  /* window     - time to live */
+  /* syncaddr   - optional addr of host to sync with */
+  /* ckey       - optional conversation key to use */
+{
+  u_char pkey_data[1024];
+  netobj pkey;
+
+  if (!getpublickey (servername, pkey_data))
+    return (NULL);
+
+  pkey.n_bytes = (char *) pkey_data;
+  pkey.n_len = strlen ((char *) pkey_data) + 1;
+  return authdes_pk_create (servername, &pkey, window, syncaddr, ckey);
+}
+
+AUTH *
+authdes_pk_create (const char *servername, netobj * pkey, u_int window,
+		   struct sockaddr * syncaddr, des_block * ckey)
+{
+  AUTH *auth;
+  struct ad_private *ad;
+  char namebuf[MAXNETNAMELEN + 1];
+
+  /*
+   * Allocate everything now
+   */
+  auth = ALLOC (AUTH);
+  ad = ALLOC (struct ad_private);
+  memcpy (ad->ad_pkey, pkey->n_bytes, pkey->n_len);
+  if (!getnetname (namebuf))
+    goto failed;
+  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)
+{
+  /* what the heck am I supposed to do??? */
+}
+
+
+
+/*
+ * 2. Marshal
+ */
+static bool_t
+authdes_marshal (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.
+   */
+  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)) != NULL)
+    {
+      IXDR_PUT_LONG (ixdr, AUTH_DES);
+      IXDR_PUT_LONG (ixdr, len);
+    }
+  else
+    {
+      ATTEMPT (xdr_putlong (xdrs, (long *)&auth->ah_cred.oa_flavor));
+      ATTEMPT (xdr_putlong (xdrs, (long *)&len));
+    }
+  ATTEMPT (xdr_authdes_cred (xdrs, cred));
+
+  len = (2 + 1) * BYTES_PER_XDR_UNIT;
+  if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL)
+    {
+      IXDR_PUT_LONG (ixdr, AUTH_DES);
+      IXDR_PUT_LONG (ixdr, len);
+    }
+  else
+    {
+      ATTEMPT (xdr_putlong (xdrs, (long *)&auth->ah_verf.oa_flavor));
+      ATTEMPT (xdr_putlong (xdrs, (long *)&len));
+    }
+  ATTEMPT (xdr_authdes_verf (xdrs, verf));
+  return (TRUE);
+}
+
+
+/*
+ * 3. Validate
+ */
+static bool_t
+authdes_validate (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)
+{
+  netobj pkey;
+  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;
+  pkey.n_bytes = (char *) (ad->ad_pkey);
+  pkey.n_len = strlen ((char *) ad->ad_pkey) + 1;
+  if (key_encryptsession_pk (ad->ad_servername, &pkey, &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)
+{
+  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 (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);
+
+  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/sunrpc/authdes_prot.c b/sunrpc/authdes_prot.c
new file mode 100644
index 0000000000..3c6eacced6
--- /dev/null
+++ b/sunrpc/authdes_prot.c
@@ -0,0 +1,81 @@
+#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 (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 (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/sunrpc/des.h b/sunrpc/des.h
new file mode 100644
index 0000000000..68bd7c47ab
--- /dev/null
+++ b/sunrpc/des.h
@@ -0,0 +1,83 @@
+/*  @(#)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.
+ */
+
+#ifndef _DES_H
+#define _DES_H
+
+#include <sys/types.h>
+
+#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)
+
+#endif
diff --git a/sunrpc/des_crypt.c b/sunrpc/des_crypt.c
new file mode 100644
index 0000000000..7a4bc5d6cf
--- /dev/null
+++ b/sunrpc/des_crypt.c
@@ -0,0 +1,120 @@
+/*
+ * 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(SCCSID)
+static char sccsid[] = "@(#)des_crypt.c	2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#endif
+/*
+ * des_crypt.c, DES encryption library routines
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+#include "des.h"
+
+extern int _des_crypt (char *, unsigned, struct desparams *);
+
+/*
+ * 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++; \
+	} \
+}
+
+/*
+ * Common code to cbc_crypt() & ecb_crypt()
+ */
+static int
+common_crypt (char *key, char *buf, register unsigned len,
+	      unsigned mode, register struct desparams *desp)
+{
+  register int desdev;
+
+  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;
+}
+
+/*
+ * CBC mode encryption
+ */
+int
+cbc_crypt (char *key, char *buf, unsigned int len, unsigned int 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
+ */
+int
+ecb_crypt (char *key, char *buf, unsigned int len, unsigned int mode)
+{
+  struct desparams dp;
+
+  dp.des_mode = ECB;
+  return common_crypt (key, buf, len, mode, &dp);
+}
diff --git a/sunrpc/des_soft.c b/sunrpc/des_soft.c
new file mode 100644
index 0000000000..ae12d7b0a6
--- /dev/null
+++ b/sunrpc/des_soft.c
@@ -0,0 +1,68 @@
+#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 (char *p)
+{
+  int i;
+
+  for (i = 0; i < 8; i++)
+    {
+      *p = partab[*p & 0x7f];
+      p++;
+    }
+}
diff --git a/sunrpc/key_call.c b/sunrpc/key_call.c
new file mode 100644
index 0000000000..ba1c2638fb
--- /dev/null
+++ b/sunrpc/key_call.c
@@ -0,0 +1,363 @@
+/*
+ * 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
+ */
+
+/*
+ * The original source is from the RPCSRC 4.0 package from Sun Microsystems.
+ * The Interface to keyserver protocoll 2 was added by 
+ * Thorsten Kukuk <kukuk@vt.uni-paderborn.de>
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/auth.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/socket.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 */
+
+extern int _openchild (char *command, FILE ** fto, FILE ** ffrom);
+
+
+static int key_call (u_long, xdrproc_t xdr_arg, char *,
+		     xdrproc_t xdr_rslt, char *);
+
+static struct timeval trytimeout = {KEY_TIMEOUT, 0};
+static struct timeval tottimeout = {KEY_TIMEOUT * KEY_NRETRY, 0};
+
+int
+key_setsecret (char *secretkey)
+{
+  keystatus status;
+
+  if (!key_call ((u_long) KEY_SET, (xdrproc_t) xdr_keybuf, secretkey, 
+		 (xdrproc_t) xdr_keystatus, (char *) &status))
+    return -1;
+  if (status != KEY_SUCCESS)
+    {
+      debug ("set status is nonzero");
+      return -1;
+    }
+  return 0;
+}
+
+/* key_secretkey_is_set() returns 1 if the keyserver has a secret key
+ * stored for the caller's effective uid; it returns 0 otherwise
+ *
+ * N.B.:  The KEY_NET_GET key call is undocumented.  Applications shouldn't
+ * be using it, because it allows them to get the user's secret key.
+ */
+int
+key_secretkey_is_set (void)
+{
+  struct key_netstres kres;
+
+  memset (&kres, 0, sizeof (kres));
+  if (key_call ((u_long) KEY_NET_GET, (xdrproc_t) xdr_void, (char *) NULL,
+		(xdrproc_t) xdr_key_netstres, (char *) &kres) &&
+      (kres.status == KEY_SUCCESS) &&
+      (kres.key_netstres_u.knet.st_priv_key[0] != 0))
+    {
+      /* avoid leaving secret key in memory */
+      memset (kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES);
+      return 1;
+    }
+  return 0;
+}
+
+int
+key_encryptsession (char *remotename, des_block * deskey)
+{
+  cryptkeyarg arg;
+  cryptkeyres res;
+
+  arg.remotename = remotename;
+  arg.deskey = *deskey;
+  if (!key_call ((u_long) KEY_ENCRYPT, (xdrproc_t) xdr_cryptkeyarg, 
+		 (char *) &arg, (xdrproc_t) 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;
+}
+
+int
+key_decryptsession (char *remotename, des_block * deskey)
+{
+  cryptkeyarg arg;
+  cryptkeyres res;
+
+  arg.remotename = remotename;
+  arg.deskey = *deskey;
+  if (!key_call ((u_long) KEY_DECRYPT, (xdrproc_t) xdr_cryptkeyarg,
+		 (char *) &arg, (xdrproc_t) 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;
+}
+
+int
+key_encryptsession_pk (char *remotename, netobj * remotekey,
+		       des_block * deskey)
+{
+  cryptkeyarg2 arg;
+  cryptkeyres res;
+
+  arg.remotename = remotename;
+  arg.remotekey = *remotekey;
+  arg.deskey = *deskey;
+  if (!key_call ((u_long) KEY_ENCRYPT_PK, (xdrproc_t) xdr_cryptkeyarg2, 
+		 (char *) &arg, (xdrproc_t) 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;
+}
+
+int
+key_decryptsession_pk (char *remotename, netobj * remotekey,
+		       des_block * deskey)
+{
+  cryptkeyarg2 arg;
+  cryptkeyres res;
+
+  arg.remotename = remotename;
+  arg.remotekey = *remotekey;
+  arg.deskey = *deskey;
+  if (!key_call ((u_long) KEY_DECRYPT_PK, (xdrproc_t) xdr_cryptkeyarg2, 
+		 (char *) &arg, (xdrproc_t) 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;
+}
+
+int
+key_gendes (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, (xdrproc_t) xdr_void, NULL,
+		    (xdrproc_t) xdr_des_block, (caddr_t) key, tottimeout);
+  clnt_destroy (client);
+  close (socket);
+  if (stat != RPC_SUCCESS)
+    return -1;
+
+  return 0;
+}
+
+int
+key_setnet (struct key_netstarg *arg)
+{
+  keystatus status;
+
+  if (!key_call ((u_long) KEY_NET_PUT, (xdrproc_t) xdr_key_netstarg, 
+		 (char *) arg,(xdrproc_t) xdr_keystatus, (char *) &status))
+    return -1;
+
+  if (status != KEY_SUCCESS)
+    {
+      debug ("key_setnet status is nonzero");
+      return -1;
+    }
+  return 1;
+}
+
+int
+key_get_conv (char *pkey, des_block * deskey)
+{
+  cryptkeyres res;
+
+  if (!key_call ((u_long) KEY_GET_CONV, (xdrproc_t) xdr_keybuf, pkey,
+		 (xdrproc_t) xdr_cryptkeyres, (char *) &res))
+    return -1;
+
+  if (res.status != KEY_SUCCESS)
+    {
+      debug ("get_conv status is nonzero");
+      return -1;
+    }
+  *deskey = res.cryptkeyres_u.deskey;
+  return 0;
+}
+
+/*
+ * Hack to allow the keyserver to use AUTH_DES (for authenticated
+ * NIS+ calls, for example).  The only functions that get called
+ * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
+ *
+ * The approach is to have the keyserver fill in pointers to local
+ * implementations of these functions, and to call those in key_call().
+ */
+
+cryptkeyres *(*__key_encryptsession_pk_LOCAL) (uid_t, char *) = 0;
+cryptkeyres *(*__key_decryptsession_pk_LOCAL) (uid_t, char *) = 0;
+des_block *(*__key_gendes_LOCAL) (uid_t, char *) = 0;
+
+static int
+key_call (u_long proc, xdrproc_t xdr_arg, char *arg,
+	  xdrproc_t xdr_rslt, char *rslt)
+{
+  XDR xdrargs;
+  XDR xdrrslt;
+  FILE *fargs;
+  FILE *frslt;
+  void (*osigchild) (int);
+  union wait status;
+  int pid;
+  int success;
+  uid_t ruid;
+  uid_t euid;
+  static char MESSENGER[] = "/usr/etc/keyenvoy";
+
+  success = 1;
+  osigchild = signal (SIGCHLD, SIG_IGN);
+
+  if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL)
+    {
+      cryptkeyres *res;
+      res = (*__key_encryptsession_pk_LOCAL) (geteuid (), arg);
+      *(cryptkeyres *) rslt = *res;
+      return 1;
+    }
+  else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL)
+    {
+      cryptkeyres *res;
+      res = (*__key_decryptsession_pk_LOCAL) (geteuid (), arg);
+      *(cryptkeyres *) rslt = *res;
+      return 1;
+    }
+  else if (proc == KEY_GEN && __key_gendes_LOCAL)
+    {
+      des_block *res;
+      res = (*__key_gendes_LOCAL) (geteuid (), 0);
+      *(des_block *) rslt = *res;
+      return 1;
+    }
+
+  /*
+   * 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 ();
+  setreuid (euid, ruid);
+  pid = _openchild (MESSENGER, &fargs, &frslt);
+  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;
+    }
+  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.
+   */
+  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;
+    }
+  signal (SIGCHLD, osigchild);
+
+  return (success);
+}
diff --git a/sunrpc/key_prot.c b/sunrpc/key_prot.c
new file mode 100644
index 0000000000..5de8e25420
--- /dev/null
+++ b/sunrpc/key_prot.c
@@ -0,0 +1,161 @@
+/*
+ * 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
+ */
+#pragma ident	"@(#)key_prot.x	1.7	94/04/29 SMI"
+
+/* Copyright (c)  1990, 1991 Sun Microsystems, Inc. */
+
+#include "rpc/key_prot.h"
+
+bool_t
+xdr_keystatus (XDR * xdrs, keystatus * objp)
+{
+  if (!xdr_enum (xdrs, (enum_t *) objp))
+    return FALSE;
+
+  return TRUE;
+}
+
+bool_t
+xdr_keybuf (XDR * xdrs, keybuf objp)
+{
+  if (!xdr_opaque (xdrs, objp, HEXKEYBYTES))
+    return FALSE;
+
+  return TRUE;
+}
+
+bool_t
+xdr_netnamestr (XDR * xdrs, netnamestr * objp)
+{
+  if (!xdr_string (xdrs, objp, MAXNETNAMELEN))
+    return FALSE;
+
+  return TRUE;
+}
+
+bool_t
+xdr_cryptkeyarg (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_cryptkeyarg2 (XDR * xdrs, cryptkeyarg2 * objp)
+{
+  if (!xdr_netnamestr (xdrs, &objp->remotename))
+    return FALSE;
+  if (!xdr_netobj (xdrs, &objp->remotekey))
+    return FALSE;
+  if (!xdr_des_block (xdrs, &objp->deskey))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_cryptkeyres (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;
+    default:
+      break;
+    }
+  return TRUE;
+}
+
+bool_t
+xdr_unixcred (XDR * xdrs, unixcred * objp)
+{
+  if (!xdr_u_int (xdrs, &objp->uid))
+    return FALSE;
+  if (!xdr_u_int (xdrs, &objp->gid))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->gids.gids_val,
+		  (u_int *) & objp->gids.gids_len, MAXGIDS,
+		  sizeof (u_int), (xdrproc_t) xdr_u_int))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_getcredres (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;
+    default:
+      break;
+    }
+  return TRUE;
+}
+
+bool_t
+xdr_key_netstarg (XDR * xdrs, key_netstarg * objp)
+{
+  if (!xdr_keybuf (xdrs, objp->st_priv_key))
+    return FALSE;
+  if (!xdr_keybuf (xdrs, objp->st_pub_key))
+    return FALSE;
+  if (!xdr_netnamestr (xdrs, &objp->st_netname))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_key_netstres (XDR * xdrs, key_netstres * objp)
+{
+  if (!xdr_keystatus (xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status)
+    {
+    case KEY_SUCCESS:
+      if (!xdr_key_netstarg (xdrs, &objp->key_netstres_u.knet))
+	return FALSE;
+      break;
+    default:
+      break;
+    }
+  return TRUE;
+}
diff --git a/sunrpc/netname.c b/sunrpc/netname.c
new file mode 100644
index 0000000000..be6c2f2ae1
--- /dev/null
+++ b/sunrpc/netname.c
@@ -0,0 +1,201 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+
+#include "nsswitch.h"
+
+#define	OPSYS_LEN 4
+#define	MAXIPRINT (11)		/* max length of printed integer */
+static const char *OPSYS = "unix";
+
+int
+user2netname (char netname[MAXNETNAMELEN + 1], const uid_t uid,
+	      const char *domain)
+{
+  char dfltdom[MAXNETNAMELEN + 1];
+  size_t i;
+
+  if (domain == NULL)
+    {
+      if (getdomainname (dfltdom, sizeof (dfltdom)) < 0)
+	return 0;
+    }
+  else
+    {
+      strncpy (dfltdom, domain, MAXNETNAMELEN);
+      dfltdom[MAXNETNAMELEN] = '\0';
+    }
+
+  if ((strlen (dfltdom) + OPSYS_LEN + 3 + MAXIPRINT) > (size_t) MAXNETNAMELEN)
+    return 0;
+
+  sprintf (netname, "%s.%d@%s", OPSYS, uid, dfltdom);
+  i = strlen (netname);
+  if (netname[i - 1] == '.')
+    netname[i - 1] = '\0';
+  return 1;
+}
+
+int
+host2netname (char netname[MAXNETNAMELEN + 1], const char *host,
+	      const char *domain)
+{
+  char *p;
+  char hostname[MAXHOSTNAMELEN + 1];
+  char domainname[MAXHOSTNAMELEN + 1];
+  char *dot_in_host;
+  size_t i;
+
+  netname[0] = '\0';		/* make null first (no need for memset) */
+
+  if (host == NULL)
+    gethostname (hostname, MAXHOSTNAMELEN);
+  else
+    {
+      strncpy (hostname, host, MAXHOSTNAMELEN);
+      hostname[MAXHOSTNAMELEN] = '\0';
+    }
+
+  dot_in_host = strchr (hostname, '.');
+  if (domain == NULL)
+    {
+      p = dot_in_host;
+      if (p)
+	{
+	  strncpy (domainname, p, MAXHOSTNAMELEN);
+	  domainname[MAXHOSTNAMELEN] = '\0';
+	}
+      else
+	{
+	  domainname[0] = 0;
+	  getdomainname (domainname, MAXHOSTNAMELEN);
+	}
+    }
+  else
+    {
+      strncpy (domainname, domain, MAXHOSTNAMELEN);
+      domainname[MAXHOSTNAMELEN] = '\0';
+    }
+
+  i = strlen (domainname);
+  if (i == 0)
+    /* No domainname */
+    return 0;
+  if (domainname[i - 1] == '.')
+    domainname[i - 1] = 0;
+
+  if (dot_in_host)		/* strip off rest of name */
+    *dot_in_host = '\0';
+
+  if ((strlen (domainname) + strlen (hostname) + OPSYS_LEN + 3)
+      > MAXNETNAMELEN)
+    return 0;
+
+  sprintf (netname, "%s.%s@%s", OPSYS, hostname, domainname);
+  return 1;
+}
+
+int
+getnetname (char name[MAXNETNAMELEN + 1])
+{
+  uid_t uid;
+  int dummy;
+
+  uid = geteuid ();
+  if (uid == 0)
+    dummy = host2netname (name, NULL, NULL);
+  else
+    dummy = user2netname (name, uid, NULL);
+  return (dummy);
+}
+
+/* Type of the lookup function for netname2user.  */
+typedef int (*netname2user_function) (const char netname[MAXNETNAMELEN + 1],
+				      uid_t *, gid_t *, int *, gid_t *);
+/* The lookup function for the first entry of this service.  */
+extern int __nss_publickey_lookup (service_user ** nip, const char *name,
+				   void **fctp);
+
+int
+netname2user (const char netname[MAXNETNAMELEN + 1], uid_t * uidp, gid_t * gidp,
+	      int *gidlenp, gid_t * gidlist)
+{
+  static service_user *startp = NULL;
+  static netname2user_function start_fct;
+  service_user *nip;
+  netname2user_function fct;
+  enum nss_status status = NSS_STATUS_UNAVAIL;
+  int no_more;
+
+  if (startp == NULL)
+    {
+      no_more = __nss_publickey_lookup (&nip, "netname2user", (void **) &fct);
+      if (no_more)
+	startp = (service_user *) - 1;
+      else
+	{
+	  startp = nip;
+	  start_fct = fct;
+	}
+    }
+  else
+    {
+      fct = start_fct;
+      no_more = (nip = startp) == (service_user *) - 1;
+    }
+
+  while (!no_more)
+    {
+      status = (*fct) (netname, uidp, gidp, gidlenp, gidlist);
+
+      no_more = __nss_next (&nip, "netname2user", (void **) &fct, status, 0);
+    }
+
+  return status == NSS_STATUS_SUCCESS;
+}
+
+int
+netname2host (const char netname[MAXNETNAMELEN + 1], char *hostname,
+	      const int hostlen)
+{
+  char *p1, *p2;
+  char buffer[MAXNETNAMELEN + 1];
+
+  p1 = strchr (buffer, '.');
+  if (p1 == NULL)
+    return 0;
+  p1++;
+
+  p2 = strchr (p1, '@');
+  if (p2 == NULL)
+    return 0;
+  *p2 = '\0';
+
+  if (hostlen > MAXNETNAMELEN)
+    return 0;
+
+  strncpy (hostname, p1, hostlen);
+  hostname[hostlen] = '\0';
+
+  return 1;
+}
diff --git a/sunrpc/openchild.c b/sunrpc/openchild.c
new file mode 100644
index 0000000000..2fa26fae45
--- /dev/null
+++ b/sunrpc/openchild.c
@@ -0,0 +1,112 @@
+#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>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/clnt.h>
+
+static char SHELL[] = "/bin/sh";
+
+/*
+ * returns pid, or -1 for failure
+ */
+int
+_openchild (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]
+       */
+      close (0);
+      dup (pdto[0]);
+      close (1);
+      dup (pdfrom[1]);
+      for (i = _rpc_dtablesize () - 1; i >= 3; i--)
+	close (i);
+      com = malloc (strlen (command) + 6);
+      if (com == NULL)
+	_exit (~0);
+      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");
+      close (pdto[0]);
+      *ffrom = fdopen (pdfrom[0], "r");
+      close (pdfrom[1]);
+      break;
+    }
+  return pid;
+
+  /*
+   * error cleanup and return
+   */
+error3:
+  close (pdfrom[0]);
+  close (pdfrom[1]);
+error2:
+  close (pdto[0]);
+  close (pdto[1]);
+error1:
+  return -1;
+}
diff --git a/sunrpc/rpc/auth.h b/sunrpc/rpc/auth.h
new file mode 100644
index 0000000000..22174193d4
--- /dev/null
+++ b/sunrpc/rpc/auth.h
@@ -0,0 +1,210 @@
+/* @(#)auth.h	2.3 88/08/07 4.0 RPCSRC; from 1.17 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
+ */
+
+/*
+ * auth.h, Authentication interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The data structures are completely opaque to the client.  The client
+ * is required to pass a AUTH * to routines that create rpc
+ * "sessions".
+ */
+
+#ifndef _RPC_AUTH_H
+
+#define _RPC_AUTH_H	1
+#include <features.h>
+#include <rpc/xdr.h>
+
+__BEGIN_DECLS
+
+#define MAX_AUTH_BYTES	400
+#define MAXNETNAMELEN	255	/* maximum length of network user's name */
+
+/*
+ * Status returned from authentication check
+ */
+enum auth_stat {
+	AUTH_OK=0,
+	/*
+	 * failed at remote end
+	 */
+	AUTH_BADCRED=1,			/* bogus credentials (seal broken) */
+	AUTH_REJECTEDCRED=2,		/* client should begin new session */
+	AUTH_BADVERF=3,			/* bogus verifier (seal broken) */
+	AUTH_REJECTEDVERF=4,		/* verifier expired or was replayed */
+	AUTH_TOOWEAK=5,			/* rejected due to security reasons */
+	/*
+	 * failed locally
+	*/
+	AUTH_INVALIDRESP=6,		/* bogus response verifier */
+	AUTH_FAILED=7			/* some unknown reason */
+};
+
+union des_block {
+	struct {
+		u_int32_t high;
+		u_int32_t low;
+	} key;
+	char c[8];
+};
+typedef union des_block des_block;
+extern bool_t xdr_des_block __P ((XDR *__xdrs, des_block *__blkp));
+
+/*
+ * Authentication info.  Opaque to client.
+ */
+struct opaque_auth {
+	enum_t	oa_flavor;		/* flavor of auth */
+	caddr_t	oa_base;		/* address of more auth stuff */
+	u_int	oa_length;		/* not to exceed MAX_AUTH_BYTES */
+};
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+typedef struct AUTH AUTH;
+struct AUTH {
+  struct opaque_auth ah_cred;
+  struct opaque_auth ah_verf;
+  union des_block ah_key;
+  struct auth_ops {
+    void (*ah_nextverf) __P ((AUTH *));
+    int  (*ah_marshal) __P ((AUTH *, XDR *));	/* nextverf & serialize */
+    int  (*ah_validate) __P ((AUTH *, struct opaque_auth *));	
+						/* validate verifier */
+    int  (*ah_refresh) __P ((AUTH *));		/* refresh credentials */
+    void (*ah_destroy) __P ((AUTH *));     	/* destroy this structure */
+  } *ah_ops;
+  caddr_t ah_private;
+};
+
+
+/*
+ * Authentication ops.
+ * The ops and the auth handle provide the interface to the authenticators.
+ *
+ * AUTH	*auth;
+ * XDR	*xdrs;
+ * struct opaque_auth verf;
+ */
+#define AUTH_NEXTVERF(auth)		\
+		((*((auth)->ah_ops->ah_nextverf))(auth))
+#define auth_nextverf(auth)		\
+		((*((auth)->ah_ops->ah_nextverf))(auth))
+
+#define AUTH_MARSHALL(auth, xdrs)	\
+		((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+#define auth_marshall(auth, xdrs)	\
+		((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+
+#define AUTH_VALIDATE(auth, verfp)	\
+		((*((auth)->ah_ops->ah_validate))((auth), verfp))
+#define auth_validate(auth, verfp)	\
+		((*((auth)->ah_ops->ah_validate))((auth), verfp))
+
+#define AUTH_REFRESH(auth)		\
+		((*((auth)->ah_ops->ah_refresh))(auth))
+#define auth_refresh(auth)		\
+		((*((auth)->ah_ops->ah_refresh))(auth))
+
+#define AUTH_DESTROY(auth)		\
+		((*((auth)->ah_ops->ah_destroy))(auth))
+#define auth_destroy(auth)		\
+		((*((auth)->ah_ops->ah_destroy))(auth))
+
+
+extern struct opaque_auth _null_auth;
+
+
+/*
+ * These are the various implementations of client side authenticators.
+ */
+
+/*
+ * Unix style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ *	char *machname;
+ *	int uid;
+ *	int gid;
+ *	int len;
+ *	int *aup_gids;
+ */
+extern AUTH *authunix_create __P ((char *__machname, __uid_t __uid,
+				   __gid_t __gid, int __len,
+				   __gid_t *__aup_gids));
+extern AUTH *authunix_create_default __P ((void));
+extern AUTH *authnone_create __P ((void));
+extern AUTH *authdes_create __P ((const char *__servername, u_int __window, 
+				  struct sockaddr *__syncaddr,
+				  des_block *__ckey));
+
+#define AUTH_NONE	0		/* no authentication */
+#define	AUTH_NULL	0		/* backward compatibility */
+#define	AUTH_SYS	1		/* unix style (uid, gids) */
+#define	AUTH_UNIX	AUTH_SYS
+#define	AUTH_SHORT	2		/* short hand unix style */
+#define AUTH_DES	3		/* des style (encrypted timestamps) */
+#define AUTH_KERB       4               /* kerberos style */
+
+/*
+ *  Netname manipulating functions
+ *
+ */
+extern int getnetname __P ((char *));
+extern int host2netname __P ((char *, __const char *, __const char *));
+extern int user2netname __P ((char *, __const uid_t, __const char *));
+extern int netname2user __P ((__const char *, uid_t *, gid_t *, int *, 
+			      gid_t *));
+extern int netname2host __P ((__const char *, char *, __const int));
+
+/*
+ *
+ * These routines interface to the keyserv daemon
+ *
+ */
+extern int key_decryptsession __P ((char *, des_block *));
+extern int key_decryptsession_pk __P ((char *, netobj *, des_block *));
+extern int key_encryptsession __P ((char *, des_block *));
+extern int key_encryptsession_pk __P ((char *, netobj *, des_block *));
+extern int key_gendes __P ((des_block *));
+extern int key_setsecret __P ((char *));
+extern int key_secretkey_is_set __P ((void));
+extern int key_get_conv __P ((char *, des_block *));
+
+__END_DECLS
+
+/* This is for compiling the glibc NIS+ code with DES auth. */
+#ifdef _LIBC
+#define HAVE_SECURE_RPC 1
+#endif
+
+#endif /* rpc/auth.h */
diff --git a/sunrpc/rpc/auth_des.h b/sunrpc/rpc/auth_des.h
new file mode 100644
index 0000000000..87fb8f0e99
--- /dev/null
+++ b/sunrpc/rpc/auth_des.h
@@ -0,0 +1,104 @@
+/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _RPC_AUTH_DES_H
+
+#define _RPC_AUTH_DES_H	1
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/* 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
+
+/* Map a des credential into a unix cred. */
+extern int authdes_getucred __P ((__const struct authdes_cred * __adc,
+				  uid_t * __uid, gid_t * __gid,
+				  short *__grouplen, gid_t * __groups));
+
+/* Get the public key for NAME and place it in KEY.  NAME can only be
+   up to MAXNETNAMELEN bytes long and the destination buffer KEY should
+   have HEXKEYBATES + 1 bytes long to fit all characters from the key.  */
+extern int getpublickey __P ((__const char *__name, char *__key));
+
+/* Get the secret key for NAME and place it in KEY.  PASSWD is used to
+   decrypt the encrypted key stored in the database.  NAME can only be
+   up to MAXNETNAMELEN bytes long and the destination buffer KEY
+   should have HEXKEYBATES + 1 bytes long to fit all characters from
+   the key.  */
+extern int getsecretkey __P ((__const char *__name, char *__key,
+			      __const char *__passwd));
+
+extern int rtime __P ((struct sockaddr_in *__addrp,  struct timeval *__timep,
+		       struct timeval *__timeout));
+
+__END_DECLS
+
+
+#endif /* rpc/auth_des.h */
diff --git a/sunrpc/rpc/des_crypt.h b/sunrpc/rpc/des_crypt.h
new file mode 100644
index 0000000000..e20cc38243
--- /dev/null
+++ b/sunrpc/rpc/des_crypt.h
@@ -0,0 +1,97 @@
+/*
+ * @(#)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
+ */
+
+#ifndef __DES_CRYPT_H__
+#define __DES_CRYPT_H__ 1
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+#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
+ */
+extern int cbc_crypt __P ((char *__key, char *__buf, unsigned __len,
+			   unsigned __mode, char *__ivec));
+
+/*
+ * Electronic Code Book mode
+ */
+extern int ecb_crypt __P ((char *__key, char *__buf, unsigned __len,
+			   unsigned __mode));
+
+/* 
+ * Set des parity for a key.
+ * DES parity is odd and in the low bit of each byte
+ */
+extern void des_setparity __P ((char *__key));
+
+__END_DECLS
+
+#endif
diff --git a/sunrpc/rpc/key_prot.h b/sunrpc/rpc/key_prot.h
new file mode 100644
index 0000000000..a23f2cd21b
--- /dev/null
+++ b/sunrpc/rpc/key_prot.h
@@ -0,0 +1,345 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _KEY_PROT_H_RPCGEN
+#define _KEY_PROT_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+/*
+ * 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
+ */
+#pragma ident	"@(#)key_prot.x	1.7	94/04/29 SMI"
+
+/* Copyright (c)  1990, 1991 Sun Microsystems, Inc. */
+
+/* 
+ * Compiled from key_prot.x using rpcgen.
+ * DO NOT EDIT THIS FILE!
+ * This is NOT source code!
+ */
+#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;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_keystatus(XDR *, keystatus*);
+#elif __STDC__ 
+extern  bool_t xdr_keystatus(XDR *, keystatus*);
+#else /* Old Style C */ 
+bool_t xdr_keystatus();
+#endif /* Old Style C */ 
+
+
+typedef char keybuf[HEXKEYBYTES];
+#ifdef __cplusplus 
+extern "C" bool_t xdr_keybuf(XDR *, keybuf);
+#elif __STDC__ 
+extern  bool_t xdr_keybuf(XDR *, keybuf);
+#else /* Old Style C */ 
+bool_t xdr_keybuf();
+#endif /* Old Style C */ 
+
+
+typedef char *netnamestr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_netnamestr(XDR *, netnamestr*);
+#elif __STDC__ 
+extern  bool_t xdr_netnamestr(XDR *, netnamestr*);
+#else /* Old Style C */ 
+bool_t xdr_netnamestr();
+#endif /* Old Style C */ 
+
+
+struct cryptkeyarg {
+	netnamestr remotename;
+	des_block deskey;
+};
+typedef struct cryptkeyarg cryptkeyarg;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_cryptkeyarg(XDR *, cryptkeyarg*);
+#elif __STDC__ 
+extern  bool_t xdr_cryptkeyarg(XDR *, cryptkeyarg*);
+#else /* Old Style C */ 
+bool_t xdr_cryptkeyarg();
+#endif /* Old Style C */ 
+
+
+struct cryptkeyarg2 {
+	netnamestr remotename;
+	netobj remotekey;
+	des_block deskey;
+};
+typedef struct cryptkeyarg2 cryptkeyarg2;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_cryptkeyarg2(XDR *, cryptkeyarg2*);
+#elif __STDC__ 
+extern  bool_t xdr_cryptkeyarg2(XDR *, cryptkeyarg2*);
+#else /* Old Style C */ 
+bool_t xdr_cryptkeyarg2();
+#endif /* Old Style C */ 
+
+
+struct cryptkeyres {
+	keystatus status;
+	union {
+		des_block deskey;
+	} cryptkeyres_u;
+};
+typedef struct cryptkeyres cryptkeyres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_cryptkeyres(XDR *, cryptkeyres*);
+#elif __STDC__ 
+extern  bool_t xdr_cryptkeyres(XDR *, cryptkeyres*);
+#else /* Old Style C */ 
+bool_t xdr_cryptkeyres();
+#endif /* Old Style C */ 
+
+#define MAXGIDS 16
+
+struct unixcred {
+	u_int uid;
+	u_int gid;
+	struct {
+		u_int gids_len;
+		u_int *gids_val;
+	} gids;
+};
+typedef struct unixcred unixcred;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_unixcred(XDR *, unixcred*);
+#elif __STDC__ 
+extern  bool_t xdr_unixcred(XDR *, unixcred*);
+#else /* Old Style C */ 
+bool_t xdr_unixcred();
+#endif /* Old Style C */ 
+
+
+struct getcredres {
+	keystatus status;
+	union {
+		unixcred cred;
+	} getcredres_u;
+};
+typedef struct getcredres getcredres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_getcredres(XDR *, getcredres*);
+#elif __STDC__ 
+extern  bool_t xdr_getcredres(XDR *, getcredres*);
+#else /* Old Style C */ 
+bool_t xdr_getcredres();
+#endif /* Old Style C */ 
+
+
+struct key_netstarg {
+	keybuf st_priv_key;
+	keybuf st_pub_key;
+	netnamestr st_netname;
+};
+typedef struct key_netstarg key_netstarg;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_key_netstarg(XDR *, key_netstarg*);
+#elif __STDC__ 
+extern  bool_t xdr_key_netstarg(XDR *, key_netstarg*);
+#else /* Old Style C */ 
+bool_t xdr_key_netstarg();
+#endif /* Old Style C */ 
+
+
+struct key_netstres {
+	keystatus status;
+	union {
+		key_netstarg knet;
+	} key_netstres_u;
+};
+typedef struct key_netstres key_netstres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_key_netstres(XDR *, key_netstres*);
+#elif __STDC__ 
+extern  bool_t xdr_key_netstres(XDR *, key_netstres*);
+#else /* Old Style C */ 
+bool_t xdr_key_netstres();
+#endif /* Old Style C */ 
+
+
+#ifndef opaque
+#define opaque char
+#endif
+
+
+#define KEY_PROG ((u_long)100029)
+#define KEY_VERS ((u_long)1)
+
+#ifdef __cplusplus
+#define KEY_SET ((u_long)1)
+extern "C" keystatus * key_set_1(opaque *, CLIENT *);
+extern "C" keystatus * key_set_1_svc(opaque *, struct svc_req *);
+#define KEY_ENCRYPT ((u_long)2)
+extern "C" cryptkeyres * key_encrypt_1(cryptkeyarg *, CLIENT *);
+extern "C" cryptkeyres * key_encrypt_1_svc(cryptkeyarg *, struct svc_req *);
+#define KEY_DECRYPT ((u_long)3)
+extern "C" cryptkeyres * key_decrypt_1(cryptkeyarg *, CLIENT *);
+extern "C" cryptkeyres * key_decrypt_1_svc(cryptkeyarg *, struct svc_req *);
+#define KEY_GEN ((u_long)4)
+extern "C" des_block * key_gen_1(void *, CLIENT *);
+extern "C" des_block * key_gen_1_svc(void *, struct svc_req *);
+#define KEY_GETCRED ((u_long)5)
+extern "C" getcredres * key_getcred_1(netnamestr *, CLIENT *);
+extern "C" getcredres * key_getcred_1_svc(netnamestr *, struct svc_req *);
+
+#elif __STDC__
+#define KEY_SET ((u_long)1)
+extern  keystatus * key_set_1(opaque *, CLIENT *);
+extern  keystatus * key_set_1_svc(opaque *, struct svc_req *);
+#define KEY_ENCRYPT ((u_long)2)
+extern  cryptkeyres * key_encrypt_1(cryptkeyarg *, CLIENT *);
+extern  cryptkeyres * key_encrypt_1_svc(cryptkeyarg *, struct svc_req *);
+#define KEY_DECRYPT ((u_long)3)
+extern  cryptkeyres * key_decrypt_1(cryptkeyarg *, CLIENT *);
+extern  cryptkeyres * key_decrypt_1_svc(cryptkeyarg *, struct svc_req *);
+#define KEY_GEN ((u_long)4)
+extern  des_block * key_gen_1(void *, CLIENT *);
+extern  des_block * key_gen_1_svc(void *, struct svc_req *);
+#define KEY_GETCRED ((u_long)5)
+extern  getcredres * key_getcred_1(netnamestr *, CLIENT *);
+extern  getcredres * key_getcred_1_svc(netnamestr *, struct svc_req *);
+
+#else /* Old Style C */ 
+#define KEY_SET ((u_long)1)
+extern  keystatus * key_set_1();
+extern  keystatus * key_set_1_svc();
+#define KEY_ENCRYPT ((u_long)2)
+extern  cryptkeyres * key_encrypt_1();
+extern  cryptkeyres * key_encrypt_1_svc();
+#define KEY_DECRYPT ((u_long)3)
+extern  cryptkeyres * key_decrypt_1();
+extern  cryptkeyres * key_decrypt_1_svc();
+#define KEY_GEN ((u_long)4)
+extern  des_block * key_gen_1();
+extern  des_block * key_gen_1_svc();
+#define KEY_GETCRED ((u_long)5)
+extern  getcredres * key_getcred_1();
+extern  getcredres * key_getcred_1_svc();
+#endif /* Old Style C */ 
+#define KEY_VERS2 ((u_long)2)
+
+#ifdef __cplusplus
+extern "C" keystatus * key_set_2(opaque *, CLIENT *);
+extern "C" keystatus * key_set_2_svc(opaque *, struct svc_req *);
+extern "C" cryptkeyres * key_encrypt_2(cryptkeyarg *, CLIENT *);
+extern "C" cryptkeyres * key_encrypt_2_svc(cryptkeyarg *, struct svc_req *);
+extern "C" cryptkeyres * key_decrypt_2(cryptkeyarg *, CLIENT *);
+extern "C" cryptkeyres * key_decrypt_2_svc(cryptkeyarg *, struct svc_req *);
+extern "C" des_block * key_gen_2(void *, CLIENT *);
+extern "C" des_block * key_gen_2_svc(void *, struct svc_req *);
+extern "C" getcredres * key_getcred_2(netnamestr *, CLIENT *);
+extern "C" getcredres * key_getcred_2_svc(netnamestr *, struct svc_req *);
+#define KEY_ENCRYPT_PK ((u_long)6)
+extern "C" cryptkeyres * key_encrypt_pk_2(cryptkeyarg2 *, CLIENT *);
+extern "C" cryptkeyres * key_encrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *);
+#define KEY_DECRYPT_PK ((u_long)7)
+extern "C" cryptkeyres * key_decrypt_pk_2(cryptkeyarg2 *, CLIENT *);
+extern "C" cryptkeyres * key_decrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *);
+#define KEY_NET_PUT ((u_long)8)
+extern "C" keystatus * key_net_put_2(key_netstarg *, CLIENT *);
+extern "C" keystatus * key_net_put_2_svc(key_netstarg *, struct svc_req *);
+#define KEY_NET_GET ((u_long)9)
+extern "C" key_netstres * key_net_get_2(void *, CLIENT *);
+extern "C" key_netstres * key_net_get_2_svc(void *, struct svc_req *);
+#define KEY_GET_CONV ((u_long)10)
+extern "C" cryptkeyres * key_get_conv_2(opaque *, CLIENT *);
+extern "C" cryptkeyres * key_get_conv_2_svc(opaque *, struct svc_req *);
+
+#elif __STDC__
+extern  keystatus * key_set_2(opaque *, CLIENT *);
+extern  keystatus * key_set_2_svc(opaque *, struct svc_req *);
+extern  cryptkeyres * key_encrypt_2(cryptkeyarg *, CLIENT *);
+extern  cryptkeyres * key_encrypt_2_svc(cryptkeyarg *, struct svc_req *);
+extern  cryptkeyres * key_decrypt_2(cryptkeyarg *, CLIENT *);
+extern  cryptkeyres * key_decrypt_2_svc(cryptkeyarg *, struct svc_req *);
+extern  des_block * key_gen_2(void *, CLIENT *);
+extern  des_block * key_gen_2_svc(void *, struct svc_req *);
+extern  getcredres * key_getcred_2(netnamestr *, CLIENT *);
+extern  getcredres * key_getcred_2_svc(netnamestr *, struct svc_req *);
+#define KEY_ENCRYPT_PK ((u_long)6)
+extern  cryptkeyres * key_encrypt_pk_2(cryptkeyarg2 *, CLIENT *);
+extern  cryptkeyres * key_encrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *);
+#define KEY_DECRYPT_PK ((u_long)7)
+extern  cryptkeyres * key_decrypt_pk_2(cryptkeyarg2 *, CLIENT *);
+extern  cryptkeyres * key_decrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *);
+#define KEY_NET_PUT ((u_long)8)
+extern  keystatus * key_net_put_2(key_netstarg *, CLIENT *);
+extern  keystatus * key_net_put_2_svc(key_netstarg *, struct svc_req *);
+#define KEY_NET_GET ((u_long)9)
+extern  key_netstres * key_net_get_2(void *, CLIENT *);
+extern  key_netstres * key_net_get_2_svc(void *, struct svc_req *);
+#define KEY_GET_CONV ((u_long)10)
+extern  cryptkeyres * key_get_conv_2(opaque *, CLIENT *);
+extern  cryptkeyres * key_get_conv_2_svc(opaque *, struct svc_req *);
+
+#else /* Old Style C */ 
+extern  keystatus * key_set_2();
+extern  keystatus * key_set_2_svc();
+extern  cryptkeyres * key_encrypt_2();
+extern  cryptkeyres * key_encrypt_2_svc();
+extern  cryptkeyres * key_decrypt_2();
+extern  cryptkeyres * key_decrypt_2_svc();
+extern  des_block * key_gen_2();
+extern  des_block * key_gen_2_svc();
+extern  getcredres * key_getcred_2();
+extern  getcredres * key_getcred_2_svc();
+#define KEY_ENCRYPT_PK ((u_long)6)
+extern  cryptkeyres * key_encrypt_pk_2();
+extern  cryptkeyres * key_encrypt_pk_2_svc();
+#define KEY_DECRYPT_PK ((u_long)7)
+extern  cryptkeyres * key_decrypt_pk_2();
+extern  cryptkeyres * key_decrypt_pk_2_svc();
+#define KEY_NET_PUT ((u_long)8)
+extern  keystatus * key_net_put_2();
+extern  keystatus * key_net_put_2_svc();
+#define KEY_NET_GET ((u_long)9)
+extern  key_netstres * key_net_get_2();
+extern  key_netstres * key_net_get_2_svc();
+#define KEY_GET_CONV ((u_long)10)
+extern  cryptkeyres * key_get_conv_2();
+extern  cryptkeyres * key_get_conv_2_svc();
+#endif /* Old Style C */ 
+
+#endif /* !_KEY_PROT_H_RPCGEN */
diff --git a/sunrpc/rpcsvc/key_prot.x b/sunrpc/rpcsvc/key_prot.x
new file mode 100644
index 0000000000..af22a208c5
--- /dev/null
+++ b/sunrpc/rpcsvc/key_prot.x
@@ -0,0 +1,284 @@
+%/*
+% * 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 server protocol definition
+ * Copyright (C) 1990, 1991 Sun Microsystems, Inc.
+ *
+ * The keyserver is a public key storage/encryption/decryption service
+ * The encryption method used is based on the Diffie-Hellman exponential
+ * key exchange technology.
+ *
+ * The key server is local to each machine, akin to the portmapper.
+ * Under TI-RPC, communication with the keyserver is through the
+ * loopback transport.
+ *
+ * NOTE: This .x file generates the USER level headers for the keyserver.
+ * the KERNEL level headers are created by hand as they kernel has special
+ * requirements.
+ */
+
+%#pragma ident	"@(#)key_prot.x	1.7	94/04/29 SMI"
+%
+%/* Copyright (c)  1990, 1991 Sun Microsystems, Inc. */
+%
+%/* 
+% * Compiled from key_prot.x using rpcgen.
+% * DO NOT EDIT THIS FILE!
+% * This is NOT source code!
+% */
+
+/*
+ * 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) */
+};
+
+typedef opaque keybuf[HEXKEYBYTES];	/* store key in hex */
+
+typedef string netnamestr<MAXNETNAMELEN>;
+
+/*
+ * Argument to ENCRYPT or DECRYPT 
+ */
+struct cryptkeyarg {
+	netnamestr remotename;
+	des_block deskey;
+};
+
+/*
+ * Argument to ENCRYPT_PK or DECRYPT_PK
+ */
+struct cryptkeyarg2 {
+	netnamestr remotename;
+	netobj	remotekey;	/* Contains a length up to 1024 bytes */
+	des_block deskey;
+};
+
+
+/*
+ * Result of ENCRYPT, DECRYPT, ENCRYPT_PK, and DECRYPT_PK
+ */
+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 {
+	u_int uid;
+	u_int gid;
+	u_int gids<MAXGIDS>;	
+};
+
+/*
+ * Result returned from GETCRED
+ */
+union getcredres switch (keystatus status) {
+case KEY_SUCCESS:
+	unixcred cred;
+default:
+	void;
+};
+/*
+ * key_netstarg;
+ */
+
+struct key_netstarg {
+	keybuf st_priv_key;
+	keybuf st_pub_key;
+	netnamestr st_netname;
+};
+
+union key_netstres switch (keystatus status){
+case KEY_SUCCESS:
+	key_netstarg knet;
+default:
+	void;
+};	
+
+#ifdef RPC_HDR
+%
+%#ifndef opaque
+%#define opaque char
+%#endif
+%
+#endif
+program KEY_PROG {
+	version KEY_VERS {
+
+		/*
+		 * This is my secret key.
+	 	 * Store it for me.
+		 */
+		keystatus 
+		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 NIS)
+		 */
+		getcredres
+		KEY_GETCRED(netnamestr) = 5;
+	} = 1;
+	version KEY_VERS2 {
+
+		/*
+		 * #######
+		 * Procedures 1-5 are identical to version 1
+		 * #######
+		 */
+
+		/*
+		 * This is my secret key.
+	 	 * Store it for me.
+		 */
+		keystatus 
+		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 NIS)
+		 */
+		getcredres
+		KEY_GETCRED(netnamestr) = 5;
+		
+		/*
+		 * I want to talk to X. and I know X's public key
+		 * Encrypt a conversation key for me.
+	 	 */
+		cryptkeyres
+		KEY_ENCRYPT_PK(cryptkeyarg2) = 6;	
+
+		/*
+		 * X just sent me a message. and I know X's public key
+		 * Decrypt the conversation key for me.
+		 */
+		cryptkeyres
+		KEY_DECRYPT_PK(cryptkeyarg2) = 7;
+		
+		/* 
+		 * Store my public key, netname and private key. 
+		 */
+		keystatus
+		KEY_NET_PUT(key_netstarg) = 8;
+		
+		/*
+		 * Retrieve my public key, netname and private key. 
+		 */
+ 		key_netstres
+		KEY_NET_GET(void) = 9;
+		
+		/*
+		 * Return me the conversation key that is constructed 
+		 * from my secret key and this publickey. 
+		 */
+
+		cryptkeyres 
+		KEY_GET_CONV(keybuf) = 10; 
+
+		
+	} = 2;
+} = 100029;
+
+
diff --git a/sunrpc/rtime.c b/sunrpc/rtime.c
new file mode 100644
index 0000000000..baaced0d5d
--- /dev/null
+++ b/sunrpc/rtime.c
@@ -0,0 +1,146 @@
+#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 <stdio.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <rpc/clnt.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <rpc/auth_des.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#define NYEARS	(u_long)(1970 - 1900)
+#define TOFFSET (u_long)(60*60*24*(365*NYEARS + (NYEARS/4)))
+
+static void do_close (int);
+
+static void
+do_close (int s)
+{
+  int save;
+
+  save = errno;
+  close (s);
+  __set_errno (save);
+}
+
+int
+rtime (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, (void *) NULL,
+			(void *) NULL, timeout);
+	}
+      while (res < 0 && errno == EINTR);
+      if (res <= 0)
+	{
+	  if (res == 0)
+	    __set_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))
+    {
+      __set_errno (EIO);
+      return -1;
+    }
+  thetime = ntohl (thetime);
+  timep->tv_sec = thetime - TOFFSET;
+  timep->tv_usec = 0;
+  return 0;
+}
diff --git a/sunrpc/svc_auth.c b/sunrpc/svc_auth.c
new file mode 100644
index 0000000000..f0aebd5358
--- /dev/null
+++ b/sunrpc/svc_auth.c
@@ -0,0 +1,119 @@
+/* @(#)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>
+#include <rpc/svc.h>
+#include <rpc/svc_auth.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;
+ *
+ */
+
+static enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *);
+				/* no authentication */
+extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *);
+				/* unix style (uid, gids) */
+extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *);
+				/* short hand unix style */
+extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *);
+				/* des style */
+
+static const struct
+  {
+    enum auth_stat (*authenticator) (struct svc_req *, struct rpc_msg *);
+  }
+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-allocated;
+ * 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 (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;
+}
+
+static enum auth_stat
+_svcauth_null (struct svc_req *rqst, struct rpc_msg *msg)
+{
+  return AUTH_OK;
+}
diff --git a/sunrpc/svcauth_des.c b/sunrpc/svcauth_des.c
new file mode 100644
index 0000000000..3547830267
--- /dev/null
+++ b/sunrpc/svcauth_des.c
@@ -0,0 +1,548 @@
+#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 <string.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/des_crypt.h>
+
+#define debug(msg)		/*printf("svcauth_des: %s\n", msg) */
+
+#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 (void);	/* initialize the cache */
+static short cache_spot (des_block *, char *, struct timeval *);
+					/* find an entry in the cache */
+static void cache_ref (short sid);	/* note that sid was ref'd */
+
+static void invalidate (char *cred);	/* 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 (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 = 0;
+  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;
+    u_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 */
+      }
+    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)
+	{
+	  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 (void)
+{
+  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 (void)
+{
+  return (authdes_lru[AUTHDES_CACHESZ - 1]);
+}
+
+/*
+ * Note that sid was referenced
+ */
+static void
+cache_ref (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 (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 */
+}
+
+
+/*
+ * 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
+{
+  uid_t uid;			/* cached uid */
+  gid_t gid;			/* cached gid */
+  short grouplen;		/* length of cached groups */
+  gid_t 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.
+ */
+int
+authdes_getucred (const struct authdes_cred *adc, uid_t * uid, gid_t * gid,
+		  short *grouplen, gid_t * groups)
+{
+  unsigned sid;
+  register int i;
+  uid_t i_uid;
+  gid_t 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 (char *cred)
+{
+  if (cred == NULL)
+    {
+      return;
+    }
+  ((struct bsdcred *) cred)->grouplen = INVALID;
+}
diff --git a/sunrpc/xcrypt.c b/sunrpc/xcrypt.c
new file mode 100644
index 0000000000..97c30d149f
--- /dev/null
+++ b/sunrpc/xcrypt.c
@@ -0,0 +1,180 @@
+/*
+ * 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-1991 by Sun Microsystems Inc.
+ */
+
+#ident	"@(#)xcrypt.c	1.11	94/08/23 SMI"
+
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xcrypt.c 1.3 89/03/24 Copyr 1986 Sun Micro";
+#endif
+
+/*
+ * xcrypt.c: Hex encryption/decryption and utility routines
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+
+static char hex[16] =
+{
+  '0', '1', '2', '3', '4', '5', '6', '7',
+  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
+};
+
+static char hexval (char);
+static void hex2bin (int, char *, char *);
+static void bin2hex (int, unsigned char *, char *);
+void passwd2des (char *pw, char *key);
+
+/*
+ * 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).
+ */
+int
+xencrypt (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);
+  memset (ivec, 0, 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
+ */
+int
+xdecrypt (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);
+  memset (ivec, 0, 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
+ */
+void
+passwd2des (char *pw, char *key)
+{
+  int i;
+
+  memset (key, 0, 8);
+  for (i = 0; *pw; i = (i + 1) % 8)
+    key[i] ^= *pw++ << 1;
+
+  des_setparity (key);
+}
+
+/*
+ * Hex to binary conversion
+ */
+static void
+hex2bin (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 void
+bin2hex (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
+hexval (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;
+}