walters / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
c2754f0
diff --git a/support/export/xtab.c b/support/export/xtab.c
c2754f0
index 3b1dcce..2a43193 100644
c2754f0
--- a/support/export/xtab.c
c2754f0
+++ b/support/export/xtab.c
c2754f0
@@ -19,7 +19,9 @@
c2754f0
 #include "exportfs.h"
c2754f0
 #include "xio.h"
c2754f0
 #include "xlog.h"
c2754f0
+#include "v4root.h"
c2754f0
 
c2754f0
+int v4root_needed;
c2754f0
 static void cond_rename(char *newfile, char *oldfile);
c2754f0
 
c2754f0
 static int
c2754f0
@@ -36,6 +38,8 @@ xtab_read(char *xtab, char *lockfn, int is_export)
c2754f0
 	if ((lockid = xflock(lockfn, "r")) < 0)
c2754f0
 		return 0;
c2754f0
 	setexportent(xtab, "r");
c2754f0
+	if (is_export == 1)
c2754f0
+		v4root_needed = 1;
c2754f0
 	while ((xp = getexportent(is_export==0, 0)) != NULL) {
c2754f0
 		if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
c2754f0
 		    !(exp = export_create(xp, is_export!=1))) {
c2754f0
@@ -48,6 +52,8 @@ xtab_read(char *xtab, char *lockfn, int is_export)
c2754f0
 		case 1:
c2754f0
 			exp->m_xtabent = 1;
c2754f0
 			exp->m_mayexport = 1;
c2754f0
+			if ((xp->e_flags & NFSEXP_FSID) && xp->e_fsid == 0)
c2754f0
+				v4root_needed = 0;
c2754f0
 			break;
c2754f0
 		case 2:
c2754f0
 			exp->m_exported = -1;/* may be exported */
c2754f0
diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
c2754f0
index f7a99ba..76953ac 100644
c2754f0
--- a/support/include/nfs/export.h
c2754f0
+++ b/support/include/nfs/export.h
c2754f0
@@ -24,6 +24,7 @@
c2754f0
 #define NFSEXP_FSID		0x2000
c2754f0
 #define	NFSEXP_CROSSMOUNT	0x4000
c2754f0
 #define NFSEXP_NOACL		0x8000 /* reserved for possible ACL related use */
c2754f0
-#define NFSEXP_ALLFLAGS		0xFFFF
c2754f0
+#define NFSEXP_V4ROOT       0x10000
c2754f0
+#define NFSEXP_ALLFLAGS		0x1FFFF
c2754f0
 
c2754f0
 #endif /* _NSF_EXPORT_H */
c2754f0
diff --git a/support/include/pseudoflavors.h b/support/include/pseudoflavors.h
c2754f0
index c21087b..c7ba8a2 100644
c2754f0
--- a/support/include/pseudoflavors.h
c2754f0
+++ b/support/include/pseudoflavors.h
c2754f0
@@ -15,3 +15,4 @@ struct flav_info {
c2754f0
 
c2754f0
 extern struct flav_info flav_map[];
c2754f0
 extern const int flav_map_size;
c2754f0
+extern unsigned int flavors_setall(struct exportent *ep);
c2754f0
diff --git a/support/include/v4root.h b/support/include/v4root.h
c2754f0
new file mode 100644
c2754f0
index 0000000..706c15c
c2754f0
--- /dev/null
c2754f0
+++ b/support/include/v4root.h
c2754f0
@@ -0,0 +1,15 @@
c2754f0
+/*
c2754f0
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
c2754f0
+ * support/include/v4root.h
c2754f0
+ *
c2754f0
+ * Support routines for dynamic pseudo roots.
c2754f0
+ *
c2754f0
+ */
c2754f0
+
c2754f0
+#ifndef V4ROOT_H
c2754f0
+#define V4ROOT_H
c2754f0
+
c2754f0
+extern int v4root_needed;
c2754f0
+extern void v4root_set(void);
c2754f0
+
c2754f0
+#endif /* V4ROOT_H */
c2754f0
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
c2754f0
index 1aaebf4..fe9ed3a 100644
c2754f0
--- a/support/nfs/exports.c
c2754f0
+++ b/support/nfs/exports.c
c2754f0
@@ -39,16 +39,18 @@ struct flav_info flav_map[] = {
c2754f0
 	{ "krb5",	RPC_AUTH_GSS_KRB5	},
c2754f0
 	{ "krb5i",	RPC_AUTH_GSS_KRB5I	},
c2754f0
 	{ "krb5p",	RPC_AUTH_GSS_KRB5P	},
c2754f0
+	{ "unix",	AUTH_UNIX		},
c2754f0
+	{ "sys",	AUTH_SYS		},
c2754f0
+	{ "null",	AUTH_NULL		},
c2754f0
+	{ "none",	AUTH_NONE		},
c2754f0
+#ifdef NOLONGERSUPPORTED
c2754f0
 	{ "lipkey",	RPC_AUTH_GSS_LKEY	},
c2754f0
 	{ "lipkey-i",	RPC_AUTH_GSS_LKEYI	},
c2754f0
 	{ "lipkey-p",	RPC_AUTH_GSS_LKEYP	},
c2754f0
 	{ "spkm3",	RPC_AUTH_GSS_SPKM	},
c2754f0
 	{ "spkm3i",	RPC_AUTH_GSS_SPKMI	},
c2754f0
 	{ "spkm3p",	RPC_AUTH_GSS_SPKMP	},
c2754f0
-	{ "unix",	AUTH_UNIX		},
c2754f0
-	{ "sys",	AUTH_SYS		},
c2754f0
-	{ "null",	AUTH_NULL		},
c2754f0
-	{ "none",	AUTH_NONE		},
c2754f0
+#endif
c2754f0
 };
c2754f0
 
c2754f0
 const int flav_map_size = sizeof(flav_map)/sizeof(flav_map[0]);
c2754f0
@@ -436,6 +438,20 @@ static unsigned int parse_flavors(char *str, struct exportent *ep)
c2754f0
 	}
c2754f0
 	return out;
c2754f0
 }
