mountd
J. Bruce Fields
bfields at fieldses.org
Wed Jul 12 16:51:43 EDT 2006
On Wed, Jul 12, 2006 at 04:49:12PM -0400, J. Bruce Fields wrote:
> By the way, appended are two diffs from Fred implementing a very basic
> form of the secinfo parsing. These are rough drafts but should give you
> something to work against.
Um, right, there's some sort of rule that nobody ever remembers to
attach anything the first time they say they will....
--b.
From: Fredric Isaman <iisaman at citi.umich.edu>
Subject: [PATCH 01/01]: nfs-utils: exports sec= parsing
Below is a patch that applies to nfs-utils-1.0.8-CITI_NFS4_ALL-3.dif that
can read sec= option and sends security data through cache via
"... secinfo n flavor1 flag1 ... flavorN flagN". If sec= is missing, it
will fill it in based on special client name.
(Note currently the only option that can vary per security flavor is
NFSEXP_READONLY, though this is easy to fix if the general method meets
approval.)
Signed-off-by: Fred Isaman <iisaman at citi.umich.edu>
---
Index: nfs-utils-1.0.8/support/include/nfslib.h
===================================================================
--- nfs-utils-1.0.8.orig/support/include/nfslib.h
+++ nfs-utils-1.0.8/support/include/nfslib.h
@@ -57,6 +57,9 @@ enum cle_maptypes {
CLE_MAP_UGIDD,
};
+extern char *secflavor_name[];
+#define SECFLAVOR_COUNT 4
+
/*
* Data related to a single exports entry as returned by getexportent.
* FIXME: export options should probably be parsed at a later time to
@@ -82,6 +85,8 @@ struct exportent {
char * e_mountpoint;
int e_fslocmethod;
char * e_fslocdata;
+ int e_secinfo_order[SECFLAVOR_COUNT+1];
+ int e_secinfo_flags[SECFLAVOR_COUNT];
};
struct rmtabent {
@@ -95,6 +100,7 @@ struct rmtabent {
*/
void setexportent(char *fname, char *type);
struct exportent * getexportent(int,int);
+void secinfo_show(FILE *fp, struct exportent *ep);
void putexportent(struct exportent *xep);
void endexportent(void);
struct exportent * mkexportent(char *hname, char *path, char *opts);
Index: nfs-utils-1.0.8/support/nfs/exports.c
===================================================================
--- nfs-utils-1.0.8.orig/support/nfs/exports.c
+++ nfs-utils-1.0.8/support/nfs/exports.c
@@ -96,6 +96,7 @@ getexportent(int fromkernel, int fromexp
ee.e_mountpoint = NULL;
ee.e_fslocmethod = FSLOC_NONE;
ee.e_fslocdata = NULL;
+ ee.e_secinfo_order[0] = -1;
ee.e_nsquids = 0;
ee.e_nsqgids = 0;
@@ -157,6 +158,18 @@ getexportent(int fromkernel, int fromexp
return ⅇ
}
+void secinfo_show(FILE *fp, struct exportent *ep)
+{
+ int *p1, *p2;
+ for (p1=ep->e_secinfo_order; *p1>=0; p1=p2) {
+ fprintf(fp, ",sec=%s", secflavor_name[*p1]);
+ for (p2=p1+1; (*p2>=0) && (ep->e_secinfo_flags[*p1]==ep->e_secinfo_flags[*p2]); p2++) {
+ fprintf(fp, ":%s", secflavor_name[*p2]);
+ }
+ fprintf(fp, ",%s", (ep->e_secinfo_flags[*p1] & NFSEXP_READONLY)? "ro" : "rw");
+ }
+}
+
void
putexportent(struct exportent *ep)
{
@@ -175,7 +188,6 @@ putexportent(struct exportent *ep)
fprintf(fp, "%c", esc[i]);
fprintf(fp, "\t%s(", ep->e_hostname);
- fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw");
fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : "");
fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)?
"" : "no_");
@@ -248,7 +260,9 @@ putexportent(struct exportent *ep)
else
fprintf(fp, "%d,", id[i]);
}
- fprintf(fp, "anonuid=%d,anongid=%d)\n", ep->e_anonuid, ep->e_anongid);
+ fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid);
+ secinfo_show(fp, ep);
+ fprintf(fp, ")\n");
}
void
@@ -295,6 +309,7 @@ mkexportent(char *hname, char *path, cha
ee.e_squids = NULL;
ee.e_sqgids = NULL;
ee.e_mountpoint = NULL;
+ ee.e_secinfo_order[0] = -1;
ee.e_nsquids = 0;
ee.e_nsqgids = 0;
@@ -325,19 +340,116 @@ updateexportent(struct exportent *eep, c
return 1;
}
+char *secflavor_name[SECFLAVOR_COUNT] = { "sys",
+ "krb5",
+ "krb5i",
+ "krb5p"
+};
+
+static void secinfo_addflavor(int bit, struct exportent *ep)
+{
+ int *p;
+ for (p=ep->e_secinfo_order; *p>=0; p++) {
+ if (*p == bit)
+ return;
+ }
+ *p++ = bit;
+ *p = -1;
+ ep->e_secinfo_flags[bit] = 0;
+}
+
+static int secinfo_nameindex(char *name)
+{
+ int i;
+ for (i=0; i<SECFLAVOR_COUNT; i++) {
+ if (strcmp(secflavor_name[i], name) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/* @str is a colon seperated list of security flavors. Their order
+ * is recorded in @ep, and a bitmap corresponding to the list is returned.
+ * A zero return indicates an error.
+ */
+static unsigned int parse_flavors(char *str, struct exportent *ep)
+{
+ unsigned int out=0;
+ char *flavor;
+ int bit;
+
+ while ( (flavor=strsep(&str, ":")) ) {
+ bit = secinfo_nameindex(flavor);
+ if (bit == -1) {
+ xlog(L_ERROR, "unknown flavor %s\n", flavor);
+ return 0;
+ }
+ out |= 1<<bit;
+ secinfo_addflavor(bit, ep);
+ }
+ return out;
+}
+
+/* Determine a default security flavor based on ep->e_hostname. */
+static int secinfo_default(struct exportent *ep)
+{
+ int i=-1;
+ if (strncmp(ep->e_hostname, "gss/", 4) == 0) {
+ i = secinfo_nameindex(ep->e_hostname + 4);
+ if (i < 0)
+ xlog(L_WARNING, "unknown flavor %s\n", ep->e_hostname);
+ }
+ /* Default to auth_sys */
+ if (i < 0)
+ i = secinfo_nameindex("sys");
+ secinfo_addflavor(i, ep);
+ return 1<<i;
+}
+
+/* Sets the bits in @mask for the appropriate security flavor flags. */
+static void setflags(int mask, unsigned int *ap, struct exportent *ep)
+{
+ int active, flavor=0;
+ if (!*ap)
+ *ap = secinfo_default(ep);
+ active = *ap;
+ while (active) {
+ if (active & 1)
+ ep->e_secinfo_flags[flavor] |= mask;
+ flavor++;
+ active >>= 1;
+ }
+}
+
+/* Clears the bits in @mask for the appropriate security flavor flags. */
+static void clearflags(int mask, unsigned int *ap, struct exportent *ep)
+{
+ int active, flavor=0;
+ if (!*ap)
+ *ap = secinfo_default(ep);
+ active = *ap;
+ while (active) {
+ if (active & 1)
+ ep->e_secinfo_flags[flavor] &= ~mask;
+ flavor++;
+ active >>= 1;
+ }
+}
+
/*
* Parse option string pointed to by cp and set mount options accordingly.
*/
static int
parseopts(char *cp, struct exportent *ep, int warn)
{
- int had_sync_opt = 0;
+ int *p, had_sync_opt = 0;
char *flname = efname?efname:"command line";
int flline = efp?efp->x_line:0;
+ unsigned int active=0;
+ int secmask=NFSEXP_READONLY; /* options that can vary per flavor */
squids = ep->e_squids; nsquids = ep->e_nsquids;
sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids;
-
if (!cp)
goto out;
@@ -356,9 +468,9 @@ parseopts(char *cp, struct exportent *ep
/* process keyword */
if (strcmp(opt, "ro") == 0)
- ep->e_flags |= NFSEXP_READONLY;
+ setflags(NFSEXP_READONLY, &active, ep);
else if (strcmp(opt, "rw") == 0)
- ep->e_flags &= ~NFSEXP_READONLY;
+ clearflags(NFSEXP_READONLY, &active, ep);
else if (!strcmp(opt, "secure"))
ep->e_flags &= ~NFSEXP_INSECURE_PORT;
else if (!strcmp(opt, "insecure"))
@@ -470,6 +582,10 @@ bad_option:
} else if (strncmp(opt, "replicas=", 9) == 0) {
ep->e_fslocmethod = FSLOC_REPLICA;
ep->e_fslocdata = strdup(opt+9);
+ } else if (strncmp(opt, "sec=", 4) == 0) {
+ active = parse_flavors(opt+4, ep);
+ if (!active)
+ goto bad_option;
} else {
xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
flname, flline, opt);
@@ -481,6 +597,12 @@ bad_option:
cp++;
}
+ if (!active)
+ active = secinfo_default(ep);
+ for (p=ep->e_secinfo_order; *p>=0; p++)
+ ep->e_secinfo_flags[*p] |= (ep->e_flags & ~secmask);
+ /* If did not use sec= option, ensure e_flags is backward compatible */
+ ep->e_flags = ep->e_secinfo_flags[ep->e_secinfo_order[0]];
ep->e_squids = squids;
ep->e_sqgids = sqgids;
ep->e_nsquids = nsquids;
Index: nfs-utils-1.0.8/utils/mountd/cache.c
===================================================================
--- nfs-utils-1.0.8.orig/utils/mountd/cache.c
+++ nfs-utils-1.0.8/utils/mountd/cache.c
@@ -263,6 +263,20 @@ static void write_fsloc(FILE *f, struct
release_replicas(servers);
}
+static void write_secinfo(FILE *f, struct exportent *ep)
+{
+ int *p;
+ qword_print(f, "secinfo");
+ for (p=ep->e_secinfo_order; *p>=0; p++)
+ ; /* Do nothing */
+ qword_printint(f, p - ep->e_secinfo_order);
+ for (p=ep->e_secinfo_order; *p>=0; p++) {
+ qword_print(f, secflavor_name[*p]);
+ qword_printint(f, ep->e_secinfo_flags[*p]);
+ }
+
+}
+
void nfsd_export(FILE *f)
{
/* requests are:
@@ -320,6 +334,7 @@ void nfsd_export(FILE *f)
qword_printint(f, found->m_export.e_anongid);
qword_printint(f, found->m_export.e_fsid);
write_fsloc(f, &found->m_export, path);
+ write_secinfo(f, &found->m_export);
mountlist_add(dom, path);
}
qword_eol(f);
Index: nfs-utils-1.0.8/utils/exportfs/exportfs.c
===================================================================
--- nfs-utils-1.0.8.orig/utils/exportfs/exportfs.c
+++ nfs-utils-1.0.8/utils/exportfs/exportfs.c
@@ -376,10 +376,12 @@ dump(int verbose)
continue;
}
c = '(';
+ /*
if (ep->e_flags & NFSEXP_READONLY)
c = dumpopt(c, "ro");
else
c = dumpopt(c, "rw");
+ */
if (ep->e_flags & NFSEXP_ASYNC)
c = dumpopt(c, "async");
if (ep->e_flags & NFSEXP_GATHERED_WRITES)
@@ -429,6 +431,7 @@ dump(int verbose)
c = dumpopt(c, "fsloc=stub");
break;
}
+ secinfo_show(stdout, ep);
printf("%c\n", (c != '(')? ')' : ' ');
}
}
From: Fredric Isaman <iisaman at citi.umich.edu>
Subject: [PATCH 01/01]: nfsd4: exports sec= parsing
Below is a patch that applies to linux-2.6.17-rc6-CITI_NFS4_ALL-1.diff
that parses and stores info sent through exports cache via
"... secinfo n flavor1 flag1 ... flavorN flagN"
Signed-off-by: Fred Isaman <iisaman at citi.umich.edu>
---
Index: linux-2.6.17-rc6/fs/nfsd/export.c
===================================================================
--- linux-2.6.17-rc6.orig/fs/nfsd/export.c
+++ linux-2.6.17-rc6/fs/nfsd/export.c
@@ -396,10 +396,13 @@ fsloc_parse(char **mesg, char *buf, stru
{
int len;
int listsize, migrated, i, err;
+ char *orig = *mesg;
len = qword_get(mesg, buf, PAGE_SIZE);
- if (len != 5 || memcmp(buf, "fsloc", 5))
+ if (len != 5 || memcmp(buf, "fsloc", 5)) {
+ *mesg = orig;
return 0;
+ }
/* listsize */
err = get_int(mesg, &listsize);
@@ -453,8 +456,71 @@ out_free_all:
return err;
}
+static int flavor_parse(char *str)
+{
+ if (!strcmp(str, "sys"))
+ return SECINFO_SYS;
+ else if (!strcmp(str, "krb5"))
+ return SECINFO_KRB5;
+ else if (!strcmp(str, "krb5i"))
+ return SECINFO_KRB5I;
+ else if (!strcmp(str, "krb5p"))
+ return SECINFO_KRB5P;
+ else
+ dprintk("Unknown security flavor %s", str);
+ return -1;
+}
+
+static void secinfo_clearall(struct svc_export *exp)
+{
+ exp->ex_si_order[0] = -1;
+}
+
+static void secinfo_useflavor(int flavor, struct svc_export *exp)
+{
+ int *p;
+ for (p=exp->ex_si_order; *p >= 0; p++)
+ ; /* Do nothing */
+ *p = flavor;
+}
+
+static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
+{
+ int len, listsize, i, flavor, err;
+ char *orig = *mesg;
+
+ len = qword_get(mesg, buf, PAGE_SIZE);
+ if (strcmp(buf, "secinfo")) {
+ *mesg = orig;
+ return 0;
+ }
+
+ /* listsize */
+ err = get_int(mesg, &listsize);
+ if (err)
+ return err;
+ if (listsize <0)
+ return -EINVAL;
+ secinfo_clearall(exp);
+
+ for (i=0; i<listsize; i++) {
+ len = qword_get(mesg, buf, PAGE_SIZE);
+ if (len <= 0)
+ return -EINVAL;
+ flavor = flavor_parse(buf);
+ if (flavor < 0)
+ return -EINVAL;
+ err = get_int(mesg, exp->ex_si_flags + flavor);
+ if (err)
+ return err;
+ secinfo_useflavor(flavor, exp);
+ }
+ return 0;
+}
+
#else /* CONFIG_NFSD_V4 */
static int fsloc_parse(char **, char *, struct svc_export *) { return 0; }
+static int secinfo_parse(char **, char *, struct svc_export *) { return 0; }
#endif
static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
@@ -538,6 +604,10 @@ static int svc_export_parse(struct cache
err = fsloc_parse(&mesg, buf, &exp);
if (err)
goto out;
+
+ err = secinfo_parse(&mesg, buf, &exp);
+ if (err)
+ goto out;
}
expp = svc_export_lookup(&exp);
Index: linux-2.6.17-rc6/include/linux/nfsd/export.h
===================================================================
--- linux-2.6.17-rc6.orig/include/linux/nfsd/export.h
+++ linux-2.6.17-rc6/include/linux/nfsd/export.h
@@ -45,6 +45,14 @@
#ifdef __KERNEL__
+#ifdef CONFIG_NFSD_V4
+#define SECINFO_SYS 0
+#define SECINFO_KRB5 1
+#define SECINFO_KRB5I 2
+#define SECINFO_KRB5P 3
+#define SECINFO_COUNT 4
+#endif
+
struct svc_export {
struct cache_head h;
struct auth_domain * ex_client;
@@ -56,6 +64,8 @@ struct svc_export {
int ex_fsid;
#ifdef CONFIG_NFSD_V4
struct nfsd4_fs_locations *ex_fslocs;
+ int ex_si_order[SECINFO_COUNT+1];
+ int ex_si_flags[SECINFO_COUNT];
#endif
};
More information about the NFSv4
mailing list