Add zfsaddhomedir
authorDavid Bartley <dtbartle@csclub.uwaterloo.ca>
Sat, 15 Mar 2008 06:22:08 +0000 (02:22 -0400)
committerDavid Bartley <dtbartle@csclub.uwaterloo.ca>
Sun, 16 Mar 2008 09:35:21 +0000 (05:35 -0400)
src/.gitignore
src/Makefile
src/addclub.c
src/addhomedir.c
src/addhomedir.h
src/addmember.c
src/config.c
src/config.h
src/zfsaddhomedir.c [new file with mode: 0644]

index d02cf79..b07d4ff 100644 (file)
@@ -1,4 +1,5 @@
 *.o
 /addmember
 /addclub
+/zfsaddhomedir
 /config-test
index 3fdcd19..fa5caf6 100644 (file)
@@ -10,7 +10,7 @@ PREFIX := /usr/local
 all: addmember addclub
 
 clean:
-       rm -f addmember addclub config-test *.o
+       rm -f addmember addclub zfsaddhomedir config-test *.o
 
 addmember: $(LIBCEO_OBJECTS) addmember.o
        $(CC) $(LDFLAGS) $(LIBCEO_LDFLAGS) $^ -o $@
@@ -18,6 +18,9 @@ addmember: $(LIBCEO_OBJECTS) addmember.o
 addclub: $(LIBCEO_OBJECTS) addclub.o
        $(CC) $(LDFLAGS) $(LIBCEO_LDFLAGS) $^ -o $@
 
+zfsaddhomedir: util.o zfsaddhomedir.o
+       $(CC) $(LDFLAGS) $^ -o $@
+
 config-test: config-test.o parser.o util.o
        $(CC) $(LDFLAGS) $^ -o $@
 
