Commit 9280c577 authored by Chuck Lever's avatar Chuck Lever

NFSD: Handle new xprtsec= export option

Enable administrators to require clients to use transport layer
security when accessing particular exports.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent b3cbf98e
...@@ -439,7 +439,6 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid) ...@@ -439,7 +439,6 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid)
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
#ifdef CONFIG_NFSD_V4 #ifdef CONFIG_NFSD_V4
...@@ -546,6 +545,29 @@ static inline int ...@@ -546,6 +545,29 @@ static inline int
secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; } secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
#endif #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 static inline int
nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid) 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) ...@@ -608,6 +630,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
exp.ex_client = dom; exp.ex_client = dom;
exp.cd = cd; exp.cd = cd;
exp.ex_devid_map = NULL; exp.ex_devid_map = NULL;
exp.ex_xprtsec_modes = NFSEXP_XPRTSEC_ALL;
/* expiry */ /* expiry */
err = get_expiry(&mesg, &exp.h.expiry_time); 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) ...@@ -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); err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid);
else if (strcmp(buf, "secinfo") == 0) else if (strcmp(buf, "secinfo") == 0)
err = secinfo_parse(&mesg, buf, &exp); err = secinfo_parse(&mesg, buf, &exp);
else if (strcmp(buf, "xprtsec") == 0)
err = xprtsec_parse(&mesg, buf, &exp);
else else
/* quietly ignore unknown words and anything /* quietly ignore unknown words and anything
* following. Newer user-space can try to set * 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) ...@@ -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); err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid);
if (err) if (err)
goto out4; goto out4;
/* /*
* No point caching this if it would immediately expire. * No point caching this if it would immediately expire.
* Also, this protects exportfs's dummy export from the * 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) ...@@ -823,6 +849,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
for (i = 0; i < MAX_SECINFO_LIST; i++) { for (i = 0; i < MAX_SECINFO_LIST; i++) {
new->ex_flavors[i] = item->ex_flavors[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) static struct cache_head *svc_export_alloc(void)
...@@ -1034,9 +1061,26 @@ static struct svc_export *exp_find(struct cache_detail *cd, ...@@ -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) __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
{ {
struct exp_flavor_info *f; struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors;
struct exp_flavor_info *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: */ /* legacy gss-only clients are always OK: */
if (exp->ex_client == rqstp->rq_gssclient) if (exp->ex_client == rqstp->rq_gssclient)
return 0; return 0;
...@@ -1061,6 +1105,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) ...@@ -1061,6 +1105,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
if (nfsd4_spo_must_allow(rqstp)) if (nfsd4_spo_must_allow(rqstp))
return 0; return 0;
denied:
return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec; return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
} }
......
...@@ -77,6 +77,7 @@ struct svc_export { ...@@ -77,6 +77,7 @@ struct svc_export {
struct cache_detail *cd; struct cache_detail *cd;
struct rcu_head ex_rcu; struct rcu_head ex_rcu;
struct export_stats ex_stats; struct export_stats ex_stats;
unsigned long ex_xprtsec_modes;
}; };
/* an "export key" (expkey) maps a filehandlefragement to an /* an "export key" (expkey) maps a filehandlefragement to an
......
...@@ -62,5 +62,18 @@ ...@@ -62,5 +62,18 @@
| NFSEXP_ALLSQUASH \ | NFSEXP_ALLSQUASH \
| NFSEXP_INSECURE_PORT) | 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 */ #endif /* _UAPINFSD_EXPORT_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment