[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Freeipa-devel] [PATCH] sss_usermod



On Mon, 2009-03-09 at 09:17 -0400, Stephen Gallagher wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Simo Sorce wrote:
> > "Jakub Hrozek" <jhrozek redhat com> wrote:
> >> This patch adds the sss_usermod tool and moves the parse_groups()
> >> function from sss_useradd.c to tools_utils.c as it's used in
> >> sss_usermod, too.
> > 
> > ack
> > 
> > _______________________________________________
> > Freeipa-devel mailing list
> > Freeipa-devel redhat com
> > https://www.redhat.com/mailman/listinfo/freeipa-devel
> 
> Nack. Please fix the following patch errors and resubmit.
> 

Sorry, new patch attached. I've verified that it applies cleanly against
current HEAD.
>From b701ef7e981c2458bb376a37a34e696379aac80f Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek redhat com>
Date: Sun, 8 Mar 2009 00:20:50 +0100
Subject: [PATCH] sss_usermod

Move parse_groups into tools_utils
---
 server/Makefile.in         |    2 +-
 server/server.mk           |    7 +
 server/tools/sss_useradd.c |   44 ------
 server/tools/sss_usermod.c |  361 ++++++++++++++++++++++++++++++++++++++++++++
 server/tools/tools_util.c  |   44 ++++++
 server/tools/tools_util.h  |    2 +
 sssd.spec                  |    1 +
 7 files changed, 416 insertions(+), 45 deletions(-)
 create mode 100644 server/tools/sss_usermod.c

diff --git a/server/Makefile.in b/server/Makefile.in
index b71d4cc..342bbcc 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -118,7 +118,7 @@ endif
 ifneq (x$(HAVE_POLICYKIT), x)
     LIBEXECBINS += sbin/sssd_pk
 endif
-TOOLSBINS = sbin/sss_useradd sbin/sss_userdel sbin/sss_groupadd sbin/sss_groupdel
+TOOLSBINS = sbin/sss_useradd sbin/sss_userdel sbin/sss_groupadd sbin/sss_groupdel sbin/sss_usermod
 BINS = sbin/sssd $(LIBEXECBINS) $(TOOLSBINS)
 
 ifneq (x$(HAVE_TESTS), x)
diff --git a/server/server.mk b/server/server.mk
index b0040f3..b09312d 100644
--- a/server/server.mk
+++ b/server/server.mk
@@ -90,6 +90,9 @@ GROUPADD_OBJ = \
 GROUPDEL_OBJ = \
 	tools/sss_groupdel.o
 
+USERMOD_OBJ = \
+	tools/sss_usermod.o
+
 sbin/sssd: $(SERVER_OBJ) $(UTIL_OBJ)
 	$(CC) -o sbin/sssd $(SERVER_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS)
 
@@ -142,3 +145,7 @@ sbin/sss_groupadd: $(GROUPADD_OBJ) $(TOOLS_OBJ) $(UTIL_OBJ)
 
 sbin/sss_groupdel: $(GROUPDEL_OBJ) $(TOOLS_OBJ) $(UTIL_OBJ)
 	$(CC) -o sbin/sss_groupdel $(GROUPDEL_OBJ) $(TOOLS_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS)
+
+sbin/sss_usermod: $(USERMOD_OBJ) $(TOOLS_OBJ) $(UTIL_OBJ)
+	$(CC) -o sbin/sss_usermod $(USERMOD_OBJ) $(TOOLS_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS)
+
diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c
index 0897cfd..710ed20 100644
--- a/server/tools/sss_useradd.c
+++ b/server/tools/sss_useradd.c
@@ -51,50 +51,6 @@ struct user_add_ctx {
     bool done;
 };
 