index 87abcae..430ae62 100644 (file)
@@ -1,7 +1,6 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <sys/acl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <getopt.h>
@@ -42,11 +41,10 @@ static void usage() {
 }
 
 int addclub() {
-    int krb_ok, user_ok, group_ok, sudo_ok, home_ok, quota_ok;
+    int krb_ok, user_ok, group_ok, sudo_ok, home_ok;
     int id;
     char homedir[1024];
-    char acl_s[1024], dacl_s[1024];
-    acl_t acl = NULL, dacl = NULL;
+    char acl_s[1024] = {0};
 
     logmsg("adding uid=%s cn=%s by %s", userid, name, user);
 
@@ -67,19 +65,7 @@ int addclub() {
     if ((id = ceo_new_uid(club_min_id, club_max_id)) <= 0)
         fatal("no available uids in range [%d, %d]", club_min_id, club_max_id);
 
-    snprintf(acl_s, sizeof(acl_s), club_home_acl, id);
-
-    acl = acl_from_text(acl_s);
-    if (acl == NULL)
-        fatalpe("Unable to parse club_home_acl");
-
-    if (*club_home_dacl) {
-        snprintf(dacl_s, sizeof(dacl_s), club_home_dacl, id);
-        dacl = acl_from_text(dacl_s);
-        if (dacl == NULL)
-            fatalpe("Unable to parse club_home_dacl");
-    }
-
+    snprintf(acl_s, sizeof(acl_s), club_home_acl, userid);
 
     krb_ok = ceo_del_princ(userid);
     if (!krb_ok)
@@ -98,14 +84,10 @@ int addclub() {
     if (!sudo_ok)
         logmsg("successfully added group sudo entry for %s", userid);
 
-    home_ok = user_ok || ceo_create_home(homedir, id, id, acl, dacl);
+    home_ok = user_ok || ceo_create_home(homedir, id, id, homedir_mode, acl_s);
     if (!home_ok)
         logmsg("successfully created home directory for %s", userid);
 
-    quota_ok = user_ok || ceo_set_quota(quota_prototype, id);
-    if (!quota_ok)
-        logmsg("successfully set quota for %s", userid);
-
     logmsg("done uid=%s", userid);
 
     if (!no_notify && !user_ok) {
@@ -136,9 +118,7 @@ int addclub() {
             fprintf(hkf, "failed to create group\n");
         if (home_ok)
             fprintf(hkf, "failed to create home directory\n");
-        if (quota_ok)
-            fprintf(hkf, "failed to set quota\n");
-        if (!group_ok && !home_ok && !quota_ok)
+        if (!group_ok && !home_ok)
             fprintf(hkf, "all failures went undetected\n");
 
         fclose(hkf);
@@ -155,7 +135,7 @@ int addclub() {
     ceo_ldap_cleanup();
     ceo_krb5_cleanup();
 
-    return krb_ok || user_ok || group_ok || home_ok || quota_ok;
+    return krb_ok || user_ok || group_ok || home_ok;
 }
 
 int main(int argc, char *argv[]) {
index 6cd27db..5c396ea 100644 (file)
 #include <dirent.h>
 #include <pwd.h>
 #include <fcntl.h>
+#include <assert.h>
 
 #include "addhomedir.h"
 #include "util.h"
 #include "config.h"
 
-int ceo_create_home(char *homedir, uid_t uid, gid_t gid, acl_t acl, acl_t dacl) {
-    int mask;
-    DIR *skel;
-    struct dirent *skelent;
-
-    mask = umask(0);
-
-    if (mkdir(homedir, 0755)) {
-        errorpe("failed to create %s", homedir);
-        return -1;
-    }
-
-    skel = opendir(skeleton_dir);
-    if (!skel) {
-        errorpe("failed to open %s", skeleton_dir);
-        return -1;
-    }
-
-    while ((skelent = readdir(skel))) {
-        struct stat sb;
-        char src[PATH_MAX], dest[PATH_MAX];
-
-        if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, ".."))
-            continue;
-
-        snprintf(src, sizeof(src), "%s/%s", skeleton_dir, skelent->d_name);
-        snprintf(dest, sizeof(dest), "%s/%s", homedir, skelent->d_name);
-        lstat(src, &sb);
-
-        if (sb.st_uid || sb.st_gid) {
-            warn("not creating %s due to ownership", dest);
-            continue;
-        }
-
-        if (S_ISREG(sb.st_mode)) {
-            int bytes;
-            char buf[4096];
-
-            int srcfd = open(src, O_RDONLY);
-            if (srcfd == -1) {
-                warnpe("open: %s", src);
-                continue;
-            }
-
-            int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777);
-            if (destfd == -1) {
-                warnpe("open: %s", dest);
-                close(srcfd);
-                continue;
-            }
-
-            for (;;) {
-                bytes = read(srcfd, buf, sizeof(buf));
-                if (!bytes)
-                    break;
-                if (bytes < 0) {
-                    warnpe("read");
-                    break;
-                }
-                if (write(destfd, buf, bytes) < 0) {
-                    warnpe("write");
-                    break;
-                }
-            }
-
-            if (fchown(destfd, uid, gid))
-                errorpe("chown: %s", dest);
-
-            close(srcfd);
-            close(destfd);
-        } else if (S_ISDIR(sb.st_mode)) {
-            if (mkdir(dest, sb.st_mode & 0777)) {
-                warnpe("mkdir: %s", dest);
-                continue;
-            }
-            if (chown(dest, uid, gid))
-                errorpe("chown: %s", dest);
-        } else if (S_ISLNK(sb.st_mode)) {
-            char lnkdest[PATH_MAX];
-            int bytes;
-            bytes = readlink(src, lnkdest, sizeof(lnkdest));
-            lnkdest[bytes] = '\0';
-            if (bytes == -1) {
-                warnpe("readlink: %s", src);
-                continue;
-            }
-            if (symlink(lnkdest, dest)) {
-                warnpe("symlink: %s", dest);
-                continue;
-            }
-            if (lchown(dest, uid, gid))
-                errorpe("lchown: %s", dest);
-        } else {
-            warn("not creating %s", dest);
-        }
-    }
-
-    closedir(skel);
-
-    if (chown(homedir, uid, gid)) {
-        errorpe("failed to chown %s", homedir);
-        return -1;
-    }
-
-    if (acl && acl_set_file(homedir, ACL_TYPE_ACCESS, acl)) {
-        errorpe("failed to set acl for %s", homedir);
-        return -1;
-    }
-
-    if (dacl && acl_set_file(homedir, ACL_TYPE_DEFAULT, dacl)) {
-        errorpe("failed to set default acl for %s", homedir);
-        return -1;
-    }
-
-    umask(mask);
-
-    return 0;
-}
-
-int ceo_set_quota(char *proto, int id) {
-    char user[128];
-    char *sqargs[] = { "setquota", "-a", "-p", proto, NULL, NULL };
-
-    snprintf(user, sizeof(user), "%d", id);
-    sqargs[4] = user;
-
-    if (spawnv("/usr/sbin/setquota", sqargs)) {
-        error("failed to set quota for %s", user);
+int ceo_create_home(char *homedir, uid_t uid, gid_t gid, char *mode, char *acl) {
+    char uid_str[16], gid_str[16];
+    char *zfs_argv[] = { "ssh", "ceo@ginseng", "/usr/sbin/zfsaddhomedir", \
+        homedir, skeleton_dir, uid_str, gid_str, mode, acl, NULL };
+
+    assert(homedir[0]);
+    snprintf(uid_str, sizeof(uid_str), "%ld", (long)uid);
+    snprintf(gid_str, sizeof(gid_str), "%ld", (long)uid);
+    if(!acl[0]) acl = NULL;
+    if(spawnv("/usr/bin/ssh", zfs_argv)) {
+        errorpe("failed calling zfsaddhomedir for %s", homedir);
         return -1;
     }
 
index 560dbc8..9d3493d 100644 (file)
@@ -1,4 +1,3 @@
 #include <sys/types.h>
 
-int ceo_create_home(char *, uid_t, gid_t, acl_t, acl_t);
-int ceo_set_quota(char *, int);
+int ceo_create_home(char *, uid_t, gid_t, char *, char *);
index f43507a..62ee408 100644 (file)
@@ -1,7 +1,6 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <sys/acl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <getopt.h>
@@ -47,11 +46,10 @@ static void usage() {
 }
 
 int addmember() {
-    int krb_ok, user_ok, group_ok, home_ok, quota_ok;
+    int krb_ok, user_ok, group_ok, home_ok;
     int id;
     char homedir[1024];
-    char acl_s[1024], dacl_s[1024];
-    acl_t acl = NULL, dacl = NULL;
+    char acl_s[1024] = {0};
 
     logmsg("adding uid=%s cn=%s program=%s by %s", userid, name, program, user);
 
@@ -76,18 +74,10 @@ int addmember() {
     if ((id = ceo_new_uid(member_min_id, member_max_id)) <= 0)
         fatal("no available uids in range [%d, %d]", member_min_id, member_max_id);
 
-    snprintf(acl_s, sizeof(acl_s), member_home_acl, id);
-
-    acl = acl_from_text(acl_s);
-    if (acl == NULL)
-        fatalpe("Unable to parse member_home_acl");
-
     if (*member_home_acl) {
-        snprintf(dacl_s, sizeof(dacl_s), member_home_dacl, id);
-        dacl = acl_from_text(dacl_s);
-        if (dacl == NULL)
-            fatalpe("Unable to parse member_home_dacl");
+        snprintf(acl_s, sizeof(acl_s), member_home_acl, userid);
     }
+
     krb_ok = ceo_del_princ(userid);
     krb_ok = krb_ok || ceo_add_princ(userid, password);
     if (!krb_ok)
@@ -102,14 +92,10 @@ int addmember() {
     if (!group_ok)
         logmsg("successfully created group for %s", userid);
 
-    home_ok = user_ok || ceo_create_home(homedir, id, id, acl, dacl);
+    home_ok = user_ok || ceo_create_home(homedir, id, id, homedir_mode, acl_s);
     if (!home_ok)
         logmsg("successfully created home directory for %s", userid);
 
-    quota_ok = user_ok || ceo_set_quota(quota_prototype, id);
-    if (!quota_ok)
-        logmsg("successfully set quota for %s", userid);
-
     logmsg("done uid=%s", userid);
 
     if (!no_notify && !user_ok) {
@@ -140,9 +126,7 @@ int addmember() {
             fprintf(hkf, "failed to create group\n");
         if (home_ok)
             fprintf(hkf, "failed to create home directory\n");
-        if (quota_ok)
-            fprintf(hkf, "failed to set quota\n");
-        if (!group_ok && !home_ok && !quota_ok)
+        if (!group_ok && !home_ok)
             fprintf(hkf, "all failures went undetected\n");
 
         fclose(hkf);
@@ -159,7 +143,7 @@ int addmember() {
     ceo_ldap_cleanup();
     ceo_krb5_cleanup();
 
-    return krb_ok || user_ok || group_ok || home_ok || quota_ok;
+    return krb_ok || user_ok || group_ok || home_ok;
 }
 
 int main(int argc, char *argv[]) {
index b805d13..4afb369 100644 (file)
@@ -15,21 +15,19 @@ char *groups_base = DEF_STR;
 char *sudo_base = DEF_STR;
 
 char *skeleton_dir = DEF_STR;
-char *quota_prototype = DEF_STR;
+char *homedir_mode = DEF_STR;
 
 char *member_shell = DEF_STR;
 long member_min_id = DEF_LONG;
 long member_max_id = DEF_LONG;
 char *member_home = DEF_STR;
 char *member_home_acl = DEF_STR;
-char *member_home_dacl = DEF_STR;
 
 char *club_shell = DEF_STR;
 long club_min_id = DEF_LONG;
 long club_max_id = DEF_LONG;
 char *club_home = DEF_STR;
 char *club_home_acl = DEF_STR;
-char *club_home_dacl = DEF_STR;
 
 char *notify_hook = DEF_STR;
 
@@ -47,17 +45,16 @@ char *sasl_mech = DEF_STR;
 char *privileged_group = DEF_STR;
 
 static char *strvarnames[] = { "server_url", "users_base", "admin_principal",
-    "admin_keytab", "skeleton_dir", "quota_prototype", "member_home",
+    "admin_keytab", "skeleton_dir", "homedir_mode", "member_home",
     "member_shell", "club_home", "club_shell", "realm", "admin_bind_userid",
     "admin_bind_keytab", "groups_base", "privileged_group", "notify_hook",
     "sasl_realm", "sasl_mech", "sudo_base", "member_home_acl",
-    "member_home_dacl", "club_home_acl", "club_home_dacl" };
+    "club_home_acl" };
 static char **strvars[] = { &server_url, &users_base, &admin_principal,
-    &admin_keytab, &skeleton_dir, &quota_prototype, &member_home,
-    &member_shell, &club_home, &club_shell, &realm, &admin_bind_userid,
-    &admin_bind_keytab, &groups_base, &privileged_group, &notify_hook,
-    &sasl_realm, &sasl_mech, &sudo_base, &member_home_acl, &member_home_dacl,
-    &club_home_acl, &club_home_dacl };
+    &admin_keytab, &skeleton_dir, &homedir_mode, &member_home, &member_shell,
+    &club_home, &club_shell, &realm, &admin_bind_userid, &admin_bind_keytab,
+    &groups_base, &privileged_group, &notify_hook, &sasl_realm, &sasl_mech,
+    &sudo_base, &member_home_acl, &club_home_acl };
 
 static char *longvarnames[] = { "member_min_id", "member_max_id",
     "club_min_id", "club_max_id" };
index 8bf4c72..e67d395 100644 (file)
@@ -6,7 +6,6 @@ extern char *groups_base;
 extern char *sudo_base;
 
 extern char *skeleton_dir;
-extern char *quota_prototype;
 
 extern char *member_shell;
 extern long member_min_id;
@@ -24,7 +23,7 @@ extern char *club_home_dacl;
 
 extern char *notify_hook;
 
-extern long homedir_mode;
+extern char *homedir_mode;
 
 extern char *realm;
 
diff --git a/src/zfsaddhomedir.c b/src/zfsaddhomedir.c
new file mode 100644 (file)
index 0000000..ebee39b
--- /dev/null
@@ -0,0 +1,140 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <assert.h>
+#include "util.h"
+
+int main(int argc, char *argv[]) {
+    if(argc < 6) {
+        fprintf(stderr, "Usage: zfsaddhomedir homedir skeldir uid gid mode acl\n");
+        return 1;
+    }
+
+    // TODO: check return of spawnv
+    {
+        char *homedir = argv[1];
+        char *skeldir = argv[2];
+        char *mode = argv[5];
+        char *acl = (argc >= 7) ? argv[6] : NULL;
+        uid_t uid, gid;
+        char *zfs_bin = "/usr/sbin/zfs";
+        char *chmod_bin = "/usr/bin/chmod";
+        char *dataset = homedir + 1;
+        char *create_argv[] = { "zfs", "create", dataset, NULL };
+        char *quota_argv[] = { "zfs", "set", "quota=3G", dataset, NULL };
+        char *mode_argv[] = { "chmod", mode, homedir, NULL };
+        char *acl_argv[] = { "chmod", acl, homedir, NULL };
+        DIR *skel;
+        struct dirent *skelent;
+
+        assert(homedir[0]);
+        uid = atol(argv[3]);
+        gid = atol(argv[4]);
+
+        if(spawnv(zfs_bin, create_argv))
+            return 1;
+        if(spawnv(zfs_bin, quota_argv))
+            return 1;
+        if(spawnv(chmod_bin, mode_argv))
+            return 1;
+        if(acl && spawnv(chmod_bin, acl_argv))
+            return 1;
+
+        skel = opendir(skeldir);
+        if (!skel) {
+            errorpe("failed to open %s", skeldir);
+            return -1;
+        }
+
+        while ((skelent = readdir(skel))) {
+            struct stat sb;
+            char src[PATH_MAX], dest[PATH_MAX];
+
+            if (!strcmp(skelent->d_name, ".") || !strcmp(skelent->d_name, ".."))
+                continue;
+
+            snprintf(src, sizeof(src), "%s/%s", skeldir, skelent->d_name);
+            snprintf(dest, sizeof(dest), "/%s/%s", homedir, skelent->d_name);
+            lstat(src, &sb);
+
+            if (sb.st_uid || sb.st_gid) {
+                warn("not creating %s due to ownership", dest);
+                continue;
+            }
+
+            if (S_ISREG(sb.st_mode)) {
+                int bytes;
+                char buf[4096];
+
+                int srcfd = open(src, O_RDONLY);
+                if (srcfd == -1) {
+                    warnpe("open: %s", src);
+                    continue;
+                }
+
+                int destfd = open(dest, O_WRONLY|O_CREAT|O_EXCL, sb.st_mode & 0777);
+                if (destfd == -1) {
+                    warnpe("open: %s", dest);
+                    close(srcfd);
+                    continue;
+                }
+
+                for (;;) {
+                    bytes = read(srcfd, buf, sizeof(buf));
+                    if (!bytes)
+                        break;
+                    if (bytes < 0) {
+                        warnpe("read");
+                        break;
+                    }
+                    if (write(destfd, buf, bytes) < 0) {
+                        warnpe("write");
+                        break;
+                    }
+                }
+            if (fchown(destfd, uid, gid))
+                errorpe("chown: %s", dest);
+
+                close(srcfd);
+                close(destfd);
+            } else if (S_ISDIR(sb.st_mode)) {
+                if (mkdir(dest, sb.st_mode & 0777)) {
+                    warnpe("mkdir: %s", dest);
+                    continue;
+                }
+                if (chown(dest, uid, gid))
+                    errorpe("chown: %s", dest);
+            } else if (S_ISLNK(sb.st_mode)) {
+                char lnkdest[PATH_MAX];
+                int bytes;
+                bytes = readlink(src, lnkdest, sizeof(lnkdest));
+                lnkdest[bytes] = '\0';
+                if (bytes == -1) {
+                    warnpe("readlink: %s", src);
+                    continue;
+                }
+                if (symlink(lnkdest, dest)) {
+                    warnpe("symlink: %s", dest);
+                    continue;
+                }
+                if (lchown(dest, uid, gid))
+                    errorpe("lchown: %s", dest);
+            } else {
+                warn("not creating %s", dest);
+            }
+        }
+
+        closedir(skel);
+
+        if (chown(homedir, uid, gid)) {
+            errorpe("failed to chown %s", homedir);
+            return -1;
+        }
+    }
+
+    return 0;
+}