History

NFSD: Handle new xprtsec= export option

Enable administrators to require clients to use transport layer security when accessing particular exports.

Chuck Lever committed 3 years ago

Commit 9280c571 parent b3cbf983 files · +62 −3Browse files

Unified · Split

3 files
  1. fs/nfsd/export.c +48 −3
  2. fs/nfsd/export.h +1 −0
  3. include/uapi/linux/nfsd/export.h +13 −0
fs/nfsd/export.c+48−3
@@ -439,7 +439,6 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid) · 438 unmodified lines
439 return -EINVAL;439 return -EINVAL;
440 }440 }
441 return 0;441 return 0;
442
443}442}
444 443
445#ifdef CONFIG_NFSD_V4444#ifdef CONFIG_NFSD_V4
@@ -546,6 +545,29 @@ static inline int · 100 unmodified lines
546secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }545secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
547#endif546#endif
548 547
548static int xprtsec_parse(char **mesg, char *buf, struct svc_export *exp)
549{
550 unsigned int i, mode, listsize;
551 int err;
552
553 err = get_uint(mesg, &listsize);
554 if (err)
555 return err;
556 if (listsize > NFSEXP_XPRTSEC_NUM)
557 return -EINVAL;
558
559 exp->ex_xprtsec_modes = 0;
560 for (i = 0; i < listsize; i++) {
561 err = get_uint(mesg, &mode);
562 if (err)
563 return err;
564 if (mode > NFSEXP_XPRTSEC_MTLS)
565 return -EINVAL;
566 exp->ex_xprtsec_modes |= mode;
567 }
568 return 0;
569}
570
549static inline int571static inline int
550nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid)572nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid)
551{573{
@@ -608,6 +630,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) · 56 unmodified lines
608 exp.ex_client = dom;630 exp.ex_client = dom;
609 exp.cd = cd;631 exp.cd = cd;
610 exp.ex_devid_map = NULL;632 exp.ex_devid_map = NULL;
633 exp.ex_xprtsec_modes = NFSEXP_XPRTSEC_ALL;
611 634
612 /* expiry */635 /* expiry */
613 err = get_expiry(&mesg, &exp.h.expiry_time);636 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) · 35 unmodified lines
649 err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid);672 err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid);
650 else if (strcmp(buf, "secinfo") == 0)673 else if (strcmp(buf, "secinfo") == 0)
651 err = secinfo_parse(&mesg, buf, &exp);674 err = secinfo_parse(&mesg, buf, &exp);
675 else if (strcmp(buf, "xprtsec") == 0)
676 err = xprtsec_parse(&mesg, buf, &exp);
652 else677 else
653 /* quietly ignore unknown words and anything678 /* quietly ignore unknown words and anything
654 * following. Newer user-space can try to set679 * 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) · 7 unmodified lines
662 err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid);687 err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid);
663 if (err)688 if (err)
664 goto out4;689 goto out4;
690
665 /*691 /*
666 * No point caching this if it would immediately expire.692 * No point caching this if it would immediately expire.
667 * Also, this protects exportfs's dummy export from the693 * 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) · 155 unmodified lines
823 for (i = 0; i < MAX_SECINFO_LIST; i++) {849 for (i = 0; i < MAX_SECINFO_LIST; i++) {
824 new->ex_flavors[i] = item->ex_flavors[i];850 new->ex_flavors[i] = item->ex_flavors[i];
825 }851 }
852 new->ex_xprtsec_modes = item->ex_xprtsec_modes;
826}853}
827 854
828static struct cache_head *svc_export_alloc(void)855static struct cache_head *svc_export_alloc(void)
@@ -1034,9 +1061,26 @@ static struct svc_export *exp_find(struct cache_detail *cd, · 205 unmodified lines
1034 1061
1035__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)1062__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
1036{1063{
1037 struct exp_flavor_info *f;1064 struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors;
1038 struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;1065 struct svc_xprt *xprt = rqstp->rq_xprt;
1066
1067 if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_NONE) {
1068 if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags))
1069 goto ok;
1070 }
1071 if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_TLS) {
1072 if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) &&
1073 !test_bit(XPT_PEER_AUTH, &xprt->xpt_flags))
1074 goto ok;
1075 }
1076 if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_MTLS) {
1077 if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) &&
1078 test_bit(XPT_PEER_AUTH, &xprt->xpt_flags))
1079 goto ok;
1080 }
1081 goto denied;
1039 1082
1083ok:
1040 /* legacy gss-only clients are always OK: */1084 /* legacy gss-only clients are always OK: */
1041 if (exp->ex_client == rqstp->rq_gssclient)1085 if (exp->ex_client == rqstp->rq_gssclient)
1042 return 0;1086 return 0;
@@ -1061,6 +1105,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) · 18 unmodified lines
1061 if (nfsd4_spo_must_allow(rqstp))1105 if (nfsd4_spo_must_allow(rqstp))
1062 return 0;1106 return 0;
1063 1107
1108denied:
1064 return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;1109 return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
1065}1110}
1066 1111
fs/nfsd/export.h+1−0
@@ -77,6 +77,7 @@ struct svc_export { · 76 unmodified lines
77 struct cache_detail *cd;77 struct cache_detail *cd;
78 struct rcu_head ex_rcu;78 struct rcu_head ex_rcu;
79 struct export_stats ex_stats;79 struct export_stats ex_stats;
80 unsigned long ex_xprtsec_modes;
80};81};
81 82
82/* an "export key" (expkey) maps a filehandlefragement to an83/* an "export key" (expkey) maps a filehandlefragement to an
include/uapi/linux/nfsd/export.h+13−0
@@ -62,5 +62,18 @@ · 61 unmodified lines
62 | NFSEXP_ALLSQUASH \62 | NFSEXP_ALLSQUASH \
63 | NFSEXP_INSECURE_PORT)63 | NFSEXP_INSECURE_PORT)
64 64
65/*
66 * Transport layer security policies that are permitted to access
67 * an export
68 */
69#define NFSEXP_XPRTSEC_NONE 0x0001
70#define NFSEXP_XPRTSEC_TLS 0x0002
71#define NFSEXP_XPRTSEC_MTLS 0x0004
72
73#define NFSEXP_XPRTSEC_NUM (3)
74
75#define NFSEXP_XPRTSEC_ALL (NFSEXP_XPRTSEC_NONE | \
76 NFSEXP_XPRTSEC_TLS | \
77 NFSEXP_XPRTSEC_MTLS)
65 78
66#endif /* _UAPINFSD_EXPORT_H */79#endif /* _UAPINFSD_EXPORT_H */