summaryrefslogtreecommitdiff
path: root/sys/nfs
diff options
context:
space:
mode:
authorThordur I. Bjornsson <thib@cvs.openbsd.org>2007-10-13 17:38:44 +0000
committerThordur I. Bjornsson <thib@cvs.openbsd.org>2007-10-13 17:38:44 +0000
commit03aa0da667eb224b857f57c160d3591493908b2b (patch)
tree72dfddec616fd537e2330a14662d1d4f6915dbbd /sys/nfs
parentee5aa9284d2c54b661f4c287b7aa777421036800 (diff)
Remove alot of dead kerberos code (add sane comments too).
Cleanup and partly redo the way we create the RPC header, by having nfsm_rpchead() do a bit more work. Right now this is pretty RPCAUTH_UNIX centric, but since it is the only auth method we support right now thats fine. Make sure we can never generate a zero xid, thats forbidden by the RFC. Misc cleanup. tested by a few.
Diffstat (limited to 'sys/nfs')
-rw-r--r--sys/nfs/nfs_socket.c75
-rw-r--r--sys/nfs/nfs_subs.c199
-rw-r--r--sys/nfs/nfs_var.h7
3 files changed, 91 insertions, 190 deletions
diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c
index b01c9f45369..8cf2daef3c4 100644
--- a/sys/nfs/nfs_socket.c
+++ b/sys/nfs/nfs_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_socket.c,v 1.51 2007/09/20 15:30:41 blambert Exp $ */
+/* $OpenBSD: nfs_socket.c,v 1.52 2007/10/13 17:38:43 thib Exp $ */
/* $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $ */
/*
@@ -836,16 +836,11 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
u_int32_t *tl;
int i;
struct nfsmount *nmp;
- struct mbuf *md, *mheadend;
- char nickv[RPCX_NICKVERF];
+ struct mbuf *md;
time_t reqtime, waituntil;
caddr_t dpos, cp2;
- int t1, s, error = 0, mrest_len, auth_len, auth_type;
- int trylater_delay, failed_auth = 0;
- int verf_len, verf_type;
- u_int32_t xid;
- char *auth_str, *verf_str;
- NFSKERBKEY_T key; /* save session key */
+ int t1, s, error = 0, mrest_len;
+ int trylater_delay;
trylater_delay = NFS_MINTIMEO;
@@ -863,36 +858,9 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
}
mrest_len = i;
- /*
- * Get the RPC header with authorization.
- */
-kerbauth:
- verf_str = auth_str = (char *)0;
- if (nmp->nm_flag & NFSMNT_KERB) {
- verf_str = nickv;
- verf_len = sizeof (nickv);
- auth_type = RPCAUTH_KERB4;
- bzero((caddr_t)key, sizeof (key));
- if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
- &auth_len, verf_str, verf_len)) {
- error = nfs_getauth(nmp, rep, cred, &auth_str,
- &auth_len, verf_str, &verf_len, key);
- if (error) {
- pool_put(&nfsreqpl, rep);
- m_freem(mrest);
- return (error);
- }
- }
- } else {
- auth_type = RPCAUTH_UNIX;
- auth_len = (((cred->cr_ngroups > nmp->nm_numgrps) ?
- nmp->nm_numgrps : cred->cr_ngroups) << 2) +
- 5 * NFSX_UNSIGNED;
- }
- m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
- auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
- if (auth_str)
- free(auth_str, M_TEMP);
+ /* Get the RPC header with authorization. */
+ nfsm_rpchead(rep, cred, RPCAUTH_UNIX, mrest, mrest_len);
+ m = rep->r_mreq;
/*
* For stream protocols, insert a Sun RPC Record Mark.
@@ -902,8 +870,7 @@ kerbauth:
*mtod(m, u_int32_t *) = htonl(0x80000000 |
(m->m_pkthdr.len - NFSX_UNSIGNED));
}
- rep->r_mreq = m;
- rep->r_xid = xid;
+
tryagain:
if (nmp->nm_flag & NFSMNT_SOFT)
rep->r_retry = nmp->nm_retry;
@@ -1001,16 +968,7 @@ tryagain:
if (*tl++ == rpc_msgdenied) {
if (*tl == rpc_mismatch)
error = EOPNOTSUPP;
- else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
- if (!failed_auth) {
- failed_auth++;
- mheadend->m_next = (struct mbuf *)0;
- m_freem(mrep);
- m_freem(rep->r_mreq);
- goto kerbauth;
- } else
- error = EAUTH;
- } else
+ else
error = EACCES;
m_freem(mrep);
m_freem(rep->r_mreq);
@@ -1019,16 +977,15 @@ tryagain:
}
/*
- * Grab any Kerberos verifier, otherwise just throw it away.
+ * Since we only support RPCAUTH_UNIX atm we step over the
+ * reply verifer type, and if the (error) case that there really
+ * is any data init, we advance over it.
*/
- verf_type = fxdr_unsigned(int, *tl++);
+ tl++; /* Step over verifer type */
i = fxdr_unsigned(int32_t, *tl);
- if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
- error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
- if (error)
- goto nfsmout;
- } else if (i > 0)
- nfsm_adv(nfsm_rndup(i));
+ if (i > 0)
+ nfsm_adv(nfsm_rndup(i)); /* Should not happen */
+
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
/* 0 == ok */
if (*tl == 0) {
diff --git a/sys/nfs/nfs_subs.c b/sys/nfs/nfs_subs.c
index 796e7f81ee8..2938cb488ee 100644
--- a/sys/nfs/nfs_subs.c
+++ b/sys/nfs/nfs_subs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_subs.c,v 1.64 2007/10/08 17:39:52 deraadt Exp $ */
+/* $OpenBSD: nfs_subs.c,v 1.65 2007/10/13 17:38:43 thib Exp $ */
/* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */
/*
@@ -93,7 +93,6 @@ u_int32_t nfs_prog, nfs_true, nfs_false;
/* And other global data */
static u_int32_t nfs_xid = 0;
-static u_int32_t nfs_xid_touched = 0;
nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
NFCHR, NFNON };
nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
@@ -555,158 +554,104 @@ nfsm_reqh(vp, procid, hsiz, bposp)
/*
* Build the RPC header and fill in the authorization info.
- * The authorization string argument is only used when the credentials
- * come from outside of the kernel.
- * Returns the head of the mbuf list.
+ * Right now we are pretty centric around RPCAUTH_UNIX, in the
+ * future, this function will need some love to be able to handle
+ * other authorization methods, such as Kerberos.
*/
-struct mbuf *
-nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
- verf_str, mrest, mrest_len, mbp, xidp)
- struct ucred *cr;
- int nmflag;
- int procid;
- int auth_type;
- int auth_len;
- char *auth_str;
- int verf_len;
- char *verf_str;
- struct mbuf *mrest;
- int mrest_len;
- struct mbuf **mbp;
- u_int32_t *xidp;
+void
+nfsm_rpchead(struct nfsreq *req, struct ucred *cr, int auth_type,
+ struct mbuf *mrest, int mrest_len)
{
- struct mbuf *mb;
- u_int32_t *tl;
- caddr_t bpos;
- int i;
- struct mbuf *mreq, *mb2;
- int siz, grpsiz, authsiz;
+ struct mbuf *mb, *mb2;
+ u_int32_t *tl;
+ u_int32_t xid;
+ caddr_t bpos;
+ int i, authsiz, auth_len, ngroups;
- authsiz = nfsm_rndup(auth_len);
+ KASSERT(auth_type == RPCAUTH_UNIX);
+
+ /*
+ * RPCAUTH_UNIX fits in an hdr mbuf, in the future other
+ * authorization methods need to figure out there own sizes
+ * and allocate and chain mbuf's accorindgly.
+ */
MGETHDR(mb, M_WAIT, MT_DATA);
- if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
- MCLGET(mb, M_WAIT);
- } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
+
+ /*
+ * We need to start out by finding how big the authorization cred
+ * and verifer are for the auth_type, to be able to correctly
+ * align the mbuf header/chain.
+ */
+ switch (auth_type) {
+ case RPCAUTH_UNIX:
+ /*
+ * In the RPCAUTH_UNIX case, the size is the static
+ * part as shown in RFC1831 + the number of groups,
+ * RPCAUTH_UNIX has a zero verifer.
+ */
+ if (cr->cr_ngroups > req->r_nmp->nm_numgrps)
+ ngroups = req->r_nmp->nm_numgrps;
+ else
+ ngroups = cr->cr_ngroups;
+
+ auth_len = (ngroups << 2) + 5 * NFSX_UNSIGNED;
+ authsiz = nfsm_rndup(auth_len);
+ /* The authorization size + the size of the static part */
MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
- } else {
- MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
+ break;
}
+
mb->m_len = 0;
- mreq = mb;
bpos = mtod(mb, caddr_t);
- /*
- * First the RPC header.
- */
- nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
+ /* First the RPC header. */
+ nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
/* Get a new (non-zero) xid */
-
- if ((nfs_xid == 0) && (nfs_xid_touched == 0)) {
- nfs_xid = arc4random();
- nfs_xid_touched = 1;
- } else {
- while ((*xidp = arc4random() % 256) == 0)
+ do {
+ while ((xid = arc4random() % 256) == 0)
;
- nfs_xid += *xidp;
- }
-
- *tl++ = *xidp = txdr_unsigned(nfs_xid);
+ nfs_xid += xid;
+ } while (nfs_xid == 0);
+
+
+ *tl++ = req->r_xid = txdr_unsigned(nfs_xid);
*tl++ = rpc_call;
*tl++ = rpc_vers;
- *tl++ = txdr_unsigned(NFS_PROG);
- if (nmflag & NFSMNT_NFSV3)
+ *tl++ = nfs_prog;
+ if (ISSET(req->r_nmp->nm_flag, NFSMNT_NFSV3)) {
*tl++ = txdr_unsigned(NFS_VER3);
- else
+ *tl = txdr_unsigned(req->r_procnum);
+ } else {
*tl++ = txdr_unsigned(NFS_VER2);
- if (nmflag & NFSMNT_NFSV3)
- *tl++ = txdr_unsigned(procid);
- else
- *tl++ = txdr_unsigned(nfsv2_procid[procid]);
+ *tl = txdr_unsigned(nfsv2_procid[req->r_procnum]);
+ }
- /*
- * And then the authorization cred.
- */
- *tl++ = txdr_unsigned(auth_type);
- *tl = txdr_unsigned(authsiz);
+ /* The Authorization cred and its verifier */
switch (auth_type) {
case RPCAUTH_UNIX:
- nfsm_build(tl, u_int32_t *, auth_len);
- *tl++ = 0; /* stamp ?? */
+ nfsm_build(tl, u_int32_t *, auth_len + 4 * NFSX_UNSIGNED);
+ *tl++ = txdr_unsigned(RPCAUTH_UNIX);
+ *tl++ = txdr_unsigned(authsiz);
+
+ /* The authorization cred */
+ *tl++ = 0; /* stamp */
*tl++ = 0; /* NULL hostname */
*tl++ = txdr_unsigned(cr->cr_uid);
*tl++ = txdr_unsigned(cr->cr_gid);
- grpsiz = (auth_len >> 2) - 5;
- *tl++ = txdr_unsigned(grpsiz);
- for (i = 0; i < grpsiz; i++)
+ *tl++ = txdr_unsigned(ngroups);
+ for (i = 0; i < ngroups; i++)
*tl++ = txdr_unsigned(cr->cr_groups[i]);
- break;
- case RPCAUTH_KERB4:
- siz = auth_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_WAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_WAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(auth_str, bpos, i);
- mb->m_len += i;
- auth_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- break;
- };
-
- /*
- * And the verifier...
- */
- nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (verf_str) {
- *tl++ = txdr_unsigned(RPCAUTH_KERB4);
- *tl = txdr_unsigned(verf_len);
- siz = verf_len;
- while (siz > 0) {
- if (M_TRAILINGSPACE(mb) == 0) {
- MGET(mb2, M_WAIT, MT_DATA);
- if (siz >= MINCLSIZE)
- MCLGET(mb2, M_WAIT);
- mb->m_next = mb2;
- mb = mb2;
- mb->m_len = 0;
- bpos = mtod(mb, caddr_t);
- }
- i = min(siz, M_TRAILINGSPACE(mb));
- bcopy(verf_str, bpos, i);
- mb->m_len += i;
- verf_str += i;
- bpos += i;
- siz -= i;
- }
- if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
- for (i = 0; i < siz; i++)
- *bpos++ = '\0';
- mb->m_len += siz;
- }
- } else {
+ /* The authorization verifier */
*tl++ = txdr_unsigned(RPCAUTH_NULL);
*tl = 0;
+ break;
}
+
mb->m_next = mrest;
- mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
- mreq->m_pkthdr.rcvif = (struct ifnet *)0;
- *mbp = mb;
- return (mreq);
+ mb->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
+ mb->m_pkthdr.rcvif = NULL;
+ req->r_mreq = mb;
}
/*
diff --git a/sys/nfs/nfs_var.h b/sys/nfs/nfs_var.h
index 7b2302d5134..ef208b888c1 100644
--- a/sys/nfs/nfs_var.h
+++ b/sys/nfs/nfs_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_var.h,v 1.28 2007/06/21 22:59:49 thib Exp $ */
+/* $OpenBSD: nfs_var.h,v 1.29 2007/10/13 17:38:43 thib Exp $ */
/* $NetBSD: nfs_var.h,v 1.3 1996/02/18 11:53:54 fvdl Exp $ */
/*
@@ -238,9 +238,8 @@ void nfsrv_cleancache(void);
/* nfs_subs.c */
struct mbuf *nfsm_reqh(struct vnode *, u_long, int, caddr_t *);
-struct mbuf *nfsm_rpchead(struct ucred *, int, int, int, int, char *, int,
- char *, struct mbuf *, int, struct mbuf **,
- u_int32_t *);
+void nfsm_rpchead(struct nfsreq *, struct ucred *, int, struct mbuf *, int);
+
int nfsm_mbuftouio(struct mbuf **, struct uio *, int, caddr_t *);
int nfsm_uiotombuf(struct uio *, struct mbuf **, int, caddr_t *);
int nfsm_disct(struct mbuf **, caddr_t *, int, int, caddr_t *);