nfsd: Add support for the SP4_MACH_CRED case in ExchangeID
Commit f4179ad46f
added support for operation bitmaps for
NFSv4.1/4.2. This commit uses those to implement the SP4_MACH_CRED
case for the NFSv4.1/4.2 ExchangeID operation since the Linux
NFSv4.1/4.2 client is now using this for Kerberized mounts.
The Linux Kerberized NFSv4.1/4.2 mounts currently work without
support for this because Linux will fall back to SP4_NONE,
but there is no guarantee this fallback will work forever.
This commit only affects Kerberized NFSv4.1/4.2 mounts from
Linux at this time.
MFC after: 3 months
This commit is contained in:
parent
66fbc19fbd
commit
ff2f1f691c
@ -99,7 +99,7 @@ int nfsrv_setclient(struct nfsrv_descript *, struct nfsclient **,
|
|||||||
nfsquad_t *, nfsquad_t *, NFSPROC_T *);
|
nfsquad_t *, nfsquad_t *, NFSPROC_T *);
|
||||||
int nfsrv_getclient(nfsquad_t, int, struct nfsclient **, struct nfsdsession *,
|
int nfsrv_getclient(nfsquad_t, int, struct nfsclient **, struct nfsdsession *,
|
||||||
nfsquad_t, uint32_t, struct nfsrv_descript *, NFSPROC_T *);
|
nfsquad_t, uint32_t, struct nfsrv_descript *, NFSPROC_T *);
|
||||||
int nfsrv_destroyclient(nfsquad_t, NFSPROC_T *);
|
int nfsrv_destroyclient(struct nfsrv_descript *, nfsquad_t, NFSPROC_T *);
|
||||||
int nfsrv_destroysession(struct nfsrv_descript *, uint8_t *);
|
int nfsrv_destroysession(struct nfsrv_descript *, uint8_t *);
|
||||||
int nfsrv_bindconnsess(struct nfsrv_descript *, uint8_t *, int *);
|
int nfsrv_bindconnsess(struct nfsrv_descript *, uint8_t *, int *);
|
||||||
int nfsrv_freestateid(struct nfsrv_descript *, nfsv4stateid_t *, NFSPROC_T *);
|
int nfsrv_freestateid(struct nfsrv_descript *, nfsv4stateid_t *, NFSPROC_T *);
|
||||||
|
@ -105,6 +105,8 @@ struct nfsclient {
|
|||||||
time_t lc_delegtime; /* Old deleg expiry (sec) */
|
time_t lc_delegtime; /* Old deleg expiry (sec) */
|
||||||
nfsquad_t lc_clientid; /* 64 bit clientid */
|
nfsquad_t lc_clientid; /* 64 bit clientid */
|
||||||
nfsquad_t lc_confirm; /* 64 bit confirm value */
|
nfsquad_t lc_confirm; /* 64 bit confirm value */
|
||||||
|
nfsopbit_t lc_mustops; /* Must ops SP4_MACH_CRED */
|
||||||
|
nfsopbit_t lc_allowops; /* Allowed ops SP4_MACH_CRED */
|
||||||
u_int32_t lc_program; /* RPC Program # */
|
u_int32_t lc_program; /* RPC Program # */
|
||||||
u_int32_t lc_callback; /* Callback id */
|
u_int32_t lc_callback; /* Callback id */
|
||||||
u_int32_t lc_stateindex; /* Current state index# */
|
u_int32_t lc_stateindex; /* Current state index# */
|
||||||
|
@ -108,6 +108,7 @@ extern time_t nfsdev_time;
|
|||||||
extern int nfsrv_writerpc[NFS_NPROCS];
|
extern int nfsrv_writerpc[NFS_NPROCS];
|
||||||
extern volatile int nfsrv_devidcnt;
|
extern volatile int nfsrv_devidcnt;
|
||||||
extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
|
extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
|
||||||
|
extern int nfsd_debuglevel;
|
||||||
|
|
||||||
NFSD_VNET_DECLARE(struct proc *, nfsd_master_proc);
|
NFSD_VNET_DECLARE(struct proc *, nfsd_master_proc);
|
||||||
|
|
||||||
@ -126,7 +127,9 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
|
|||||||
{
|
{
|
||||||
struct nfsrv_descript nd;
|
struct nfsrv_descript nd;
|
||||||
struct nfsrvcache *rp = NULL;
|
struct nfsrvcache *rp = NULL;
|
||||||
int cacherep, credflavor;
|
rpc_gss_rawcred_t *rcredp;
|
||||||
|
int cacherep, credflavor, i, j;
|
||||||
|
u_char *p;
|
||||||
#ifdef KERN_TLS
|
#ifdef KERN_TLS
|
||||||
u_int maxlen;
|
u_int maxlen;
|
||||||
#endif
|
#endif
|
||||||
@ -245,6 +248,58 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Acquire the principal name for the RPCSEC_GSS cases. */
|
||||||
|
if ((nd.nd_flag & (ND_NFSV4 | ND_GSS)) == (ND_NFSV4 | ND_GSS)) {
|
||||||
|
rcredp = NULL;
|
||||||
|
rpc_gss_getcred_call(rqst, &rcredp, NULL, NULL);
|
||||||
|
/*
|
||||||
|
* The exported principal name consists of:
|
||||||
|
* - TOK_ID bytes with value of 4 and 1.
|
||||||
|
* - 2 byte mech length
|
||||||
|
* - mech
|
||||||
|
* - 4 byte principal name length
|
||||||
|
* - principal name
|
||||||
|
* A call to gss_import_name() would be an
|
||||||
|
* upcall to the gssd, so parse it here.
|
||||||
|
* See lib/libgssapi/gss_import_name.c for the
|
||||||
|
* above format.
|
||||||
|
*/
|
||||||
|
if (rcredp != NULL &&
|
||||||
|
rcredp->client_principal->len > 4 &&
|
||||||
|
rcredp->client_principal->name[0] == 4 &&
|
||||||
|
rcredp->client_principal->name[1] == 1) {
|
||||||
|
/* Skip over the mech. */
|
||||||
|
p = &rcredp->client_principal->name[2];
|
||||||
|
i = (p[0] << 8) | p[1];
|
||||||
|
p += i + 2;
|
||||||
|
i += 4;
|
||||||
|
/*
|
||||||
|
* Set "j" to a bogus length so that the
|
||||||
|
* "i + j" check will fail unless the below
|
||||||
|
* code sets "j" correctly.
|
||||||
|
*/
|
||||||
|
j = rcredp->client_principal->len;
|
||||||
|
if (rcredp->client_principal->len > i + 4) {
|
||||||
|
j = (p[0] << 24) | (p[1] << 16) |
|
||||||
|
(p[2] << 8) | p[3];
|
||||||
|
i += 4;
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
if (i + j == rcredp->client_principal->len) {
|
||||||
|
nd.nd_principal = malloc(j + 1, M_TEMP,
|
||||||
|
M_WAITOK);
|
||||||
|
nd.nd_princlen = j;
|
||||||
|
memcpy(nd.nd_principal, p, j);
|
||||||
|
nd.nd_principal[j] = '\0';
|
||||||
|
NFSD_DEBUG(1, "nfssvc_program: "
|
||||||
|
"principal=%s\n", nd.nd_principal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nd.nd_princlen == 0)
|
||||||
|
printf("nfssvc_program: cannot get RPCSEC_GSS "
|
||||||
|
"principal name\n");
|
||||||
|
}
|
||||||
|
|
||||||
if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0) {
|
if ((xprt->xp_tls & RPCTLS_FLAGS_HANDSHAKE) != 0) {
|
||||||
nd.nd_flag |= ND_TLS;
|
nd.nd_flag |= ND_TLS;
|
||||||
if ((xprt->xp_tls & RPCTLS_FLAGS_VERIFIED) != 0)
|
if ((xprt->xp_tls & RPCTLS_FLAGS_VERIFIED) != 0)
|
||||||
@ -334,6 +389,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
|
|||||||
svc_freereq(rqst);
|
svc_freereq(rqst);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
free(nd.nd_principal, M_TEMP);
|
||||||
NFSD_CURVNET_RESTORE();
|
NFSD_CURVNET_RESTORE();
|
||||||
ast_kclear(curthread);
|
ast_kclear(curthread);
|
||||||
NFSEXITCODE(0);
|
NFSEXITCODE(0);
|
||||||
|
@ -4282,6 +4282,7 @@ nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
uint8_t *verf;
|
uint8_t *verf;
|
||||||
uint32_t sp4type, v41flags;
|
uint32_t sp4type, v41flags;
|
||||||
struct timespec verstime;
|
struct timespec verstime;
|
||||||
|
nfsopbit_t mustops, allowops;
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
struct sockaddr_in *sin, *rin;
|
struct sockaddr_in *sin, *rin;
|
||||||
#endif
|
#endif
|
||||||
@ -4376,7 +4377,22 @@ nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
else
|
else
|
||||||
v41flags = NFSV4EXCH_USEPNFSMDS;
|
v41flags = NFSV4EXCH_USEPNFSMDS;
|
||||||
sp4type = fxdr_unsigned(uint32_t, *tl);
|
sp4type = fxdr_unsigned(uint32_t, *tl);
|
||||||
if (sp4type != NFSV4EXCH_SP4NONE) {
|
if (sp4type == NFSV4EXCH_SP4MACHCRED) {
|
||||||
|
if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_GSSPRIVACY)) == 0 ||
|
||||||
|
nd->nd_princlen == 0)
|
||||||
|
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||||
|
if (nd->nd_repstat == 0)
|
||||||
|
nd->nd_repstat = nfsrv_getopbits(nd, &mustops, NULL);
|
||||||
|
if (nd->nd_repstat == 0)
|
||||||
|
nd->nd_repstat = nfsrv_getopbits(nd, &allowops, NULL);
|
||||||
|
if (nd->nd_repstat != 0)
|
||||||
|
goto nfsmout;
|
||||||
|
NFSOPBIT_CLRNOTMUST(&mustops);
|
||||||
|
NFSSET_OPBIT(&clp->lc_mustops, &mustops);
|
||||||
|
NFSOPBIT_CLRNOTALLOWED(&allowops);
|
||||||
|
NFSSET_OPBIT(&clp->lc_allowops, &allowops);
|
||||||
|
clp->lc_flags |= LCL_MACHCRED;
|
||||||
|
} else if (sp4type != NFSV4EXCH_SP4NONE) {
|
||||||
nd->nd_repstat = NFSERR_NOTSUPP;
|
nd->nd_repstat = NFSERR_NOTSUPP;
|
||||||
goto nfsmout;
|
goto nfsmout;
|
||||||
}
|
}
|
||||||
@ -4398,12 +4414,17 @@ nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
if (nd->nd_repstat == 0) {
|
if (nd->nd_repstat == 0) {
|
||||||
if (confirm.lval[1] != 0)
|
if (confirm.lval[1] != 0)
|
||||||
v41flags |= NFSV4EXCH_CONFIRMEDR;
|
v41flags |= NFSV4EXCH_CONFIRMEDR;
|
||||||
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + 3 * NFSX_UNSIGNED);
|
NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 3 * NFSX_UNSIGNED);
|
||||||
*tl++ = clientid.lval[0]; /* ClientID */
|
*tl++ = clientid.lval[0]; /* ClientID */
|
||||||
*tl++ = clientid.lval[1];
|
*tl++ = clientid.lval[1];
|
||||||
*tl++ = txdr_unsigned(confirm.lval[0]); /* SequenceID */
|
*tl++ = txdr_unsigned(confirm.lval[0]); /* SequenceID */
|
||||||
*tl++ = txdr_unsigned(v41flags); /* Exch flags */
|
*tl++ = txdr_unsigned(v41flags); /* Exch flags */
|
||||||
*tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE); /* No SSV */
|
*tl = txdr_unsigned(sp4type); /* No SSV */
|
||||||
|
if (sp4type == NFSV4EXCH_SP4MACHCRED) {
|
||||||
|
nfsrv_putopbit(nd, &mustops);
|
||||||
|
nfsrv_putopbit(nd, &allowops);
|
||||||
|
}
|
||||||
|
NFSM_BUILD(tl, uint32_t *, NFSX_HYPER);
|
||||||
txdr_hyper(nfsrv_owner_minor, tl); /* Owner Minor */
|
txdr_hyper(nfsrv_owner_minor, tl); /* Owner Minor */
|
||||||
if (nfsrv_owner_major[0] != 0)
|
if (nfsrv_owner_major[0] != 0)
|
||||||
s = nfsrv_owner_major;
|
s = nfsrv_owner_major;
|
||||||
@ -4642,7 +4663,7 @@ nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram,
|
|||||||
NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
||||||
clientid.lval[0] = *tl++;
|
clientid.lval[0] = *tl++;
|
||||||
clientid.lval[1] = *tl;
|
clientid.lval[1] = *tl;
|
||||||
nd->nd_repstat = nfsrv_destroyclient(clientid, p);
|
nd->nd_repstat = nfsrv_destroyclient(nd, clientid, p);
|
||||||
nfsmout:
|
nfsmout:
|
||||||
NFSEXITCODE2(error, nd);
|
NFSEXITCODE2(error, nd);
|
||||||
return (error);
|
return (error);
|
||||||
|
@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <fs/nfs/nfsport.h>
|
#include <fs/nfs/nfsport.h>
|
||||||
|
|
||||||
|
#include <security/mac/mac_framework.h>
|
||||||
|
|
||||||
extern struct nfsrvfh nfs_pubfh;
|
extern struct nfsrvfh nfs_pubfh;
|
||||||
extern int nfs_pubfhset;
|
extern int nfs_pubfhset;
|
||||||
extern struct nfsv4lock nfsv4rootfs_lock;
|
extern struct nfsv4lock nfsv4rootfs_lock;
|
||||||
@ -466,6 +468,8 @@ static int nfsv3to4op[NFS_V3NPROCS] = {
|
|||||||
static struct mtx nfsrvd_statmtx;
|
static struct mtx nfsrvd_statmtx;
|
||||||
MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
|
MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
|
||||||
|
|
||||||
|
static struct ucred *nfsrv_createrootcred(void);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nfsrvd_statstart(int op, struct bintime *now)
|
nfsrvd_statstart(int op, struct bintime *now)
|
||||||
{
|
{
|
||||||
@ -715,7 +719,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
|
|||||||
vnode_t vp, nvp, savevp;
|
vnode_t vp, nvp, savevp;
|
||||||
struct nfsrvfh fh;
|
struct nfsrvfh fh;
|
||||||
mount_t new_mp, temp_mp = NULL;
|
mount_t new_mp, temp_mp = NULL;
|
||||||
struct ucred *credanon;
|
struct ucred *credanon, *rootcred, *savecred;
|
||||||
struct nfsexstuff nes, vpnes, savevpnes;
|
struct nfsexstuff nes, vpnes, savevpnes;
|
||||||
fsid_t cur_fsid, save_fsid;
|
fsid_t cur_fsid, save_fsid;
|
||||||
static u_int64_t compref = 0;
|
static u_int64_t compref = 0;
|
||||||
@ -726,6 +730,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
|
|||||||
int bextpg, bextpgsiz;
|
int bextpg, bextpgsiz;
|
||||||
|
|
||||||
p = curthread;
|
p = curthread;
|
||||||
|
rootcred = savecred = NULL;
|
||||||
|
|
||||||
/* Check for and optionally clear the no space flags for DSs. */
|
/* Check for and optionally clear the no space flags for DSs. */
|
||||||
nfsrv_checknospc();
|
nfsrv_checknospc();
|
||||||
@ -967,6 +972,30 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
|
|||||||
retops++;
|
retops++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for the case of SP4_MACH_CRED and an operation in
|
||||||
|
* the allow set. For these operations, replace nd_cred with
|
||||||
|
* root credentials so that the operation will not fail due
|
||||||
|
* to credentials.
|
||||||
|
* NB: ND_MACHCRED is set by Sequence when the ClientID
|
||||||
|
* specifies LCL_MACHCRED and the RPC is being performed
|
||||||
|
* via krb5i or krb5p using the machine principal.
|
||||||
|
*/
|
||||||
|
if ((nd->nd_flag & ND_MACHCRED) != 0) {
|
||||||
|
if (NFSISSET_OPBIT(&nd->nd_allowops, op)) {
|
||||||
|
/* Replace nd_cred with root creds. */
|
||||||
|
if (rootcred == NULL)
|
||||||
|
rootcred = nfsrv_createrootcred();
|
||||||
|
if (savecred == NULL)
|
||||||
|
savecred = nd->nd_cred;
|
||||||
|
nd->nd_cred = rootcred;
|
||||||
|
} else if (savecred != NULL) {
|
||||||
|
nd->nd_cred = savecred;
|
||||||
|
savecred = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (nfsv4_opflag[op].savereply)
|
if (nfsv4_opflag[op].savereply)
|
||||||
nd->nd_flag |= ND_SAVEREPLY;
|
nd->nd_flag |= ND_SAVEREPLY;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -1379,9 +1408,33 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
|
|||||||
vrele(vp);
|
vrele(vp);
|
||||||
if (savevp)
|
if (savevp)
|
||||||
vrele(savevp);
|
vrele(savevp);
|
||||||
|
if (savecred != NULL)
|
||||||
|
nd->nd_cred = savecred;
|
||||||
|
if (rootcred != NULL)
|
||||||
|
crfree(rootcred);
|
||||||
NFSLOCKV4ROOTMUTEX();
|
NFSLOCKV4ROOTMUTEX();
|
||||||
nfsv4_relref(&nfsv4rootfs_lock);
|
nfsv4_relref(&nfsv4rootfs_lock);
|
||||||
NFSUNLOCKV4ROOTMUTEX();
|
NFSUNLOCKV4ROOTMUTEX();
|
||||||
|
|
||||||
NFSEXITCODE2(0, nd);
|
NFSEXITCODE2(0, nd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create a credential for "root". */
|
||||||
|
static struct ucred *
|
||||||
|
nfsrv_createrootcred(void)
|
||||||
|
{
|
||||||
|
struct ucred *cr;
|
||||||
|
gid_t grp;
|
||||||
|
|
||||||
|
cr = crget();
|
||||||
|
cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT;
|
||||||
|
grp = GID_WHEEL;
|
||||||
|
crsetgroups(cr, 1, &grp);
|
||||||
|
cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
|
||||||
|
cr->cr_prison = curthread->td_ucred->cr_prison;
|
||||||
|
prison_hold(cr->cr_prison);
|
||||||
|
#ifdef MAC
|
||||||
|
mac_cred_associate_nfsd(cr);
|
||||||
|
#endif
|
||||||
|
return (cr);
|
||||||
|
}
|
||||||
|
@ -184,7 +184,7 @@ static int nfsrv_delegconflict(struct nfsstate *stp, int *haslockp,
|
|||||||
NFSPROC_T *p, vnode_t vp);
|
NFSPROC_T *p, vnode_t vp);
|
||||||
static int nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
|
static int nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
|
||||||
struct nfsclient *clp, int *haslockp, NFSPROC_T *p);
|
struct nfsclient *clp, int *haslockp, NFSPROC_T *p);
|
||||||
static int nfsrv_notsamecredname(struct nfsrv_descript *nd,
|
static int nfsrv_notsamecredname(int op, struct nfsrv_descript *nd,
|
||||||
struct nfsclient *clp);
|
struct nfsclient *clp);
|
||||||
static time_t nfsrv_leaseexpiry(void);
|
static time_t nfsrv_leaseexpiry(void);
|
||||||
static void nfsrv_delaydelegtimeout(struct nfsstate *stp);
|
static void nfsrv_delaydelegtimeout(struct nfsstate *stp);
|
||||||
@ -205,7 +205,8 @@ static void nfsrv_locallock_commit(struct nfslockfile *lfp, int flags,
|
|||||||
static void nfsrv_locklf(struct nfslockfile *lfp);
|
static void nfsrv_locklf(struct nfslockfile *lfp);
|
||||||
static void nfsrv_unlocklf(struct nfslockfile *lfp);
|
static void nfsrv_unlocklf(struct nfslockfile *lfp);
|
||||||
static struct nfsdsession *nfsrv_findsession(uint8_t *sessionid);
|
static struct nfsdsession *nfsrv_findsession(uint8_t *sessionid);
|
||||||
static int nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid);
|
static int nfsrv_freesession(struct nfsrv_descript *nd, struct nfsdsession *sep,
|
||||||
|
uint8_t *sessionid);
|
||||||
static int nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
|
static int nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
|
||||||
int dont_replycache, struct nfsdsession **sepp, int *slotposp);
|
int dont_replycache, struct nfsdsession **sepp, int *slotposp);
|
||||||
static int nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp);
|
static int nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp);
|
||||||
@ -239,6 +240,8 @@ static int nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf,
|
|||||||
vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p,
|
vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p,
|
||||||
vnode_t *tvpp);
|
vnode_t *tvpp);
|
||||||
static struct nfsdevice *nfsrv_findmirroredds(struct nfsmount *nmp);
|
static struct nfsdevice *nfsrv_findmirroredds(struct nfsmount *nmp);
|
||||||
|
static int nfsrv_checkmachcred(int op, struct nfsrv_descript *nd,
|
||||||
|
struct nfsclient *clp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the client list for a match and either return the current one,
|
* Scan the client list for a match and either return the current one,
|
||||||
@ -378,7 +381,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
|
|||||||
/*
|
/*
|
||||||
* Now, handle the cases where the id is already issued.
|
* Now, handle the cases where the id is already issued.
|
||||||
*/
|
*/
|
||||||
if (nfsrv_notsamecredname(nd, clp)) {
|
if (nfsrv_notsamecredname(NFSV4OP_EXCHANGEID, nd, clp)) {
|
||||||
/*
|
/*
|
||||||
* Check to see if there is expired state that should go away.
|
* Check to see if there is expired state that should go away.
|
||||||
*/
|
*/
|
||||||
@ -447,7 +450,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
|
|||||||
|
|
||||||
/* Get rid of all sessions on this clientid. */
|
/* Get rid of all sessions on this clientid. */
|
||||||
LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) {
|
LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) {
|
||||||
ret = nfsrv_freesession(sep, NULL);
|
ret = nfsrv_freesession(NULL, sep, NULL);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
printf("nfsrv_setclient: verifier changed free"
|
printf("nfsrv_setclient: verifier changed free"
|
||||||
" session failed=%d\n", ret);
|
" session failed=%d\n", ret);
|
||||||
@ -706,7 +709,8 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
|
|||||||
} else if ((nd->nd_flag & ND_NFSV41) == 0 &&
|
} else if ((nd->nd_flag & ND_NFSV41) == 0 &&
|
||||||
clp->lc_confirm.qval != confirm.qval)
|
clp->lc_confirm.qval != confirm.qval)
|
||||||
error = NFSERR_STALECLIENTID;
|
error = NFSERR_STALECLIENTID;
|
||||||
if (error == 0 && nfsrv_notsamecredname(nd, clp))
|
if (error == 0 && nfsrv_notsamecredname(NFSV4OP_CREATESESSION,
|
||||||
|
nd, clp))
|
||||||
error = NFSERR_CLIDINUSE;
|
error = NFSERR_CLIDINUSE;
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
@ -779,7 +783,7 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
|
|||||||
* If called by the Renew Op, we must check the principal.
|
* If called by the Renew Op, we must check the principal.
|
||||||
*/
|
*/
|
||||||
if (!error && (opflags & CLOPS_RENEWOP)) {
|
if (!error && (opflags & CLOPS_RENEWOP)) {
|
||||||
if (nfsrv_notsamecredname(nd, clp)) {
|
if (nfsrv_notsamecredname(0, nd, clp)) {
|
||||||
doneok = 0;
|
doneok = 0;
|
||||||
for (i = 0; i < nfsrv_statehashsize && doneok == 0; i++) {
|
for (i = 0; i < nfsrv_statehashsize && doneok == 0; i++) {
|
||||||
LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
|
LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
|
||||||
@ -819,7 +823,7 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
|
|||||||
* Perform the NFSv4.1 destroy clientid.
|
* Perform the NFSv4.1 destroy clientid.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p)
|
nfsrv_destroyclient(struct nfsrv_descript *nd, nfsquad_t clientid, NFSPROC_T *p)
|
||||||
{
|
{
|
||||||
struct nfsclient *clp;
|
struct nfsclient *clp;
|
||||||
struct nfsclienthashhead *hp;
|
struct nfsclienthashhead *hp;
|
||||||
@ -852,6 +856,15 @@ nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for the SP4_MACH_CRED case. */
|
||||||
|
error = nfsrv_checkmachcred(NFSV4OP_DESTROYCLIENTID, nd, clp);
|
||||||
|
if (error != 0) {
|
||||||
|
NFSLOCKV4ROOTMUTEX();
|
||||||
|
nfsv4_unlock(&nfsv4rootfs_lock, 1);
|
||||||
|
NFSUNLOCKV4ROOTMUTEX();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free up all layouts on the clientid. Should the client return the
|
* Free up all layouts on the clientid. Should the client return the
|
||||||
* layouts?
|
* layouts?
|
||||||
@ -1374,7 +1387,7 @@ nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p)
|
|||||||
nfsrv_freeopenowner(stp, 1, p);
|
nfsrv_freeopenowner(stp, 1, p);
|
||||||
if ((clp->lc_flags & LCL_ADMINREVOKED) == 0)
|
if ((clp->lc_flags & LCL_ADMINREVOKED) == 0)
|
||||||
LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep)
|
LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep)
|
||||||
(void)nfsrv_freesession(sep, NULL);
|
(void)nfsrv_freesession(NULL, sep, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4605,7 +4618,7 @@ nfsrv_docallback(struct nfsclient *clp, int procnum, nfsv4stateid_t *stateidp,
|
|||||||
if (procnum != NFSV4PROC_CBNULL)
|
if (procnum != NFSV4PROC_CBNULL)
|
||||||
nfsv4_freeslot(&sep->sess_cbsess, slotpos,
|
nfsv4_freeslot(&sep->sess_cbsess, slotpos,
|
||||||
true);
|
true);
|
||||||
nfsrv_freesession(sep, NULL);
|
nfsrv_freesession(NULL, sep, NULL);
|
||||||
} else if (nd->nd_procnum == NFSV4PROC_CBNULL)
|
} else if (nd->nd_procnum == NFSV4PROC_CBNULL)
|
||||||
error = newnfs_connect(NULL, &clp->lc_req, cred,
|
error = newnfs_connect(NULL, &clp->lc_req, cred,
|
||||||
NULL, 1, dotls, &clp->lc_req.nr_client);
|
NULL, 1, dotls, &clp->lc_req.nr_client);
|
||||||
@ -4654,7 +4667,7 @@ nfsrv_docallback(struct nfsclient *clp, int procnum, nfsv4stateid_t *stateidp,
|
|||||||
nfsv4_freeslot(&sep->sess_cbsess, slotpos,
|
nfsv4_freeslot(&sep->sess_cbsess, slotpos,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
nfsrv_freesession(sep, NULL);
|
nfsrv_freesession(NULL, sep, NULL);
|
||||||
} else
|
} else
|
||||||
error = newnfs_request(nd, NULL, clp, &clp->lc_req,
|
error = newnfs_request(nd, NULL, clp, &clp->lc_req,
|
||||||
NULL, NULL, cred, clp->lc_program,
|
NULL, NULL, cred, clp->lc_program,
|
||||||
@ -5877,12 +5890,18 @@ nfsrv_throwawayopens(NFSPROC_T *p)
|
|||||||
/*
|
/*
|
||||||
* This function checks to see if the credentials are the same.
|
* This function checks to see if the credentials are the same.
|
||||||
* The check for same credentials is needed for state management operations
|
* The check for same credentials is needed for state management operations
|
||||||
* for NFSv4.0 where 1 is returned if not same, 0 is returned otherwise.
|
* for NFSv4.0 or NFSv4.1/4.2 when SP4_MACH_CRED is configured via
|
||||||
|
* ExchangeID.
|
||||||
|
* Returns 1 for not same, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp)
|
nfsrv_notsamecredname(int op, struct nfsrv_descript *nd, struct nfsclient *clp)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/* Check for the SP4_MACH_CRED case. */
|
||||||
|
if (op != 0 && nfsrv_checkmachcred(op, nd, clp) != 0)
|
||||||
|
return (1);
|
||||||
|
|
||||||
/* For NFSv4.1/4.2, SP4_NONE always allows this. */
|
/* For NFSv4.1/4.2, SP4_NONE always allows this. */
|
||||||
if ((nd->nd_flag & ND_NFSV41) != 0)
|
if ((nd->nd_flag & ND_NFSV41) != 0)
|
||||||
return (0);
|
return (0);
|
||||||
@ -6301,6 +6320,16 @@ nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid,
|
|||||||
nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
|
nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
|
||||||
nd->nd_flag |= ND_IMPLIEDCLID;
|
nd->nd_flag |= ND_IMPLIEDCLID;
|
||||||
|
|
||||||
|
/* Handle the SP4_MECH_CRED case for NFSv4.1/4.2. */
|
||||||
|
if ((sep->sess_clp->lc_flags & LCL_MACHCRED) != 0 &&
|
||||||
|
(nd->nd_flag & (ND_GSSINTEGRITY | ND_GSSPRIVACY)) != 0 &&
|
||||||
|
nd->nd_princlen == sep->sess_clp->lc_namelen &&
|
||||||
|
!NFSBCMP(sep->sess_clp->lc_name, nd->nd_principal,
|
||||||
|
nd->nd_princlen)) {
|
||||||
|
nd->nd_flag |= ND_MACHCRED;
|
||||||
|
NFSSET_OPBIT(&nd->nd_allowops, &sep->sess_clp->lc_allowops);
|
||||||
|
}
|
||||||
|
|
||||||
/* Save maximum request and reply sizes. */
|
/* Save maximum request and reply sizes. */
|
||||||
nd->nd_maxreq = sep->sess_maxreq;
|
nd->nd_maxreq = sep->sess_maxreq;
|
||||||
nd->nd_maxresp = sep->sess_maxresp;
|
nd->nd_maxresp = sep->sess_maxresp;
|
||||||
@ -6458,7 +6487,7 @@ nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid)
|
|||||||
} while (igotlock == 0);
|
} while (igotlock == 0);
|
||||||
NFSUNLOCKV4ROOTMUTEX();
|
NFSUNLOCKV4ROOTMUTEX();
|
||||||
|
|
||||||
error = nfsrv_freesession(NULL, sessionid);
|
error = nfsrv_freesession(nd, NULL, sessionid);
|
||||||
if (error == 0 && samesess != 0)
|
if (error == 0 && samesess != 0)
|
||||||
nd->nd_flag &= ~ND_HASSEQUENCE;
|
nd->nd_flag &= ~ND_HASSEQUENCE;
|
||||||
|
|
||||||
@ -6491,6 +6520,9 @@ nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp)
|
|||||||
sep = nfsrv_findsession(sessionid);
|
sep = nfsrv_findsession(sessionid);
|
||||||
if (sep != NULL) {
|
if (sep != NULL) {
|
||||||
clp = sep->sess_clp;
|
clp = sep->sess_clp;
|
||||||
|
error = nfsrv_checkmachcred(NFSV4OP_BINDCONNTOSESS, nd, clp);
|
||||||
|
if (error != 0)
|
||||||
|
goto out;
|
||||||
if (*foreaftp == NFSCDFC4_BACK ||
|
if (*foreaftp == NFSCDFC4_BACK ||
|
||||||
*foreaftp == NFSCDFC4_BACK_OR_BOTH ||
|
*foreaftp == NFSCDFC4_BACK_OR_BOTH ||
|
||||||
*foreaftp == NFSCDFC4_FORE_OR_BOTH) {
|
*foreaftp == NFSCDFC4_FORE_OR_BOTH) {
|
||||||
@ -6538,6 +6570,7 @@ nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp)
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
error = NFSERR_BADSESSION;
|
error = NFSERR_BADSESSION;
|
||||||
|
out:
|
||||||
NFSUNLOCKSESSION(shp);
|
NFSUNLOCKSESSION(shp);
|
||||||
NFSUNLOCKSTATE();
|
NFSUNLOCKSTATE();
|
||||||
if (savxprt != NULL)
|
if (savxprt != NULL)
|
||||||
@ -6549,7 +6582,8 @@ nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp)
|
|||||||
* Free up a session structure.
|
* Free up a session structure.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid)
|
nfsrv_freesession(struct nfsrv_descript *nd, struct nfsdsession *sep,
|
||||||
|
uint8_t *sessionid)
|
||||||
{
|
{
|
||||||
struct nfssessionhash *shp;
|
struct nfssessionhash *shp;
|
||||||
int i;
|
int i;
|
||||||
@ -6564,6 +6598,14 @@ nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid)
|
|||||||
NFSLOCKSESSION(shp);
|
NFSLOCKSESSION(shp);
|
||||||
}
|
}
|
||||||
if (sep != NULL) {
|
if (sep != NULL) {
|
||||||
|
/* Check for the SP4_MACH_CRED case. */
|
||||||
|
if (nd != NULL && nfsrv_checkmachcred(NFSV4OP_DESTROYSESSION,
|
||||||
|
nd, sep->sess_clp) != 0) {
|
||||||
|
NFSUNLOCKSESSION(shp);
|
||||||
|
NFSUNLOCKSTATE();
|
||||||
|
return (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||||
|
}
|
||||||
|
|
||||||
sep->sess_refcnt--;
|
sep->sess_refcnt--;
|
||||||
if (sep->sess_refcnt > 0) {
|
if (sep->sess_refcnt > 0) {
|
||||||
NFSUNLOCKSESSION(shp);
|
NFSUNLOCKSESSION(shp);
|
||||||
@ -8883,3 +8925,23 @@ nfsrv_marknospc(char *devid, bool setit)
|
|||||||
NFSUNLOCKLAYOUT(lhyp);
|
NFSUNLOCKLAYOUT(lhyp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if SP4_MACH_CRED is in use and, if it is, check that the
|
||||||
|
* correct machine credential is being used.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
nfsrv_checkmachcred(int op, struct nfsrv_descript *nd, struct nfsclient *clp)
|
||||||
|
{
|
||||||
|
|
||||||
|
if ((clp->lc_flags & LCL_MACHCRED) == 0 ||
|
||||||
|
!NFSISSET_OPBIT(&clp->lc_mustops, op))
|
||||||
|
return (0);
|
||||||
|
KASSERT((nd->nd_flag & ND_NFSV41) != 0,
|
||||||
|
("nfsrv_checkmachcred: MachCred for NFSv4.0"));
|
||||||
|
if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_GSSPRIVACY)) != 0 &&
|
||||||
|
nd->nd_princlen == clp->lc_namelen &&
|
||||||
|
!NFSBCMP(nd->nd_principal, clp->lc_name, nd->nd_princlen))
|
||||||
|
return (0);
|
||||||
|
return (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user