* NFSv3 UID/GID mapping
@ 2004-04-22 9:36 Ed V. Bartosh
2004-04-22 17:25 ` J. Bruce Fields
0 siblings, 1 reply; 4+ messages in thread
From: Ed V. Bartosh @ 2004-04-22 9:36 UTC (permalink / raw)
To: nfs
[-- Attachment #1: Type: text/plain, Size: 291 bytes --]
Dear NFS developers,
Here is the NFSv3 uid/gid mapping implementation (both kernel and
nfs-utils parts). Userspace part uses idmap daemon from CITI NFSv4,
so the NFSv4 patches are required.
Look at this, please. Any kind of feedback will be appreciated.
--
Best regards,
Ed V. Bartosh
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: linux-2.6.4-nfsd3_idmap.patch --]
[-- Type: text/x-patch, Size: 16658 bytes --]
diff -ruN kernel-source-2.6.4/fs/nfsd.orig/auth.c kernel-source-2.6.4/fs/nfsd/auth.c
--- kernel-source-2.6.4/fs/nfsd.orig/auth.c 2004-03-23 16:20:09 +0200
+++ kernel-source-2.6.4/fs/nfsd/auth.c 2004-04-21 17:16:49 +0300
@@ -4,11 +4,17 @@
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcauth.h>
#include <linux/nfsd/nfsd.h>
+#ifdef CONFIG_NFSD3_IDMAP
+#include <linux/nfsd_idmap.h>
+#endif
+
+#define NFSDDBG_FACILITY NFSDDBG_AUTH
#define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
@@ -17,6 +23,33 @@
struct svc_cred *cred = &rqstp->rq_cred;
int i;
int ret;
+
+#ifdef CONFIG_NFSD3_IDMAP
+ __u32 uidm = IDMAP_UID_NONE;
+ __u32 gidm = IDMAP_UID_NONE;
+
+ if (exp->ex_flags & NFSEXP_IDMAPD) {
+ struct group_info *gi;
+ ret = nfsd3_map_uid_to_uid(rqstp, cred->cr_uid, &uidm);
+ if (ret == 0 && uidm != IDMAP_UID_NONE)
+ cred->cr_uid = uidm;
+
+ ret = nfsd3_map_gid_to_gid(rqstp, cred->cr_gid, &gidm);
+ if (ret == 0 && gidm != IDMAP_UID_NONE)
+ cred->cr_gid = gidm;
+
+ gi = groups_alloc(cred->cr_group_info->ngroups);
+ if (gi) {
+ for (i = 0; i < cred->cr_group_info->ngroups; i++) {
+ ret = nfsd3_map_gid_to_gid(rqstp, GROUP_AT(cred->cr_group_info, i), &gidm);
+ if (ret == 0 && gidm != IDMAP_UID_NONE)
+ GROUP_AT(gi, i) = gidm;
+ }
+ put_group_info(cred->cr_group_info);
+ cred->cr_group_info = gi;
+ }
+ }
+#else
if (exp->ex_flags & NFSEXP_ALLSQUASH) {
cred->cr_uid = exp->ex_anon_uid;
@@ -40,7 +73,7 @@
put_group_info(cred->cr_group_info);
cred->cr_group_info = gi;
}
-
+#endif
if (cred->cr_uid != (uid_t) -1)
current->fsuid = cred->cr_uid;
else
diff -ruN kernel-source-2.6.4/fs/nfsd.orig/export.c kernel-source-2.6.4/fs/nfsd/export.c
--- kernel-source-2.6.4/fs/nfsd.orig/export.c 2004-03-23 16:20:09 +0200
+++ kernel-source-2.6.4/fs/nfsd/export.c 2004-04-08 21:26:11 +0300
@@ -1010,6 +1010,7 @@
{ NFSEXP_ALLSQUASH, {"all_squash", ""}},
{ NFSEXP_ASYNC, {"async", "sync"}},
{ NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
+ { NFSEXP_IDMAPD, {"mapping=idmapd", ""}},
{ NFSEXP_NOHIDE, {"nohide", ""}},
{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
diff -ruN kernel-source-2.6.4/fs/nfsd.orig/Makefile kernel-source-2.6.4/fs/nfsd/Makefile
--- kernel-source-2.6.4/fs/nfsd.orig/Makefile 2004-03-23 16:20:09 +0200
+++ kernel-source-2.6.4/fs/nfsd/Makefile 2004-03-25 12:41:43 +0200
@@ -7,5 +7,6 @@
nfsd-y := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
+nfsd-$(CONFIG_NFSD3_IDMAP) += nfs3idmap.o
nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o
nfsd-objs := $(nfsd-y)
diff -ruN kernel-source-2.6.4/fs/nfsd.orig/nfsctl.c kernel-source-2.6.4/fs/nfsd/nfsctl.c
--- kernel-source-2.6.4/fs/nfsd.orig/nfsctl.c 2004-03-23 16:20:09 +0200
+++ kernel-source-2.6.4/fs/nfsd/nfsctl.c 2004-04-08 18:10:36 +0300
@@ -438,6 +436,9 @@
nfsd_cache_init(); /* RPC reply cache */
nfsd_export_init(); /* Exports table */
nfsd_lockd_init(); /* lockd->nfsd callbacks */
+#ifdef CONFIG_NFSD3_IDMAP
+ nfsd3_idmap_init(); /* User/Group ID mapping */
+#endif /* CONFIG_NFSD3_IDMAP */
#ifdef CONFIG_NFSD_V4
nfsd_idmap_init(); /* Name to ID mapping */
#endif /* CONFIG_NFSD_V4 */
@@ -467,6 +468,9 @@
remove_proc_entry("fs/nfs", NULL);
nfsd_stat_shutdown();
nfsd_lockd_shutdown();
+#ifdef CONFIG_NFSD3_IDMAP
+ nfsd3_idmap_shutdown();
+#endif /* CONFIG_NFSD3_IDMAP */
#ifdef CONFIG_NFSD_V4
nfsd_idmap_shutdown();
#endif /* CONFIG_NFSD_V4 */
--- kernel-source-2.6.4/include/linux/nfsd_idmap.h.orig 2004-03-23 17:23:13 +0200
+++ kernel-source-2.6.4/include/linux/nfsd_idmap.h 2004-04-12 15:56:33 +0300
@@ -51,4 +51,16 @@
int nfsd_map_uid_to_name(struct svc_rqst *, __u32, char *);
int nfsd_map_gid_to_name(struct svc_rqst *, __u32, char *);
+#ifdef CONFIG_NFSD3_IDMAP
+
+#define IDMAP_UID_NONE ((uid_t)-1)
+
+void nfsd3_idmap_init(void);
+void nfsd3_idmap_shutdown(void);
+
+int nfsd3_map_uid_to_uid(struct svc_rqst *rqstp, __u32 id, __u32 *idm);
+
+int nfsd3_map_gid_to_gid(struct svc_rqst *rqstp, __u32 id, __u32 *idm);
+#endif
+
#endif /* LINUX_NFSD_IDMAP_H */
--- kernel-source-2.6.4/include/linux/nfsd/export.h~ 2004-02-04 05:43:56 +0200
+++ kernel-source-2.6.4/include/linux/nfsd/export.h 2004-04-08 21:36:29 +0300
@@ -32,7 +32,8 @@
#define NFSEXP_ALLSQUASH 0x0008
#define NFSEXP_ASYNC 0x0010
#define NFSEXP_GATHERED_WRITES 0x0020
-/* 40 80 100 currently unused */
+#define NFSEXP_IDMAPD 0x0040
+/* 80 100 currently unused */
#define NFSEXP_NOHIDE 0x0200
#define NFSEXP_NOSUBTREECHECK 0x0400
#define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */
--- kernel-source-2.6.4/fs/Kconfig.orig 2004-03-23 16:58:28 +0200
+++ kernel-source-2.6.4/fs/Kconfig 2004-03-25 12:42:09 +0200
@@ -1373,6 +1373,13 @@
If you would like to include the NFSv3 server as well as the NFSv2
server, say Y here. If unsure, say Y.
+config NFSD3_IDMAP
+ bool "Provide NFS User/Group ID Mapping support (EXPERIMENTAL)"
+ depends on NFSD_V3 && EXPERIMENTAL
+ help
+ If you want NFSv3 server to map client's UID or/and GID to
+ the server's one, say Y here. If unsure, say N.
+
config NFSD_V4
bool "Provide NFSv4 server support (EXPERIMENTAL)"
depends on NFSD_V3 && EXPERIMENTAL
--- kernel-source-2.6.4/fs/nfsd.orig/nfs3idmap.c 1970-01-01 02:00:00 +0200
+++ kernel-source-2.6.4/fs/nfsd/nfs3idmap.c 2004-04-15 15:39:31 +0300
@@ -0,0 +1,444 @@
+/*
+ * fs/nfsd/nfs3idmap.c
+ *
+ * User/Group ID Mapping.
+ *
+ * Copyright (c) 2002, 2003 The Regents of the University of
+ * Michigan. All rights reserved.
+ *
+ * Marius Aamodt Eriksen <marius@umich.edu>
+ *
+ * Ed V. Bartosh <ed@sam-solutions.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/mm.h>
+#include <linux/utsname.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/nfs.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_page.h>
+#include <linux/smp_lock.h>
+#include <linux/sunrpc/cache.h>
+#include <linux/nfsd_idmap.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/seq_file.h>
+#include <linux/sunrpc/svcauth.h>
+
+/*
+ * Cache entry
+ */
+
+/*
+ * XXX we know that IDMAP_NAMESZ < PAGE_SIZE, but it's ugly to rely on
+ * that.
+ */
+
+#define IDMAP_TYPE_USER 0
+#define IDMAP_TYPE_GROUP 1
+
+struct ent {
+ struct cache_head h;
+ int type; /* User / Group */
+ uid_t id; /* ID */
+ uid_t idm; /* mapped ID */
+ char authname[IDMAP_NAMESZ];
+};
+
+#define DefineSimpleCacheLookupMap(STRUCT, FUNC) \
+ DefineCacheLookup(struct STRUCT, h, FUNC##_lookup, \
+ (struct STRUCT *item, int set), /*no setup */, \
+ & FUNC##_cache, FUNC##_hash(item), FUNC##_match(item, tmp), \
+ STRUCT##_init(new, item), STRUCT##_update(tmp, item), 0)
+
+/* Common entry handling */
+
+#define ENT_HASHBITS 8
+#define ENT_HASHMAX (1 << ENT_HASHBITS)
+#define ENT_HASHMASK (ENT_HASHMAX - 1)
+
+static inline void
+ent_init(struct ent *new, struct ent *itm)
+{
+ new->id = itm->id;
+ new->idm = itm->idm;
+ new->type = itm->type;
+ strlcpy(new->authname, itm->authname, sizeof(new->authname));
+}
+
+static inline void
+ent_update(struct ent *new, struct ent *itm)
+{
+ ent_init(new, itm);
+}
+
+static void
+ent_put(struct cache_head *ch, struct cache_detail *cd)
+{
+ if (cache_put(ch, cd)) {
+ struct ent *map = container_of(ch, struct ent, h);
+ kfree(map);
+ }
+}
+
+/*
+ * cache
+ */
+
+static struct cache_head *idtoid_table[ENT_HASHMAX];
+
+static uint32_t
+idtoid_hash(struct ent *ent)
+{
+ uint32_t hash;
+
+ hash = hash_str(ent->authname, ENT_HASHBITS);
+ hash = hash_long(hash ^ ent->id, ENT_HASHBITS);
+
+ /* Flip LSB for user/group */
+ if (ent->type == IDMAP_TYPE_GROUP)
+ hash ^= 1;
+
+ return hash;
+}
+
+static void
+idtoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
+ int *blen)
+{
+ struct ent *ent = container_of(ch, struct ent, h);
+ char idstr[11];
+
+ qword_add(bpp, blen, ent->authname);
+ snprintf(idstr, sizeof(idstr), "%d", ent->id);
+ qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
+ qword_add(bpp, blen, idstr);
+ qword_add(bpp, blen, idstr); /* mapped id */
+
+ (*bpp)[-1] = '\n';
+}
+
+static inline int
+idtoid_match(struct ent *a, struct ent *b)
+{
+ return (a->id == b->id && a->type == b->type &&
+ strcmp(a->authname, b->authname) == 0);
+}
+
+static int
+idtoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
+{
+ struct ent *ent;
+
+ if (h == NULL) {
+ seq_puts(m, "#domain type id id\n");
+ return 0;
+ }
+ ent = container_of(h, struct ent, h);
+ seq_printf(m, "%s %s %d", ent->authname,
+ ent->type == IDMAP_TYPE_GROUP ? "group" : "user", ent->id);
+ if (test_bit(CACHE_VALID, &h->flags))
+ seq_printf(m, " %d", ent->idm);
+ seq_printf(m, "\n");
+ return 0;
+}
+
+static int idtoid_parse(struct cache_detail *, char *, int);
+
+struct cache_detail idtoid_cache = {
+ .hash_size = ENT_HASHMAX,
+ .hash_table = idtoid_table,
+ .name = "nfs3.idtoid",
+ .cache_put = ent_put,
+ .cache_request = idtoid_request,
+ .cache_parse = idtoid_parse,
+ .cache_show = idtoid_show,
+};
+
+static struct ent *idtoid_lookup(struct ent *, int);
+
+static int
+idtoid_parse(struct cache_detail *cd, char *buf, int buflen)
+{
+ struct ent ent, *res;
+ char *buf1, *bp;
+ int error = -EINVAL;
+
+ if (buf[buflen - 1] != '\n')
+ return (-EINVAL);
+ buf[buflen - 1]= '\0';
+
+ buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (buf1 == NULL)
+ return (-ENOMEM);
+
+ memset(&ent, 0, sizeof(ent));
+
+ /* Authentication name */
+ if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
+ goto out;
+ memcpy(ent.authname, buf1, sizeof(ent.authname));
+
+ /* Type */
+ if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
+ goto out;
+ ent.type = strcmp(buf1, "user") == 0 ?
+ IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;
+
+ /* ID */
+ if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
+ goto out;
+ ent.id = simple_strtoul(buf1, &bp, 10);
+ if (bp == buf1)
+ goto out;
+
+ /* expiry */
+ ent.h.expiry_time = get_expiry(&buf);
+ if (ent.h.expiry_time == 0)
+ goto out;
+
+ /* Mapped ID */
+ if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
+ goto out;
+ ent.idm = simple_strtoul(buf1, &bp, 10);
+ if (bp == buf1)
+ goto out;
+
+ error = -ENOMEM;
+ if ((res = idtoid_lookup(&ent, 1)) == NULL)
+ goto out;
+
+ ent_put(&res->h, &idtoid_cache);
+
+ error = 0;
+out:
+ kfree(buf1);
+
+ return error;
+}
+
+static DefineSimpleCacheLookupMap(ent, idtoid);
+
+/*
+ * Exported API
+ */
+
+void
+nfsd3_idmap_init(void)
+{
+ cache_register(&idtoid_cache);
+}
+
+void
+nfsd3_idmap_shutdown(void)
+{
+ cache_unregister(&idtoid_cache);
+}
+
+/*
+ * Deferred request handling
+ */
+
+struct idmap_defer_req {
+ struct cache_req req;
+ struct cache_deferred_req deferred_req;
+ wait_queue_head_t waitq;
+ atomic_t count;
+};
+
+static void
+put_mdr(struct idmap_defer_req *mdr)
+{
+ wait_queue_head_t *waitq = &mdr->waitq;
+
+ if (atomic_dec_and_test(&mdr->count))
+ kfree(mdr);
+ else
+ wake_up(waitq);
+}
+
+static void
+idmap_revisit(struct cache_deferred_req *dreq, int toomany)
+{
+ struct idmap_defer_req *mdr =
+ container_of(dreq, struct idmap_defer_req, deferred_req);
+
+ put_mdr(mdr);
+}
+
+static struct cache_deferred_req *
+idmap_defer(struct cache_req *req)
+{
+ struct idmap_defer_req *mdr =
+ container_of(req, struct idmap_defer_req, req);
+
+ mdr->deferred_req.revisit = idmap_revisit;
+ return (&mdr->deferred_req);
+}
+
+static int threads_waiting = 0;
+
+static inline void
+idmap_wait(struct idmap_defer_req *mdr, struct svc_rqst *rqstp) {
+
+ /* Note: BKL prevents races with nfsd_svc and other lookups */
+ lock_kernel();
+ /* XXX: Does it matter that threads_waiting isn't per-server? */
+
+ if (2 * threads_waiting > rqstp->rq_server->sv_nrthreads)
+ goto out;
+ threads_waiting++;
+ schedule_timeout(10 * HZ);
+ threads_waiting--;
+out:
+ unlock_kernel();
+}
+
+static inline int
+do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
+ struct cache_detail *detail, struct ent **item,
+ struct idmap_defer_req *mdr)
+{
+ *item = lookup_fn(key, 0);
+ if (!*item)
+ return -ENOMEM;
+ return cache_check(detail, &(*item)->h, &mdr->req);
+}
+
+static inline int
+do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int),
+ struct ent *key, struct cache_detail *detail,
+ struct ent **item)
+{
+ int ret = -ENOMEM;
+
+ *item = lookup_fn(key, 0);
+ if (!*item)
+ goto out_err;
+ ret = -ETIMEDOUT;
+ if (!test_bit(CACHE_VALID, &(*item)->h.flags)
+ || (*item)->h.expiry_time < get_seconds()
+ || detail->flush_time > (*item)->h.last_refresh)
+ goto out_put;
+ ret = -ENOENT;
+ if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags))
+ goto out_put;
+ return 0;
+out_put:
+ ent_put(&(*item)->h, detail);
+out_err:
+ *item = NULL;
+ return ret;
+}
+
+static inline void
+init_mdr(struct idmap_defer_req *mdr, wait_queue_t *waitq)
+{
+
+ memset(mdr, 0, sizeof(*mdr));
+ init_waitqueue_head(&mdr->waitq);
+ add_wait_queue(&mdr->waitq, waitq);
+ atomic_set(&mdr->count, 2);
+ mdr->req.defer = idmap_defer;
+}
+
+static inline void
+warn_no_idmapd(void) {
+ static time_t last_warning = 0;
+
+ if (last_warning < get_seconds() - 60) {
+ last_warning = get_seconds();
+ printk(KERN_WARNING "nfsd: idmapd timed out; "
+ "check if idmapd is running?\n");
+ }
+}
+
+static int
+idmap_lookup(struct svc_rqst *rqstp,
+ struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
+ struct cache_detail *detail, struct ent **item)
+{
+ DECLARE_WAITQUEUE(waitq, current);
+ struct idmap_defer_req *mdr;
+ int ret;
+
+ mdr = kmalloc(sizeof(*mdr), GFP_KERNEL);
+ if (!mdr)
+ return -ENOMEM;
+
+ init_mdr(mdr, &waitq);
+ set_task_state(current, TASK_INTERRUPTIBLE);
+ ret = do_idmap_lookup(lookup_fn, key, detail, item, mdr);
+
+ if (ret == -EAGAIN) {
+ idmap_wait(mdr, rqstp);
+ ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item);
+ } else {
+ put_mdr(mdr);
+ put_mdr(mdr);
+ }
+ return ret;
+ }
+
+static int
+idmap_id_to_id(struct svc_rqst *rqstp, int type, uid_t id, uid_t *idm)
+{
+ struct ent *item, key = {
+ .type = type,
+ .id = id,
+ };
+ int ret;
+
+ strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+ ret = idmap_lookup(rqstp, idtoid_lookup, &key, &idtoid_cache, &item);
+ if (ret)
+ return ret;
+ *idm = item->idm;
+ ent_put(&item->h, &idtoid_cache);
+ return 0;
+}
+
+int
+nfsd3_map_uid_to_uid(struct svc_rqst *rqstp, __u32 id, __u32 *idm)
+{
+ return idmap_id_to_id(rqstp, IDMAP_TYPE_USER, id, idm);
+}
+
+int
+nfsd3_map_gid_to_gid(struct svc_rqst *rqstp, __u32 id, __u32 *idm)
+{
+ return idmap_id_to_id(rqstp, IDMAP_TYPE_GROUP, id, idm);
+}
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: nfs-utils-1.0.6-uidmapping.patch --]
[-- Type: text/x-patch, Size: 10339 bytes --]
--- nfs-utils-1.0.6/utils/idmapd/idmapd.c.orig 2004-03-23 16:12:15 +0200
+++ nfs-utils-1.0.6/utils/idmapd/idmapd.c 2004-04-08 16:22:44 +0300
@@ -96,6 +96,8 @@
#define IC_IDNAME 1
#define IC_NAMEID 2
+#define IC_IDID 3
+
struct idmap_client {
int ic_fd;
int ic_dirfd;
@@ -122,9 +124,10 @@
static void imconv(struct idmap_client *, struct idmap_msg *);
static void idtonameres(struct idmap_msg *);
static void nametoidres(struct idmap_msg *);
+static void idtoidres(struct idmap_msg *);
static int nfsdopen(char *);
-static int nfsdopenone(struct idmap_client *, short, char *);
+static int nfsdopenone(struct idmap_client *, short, char *, int);
size_t strlcat(char *, const char *, size_t);
size_t strlcpy(char *, const char *, size_t);
@@ -137,7 +140,7 @@
static char *nobodyuser, *nobodygroup;
static uid_t nobodyuid;
static gid_t nobodygid;
-static struct idmap_client nfsd_ic[2];
+static struct idmap_client nfsd_ic[3];
/* Used by cfg.c */
char *conf_path;
@@ -418,6 +428,18 @@
return;
break;
+ case IC_IDID:
+ im.im_conv = IDMAP_CONV_IDTOID;
+ if (getfield(&bp, buf1, sizeof(buf1)) == -1)
+ return;
+ if ((im.im_id = strtoul(buf1, (char **)NULL, 10)) == ULONG_MAX &&
+ errno == ERANGE)
+ return;
+ /* Ugly, but we need client name */
+ strlcpy(im.im_name, authbuf, sizeof(im.im_name));
+
+ break;
+
default:
warnx("Unknown which type %d", ic->ic_which);
return;
@@ -468,6 +490,25 @@
bp[-1] = '\n';
break;
+
+ case IC_IDID:
+ /* Type */
+ p = im.im_type == IDMAP_TYPE_USER ? "user" : "group";
+ addfield(&bp, &bsiz, p);
+ /* ID */
+ snprintf(buf1, sizeof(buf1), "%u", im.im_id);
+ addfield(&bp, &bsiz, buf1);
+ /* expiry */
+ snprintf(buf1, sizeof(buf1), "%lu", time(NULL) + NFSD_EXPIRY);
+ addfield(&bp, &bsiz, buf1);
+ /* Mapped ID */
+ snprintf(buf1, sizeof(buf1), "%u", im.im_idm);
+ addfield(&bp, &bsiz, buf1);
+
+ bp[-1] = '\n';
+
+ break;
+
default:
warnx("Unknown which type %d", ic->ic_which);
return;
@@ -506,6 +547,14 @@
im->im_type == IDMAP_TYPE_USER ? "user" : "group",
im->im_name, im->im_id);
break;
+ case IDMAP_CONV_IDTOID:
+ idtoidres(im);
+ if (verbose > 1)
+ warnx("%s %s: (%s) id \"%s:%d\" -> id \"%d\"",
+ ic->ic_id, ic->ic_clid,
+ im->im_type == IDMAP_TYPE_USER ? "user" : "group",
+ im->im_name, im->im_id, im->im_idm);
+ break;
default:
warnx("Invalid conversion type (%d) in message", im->im_conv);
im->im_status |= IDMAP_STATUS_INVALIDMSG;
@@ -541,18 +590,18 @@
static int
nfsdopen(char *path)
{
- return ((nfsdopenone(&nfsd_ic[0], IC_NAMEID, path) == 0 &&
- nfsdopenone(&nfsd_ic[1], IC_IDNAME, path) == 0) ? 0 : -1);
+ return ((nfsdopenone(&nfsd_ic[2], IC_IDID, path, 3) == 0 || (nfsdopenone(&nfsd_ic[0], IC_NAMEID, path, 4) == 0 &&
+ nfsdopenone(&nfsd_ic[1], IC_IDNAME, path,4)) == 0) ? 0 : -1);
}
static int
-nfsdopenone(struct idmap_client *ic, short which, char *path)
+nfsdopenone(struct idmap_client *ic, short which, char *path, int version)
{
char *whichstr;
whichstr = which == IC_IDNAME ? "idtoname" : "nametoid";
snprintf(ic->ic_path, sizeof(ic->ic_path),
- "%s/nfs4.%s/channel", path, whichstr);
+ "%s/nfs%d.%s/channel", path, version, "idtoid");
if ((ic->ic_fd = open(ic->ic_path, O_RDWR, 0)) == -1) {
warn("%s", ic->ic_path);
return (-1);
@@ -661,6 +710,31 @@
im->im_id = id;
}
+static void
+idtoidres(struct idmap_msg *im)
+{
+ struct passwd *pw;
+ struct group *gr;
+ char *name = NULL;
+ char buf[IDMAP_MAXMSGSZ];
+
+ switch (im->im_type) {
+ case IDMAP_TYPE_USER:
+ snprintf(buf, IDMAP_MAXMSGSZ-1, "%s:%u", im->im_name, im->im_id);
+ name = conf_get_str("Mapping3", buf);
+ pw = (name != NULL) ? getpwnam(name) : NULL;
+ im->im_idm = (pw != NULL) ? pw->pw_uid : IDMAP_UID_NONE;
+ break;
+ case IDMAP_TYPE_GROUP:
+ snprintf(buf, IDMAP_MAXMSGSZ-1, "@%s:%u", im->im_name, im->im_id);
+ name = conf_get_str("Mapping3", buf);
+ gr = (name != NULL) ? getgrnam(name) : NULL;
+ im->im_idm = (gr != NULL) ? gr->gr_gid : IDMAP_UID_NONE;
+ break;
+ }
+
+ im->im_status |= IDMAP_STATUS_SUCCESS;
+}
static int
validateascii(char *string, u_int32_t len)
--- nfs-utils-1.0.6/utils/idmapd/nfs_idmap.h.orig 2004-04-12 16:02:21 +0300
+++ nfs-utils-1.0.6/utils/idmapd/nfs_idmap.h 2004-04-12 16:04:04 +0300
@@ -45,6 +45,7 @@
#define IDMAP_CONV_IDTONAME 0
#define IDMAP_CONV_NAMETOID 1
+#define IDMAP_CONV_IDTOID 2
#define IDMAP_STATUS_INVALIDMSG 0x01
#define IDMAP_STATUS_AGAIN 0x02
@@ -53,11 +54,14 @@
#define IDMAP_MAXMSGSZ 256
+#define IDMAP_UID_NONE ((u_int32_t)-1)
+
struct idmap_msg {
u_int8_t im_type;
u_int8_t im_conv;
char im_name[IDMAP_NAMESZ];
u_int32_t im_id;
+ u_int32_t im_idm;
u_int8_t im_status;
};
diff -ruN nfs-utils-0.3.3.orig/support/nfs/xmalloc.c nfs-utils-0.3.3/support/nfs/xmalloc.c
--- nfs-utils-1.0.6/support/export/nfsctl.c~ 2004-03-23 16:12:15 +0200
+++ nfs-utils-1.0.6/support/export/nfsctl.c 2004-04-08 16:40:56 +0300
@@ -90,8 +90,12 @@
if (stat(exp->m_export.m_path, &stb) < 0)
return 0;
- if (exp->m_export.e_maptype != CLE_MAP_IDENT) {
- xlog(L_ERROR, "%s: unsupported mapping; kernel supports only 'identity' (default)",
+ if (exp->m_export.e_maptype != CLE_MAP_IDENT
+#ifdef UGIDMAP_SUPPORTED
+ && exp->m_export.e_maptype != CLE_MAP_IDMAPD
+#endif
+ ) {
+ xlog(L_ERROR, "%s: unsupported mapping; kernel supports only 'identity' (default) and 'idmapd'",
exp->m_export.m_path);
errno = EINVAL;
return 0;
--- nfs-utils-1.0.6/configure.in.orig 2004-04-08 15:47:39 +0300
+++ nfs-utils-1.0.6/configure.in 2004-04-08 15:48:51 +0300
@@ -40,12 +40,12 @@
fi
AC_SUBST(enable_nfsv3)
AC_ARG_ENABLE(kprefix,
- [ --enable-kprefix install progs as rpc.knfsd etc],
+ [ --enable-kprefix install progs as rpc.knfsd etc],
test "$enableval" = "yes" && kprefix=k,
kprefix=)
AC_SUBST(kprefix)
AC_ARG_ENABLE(secure-statd,
- [ --enable-secure-statd Only lockd can use statd (security)],
+ [ --enable-secure-statd Only lockd can use statd (security)],
test "$enableval" = "yes" && secure_statd=yes,
secure_statd=no)
if test "$secure_statd" = yes; then
@@ -53,7 +53,7 @@
fi
AC_SUBST(secure_statd)
AC_ARG_ENABLE(rquotad,
- [ --enable-rquotad enable rquotad],
+ [ --enable-rquotad enable rquotad],
enable_rquotad=$enableval,
enable_rquotad=yes)
if test "$enable_rquotad" = yes; then
@@ -62,6 +62,17 @@
RQUOTAD=
fi
AC_SUBST(RQUOTAD)
+AC_ARG_ENABLE(ugidmapping,
+ [ --enable-uidmapping enable uid/gid mapping],
+ enable_ugidmapping=$enableval,
+ enable_ugidmapping=no)
+ if test "$enable_ugidmapping" = yes; then
+ AC_DEFINE(UGIDMAP_SUPPORTED)
+ else
+ enable_ugidmapping=
+ fi
+ AC_SUBST(enable_ugidmapping)
+
dnl AC_ARG_ENABLE(frob, enable frobnicator,, enable_frob=test)
AC_CONFIG_HEADER(support/include/config.h)
--- nfs-utils-0.3.3.orig/rules.mk Sun Dec 5 00:02:01 1999
+++ nfs-utils-0.3.3/rules.mk Thu Jun 27 17:55:08 2002
@@ -70,7 +70,7 @@
# Cleaning rules
##################################################################
clean distclean::
- rm -f *.o *~ \#* a.out core
+ rm -f *.o *~ *.a \#* a.out core
distclean::
rm -f LOG X Y Z x y z .depend
--- nfs-utils-1.0.6/support/nfs/exports.c.orig 2003-08-06 08:19:42 +0300
+++ nfs-utils-1.0.6/support/nfs/exports.c 2004-04-12 11:15:12 +0300
@@ -197,6 +197,9 @@
case CLE_MAP_IDENT:
fprintf(fp, "identity,");
break;
+ case CLE_MAP_IDMAPD:
+ fprintf(fp, "idmapd,");
+ break;
case CLE_MAP_UGIDD:
fprintf(fp, "ugidd,");
break;
@@ -374,8 +377,11 @@
ep->e_flags &= ~NFSEXP_NOAUTHNLM;
else if (strcmp(opt, "insecure_locks") == 0)
ep->e_flags |= NFSEXP_NOAUTHNLM;
- else if (strncmp(opt, "mapping=", 8) == 0)
+ else if (strncmp(opt, "mapping=", 8) == 0) {
ep->e_maptype = parsemaptype(opt+8);
+ if (ep->e_maptype == CLE_MAP_IDMAPD)
+ ep->e_flags |= NFSEXP_IDMAPD;
+ }
else if (strcmp(opt, "map_identity") == 0) /* old style */
ep->e_maptype = CLE_MAP_IDENT;
else if (strcmp(opt, "map_daemon") == 0) /* old style */
@@ -528,11 +534,13 @@
static int
parsemaptype(char *type)
{
- if (!strcmp(type, "identity"))
+ if (!strncmp(type, "identity", 8))
return CLE_MAP_IDENT;
- if (!strcmp(type, "ugidd"))
+ if (!strncmp(type, "idmapd", 6))
+ return CLE_MAP_IDMAPD;
+ if (!strncmp(type, "ugidd", 5))
return CLE_MAP_UGIDD;
- if (!strcmp(type, "file"))
+ if (!strncmp(type, "file", 4))
return CLE_MAP_FILE;
syntaxerr("invalid map type");
return CLE_MAP_IDENT; /* default */
--- nfs-utils-1.0.6/support/include/config.h.in~ 2004-04-08 16:56:26 +0300
+++ nfs-utils-1.0.6/support/include/config.h.in 2004-04-08 17:00:01 +0300
@@ -29,3 +29,7 @@
#undef HAVE_KRB5
/* XXX: you don't want to know: */
#undef USE_PRIVATE_KRB5_FUNCTIONS
+
+/* Define this if you want uid/gid mapping support compiled in
+ */
+#undef UGIDMAP_SUPPORTED
--- nfs-utils-1.0.6/utils/exportfs/exportfs.c~ 2004-04-08 16:56:28 +0300
+++ nfs-utils-1.0.6/utils/exportfs/exportfs.c 2004-04-08 17:07:30 +0300
@@ -142,6 +142,8 @@
if (!new_cache)
xtab_mount_write();
+ export_freeall();
+
return export_errno;
}
--- nfs-utils-1.0.6/support/include/nfslib.h~ 2004-04-08 16:56:26 +0300
+++ nfs-utils-1.0.6/support/include/nfslib.h 2004-04-08 17:18:17 +0300
@@ -53,6 +53,7 @@
CLE_MAP_IDENT = 0,
CLE_MAP_FILE,
CLE_MAP_UGIDD,
+ CLE_MAP_IDMAPD,
};
/*
--- nfs-utils-1.0.6/support/include/nfs/export.h~ 2004-04-08 16:56:26 +0300
+++ nfs-utils-1.0.6/support/include/nfs/export.h 2004-04-08 17:29:07 +0300
@@ -17,7 +17,8 @@
#define NFSEXP_ALLSQUASH 0x0008
#define NFSEXP_ASYNC 0x0010
#define NFSEXP_GATHERED_WRITES 0x0020
-/* 40, 80, 100 unused */
+#define NFSEXP_IDMAPD 0x0040
+/* 80, 100 unused */
#define NFSEXP_NOHIDE 0x0200
#define NFSEXP_NOSUBTREECHECK 0x0400
#define NFSEXP_NOAUTHNLM 0x0800
--- nfs-utils-1.0.6/utils/idmapd/idmapd.conf~ 2004-04-12 16:08:15 +0300
+++ nfs-utils-1.0.6/utils/idmapd/idmapd.conf 2004-04-12 16:12:06 +0300
@@ -8,3 +8,7 @@
Nobody-User = nobody
Nobody-Group = nobody
+
+[Mapping3]
+
+
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: NFSv3 UID/GID mapping
2004-04-22 9:36 NFSv3 UID/GID mapping Ed V. Bartosh
@ 2004-04-22 17:25 ` J. Bruce Fields
2004-04-23 9:12 ` Ed V. Bartosh
0 siblings, 1 reply; 4+ messages in thread
From: J. Bruce Fields @ 2004-04-22 17:25 UTC (permalink / raw)
To: Ed V. Bartosh; +Cc: nfs
On Thu, Apr 22, 2004 at 12:36:13PM +0300, Ed V. Bartosh wrote:
> Here is the NFSv3 uid/gid mapping implementation (both kernel and
> nfs-utils parts). Userspace part uses idmap daemon from CITI NFSv4,
> so the NFSv4 patches are required.
Just out of curiosity:
* This does the server side only. Have you looked at the client side
at all?
* What sort of applications are you considering for this?
> Look at this, please. Any kind of feedback will be appreciated.
Do you also need to do map the id's in nfs3xdr.c:xdr_encode_setattr() and
xdr_decode_fattr()?
Is IDMAP_UID_NONE really needed, or could you just use an ENOENT return?
We need to figure out a way to do this without duplicating so much code
from nfs4idmap.c.
Also note some of that code is wrong. (See the nfsd_idmap patches in
http://www.citi.umich.edu/projects/nfsv4/linux/kernel-patches/2.6.6-rc1-3/).
--Bruce Fields
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: NFSv3 UID/GID mapping
2004-04-22 17:25 ` J. Bruce Fields
@ 2004-04-23 9:12 ` Ed V. Bartosh
2004-04-23 18:23 ` J. Bruce Fields
0 siblings, 1 reply; 4+ messages in thread
From: Ed V. Bartosh @ 2004-04-23 9:12 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: nfs
"J. Bruce Fields" <bfields@fieldses.org> writes:
> On Thu, Apr 22, 2004 at 12:36:13PM +0300, Ed V. Bartosh wrote:
>> Here is the NFSv3 uid/gid mapping implementation (both kernel and
>> nfs-utils parts). Userspace part uses idmap daemon from CITI NFSv4,
>> so the NFSv4 patches are required.
>
> Just out of curiosity:
> * This does the server side only. Have you looked at the client side
> at all?
No. It's just a server-side mapping. I think we don't need to rely on
client for that. There are many other possibilities to change uids on
client side. Also client-based solution is less secure than
server-side one and also it's the linux-only solution.
> * What sort of applications are you considering for this?
>
I'm considering that this should be used in cases when there is no
possibility to have equal uids on the NFS server and client. For
example we have this situation when we use the same share as SMB and
NFS share and we have to map uids of NFS users to uids of samba users
(preferable windows boxes). In our situation this mapping is
required because we need server XFS ACLs to work properly for any type
of clients.
I think there are many other situations when it may be useful to use
this kind of mapping.
>> Look at this, please. Any kind of feedback will be appreciated.
>
> Do you also need to do map the id's in nfs3xdr.c:xdr_encode_setattr() and
> xdr_decode_fattr()?
Yes, I do. Thank you.
> Is IDMAP_UID_NONE really needed, or could you just use an ENOENT return?
>
It's not important, i think, because '(uid_t) -1' is already used in
auth.c, I've just named it. But, yes, it can be used partly. I mean that
uids which can't be mapped will be passed from userspace in any
case and we'll need to check it somewhere.
> We need to figure out a way to do this without duplicating so much code
> from nfs4idmap.c.
Yes, we need it, but it's not too much code. I think that there is
sense to move only deferred request handling functions somewhere in
separate file and use it from nfs4 and nfs3 idmap functions.
> Also note some of that code is wrong. (See the nfsd_idmap patches in
> http://www.citi.umich.edu/projects/nfsv4/linux/kernel-patches/2.6.6-rc1-3/).
>
Yes, sure. When I worked on this patches there where only CITI patches
for 2.6.5 available. I used them for my work.
Thank you for your feedback.
I'll change the code according to your suggestions.
BTW, Is any chance for this functionality to be in mainstream
sometime ?
--
Best regards,
Ed V. Bartosh
-------------------------------------------------------
This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek
For a limited time only, get FREE Ground shipping on all orders of $35
or more. Hurry up and shop folks, this offer expires April 30th!
http://www.thinkgeek.com/freeshipping/?cpg=12297
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: NFSv3 UID/GID mapping
2004-04-23 9:12 ` Ed V. Bartosh
@ 2004-04-23 18:23 ` J. Bruce Fields
0 siblings, 0 replies; 4+ messages in thread
From: J. Bruce Fields @ 2004-04-23 18:23 UTC (permalink / raw)
To: Ed V. Bartosh; +Cc: nfs
On Fri, Apr 23, 2004 at 12:12:05PM +0300, Ed V. Bartosh wrote:
> It's just a server-side mapping. I think we don't need to rely on
> client for that. There are many other possibilities to change uids on
> client side.
The situation where I can imagine it being useful is when you had a
client (maybe a laptop) that you wanted to be able to access shares on
servers in different uid domains (possibly simultaneously).
> Also client-based solution is less secure than server-side one and
> also it's the linux-only solution.
I don't see the argument there.
> I think there are many other situations when it may be useful to use
> this kind of mapping.
Sure. I think someone on the linux kernel mailing list said they wanted
to able to squash ranges of uid's.
> > Do you also need to do map the id's in nfs3xdr.c:xdr_encode_setattr() and
> > xdr_decode_fattr()?
> Yes, I do. Thank you.
That means you need a second mapping: in addition to mapping remove
clients' id's to local server id's, you need the inverse mapping from
local id's to the clients' id's (to get ls right).
> > We need to figure out a way to do this without duplicating so much code
> > from nfs4idmap.c.
> Yes, we need it, but it's not too much code. I think that there is
> sense to move only deferred request handling functions somewhere in
> separate file and use it from nfs4 and nfs3 idmap functions.
OK.
> BTW, Is any chance for this functionality to be in mainstream sometime ?
It seems useful, but it's not really up to me.
--Bruce Fields
-------------------------------------------------------
This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek
For a limited time only, get FREE Ground shipping on all orders of $35
or more. Hurry up and shop folks, this offer expires April 30th!
http://www.thinkgeek.com/freeshipping/?cpg=12297
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2004-04-23 18:23 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-22 9:36 NFSv3 UID/GID mapping Ed V. Bartosh
2004-04-22 17:25 ` J. Bruce Fields
2004-04-23 9:12 ` Ed V. Bartosh
2004-04-23 18:23 ` J. Bruce Fields
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.