Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 05 May 1997 18:50:23 +0200
From:      Mark Murray <mark@grondar.za>
To:        rick@snowhite.cis.uoguelph.ca, wollman@freebsd.org, dfr@freebsd.org
Cc:        current@freebsd.org
Subject:   Kerberised NFSD is broken.
Message-ID:  <199705051650.SAA11805@grackle.grondar.za>

next in thread | raw e-mail | index | archive | help
Hello

Way back in June '95, we broke Kerberised NFSD with this commit. (And
nobody noticed :-) )

In it, the #ifdef's enabling Kerberos were changed from KERBEROS
to NFSKERB, and some (obviously) broken code was inserted between
the #if / #endif pair.

Has anyone got a repaired version of this? Has anyone made it work?
Can anyone spend some time on it to make it work?
(Methinks the Kerberos bits can be just backed out, But I have other
things on my plate right now)

Here Is the log entry:

RCS file: /home/ncvs/src/sbin/nfsd/nfsd.c,v
keyword substitution: kv
total revisions: 17;	selected revisions: 1
description:
----------------------------
revision 1.4
date: 1995/06/27 11:06:22;  author: dfr;  state: Exp;  lines: +85 -25
Changes to support version 3 of the NFS protocol.
The version 2 support has been tested (client+server) against FreeBSD-2.0,
IRIX 5.3 and FreeBSD-current (using a loopback mount).  The version 2 support
is stable AFAIK.
The version 3 support has been tested with a loopback mount and minimally
against an IRIX 5.3 server.  It needs more testing and may have problems.
I have patched amd to support the new variable length filehandles although
it will still only use version 2 of the protocol.

Before booting a kernel with these changes, nfs clients will need to at least
build and install /usr/sbin/mount_nfs.  Servers will need to build and
install /usr/sbin/mountd.

NFS diskless support is untested.

Obtained from: Rick Macklem <rick@snowhite.cis.uoguelph.ca>

...and here is the diff itself (Hunt down for the exposed "XXX" that
breaks this - showing incomplete code?):

Index: nfsd.c
===================================================================
RCS file: /home/ncvs/src/sbin/nfsd/nfsd.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- nfsd.c	1994/09/22 22:16:56	1.3
+++ nfsd.c	1995/06/27 11:06:22	1.4
@@ -63,10 +63,10 @@
 #include <netiso/iso.h>
 #endif
 #include <nfs/rpcv2.h>
-#include <nfs/nfsv2.h>
+#include <nfs/nfsproto.h>
 #include <nfs/nfs.h>
 
-#ifdef KERBEROS
+#ifdef NFSKERB
 #include <kerberosIV/des.h>
 #include <kerberosIV/krb.h>
 #endif
@@ -94,16 +94,23 @@
 char	**Argv = NULL;		/* pointer to argument vector */
 char	*LastArg = NULL;	/* end of argv */
 
-#ifdef KERBEROS
+#ifdef NFSKERB
 char		lnam[ANAME_SZ];
 KTEXT_ST	kt;
-AUTH_DAT	auth;
+AUTH_DAT	kauth;
 char		inst[INST_SZ];
+struct nfsrpc_fullblock kin, kout;
+struct nfsrpc_fullverf kverf;
+NFSKERBKEY_T	kivec;
+struct timeval	ktv;
+NFSKERBKEYSCHED_T kerb_keysched;
 #endif
 
 void	nonfs __P((int));
 void	reapchild __P((int));
+#ifdef __FreeBSD__
 void	setproctitle __P((char *));
+#endif
 void	usage __P((void));
 
 /*
@@ -139,11 +146,13 @@
 #ifdef ISO
 	struct sockaddr_iso isoaddr, isopeer;
 #endif
+	struct timeval ktv;
 	fd_set ready, sockbits;
 	int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
 	int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
 	int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
 	char *cp, **cpp;
+#ifdef __FreeBSD__
 	struct vfsconf *vfc;
 
 	vfc = getvfsbyname("nfs");
@@ -156,6 +165,7 @@
 	if(!vfc) {
 		errx(1, "NFS is not available in the running kernel");
 	}
+#endif
 
 	/* Save start and extent of argv for setproctitle. */
 	Argv = argv;
@@ -241,10 +251,12 @@
 
 	if (reregister) {
 		if (udpflag &&
-		    !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT))
+		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
+		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
 			err(1, "can't register with portmap for UDP.");
 		if (tcpflag &&
-		    !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT))
+		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
+		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
 			err(1, "can't register with portmap for TCP.");
 		exit(0);
 	}
@@ -261,11 +273,17 @@
 			continue;
 		}
 
-		setproctitle("nfsd-srv");
+		setproctitle("server");
 		nfssvc_flag = NFSSVC_NFSD;
 		nsd.nsd_nfsd = NULL;
-#ifdef KERBEROS
-		nsd.nsd_authstr = (char *)kt.dat;
+#ifdef NFSKERB
+		if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
+		    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
+		    syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
+		nsd.nsd_authstr = (u_char *)&kt;
+		nsd.nsd_authlen = sizeof (kt);
+		nsd.nsd_verfstr = (u_char *)&kverf;
+		nsd.nsd_verflen = sizeof (kverf);
 #endif
 		while (nfssvc(nfssvc_flag, &nsd) < 0) {
 			if (errno != ENEEDAUTH) {
@@ -273,14 +291,27 @@
 				exit(1);
 			}
 			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
-#ifdef KERBEROS
-			kt.length = nsd.nsd_authlen;
-			kt.mbz = 0;
-			(void)strcpy(inst, "*");
-			if (krb_rd_req(&kt, "rcmd",
-			    inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK &&
-			    krb_kntoln(&auth, lnam) == KSUCCESS &&
-			    (pwd = getpwnam(lnam)) != NULL) {
+#ifdef NFSKERB
+			/*
+			 * Get the Kerberos ticket out of the authenticator
+			 * verify it and convert the principal name to a user
+			 * name. The user name is then converted to a set of
+			 * user credentials via the password and group file.
+			 * Finally, decrypt the timestamp and validate it.
+			 * For more info see the IETF Draft "Authentication
+			 * in ONC RPC".
+			 */
+			kt.length = ntohl(kt.length);
+			if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
+			    kt.length > 0 && kt.length <=
+			    (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
+			    kin.w1 = NFS_KERBW1(kt);
+			    kt.mbz = 0;
+			    (void)strcpy(inst, "*");
+			    if (krb_rd_req(&kt, NFS_KERBSRV,
+				inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
+				krb_kntoln(&kauth, lnam) == KSUCCESS &&
+				(pwd = getpwnam(lnam)) != NULL) {
 				cr = &nsd.nsd_cr;
 				cr->cr_uid = pwd->pw_uid;
 				cr->cr_groups[0] = pwd->pw_gid;
@@ -301,9 +332,34 @@
 						break;
 				}
 				endgrent();
-				nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
+
+				/*
+				 * Get the timestamp verifier out of the
+				 * authenticator and verifier strings.
+				 */
+				kin.t1 = kverf.t1;
+				kin.t2 = kverf.t2;
+				kin.w2 = kverf.w2;
+				bzero((caddr_t)kivec, sizeof (kivec));
+				bcopy((caddr_t)kauth.session,
+				    (caddr_t)nsd.nsd_key,sizeof(kauth.session));
+
+				/*
+				 * Decrypt the timestamp verifier in CBC mode.
+				 */
+				XXX
+
+				/*
+				 * Validate the timestamp verifier, to
+				 * check that the session key is ok.
+				 */
+				nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
+				nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
+				nsd.nsd_ttl = ntohl(kout.w1);
+				if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
+				    nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
 			}
-#endif /* KERBEROS */
+#endif /* NFSKERB */
 		}
 		exit(0);
 	}
@@ -323,7 +379,8 @@
 			syslog(LOG_ERR, "can't bind udp addr");
 			exit(1);
 		}
-		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
+		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
+		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
 			syslog(LOG_ERR, "can't register with udp portmap");
 			exit(1);
 		}
@@ -403,7 +460,8 @@
 			syslog(LOG_ERR, "listen failed");
 			exit(1);
 		}
-		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
+		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
+		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
 			syslog(LOG_ERR, "can't register tcp with portmap");
 			exit(1);
 		}
@@ -492,7 +550,7 @@
 	if (connect_type_cnt == 0)
 		exit(0);
 
-	setproctitle("nfsd-master");
+	setproctitle("master");
 
 	/*
 	 * Loop forever accepting connections and passing the sockets
@@ -566,7 +624,7 @@
 void
 usage()
 {
-	(void)fprintf(stderr, "nfsd %s\n", USAGE);
+	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
 	exit(1);
 }
 
@@ -582,9 +640,10 @@
 	int signo;
 {
 
-	while (wait3(NULL, WNOHANG, NULL));
+	while (wait3(NULL, WNOHANG, NULL) > 0);
 }
 
+#ifdef __FreeBSD__
 void
 setproctitle(a)
 	char *a;
@@ -593,9 +652,10 @@
 	char buf[80];
 
 	cp = Argv[0];
-	(void)snprintf(buf, sizeof(buf), "%s", a);
+	(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
 	(void)strncpy(cp, buf, LastArg - cp);
 	cp += strlen(cp);
 	while (cp < LastArg)
 		*cp++ = '\0';
 }
+#endif	/* __FreeBSD__ */

-- 
Mark Murray                PGP key fingerprint = 80 36 6E 40 83 D6 8A 36
This .sig is umop ap!sdn.                        BC 06 EA 0E 7A F2 CE CE



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199705051650.SAA11805>