c2754f0
+unsigned int flavors_setall(struct exportent *ep)
c2754f0
+{
c2754f0
+	struct flav_info *flav;
c2754f0
+	unsigned int out=0;
c2754f0
+	int bit;
c2754f0
+
c2754f0
+	for (flav = flav_map; flav < flav_map + flav_map_size; flav++) {
c2754f0
+		bit = secinfo_addflavor(flav, ep);
c2754f0
+		if (bit < 0)
c2754f0
+			return 0;
c2754f0
+		out |= 1<
c2754f0
+	}
c2754f0
+	return out;
c2754f0
+}
c2754f0
 
c2754f0
 /* Sets the bits in @mask for the appropriate security flavor flags. */
c2754f0
 static void setflags(int mask, unsigned int active, struct exportent *ep)
c2754f0
diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am
c2754f0
index 1e76cf8..eba81fc 100644
c2754f0
--- a/utils/mountd/Makefile.am
c2754f0
+++ b/utils/mountd/Makefile.am
c2754f0
@@ -8,7 +8,7 @@ KPREFIX		= @kprefix@
c2754f0
 sbin_PROGRAMS	= mountd
c2754f0
 
c2754f0
 mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
c2754f0
-		 svc_run.c fsloc.c mountd.h
c2754f0
+		 svc_run.c fsloc.c v4root.c mountd.h
c2754f0
 mountd_LDADD = ../../support/export/libexport.a \
c2754f0
 	       ../../support/nfs/libnfs.a \
c2754f0
 	       ../../support/misc/libmisc.a \
