Sophie

Sophie

distrib > Mandriva > 2007.1 > x86_64 > by-pkgid > ec1353c51cf2bd4d46fb842cdb5d4cdc > files > 16

nfs-utils-1.0.12-13mdv2007.1.src.rpm

Add secinfo processing.

From: Fred Isaman <iisaman@citi.umich.edu>

Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>

Add secinfo processing.
---

 support/include/nfslib.h  |    6 ++
 support/nfs/exports.c     |  145 ++++++++++++++++++++++++++++++++++++++++++++-
 utils/exportfs/exportfs.c |    3 +
 utils/mountd/cache.c      |   14 ++++
 4 files changed, 164 insertions(+), 4 deletions(-)

diff --git a/support/include/nfslib.h b/support/include/nfslib.h
index c085029..6d7743d 100644
--- a/support/include/nfslib.h
+++ b/support/include/nfslib.h
@@ -57,6 +57,9 @@ enum cle_maptypes {
 	CLE_MAP_UGIDD,
 };
 
+#define SECFLAVOR_COUNT 7
+extern char *secflavor_name[SECFLAVOR_COUNT];
+
 /*
  * Data related to a single exports entry as returned by getexportent.
  * FIXME: export options should probably be parsed at a later time to
@@ -83,6 +86,8 @@ struct exportent {
 	int             e_fslocmethod;
 	char *          e_fslocdata;
 	char *		e_uuid;
+	int		e_secinfo_order[SECFLAVOR_COUNT+1];
+	int		e_secinfo_flags[SECFLAVOR_COUNT];
 };
 
 struct rmtabent {
@@ -96,6 +101,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);
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
index 294e1c9..af9ab2f 100644
--- a/support/nfs/exports.c
+++ b/support/nfs/exports.c
@@ -51,6 +51,10 @@ static int	parsenum(char **cpp);
 static int	parsemaptype(char *type);
 static void	freesquash(void);
 static void	syntaxerr(char *msg);
+static unsigned int parse_flavors(char *str, struct exportent *ep);
+static int	secinfo_default(struct exportent *ep);
+static void	setflags(int mask, unsigned int *ap, struct exportent *ep);
+static void	clearflags(int mask, unsigned int *ap, struct exportent *ep);
 
 void
 setexportent(char *fname, char *type)
@@ -102,6 +106,7 @@ getexportent(int fromkernel, int fromexp
 		def_ee.e_mountpoint = NULL;
 		def_ee.e_fslocmethod = FSLOC_NONE;
 		def_ee.e_fslocdata = NULL;
+		def_ee.e_secinfo_order[0] = -1;
 		def_ee.e_nsquids = 0;
 		def_ee.e_nsqgids = 0;
 
@@ -182,6 +187,19 @@ getexportent(int fromkernel, int fromexp
 }
 
 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)
 {
 	FILE	*fp;
@@ -199,7 +217,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_");
@@ -276,7 +293,9 @@ #endif
 			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
@@ -325,6 +344,7 @@ mkexportent(char *hname, char *path, cha
 	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;
 	ee.e_uuid = NULL;
@@ -376,6 +396,9 @@ parseopts(char *cp, struct exportent *ep
 	int	had_subtree_opt = 0;
 	char 	*flname = efname?efname:"command line";
 	int	flline = efp?efp->x_line:0;
+	int	*p;
+	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;
@@ -398,9 +421,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"))
@@ -522,6 +545,10 @@ #endif
 		} 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);
@@ -533,6 +560,12 @@ #endif
 			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;
@@ -663,3 +696,107 @@ syntaxerr(char *msg)
 			efname, efp?efp->x_line:0, msg);
 }
 
+char *secflavor_name[SECFLAVOR_COUNT] = { "sys",
+					  "krb5",
+					  "krb5i",
+					  "krb5p",
+					  "spkm3",
+					  "spkm3i",
+					  "spkm3p"
+};
+
+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;
+	}
+}
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index 22e13a3..30732b8 100644
--- a/utils/exportfs/exportfs.c
+++ b/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)
@@ -433,6 +435,7 @@ #ifdef DEBUG
 				break;
 #endif
 			}
+			secinfo_show(stdout, ep);
 			printf("%c\n", (c != '(')? ')' : ' ');
 		}
 	}
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
index 5f0d12a..78a8f75 100644
--- a/utils/mountd/cache.c
+++ b/utils/mountd/cache.c
@@ -445,6 +445,19 @@ 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]);
+	}
+}
+
 static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
 {
 	qword_print(f, domain);
@@ -466,6 +479,7 @@ static int dump_to_cache(FILE *f, char *
  			qword_print(f, "uuid");
  			qword_printhex(f, exp->e_uuid, 16);
  		}
+		write_secinfo(f, exp);
 	}
 	return qword_eol(f);
 }