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

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
Loading
Loading
Loading
Loading
+48 −3
Original line number Diff line number Diff line
@@ -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;
}

+1 −0
Original line number Diff line number Diff line
@@ -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
+13 −0
Original line number Diff line number Diff line
@@ -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 */