From owner-freebsd-current Mon May 5 09:52:55 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id JAA05474 for current-outgoing; Mon, 5 May 1997 09:52:55 -0700 (PDT) Received: from grackle.grondar.za (yd21+n7vLY2fcbEiIEzV4hyHweRbVfSd@grackle.grondar.za [196.7.18.131]) by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id JAA05386; Mon, 5 May 1997 09:51:08 -0700 (PDT) Received: from grackle.grondar.za (KCl6f/NkVEUf3tMCKadzs16aoo1r1Usd@localhost [127.0.0.1]) by grackle.grondar.za (8.8.5/8.8.4) with ESMTP id SAA11805; Mon, 5 May 1997 18:50:26 +0200 (SAT) Message-Id: <199705051650.SAA11805@grackle.grondar.za> To: rick@snowhite.cis.uoguelph.ca, wollman@freebsd.org, dfr@freebsd.org cc: current@freebsd.org Subject: Kerberised NFSD is broken. X-Face: "=q0"STs_81w9y4&#}>]hpQ-VBL.1^,QB{9u[05?&^k1*y#*OpIkS7b?V0Rs8qg]`Z}LBTa JT}q{S+z%%SR{~1@;Ybho~Ck.)PC/#3$lceQZ`O Sender: owner-current@freebsd.org X-Loop: FreeBSD.org Precedence: bulk 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 ...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 #endif #include -#include +#include #include -#ifdef KERBEROS +#ifdef NFSKERB #include #include #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