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 &ee;
 }

+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