summaryrefslogtreecommitdiffstats
path: root/sbin/idmapd
diff options
context:
space:
mode:
authoralfred <alfred@FreeBSD.org>2003-11-14 21:04:33 +0000
committeralfred <alfred@FreeBSD.org>2003-11-14 21:04:33 +0000
commit192df7a5bb0d8225b515fb61c5fca981b837690c (patch)
treee888ad11e853530ba060c19704b82ba4cc73fef0 /sbin/idmapd
parent5d2ca7489321484dd03f7fe16c04f2c09a4e58e5 (diff)
downloadFreeBSD-src-192df7a5bb0d8225b515fb61c5fca981b837690c.zip
FreeBSD-src-192df7a5bb0d8225b515fb61c5fca981b837690c.tar.gz
University of Michigan's Citi NFSv4 userland client code.
Submitted by: Jim Rees <rees@umich.edu>
Diffstat (limited to 'sbin/idmapd')
-rw-r--r--sbin/idmapd/Makefile14
-rw-r--r--sbin/idmapd/idmapd.82
-rw-r--r--sbin/idmapd/idmapd.c431
3 files changed, 447 insertions, 0 deletions
diff --git a/sbin/idmapd/Makefile b/sbin/idmapd/Makefile
new file mode 100644
index 0000000..6592157
--- /dev/null
+++ b/sbin/idmapd/Makefile
@@ -0,0 +1,14 @@
+# @(#)Makefile 8.2 (Berkeley) 3/27/94
+#
+# $FreeBSD$
+
+PROG= idmapd
+SRCS= idmapd.c
+MAN= idmapd.8
+
+CFLAGS+= -DNFS -I/usr/src/sys
+WARNS= 2
+
+.PATH:
+
+.include <bsd.prog.mk>
diff --git a/sbin/idmapd/idmapd.8 b/sbin/idmapd/idmapd.8
new file mode 100644
index 0000000..26c2c28
--- /dev/null
+++ b/sbin/idmapd/idmapd.8
@@ -0,0 +1,2 @@
+.\" $FreeBSD$
+man
diff --git a/sbin/idmapd/idmapd.c b/sbin/idmapd/idmapd.c
new file mode 100644
index 0000000..0cccde8
--- /dev/null
+++ b/sbin/idmapd/idmapd.c
@@ -0,0 +1,431 @@
+/* $FreeBSD$ */
+/* $Id: idmapd.c,v 1.5 2003/11/05 14:58:58 rees Exp $ */
+
+/*
+ * copyright (c) 2003
+ * the regents of the university of michigan
+ * all rights reserved
+ *
+ * permission is granted to use, copy, create derivative works and redistribute
+ * this software and such derivative works for any purpose, so long as the name
+ * of the university of michigan is not used in any advertising or publicity
+ * pertaining to the use or distribution of this software without specific,
+ * written prior authorization. if the above copyright notice or any other
+ * identification of the university of michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must also be included.
+ *
+ * this software is provided as is, without representation from the university
+ * of michigan as to its fitness for any purpose, and without warranty by the
+ * university of michigan of any kind, either express or implied, including
+ * without limitation the implied warranties of merchantability and fitness for
+ * a particular purpose. the regents of the university of michigan shall not be
+ * liable for any damages, including special, indirect, incidental, or
+ * consequential damages, with respect to any claim arising out of or in
+ * connection with the use of the software, even if it has been or is hereafter
+ * advised of the possibility of such damages.
+ */
+
+/* XXX ignores the domain of recieved names. */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/syscall.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <nfs4client/nfs4_dev.h>
+#include <nfs4client/nfs4_idmap.h>
+
+/* #include "idmap.h" */
+
+#define DEV_PATH "/dev/nfs4"
+
+#define DOMAIN "@citi.umich.edu"
+#define BADUSER "nobody"
+#define BADGROUP "nogroup"
+#define BADUID (-2)
+#define BADGID (-2)
+
+struct idmap_e {
+ struct nfs4dev_msg msg;
+
+ TAILQ_ENTRY(idmap_e) next;
+};
+
+int fd, verbose;
+char *domain = DOMAIN;
+
+TAILQ_HEAD(, idmap_e) upcall_q;
+
+#define add_idmap_e(E) do { \
+ assert(E != NULL); \
+ TAILQ_INSERT_TAIL(&upcall_q, E, next); \
+} while(0)
+
+#define remove_idmap_e(E) do { \
+ assert(E != NULL && !TAILQ_EMPTY(&upcall_q)); \
+ E = TAILQ_FIRST(&upcall_q); \
+ TAILQ_REMOVE(&upcall_q, E, next); \
+} while(0)
+
+#define get_idmap_e(E) do { \
+ if ((E = (struct idmap_e *) malloc(sizeof(struct idmap_e))) == NULL) {\
+ fprintf(stderr, "get_idmap_e(): error in malloc\n");\
+ } } while(0)
+
+#define put_idmap_e(E) free(E)
+
+/* from marius */
+int
+validateascii(char *string, u_int32_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (string[i] == '\0')
+ break;
+ if (string[i] & 0x80)
+ return (-1);
+ }
+
+ if (string[i] != '\0')
+ return (-1);
+ return (i + 1);
+}
+
+char *
+idmap_prune_domain(struct idmap_msg * m)
+{
+ size_t i;
+ size_t len;
+ char * ret = NULL;
+
+ if (m == NULL)
+ return NULL;
+
+ len = m->id_namelen;
+
+ if (validateascii(m->id_name, len) < 0) {
+ fprintf(stderr, "msg has invalid ascii\n");
+ return NULL;
+ }
+
+ for (i=0; i < len && m->id_name[i] != '@' ; i++);
+
+ ret = (char *)malloc(i+1);
+ if (ret == NULL)
+ return NULL;
+
+ bcopy(m->id_name, ret, i);
+ ret[i] = '\0';
+
+ return ret;
+}
+
+int
+idmap_add_domain(struct idmap_msg * m, char * name)
+{
+ size_t len, nlen;
+
+ if (m == NULL || name == NULL)
+ return -1;
+
+ len = strlen(name);
+
+ nlen = len + strlen(domain);
+
+ if (nlen > IDMAP_MAXNAMELEN)
+ return -1;
+
+ bcopy(name, &m->id_name[0], len);
+ bcopy(domain, &m->id_name[len], strlen(domain));
+
+ m->id_name[nlen] = '\0';
+ m->id_namelen = nlen;
+
+ return 0;
+}
+
+int
+idmap_name(struct idmap_msg * m, char *name)
+{
+ if (m == NULL || name == NULL || m->id_namelen != 0)
+ return -1;
+
+ if (idmap_add_domain(m, name))
+ return -1;
+
+ return 0;
+}
+
+int
+idmap_id(struct idmap_msg * m, ident_t id)
+{
+ if (m == NULL || m->id_namelen == 0) {
+ fprintf(stderr, "idmap_id: bad msg\n");
+ return -1;
+ }
+
+ switch(m->id_type) {
+ case IDMAP_TYPE_UID:
+ m->id_id.uid = id.uid;
+ break;
+ case IDMAP_TYPE_GID:
+ m->id_id.gid = id.gid;
+ break;
+ default:
+ return -1;
+ break;
+ };
+
+ return 0;
+}
+
+int
+idmap_service(struct idmap_e * e)
+{
+ struct idmap_msg * m;
+ struct passwd * pwd;
+ struct group * grp;
+ ident_t id;
+ char * name;
+
+ if (e == NULL) {
+ fprintf(stderr, "bad entry\n");
+ return -1;
+ }
+
+ if (e->msg.msg_vers != NFS4DEV_VERSION) {
+ fprintf(stderr, "kernel/userland version mismatch! %d/%d\n",
+ e->msg.msg_vers, NFS4DEV_VERSION);
+ return -1;
+ }
+
+ if (e->msg.msg_type != NFS4DEV_TYPE_IDMAP) {
+ fprintf(stderr, "bad type!\n");
+ return -1;
+ }
+
+ if (e->msg.msg_len != sizeof(struct idmap_msg)) {
+ fprintf(stderr, "bad message length: %d/%d\n", e->msg.msg_len,
+ sizeof(struct idmap_msg));
+ return -1;
+ }
+
+ if (verbose)
+ printf("servicing msg xid: %x\n", e->msg.msg_xid);
+
+
+ m = (struct idmap_msg *)e->msg.msg_data;
+
+ if (m->id_namelen != 0 && m->id_namelen != strlen(m->id_name)) {
+ fprintf(stderr, "bad name length in idmap_msg\n");
+ return -1;
+ }
+
+ switch (m->id_type) {
+ case IDMAP_TYPE_UID:
+ if (m->id_namelen == 0) {
+ /* id to name */
+ pwd = getpwuid(m->id_id.uid);
+
+ if (pwd == NULL) {
+ fprintf(stderr, "unknown uid %d!\n",
+ (uint32_t)m->id_id.uid);
+ name = BADUSER;
+ } else
+ name = pwd->pw_name;
+
+ if (idmap_name(m, name))
+ return -1;
+
+ } else {
+ /* name to id */
+ name = idmap_prune_domain(m);
+ if (name == NULL)
+ return -1;
+
+ pwd = getpwnam(name);
+
+ if (pwd == NULL) {
+ fprintf(stderr, "unknown username %s!\n", name);
+
+ id.uid = (uid_t)BADUID;
+ } else
+ id.uid = pwd->pw_uid;
+
+ free(name);
+
+ if (idmap_id(m, id))
+ return -1;
+ }
+ break;
+ case IDMAP_TYPE_GID:
+ if (m->id_namelen == 0) {
+ /* id to name */
+ grp = getgrgid(m->id_id.gid);
+
+ if (grp == NULL) {
+ fprintf(stderr, "unknown gid %d!\n",
+ (uint32_t)m->id_id.gid);
+ name = BADGROUP;
+ } else
+ name = grp->gr_name;
+
+ if (idmap_name(m, name))
+ return -1;
+ } else {
+ /* name to id */
+ name = idmap_prune_domain(m);
+ if (name == NULL)
+ return -1;
+
+ grp = getgrnam(name);
+
+ if (grp == NULL) {
+ fprintf(stderr, "unknown groupname %s!\n", name);
+
+ id.gid = (gid_t)BADGID;
+ } else
+ id.gid = grp->gr_gid;
+
+ free(name);
+
+ if (idmap_id(m, id))
+ return -1;
+ }
+ break;
+ default:
+ fprintf(stderr, "bad idmap type: %d\n", m->id_type);
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char ** argv)
+{
+ int error = 0;
+ struct idmap_e * entry;
+ fd_set read_fds, write_fds;
+ int maxfd;
+ int ret, ch;
+
+ while ((ch = getopt(argc, argv, "d:v")) != -1) {
+ switch (ch) {
+ case 'd':
+ domain = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v] [-d domain]\n", argv[0]);
+ exit(1);
+ break;
+ }
+ }
+
+
+ TAILQ_INIT(&upcall_q);
+
+ if (error) {
+ perror("sigaction");
+ exit(1);
+ }
+
+
+ fd = open(DEV_PATH, O_RDWR, S_IRUSR | S_IWUSR);
+
+ if (fd < 0) {
+ perror(DEV_PATH);
+ exit(1);
+ }
+
+ if (!verbose)
+ daemon(0,0);
+
+ if (verbose)
+ printf("sizeof nfs4dev_msg: %d\n", sizeof(struct nfs4dev_msg));
+
+ maxfd = fd;
+ for (;;) {
+ struct timeval timo = {1, 0};
+ do {
+ FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
+
+ FD_SET(fd, &read_fds);
+ FD_SET(fd, &write_fds);
+
+ ret = select(maxfd+1, &read_fds, &write_fds, NULL, &timo);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret <= 0) {
+ if (ret != 0)
+ perror("select");
+ continue;
+ }
+
+
+ if (FD_ISSET(fd, &read_fds)) {
+ for (;;) {
+ get_idmap_e(entry);
+
+ error = ioctl(fd, NFS4DEVIOCGET, &entry->msg);
+
+ if (error == -1) {
+ if (errno != EAGAIN)
+ perror("get ioctl:");
+ put_idmap_e(entry);
+ break;
+ }
+
+ switch (entry->msg.msg_type ) {
+ case NFS4DEV_TYPE_IDMAP:
+ if (idmap_service(entry))
+ entry->msg.msg_error = EIO;
+ break;
+ default:
+ fprintf(stderr, "unknown nfs4dev_msg type\n");
+ entry->msg.msg_error = EIO;
+ break;
+ }
+
+ add_idmap_e(entry);
+ }
+ }
+
+ if (FD_ISSET(fd, &write_fds)) {
+ while (!TAILQ_EMPTY(&upcall_q)) {
+ remove_idmap_e(entry);
+
+ error = ioctl(fd, NFS4DEVIOCPUT, &entry->msg);
+
+ if (error == -1) {
+ if (errno != EAGAIN)
+ perror("put ioctl");
+ break;
+ }
+ put_idmap_e(entry);
+ }
+ }
+ }
+
+ /* never reached */
+ exit(1);
+}
OpenPOWER on IntegriCloud