-/* FIXME: avoid using strtok !! */
-static int parse_groups(TALLOC_CTX *mem_ctx, const char *optstr, char ***_out)
-{
-    char **out;
-    char *orig, *n, *o;
-    char delim = ',';
-    unsigned int tokens = 1;
-    int i;
-
-    orig = talloc_strdup(mem_ctx, optstr);
-    if (!orig) return ENOMEM;
-
-    n = orig;
-    tokens = 1;
-    while ((n = strchr(n, delim))) {
-        n++;
-        tokens++;
-    }
-
-    out = talloc_array(mem_ctx, char *, tokens+1);
-    if (!out) {
-        talloc_free(orig);
-        return ENOMEM;
-    }
-
-    n = orig;
-    for (i = 0; i < tokens; i++) {
-        o = n;
-        n = strchr(n, delim);
-        if (!n) {
-            break;
-        }
-        *n = '\0';
-        n++;
-        out[i] = talloc_strdup(out, o);
-    }
-    out[tokens-1] = talloc_strdup(out, o);
-    out[tokens] = NULL;
-
-    talloc_free(orig);
-    *_out = out;
-    return EOK;
-}
-
 struct fetch_group {
     gid_t gid;
     int error;
diff --git a/server/tools/sss_usermod.c b/server/tools/sss_usermod.c
new file mode 100644
index 0000000..0312789
--- /dev/null
+++ b/server/tools/sss_usermod.c
@@ -0,0 +1,361 @@
+/*
+   SSSD
+
+   sss_usermod
+
+   Copyright (C) Jakub Hrozek <jhrozek redhat com>        2009
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <talloc.h>
+#include <popt.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "util/util.h"
+#include "db/sysdb.h"
+#include "tools/tools_util.h"
+
+#define DO_LOCK     1
+#define DO_UNLOCK   2
+
+#define VAR_CHECK(var, val, msg) do { \
+        if (var != (val)) { \
+            DEBUG(0, (msg)); \
+            var = EXIT_FAILURE; \
+            goto fini; \
+        } \
+} while(0)
+
+struct user_mod_ctx {
+    struct sysdb_req *sysreq;
+
+    struct sss_domain_info *domain;
+    struct tools_ctx *ctx;
+
+    const char *username;
+    struct sysdb_attrs *attrs;
+
+    char **addgroups;
+    char **rmgroups;
+    int cur;
+
+    int error;
+    bool done;
+};
+
+/* sysdb callback */
+static void mod_user_done(void *pvt, int error, struct ldb_result *ignore)
+{
+    struct user_mod_ctx *data = talloc_get_type(pvt, struct user_mod_ctx);
+
+    data->done = true;
+
+    sysdb_transaction_done(data->sysreq, error);
+
+    if (error)
+        data->error = error;
+}
+
+static void add_to_groups(void *, int, struct ldb_result *);
+
+/* sysdb_req_fn_t */
+static void mod_user(struct sysdb_req *req, void *pvt)
+{
+    struct user_mod_ctx *user_ctx;
+    int ret;
+
+    user_ctx = talloc_get_type(pvt, struct user_mod_ctx);
+    user_ctx->sysreq = req;
+
+    if(user_ctx->attrs->num == 0) {
+        add_to_groups(user_ctx, EOK, NULL);
+    } else {
+        ret = sysdb_set_user_attr(req,
+                                  sysdb_req_get_ctx(req),
+                                  user_ctx->domain->name,
+                                  user_ctx->username,
+                                  user_ctx->attrs,
+                                  add_to_groups,
+                                  user_ctx);
+
+        if (ret != EOK) {
+            mod_user_done(user_ctx, ret, NULL);
+        }
+    }
+}
+
+static void remove_from_groups(void *pvt, int error, struct ldb_result *ignore)
+{
+    struct user_mod_ctx *user_ctx = talloc_get_type(pvt, struct user_mod_ctx);
+    struct ldb_dn *group_dn;
+    struct ldb_dn *user_dn;
+    int ret;
+
+    if (error) {
+        mod_user_done(pvt, error, NULL);
+        return;
+    }
+
+    /* check if we removed all of them */
+    if (user_ctx->rmgroups == NULL ||
+        user_ctx->rmgroups[user_ctx->cur] == NULL) {
+        mod_user_done(user_ctx, EOK, NULL);
+        return;
+    }
+
+    user_dn = sysdb_user_dn(user_ctx->ctx->sysdb, user_ctx,
+                            user_ctx->domain->name, user_ctx->username);
+    if (!user_dn) {
+        mod_user_done(pvt, ENOMEM, NULL);
+        return;
+    }
+
+    group_dn = sysdb_group_dn(user_ctx->ctx->sysdb, user_ctx,
+                              user_ctx->domain->name,
+                              user_ctx->rmgroups[user_ctx->cur]);
+    if (!group_dn) {
+        mod_user_done(pvt, ENOMEM, NULL);
+        return;
+    }
+
+    ret = sysdb_remove_group_member(user_ctx->sysreq,
+                                    user_dn, group_dn,
+                                    remove_from_groups, user_ctx);
+    if (ret != EOK)
+        mod_user_done(user_ctx, ret, NULL);
+
+    /* go on to next group */
+    user_ctx->cur++;
+}
+
+static void add_to_groups(void *pvt, int error, struct ldb_result *ignore)
+{
+    struct user_mod_ctx *user_ctx = talloc_get_type(pvt, struct user_mod_ctx);
+    struct ldb_dn *group_dn;
+    struct ldb_dn *user_dn;
+    int ret;
+
+    if (error) {
+        mod_user_done(pvt, error, NULL);
+        return;
+    }
+
+    /* check if we added all of them */
+    if (user_ctx->addgroups == NULL ||
+        user_ctx->addgroups[user_ctx->cur] == NULL) {
+        user_ctx->cur = 0;
+        remove_from_groups(user_ctx, EOK, NULL);
+        return;
+    }
+
+    user_dn = sysdb_user_dn(user_ctx->ctx->sysdb, user_ctx,
+                            user_ctx->domain->name, user_ctx->username);
+    if (!user_dn) {
+        mod_user_done(pvt, ENOMEM, NULL);
+        return;
+    }
+
+    group_dn = sysdb_group_dn(user_ctx->ctx->sysdb, user_ctx,
+                              user_ctx->domain->name,
+                              user_ctx->addgroups[user_ctx->cur]);
+    if (!group_dn) {
+        mod_user_done(pvt, ENOMEM, NULL);
+        return;
+    }
+
+    ret = sysdb_add_group_member(user_ctx->sysreq,
+                                 user_dn, group_dn,
+                                 add_to_groups, user_ctx);
+    if (ret != EOK)
+        mod_user_done(user_ctx, ret, NULL);
+
+    /* go on to next group */
+    user_ctx->cur++;
+}
+
+int main(int argc, const char **argv)
+{
+    int pc_lock;
+    uid_t pc_uid = 0;
+    gid_t pc_gid = 0;
+    const char *pc_gecos = NULL;
+    const char *pc_home = NULL;
+    const char *pc_shell = NULL;
+    struct poptOption long_options[] = {
+        POPT_AUTOHELP
+        { "uid",   'u', POPT_ARG_INT, &pc_uid, 0, "The UID of the user", NULL },
+        { "gid",   'g', POPT_ARG_INT, &pc_gid, 0, "The GID of the user", NULL },
+        { "gecos", 'c', POPT_ARG_STRING, &pc_gecos, 0, "The comment string", NULL },
+        { "home",  'h', POPT_ARG_STRING, &pc_home, 0, "Home directory", NULL },
+        { "shell", 's', POPT_ARG_STRING, &pc_shell, 0, "Login shell", NULL },
+        { "append-group", 'a', POPT_ARG_STRING, NULL, 'a', "Groups to add this user to", NULL },
+        { "remove-group", 'r', POPT_ARG_STRING, NULL, 'r', "Groups to remove this user from", NULL },
+        { "lock", 'L', POPT_ARG_INT, &pc_lock, DO_LOCK, "Lock the account", NULL },
+        { "unlock", 'U', POPT_ARG_INT, &pc_lock, DO_UNLOCK, "Unlock the account", NULL },
+        POPT_TABLEEND
+    };
+    poptContext pc = NULL;
+    struct user_mod_ctx *user_ctx = NULL;
+    struct tools_ctx *ctx = NULL;
+    char *groups;
+    int ret;
+
+    debug_prg_name = argv[0];
+
+    ret = setup_db(&ctx);
+    if (ret != EOK) {
+        DEBUG(0, ("Could not set up database\n"));
+        ret = EXIT_FAILURE;
+        goto fini;
+    }
+
+    user_ctx = talloc_zero(ctx, struct user_mod_ctx);
+    if (user_ctx == NULL) {
+        DEBUG(0, ("Could not allocate memory for user_ctx context\n"));
+        return ENOMEM;
+    }
+    user_ctx->ctx = ctx;
+
+    user_ctx->attrs = sysdb_new_attrs(ctx);
+    if (user_ctx->attrs == NULL) {
+        DEBUG(0, ("Could not allocate memory for sysdb_attrs\n"));
+        return ENOMEM;
+    }
+
+    /* parse user_ctx */
+    pc = poptGetContext(NULL, argc, argv, long_options, 0);
+    poptSetOtherOptionHelp(pc, "USERNAME");
+    while ((ret = poptGetNextOpt(pc)) > 0) {
+        if (ret == 'a' || ret == 'r') {
+            groups = poptGetOptArg(pc);
+            if (!groups) {
+                ret = -1;
+                break;
+            }
+
+            ret = parse_groups(ctx,
+                    groups,
+                    (ret == 'a') ? (&user_ctx->addgroups) : (&user_ctx->rmgroups));
+
+            free(groups);
+            if (ret != EOK) {
+                break;
+            }
+        }
+    }
+
+    if(ret != -1) {
+        usage(pc, poptStrerror(ret));
+        ret = EXIT_FAILURE;
+        goto fini;
+    }
+
+    /* username is an argument without --option */
+    user_ctx->username = poptGetArg(pc);
+    if (user_ctx->username == NULL) {
+        usage(pc, "Specify user to modify\n");
+        ret = EXIT_FAILURE;
+        goto fini;
+    }
+
+    /* add parameters to changeset */
+    /* FIXME - might want to do this via attr:pc_var mapping in a loop */
+
+    if(pc_shell) {
+        ret = sysdb_attrs_add_string(user_ctx->attrs,
+                                     SYSDB_SHELL,
+                                     pc_shell);
+        VAR_CHECK(ret, EOK, "Could not add attribute to changeset\n");
+    }
+
+    if(pc_home) {
+        ret = sysdb_attrs_add_string(user_ctx->attrs,
+                                     SYSDB_HOMEDIR,
+                                     pc_home);
+        VAR_CHECK(ret, EOK, "Could not add attribute to changeset\n");
+    }
+
+    if(pc_gecos) {
+        ret = sysdb_attrs_add_string(user_ctx->attrs,
+                                     SYSDB_FULLNAME,
+                                     pc_gecos);
+        VAR_CHECK(ret, EOK, "Could not add attribute to changeset\n");
+    }
+
+    if(pc_uid) {
+        ret = sysdb_attrs_add_long(user_ctx->attrs,
+                                   SYSDB_UIDNUM,
+                                   pc_uid);
+        VAR_CHECK(ret, EOK, "Could not add attribute to changeset\n");
+    }
+
+    if(pc_gid) {
+        ret = sysdb_attrs_add_long(user_ctx->attrs,
+                                   SYSDB_GIDNUM,
+                                   pc_gid);
+        VAR_CHECK(ret, EOK, "Could not add attribute to changeset\n");
+    }
+
+    if(pc_lock == DO_LOCK) {
+        ret = sysdb_attrs_add_string(user_ctx->attrs,
+                                     SYSDB_DISABLED,
+                                     "true");
+        VAR_CHECK(ret, EOK, "Could not add attribute to changeset\n");
+    }
+
+    if(pc_lock == DO_UNLOCK) {
+        /* PAM code checks for 'false' value in SYSDB_DISABLED attribute */
+        ret = sysdb_attrs_add_string(user_ctx->attrs,
+                                     SYSDB_DISABLED,
+                                     "false");
+        VAR_CHECK(ret, EOK, "Could not add attribute to changeset\n");
+    }
+
+
+    /* arguments processed, go on to actual work */
+    user_ctx->domain = btreemap_get_value(ctx->domains, "LOCAL");
+    if (user_ctx->domain == NULL) {
+        VAR_CHECK(ret, EOK, "Could not set default values\n");
+    }
+
+    ret = sysdb_transaction(ctx, ctx->sysdb, mod_user, user_ctx);
+    if (ret != EOK) {
+        DEBUG(0, ("Could not start transaction (%d)[%s]\n",
+                  ret, strerror(ret)));
+        ret = EXIT_FAILURE;
+        goto fini;
+    }
+
+    while (!user_ctx->done) {
+        tevent_loop_once(ctx->ev);
+    }
+
+    if (user_ctx->error) {
+        ret = user_ctx->error;
+        DEBUG(0, ("Operation failed (%d)[%s]\n", ret, strerror(ret)));
+        ret = EXIT_FAILURE;
+        goto fini;
+    }
+
+    ret = EXIT_SUCCESS;
+
+fini:
+    poptFreeContext(pc);
+    talloc_free(ctx);
+    exit(ret);
+}
diff --git a/server/tools/tools_util.c b/server/tools/tools_util.c
index 241e1f9..daf9b41 100644
--- a/server/tools/tools_util.c
+++ b/server/tools/tools_util.c
@@ -194,3 +194,47 @@ void usage(poptContext pc, const char *error)
     if (error) fprintf(stderr, "%s", error);
 }
 
