mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
NFSD: Handle new xprtsec= export option
Enable administrators to require clients to use transport layer security when accessing particular exports. Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
b3cbf98e2f
commit
9280c57743
|
@ -439,7 +439,6 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid)
|
|||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NFSD_V4
|
||||
|
@ -546,6 +545,29 @@ static inline int
|
|||
secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
|
||||
#endif
|
||||
|
||||
static int xprtsec_parse(char **mesg, char *buf, struct svc_export *exp)
|
||||
{
|
||||
unsigned int i, mode, listsize;
|
||||
int err;
|
||||
|
||||
err = get_uint(mesg, &listsize);
|
||||
if (err)
|
||||
return err;
|
||||
if (listsize > NFSEXP_XPRTSEC_NUM)
|
||||
return -EINVAL;
|
||||
|
||||
exp->ex_xprtsec_modes = 0;
|
||||
for (i = 0; i < listsize; i++) {
|
||||
err = get_uint(mesg, &mode);
|
||||
if (err)
|
||||
return err;
|
||||
if (mode > NFSEXP_XPRTSEC_MTLS)
|
||||
return -EINVAL;
|
||||
exp->ex_xprtsec_modes |= mode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid)
|
||||
{
|
||||
|
@ -608,6 +630,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|||
exp.ex_client = dom;
|
||||
exp.cd = cd;
|
||||
exp.ex_devid_map = NULL;
|
||||
exp.ex_xprtsec_modes = NFSEXP_XPRTSEC_ALL;
|
||||
|
||||
/* expiry */
|
||||
err = get_expiry(&mesg, &exp.h.expiry_time);
|
||||
|
@ -649,6 +672,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|||
err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid);
|
||||
else if (strcmp(buf, "secinfo") == 0)
|
||||
err = secinfo_parse(&mesg, buf, &exp);
|
||||
else if (strcmp(buf, "xprtsec") == 0)
|
||||
err = xprtsec_parse(&mesg, buf, &exp);
|
||||
else
|
||||
/* quietly ignore unknown words and anything
|
||||
* following. Newer user-space can try to set
|
||||
|
@ -662,6 +687,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|||
err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid);
|
||||
if (err)
|
||||
goto out4;
|
||||
|
||||
/*
|
||||
* No point caching this if it would immediately expire.
|
||||
* Also, this protects exportfs's dummy export from the
|
||||
|
@ -823,6 +849,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
|
|||
for (i = 0; i < MAX_SECINFO_LIST; i++) {
|
||||
new->ex_flavors[i] = item->ex_flavors[i];
|
||||
}
|
||||
new->ex_xprtsec_modes = item->ex_xprtsec_modes;
|
||||
}
|
||||
|
||||
static struct cache_head *svc_export_alloc(void)
|
||||
|
@ -1034,9 +1061,26 @@ static struct svc_export *exp_find(struct cache_detail *cd,
|
|||
|
||||
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
|
||||
{
|
||||
struct exp_flavor_info *f;
|
||||
struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
|
||||
struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors;
|
||||
struct svc_xprt *xprt = rqstp->rq_xprt;
|
||||
|
||||
if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_NONE) {
|
||||
if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags))
|
||||
goto ok;
|
||||
}
|
||||
if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_TLS) {
|
||||
if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) &&
|
||||
!test_bit(XPT_PEER_AUTH, &xprt->xpt_flags))
|
||||
goto ok;
|
||||
}
|
||||
if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_MTLS) {
|
||||
if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) &&
|
||||
test_bit(XPT_PEER_AUTH, &xprt->xpt_flags))
|
||||
goto ok;
|
||||
}
|
||||
goto denied;
|
||||
|
||||
ok:
|
||||
/* legacy gss-only clients are always OK: */
|
||||
if (exp->ex_client == rqstp->rq_gssclient)
|
||||
return 0;
|
||||
|
@ -1061,6 +1105,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
|
|||
if (nfsd4_spo_must_allow(rqstp))
|
||||
return 0;
|
||||
|
||||
denied:
|
||||
return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ struct svc_export {
|
|||
struct cache_detail *cd;
|
||||
struct rcu_head ex_rcu;
|
||||
struct export_stats ex_stats;
|
||||
unsigned long ex_xprtsec_modes;
|
||||
};
|
||||
|
||||
/* an "export key" (expkey) maps a filehandlefragement to an
|
||||
|
|
|
@ -62,5 +62,18 @@
|
|||
| NFSEXP_ALLSQUASH \
|
||||
| NFSEXP_INSECURE_PORT)
|
||||
|
||||
/*
|
||||
* Transport layer security policies that are permitted to access
|
||||
* an export
|
||||
*/
|
||||
#define NFSEXP_XPRTSEC_NONE 0x0001
|
||||
#define NFSEXP_XPRTSEC_TLS 0x0002
|
||||
#define NFSEXP_XPRTSEC_MTLS 0x0004
|
||||
|
||||
#define NFSEXP_XPRTSEC_NUM (3)
|
||||
|
||||
#define NFSEXP_XPRTSEC_ALL (NFSEXP_XPRTSEC_NONE | \
|
||||
NFSEXP_XPRTSEC_TLS | \
|
||||
NFSEXP_XPRTSEC_MTLS)
|
||||
|
||||
#endif /* _UAPINFSD_EXPORT_H */
|
||||
|
|
Loading…
Reference in a new issue