diff --git a/debian/control b/debian/control index 80500d3..46595da 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: ceo Section: admin Priority: optional Maintainer: Systems Committee -Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev, libprotobuf-c0-dev +Build-Depends: debhelper (>= 5.0.0), python-dev (>= 2.4), python-support (>= 0.3), libkrb5-dev, libldap2-dev, libsasl2-dev, libsctp-dev, libprotobuf-c0-dev, libacl1-dev Standards-Version: 3.8.2 Package: ceo diff --git a/src/Makefile b/src/Makefile index e9ac610..7b4bec0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,6 +16,9 @@ LDAP_PROGS := addmember addclub op-adduser KRB5_OBJECTS := krb5.o kadm.o KRB5_LDFLAGS := $(shell krb5-config --libs krb5 kadm-client) KRB5_PROGS := addmember addclub op-adduser +HOME_OBJECTS := homedir.o +HOME_LDFLAGS := -lacl +HOME_PROGS := op-adduser NET_OBJECTS := net.o gss.o ops.o NET_LDFLAGS := -lsctp $(shell krb5-config --libs gssapi) NET_PROGS := ceod ceoc @@ -57,6 +60,8 @@ $(LDAP_PROGS): LDFLAGS += $(LDAP_LDFLAGS) $(LDAP_PROGS): $(LDAP_OBJECTS) $(KRB5_PROGS): LDFLAGS += $(KRB5_LDFLAGS) $(KRB5_PROGS): $(KRB5_OBJECTS) +$(HOME_PROGS): LDFLAGS += $(HOME_LDFLAGS) +$(HOME_PROGS): $(HOME_OBJECTS) $(PROTO_PROGS): LDFLAGS += $(PROTO_LDFLAGS) $(PROTO_PROGS): $(PROTO_OBJECTS) $(CONFIG_PROGS): LDFLAGS += $(CONFIG_LDFLAGS) diff --git a/src/config-vars.h b/src/config-vars.h index 2c2334c..c7a2094 100644 --- a/src/config-vars.h +++ b/src/config-vars.h @@ -5,20 +5,16 @@ CONFIG_STR(groups_base) CONFIG_STR(sudo_base) CONFIG_STR(skeleton_dir) -CONFIG_STR(homedir_mode) -CONFIG_STR(refquota) CONFIG_STR(member_shell) CONFIG_INT(member_min_id) CONFIG_INT(member_max_id) CONFIG_STR(member_home) -CONFIG_STR(member_home_acl) CONFIG_STR(club_shell) CONFIG_INT(club_min_id) CONFIG_INT(club_max_id) CONFIG_STR(club_home) -CONFIG_STR(club_home_acl) CONFIG_STR(notify_hook) diff --git a/src/homedir.c b/src/homedir.c new file mode 100644 index 0000000..83772df --- /dev/null +++ b/src/homedir.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "homedir.h" +#include "util.h" +#include "config.h" + +int ceo_create_home(char *homedir, uid_t uid, gid_t gid) { + 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; + } + + umask(mask); + + return 0; +} diff --git a/src/homedir.h b/src/homedir.h new file mode 100644 index 0000000..8bc04bf --- /dev/null +++ b/src/homedir.h @@ -0,0 +1,3 @@ +#include + +int ceo_create_home(char *homedir, uid_t uid, gid_t gid); diff --git a/src/op-adduser.c b/src/op-adduser.c index c75f8bb..17f3602 100644 --- a/src/op-adduser.c +++ b/src/op-adduser.c @@ -19,6 +19,7 @@ #include "gss.h" #include "krb5.h" #include "ldap.h" +#include "homedir.h" #include "kadm.h" #include "daemon.h" #include "strbuf.h" @@ -136,7 +137,7 @@ static void adduser_spam(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *clie static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { char homedir[1024]; - int user_stat, group_stat, krb_stat; + int user_stat, group_stat, krb_stat, home_stat; int id; if (snprintf(homedir, sizeof(homedir), "%s/%s", @@ -165,12 +166,15 @@ static int32_t addmember(Ceo__AddUser *in, Ceo__AddUserResponse *out) { else response_message(out, 0, "successfully created ldap group"); - return krb_stat || user_stat || group_stat; + if ((home_stat = ceo_create_home(homedir, id, id))) + notice("successfully created home directory for %s", in->username); + + return krb_stat || user_stat || group_stat || home_stat; } static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) { char homedir[1024]; - int krb_stat, user_stat, group_stat, sudo_stat; + int krb_stat, user_stat, group_stat, sudo_stat, home_stat; int id; if (snprintf(homedir, sizeof(homedir), "%s/%s", @@ -200,7 +204,10 @@ static int32_t addclub(Ceo__AddUser *in, Ceo__AddUserResponse *out) { else response_message(out, 0, "successfully created ldap sudoers"); - return user_stat || group_stat || sudo_stat; + if ((home_stat = ceo_create_home(homedir, id, id))) + notice("successfully created home directory for %s", in->username); + + return user_stat || group_stat || sudo_stat || home_stat; } static int32_t adduser(Ceo__AddUser *in, Ceo__AddUserResponse *out, char *client) {