+/* FIXME: avoid using strtok !! */
+int parse_groups(TALLOC_CTX *mem_ctx, const char *optstr, char ***_out)
+{
+    char **out;
+    char *orig, *n, *o;
+    char delim = ',';
+    unsigned int tokens = 1;
+    int i;
+
+    orig = talloc_strdup(mem_ctx, optstr);
+    if (!orig) return ENOMEM;
+
+    n = orig;
+    tokens = 1;
+    while ((n = strchr(n, delim))) {
+        n++;
+        tokens++;
+    }
+
+    out = talloc_array(mem_ctx, char *, tokens+1);
+    if (!out) {
+        talloc_free(orig);
+        return ENOMEM;
+    }
+
+    n = orig;
+    for (i = 0; i < tokens; i++) {
+        o = n;
+        n = strchr(n, delim);
+        if (!n) {
+            break;
+        }
+        *n = '\0';
+        n++;
+        out[i] = talloc_strdup(out, o);
+    }
+    out[tokens-1] = talloc_strdup(out, o);
+    out[tokens] = NULL;
+
+    talloc_free(orig);
+    *_out = out;
+    return EOK;
+}
+
diff --git a/server/tools/tools_util.h b/server/tools/tools_util.h
index cf0e1fe..d8edd49 100644
--- a/server/tools/tools_util.h
+++ b/server/tools/tools_util.h
@@ -18,4 +18,6 @@ int setup_db(struct tools_ctx **ctx);
 
 void usage(poptContext pc, const char *error);
 
+int parse_groups(TALLOC_CTX *mem_ctx, const char *optstr, char ***_out);
+
 #endif  /* __TOOLS_UTIL_H__ */
diff --git a/sssd.spec b/sssd.spec
index 923bf31..b7f817c 100644
--- a/sssd.spec
+++ b/sssd.spec
@@ -89,6 +89,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_sbindir}/sssd
 %{_sbindir}/sss_useradd
 %{_sbindir}/sss_userdel
+%{_sbindir}/sss_usermod
 %{_sbindir}/sss_groupadd
 %{_sbindir}/sss_groupdel
 %{_libexecdir}/%{servicename}/
-- 
1.6.0.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]