c2754f0
diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c
c2754f0
index 5a7ff8c..2ed80bc 100644
c2754f0
--- a/utils/mountd/auth.c
c2754f0
+++ b/utils/mountd/auth.c
c2754f0
@@ -20,6 +20,7 @@
c2754f0
 #include "exportfs.h"
c2754f0
 #include "mountd.h"
c2754f0
 #include "xmalloc.h"
c2754f0
+#include "v4root.h"
c2754f0
 
c2754f0
 enum auth_error
c2754f0
 {
c2754f0
@@ -102,6 +103,8 @@ auth_reload()
c2754f0
 	memset(&my_client, 0, sizeof(my_client));
c2754f0
 	xtab_export_read();
c2754f0
 	check_useipaddr();
c2754f0
+	v4root_set();
c2754f0
+
c2754f0
 	++counter;
c2754f0
 
c2754f0
 	return counter;
c2754f0
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
c2754f0
index 888fd8c..179ef17 100644
c2754f0
--- a/utils/mountd/mountd.c
c2754f0
+++ b/utils/mountd/mountd.c
c2754f0
@@ -540,6 +540,10 @@ get_exportlist(void)
c2754f0
 
c2754f0
 	for (i = 0; i < MCL_MAXTYPES; i++) {
c2754f0
 		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
c2754f0
+			 /* Don't show pseudo exports */
c2754f0
+			if (exp->m_export.e_flags & NFSEXP_V4ROOT)
c2754f0
+				continue;
c2754f0
+
c2754f0
 			for (e = elist; e != NULL; e = e->ex_next) {
c2754f0
 				if (!strcmp(exp->m_export.e_path, e->ex_dir))
c2754f0
 					break;
c2754f0
diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c
c2754f0
new file mode 100644
9d5e785
index 0000000..b1e483a
c2754f0
--- /dev/null
c2754f0
+++ b/utils/mountd/v4root.c
9d5e785
@@ -0,0 +1,218 @@
c2754f0
+/*
c2754f0
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
c2754f0
+ *
c2754f0
+ * support/export/v4root.c
c2754f0
+ *
c2754f0
+ * Routines used to support NFSv4 pseudo roots
c2754f0
+ *
c2754f0
+ */
c2754f0
+
c2754f0
+#ifdef HAVE_CONFIG_H
c2754f0
+#include <config.h>
c2754f0
+#endif
c2754f0
+
c2754f0
+#include <sys/types.h>
c2754f0
+#include <sys/stat.h>
c2754f0
+#include <sys/queue.h>
c2754f0
+#include <stdio.h>
c2754f0
+#include <stdlib.h>
c2754f0
+#include <ctype.h>
c2754f0
+
c2754f0
+#include <unistd.h>
c2754f0
+#include <errno.h>
c2754f0
+
c2754f0
+#include "xlog.h"
c2754f0
+#include "exportfs.h"
c2754f0
+#include "nfslib.h"
c2754f0
+#include "misc.h"
c2754f0
+#include "pseudoflavors.h"
c2754f0
+#include "v4root.h"
c2754f0
+
c2754f0
+#ifndef _PATH_PSEUDO_ROOT
c2754f0
+#define _PATH_PSEUDO_ROOT		"/"
c2754f0
+#endif
c2754f0
+
c2754f0
+#ifndef _PSEUDO_ROOT_FSID
c2754f0
+#define _PSEUDO_ROOT_FSID	0
c2754f0
+#endif
c2754f0
+
c2754f0
+void v4root_set(void);
c2754f0
+void v4root_unset(void);
c2754f0
+static int v4root_support(void);
c2754f0
+
c2754f0
+static struct exportent *v4root_create(char *, nfs_export *);
c2754f0
+
c2754f0
+int v4root_needed;
c2754f0
+static nfs_export pseudo_root = {
c2754f0
+	.m_next = NULL,
c2754f0
+	.m_client = NULL,
c2754f0
+	.m_export = {
c2754f0
+		.e_hostname = "*",
c2754f0
+		.e_path = _PATH_PSEUDO_ROOT,
c2754f0
+		.e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH
c2754f0
+				| NFSEXP_NOSUBTREECHECK | NFSEXP_FSID
c2754f0
+				| NFSEXP_CROSSMOUNT | NFSEXP_V4ROOT,
c2754f0
+		.e_anonuid = 65534,
c2754f0
+		.e_anongid = 65534,
c2754f0
+		.e_squids = NULL,
c2754f0
+		.e_nsquids = 0,
c2754f0
+		.e_sqgids = NULL,
c2754f0
+		.e_nsqgids = 0,
c2754f0
+		.e_fsid = 0,
c2754f0
+		.e_mountpoint = NULL,
c2754f0
+		.e_secinfo[0].flav = NULL,
c2754f0
+	},
c2754f0
+	.m_exported = 0,
c2754f0
+	.m_xtabent = 1,
c2754f0
+	.m_mayexport = 1,
c2754f0
+	.m_changed = 0,
c2754f0
+	.m_warned = 0,
c2754f0
+};
c2754f0
+
c2754f0
+/*
c2754f0
+ * Create a pseudo export
c2754f0
+ */
c2754f0
+static struct exportent *
c2754f0
+v4root_create(char *path, nfs_export *export)
c2754f0
+{
c2754f0
+	nfs_export *exp;
c2754f0
+	struct exportent eep;
c2754f0
+	struct exportent *curexp = &export->m_export;
c2754f0
+
c2754f0
+	dupexportent(&eep, curexp);
c2754f0
+	eep.e_hostname = strdup(curexp->e_hostname);
c2754f0
+	strncpy(eep.e_path, path, sizeof(eep.e_path));
c2754f0
+	exp = export_create(&eep, 0);
c2754f0
+	if (exp == NULL)
c2754f0
+		return NULL;
c2754f0
+
c2754f0
+	exp->m_export.e_flags |= NFSEXP_V4ROOT;
c2754f0
+	if (strcmp(path, _PATH_PSEUDO_ROOT) != 0)
c2754f0
+		exp->m_export.e_flags &= ~NFSEXP_FSID;
c2754f0
+
c2754f0
+	xlog(D_CALL, "v4root_create: path '%s'", exp->m_export.e_path);
c2754f0
+
c2754f0
+	return &exp->m_export;
c2754f0
+}
c2754f0
+
c2754f0
+/*
c2754f0
+ * Make sure the kernel has pseudo root support.
c2754f0
+ */
c2754f0
+static int
c2754f0
+v4root_support()
c2754f0
+{
c2754f0
+	static int kernel_support = -1;
c2754f0
+	char *ptr, version[64];
c2754f0
+	int major, minor;
c2754f0
+	FILE *fp;
c2754f0
+
c2754f0
+	if (kernel_support != -1)
c2754f0
+		return kernel_support;
c2754f0
+
c2754f0
+	kernel_support = 0;
c2754f0
+	fp = fopen("/proc/fs/nfsd/exports", "r");
c2754f0
+	if (fp == NULL)
c2754f0
+		goto out;
c2754f0
+
c2754f0
+	ptr = fgets(version, 64, fp);
c2754f0
+	fclose(fp);
c2754f0
+	if (ptr == NULL)
c2754f0
+		goto out;
c2754f0
+
c2754f0
+	while(*ptr && isdigit(*ptr) == 0)
c2754f0
+		ptr++;
c2754f0
+	if (*ptr == '\0')
c2754f0
+		goto out;
c2754f0
+
c2754f0
+	major = minor = 0;
c2754f0
+	sscanf(ptr, " %d.%d",&major, &minor);
c2754f0
+	if (major >= 1 && minor >= 2)
c2754f0
+		kernel_support = 1;
c2754f0
+out:
c2754f0
+	if (!kernel_support) {
c2754f0
+		xlog(L_WARNING, "Kernel does not have pseudo root support.");
c2754f0
+		xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0");
c2754f0
+		xlog(L_WARNING, "is specfied in /etc/exports file.");
c2754f0
+	}
c2754f0
+
c2754f0
+	return kernel_support;
c2754f0
+}
c2754f0
+
c2754f0
+/*
c2754f0
+ * Create pseudo exports by running through the real export 
c2754f0
+ * looking at the components of the path that make up the export. 
c2754f0
+ * Those path components, if not exported, will become pseudo 
c2754f0
+ * exports allowing them to be found when the kernel does an upcall 
c2754f0
+ * looking for components of the v4 mount.
c2754f0
+ */
c2754f0
+void
c2754f0
+v4root_set()
c2754f0
+{
c2754f0
+	nfs_export	*exp, *nxt;
c2754f0
+	struct exportent *proot;
c2754f0
+	int	i, insecure = 0, secflavors = 0;
c2754f0
+	char *path, *ptr;
c2754f0
+	char *hostname;
c2754f0
+
c2754f0
+	if (!v4root_needed)
c2754f0
+		return;
c2754f0
+
c2754f0
+	if (!v4root_support())
c2754f0
+		return;
c2754f0
+
c2754f0
+	proot = v4root_create(_PATH_PSEUDO_ROOT, &pseudo_root);
c2754f0
+	if (proot == NULL) {
c2754f0
+		xlog(L_WARNING, "v4root_set: Unable to create "
c2754f0
+			"pseudo export for '%s'", _PATH_PSEUDO_ROOT);
c2754f0
+		return;
c2754f0
+	}
c2754f0
+
c2754f0
+	for (i = 0; i < MCL_MAXTYPES; i++) {
c2754f0
+		for (exp = exportlist[i].p_head; exp; exp = nxt) {
c2754f0
+			nxt = exp->m_next;
c2754f0
+			hostname = exp->m_export.e_hostname;
c2754f0
+
c2754f0
+			path = strdup(exp->m_export.e_path);
c2754f0
+			ptr = path + 1;
c2754f0
+			while ((ptr = strchr(ptr, '/')) != NULL) {
c2754f0
+				*ptr = '\0';
c2754f0
+				if (export_lookup(hostname, path, 0) == NULL)
c2754f0
+					if (v4root_create(path, exp) == NULL) {
c2754f0
+						xlog(L_WARNING, "v4root_set: Unable to create "
c2754f0
+							"pseudo export for '%s'", path);
c2754f0
+						break;
c2754f0
+					}
c2754f0
+				*ptr = '/';
c2754f0
+				ptr++;
c2754f0
+			}
c2754f0
+			/* Make note of insecure exports */
c2754f0
+			if (!insecure)
c2754f0
+				insecure = (exp->m_export.e_flags & NFSEXP_INSECURE_PORT);
c2754f0
+
c2754f0
+			/* Make note of security flavors being set */
c2754f0
+			if (!secflavors)
c2754f0
+				secflavors = (exp->m_export.e_secinfo[0].flav != NULL);
c2754f0
+
c2754f0
+			free(path);
c2754f0
+		}
c2754f0
+	}
c2754f0
+
c2754f0
+	/*
c2754f0
+	 * If there are any insecure exports, the pseudo root
c2754f0
+	 * also has to be insecure
c2754f0
+	 */
c2754f0
+	if (insecure) {
c2754f0
+		proot->e_flags |= NFSEXP_INSECURE_PORT;
c2754f0
+	}
c2754f0
+
c2754f0
+	/*
c2754f0
+	 * Make sure the pseudo root is accessible from all
9d5e785
+	 * security flavors when it needs to be.
c2754f0
+	 */
9d5e785
+	if (secflavors && !flavors_setall(proot)) {
9d5e785
+		xlog(L_WARNING, "v4root_set: Unable to set security "
9d5e785
+			"flavors on pseudo root");
c2754f0
+	}
c2754f0
+
9d5e785
+}
c2754f0
+