-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Add getpwnam, getgrnam sync versions

Fix ticket #164: Groupnames in non-local domains
Fix ticket #100: Error Message Modifying a user that doesn't Exist
Fix ticket #214: incorrect error message when MPG already exists
Fix ticket #188: Deleting and modifying users in non-local domain
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAkrKFW4ACgkQHsardTLnvCUcXACdGqxaygjMKYlyZbiA/vCtvtGO
K8kAoM/lyHFqXodgQabOpWj2Z9mqimBi
=xuM3
-----END PGP SIGNATURE-----
>From 0e6b330e0daaa68467c6a6d98251d6d4f9d4a4df Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Fri, 2 Oct 2009 10:39:02 +0200
Subject: [PATCH] Fix error messages in tools

Add getpwnam, getgrnam sync versions

Fix ticket #164: Groupnames in non-local domains
Fix ticket #100: Error Message Modifying a user that doesn't Exist
Fix ticket #214: incorrect error message when MPG already exists
Fix ticket #188: Deleting and modifying users in non-local domain
---
 server/tools/sss_groupdel.c |   19 +----
 server/tools/sss_groupmod.c |   27 +++++++
 server/tools/sss_sync_ops.c |  179 +++++++++++++++++++++++++++++++++++++++++++
 server/tools/sss_sync_ops.h |   14 ++++
 server/tools/sss_useradd.c  |   10 ++-
 server/tools/sss_userdel.c  |   18 +----
 server/tools/sss_usermod.c  |   28 +++++++-
 server/tools/tools_util.c   |   31 ++++++++
 server/tools/tools_util.h   |    4 +
 9 files changed, 295 insertions(+), 35 deletions(-)

diff --git a/server/tools/sss_groupdel.c b/server/tools/sss_groupdel.c
index a4451c4..d6e3dfd 100644
--- a/server/tools/sss_groupdel.c
+++ b/server/tools/sss_groupdel.c
@@ -23,8 +23,6 @@
 #include <stdlib.h>
 #include <talloc.h>
 #include <popt.h>
-#include <grp.h>
-#include <unistd.h>
 
 #include "db/sysdb.h"
 #include "util/util.h"
@@ -35,7 +33,6 @@ int main(int argc, const char **argv)
 {
     int ret = EXIT_SUCCESS;
     int pc_debug = 0;
-    struct group *grp_info;
     const char *pc_groupname = NULL;
     struct tools_ctx *tctx = NULL;
 
@@ -93,19 +90,6 @@ int main(int argc, const char **argv)
         goto fini;
     }
 
-    /* arguments processed, go on to actual work */
-    grp_info = getgrnam(tctx->octx->name);
-    if (grp_info) {
-        tctx->octx->gid = grp_info->gr_gid;
-    }
-
-    /* arguments processed, go on to actual work */
-    if (id_in_range(tctx->octx->uid, tctx->octx->domain) != EOK) {
-        ERROR("The selected GID is outside the allowed range\n");
-        ret = EXIT_FAILURE;
-        goto fini;
-    }
-
     start_transaction(tctx);
     if (tctx->error != EOK) {
         goto done;
@@ -129,7 +113,8 @@ done:
         DEBUG(1, ("sysdb operation failed (%d)[%s]\n", ret, strerror(ret)));
         switch (ret) {
             case ENOENT:
-                ERROR("No such group\n");
+                ERROR("No such group in local domain. "
+                      "Removing groups only allowed in local domain.\n");
                 break;
 
             default:
diff --git a/server/tools/sss_groupmod.c b/server/tools/sss_groupmod.c
index e821fdc..c0528c8 100644
--- a/server/tools/sss_groupmod.c
+++ b/server/tools/sss_groupmod.c
@@ -53,6 +53,7 @@ int main(int argc, const char **argv)
     char *addgroups = NULL, *rmgroups = NULL;
     int ret;
     const char *pc_groupname = NULL;
+    char *badgroup = NULL;
 
     debug_prg_name = argv[0];
 
@@ -117,6 +118,16 @@ int main(int argc, const char **argv)
         ret = EXIT_FAILURE;
         goto fini;
     }
+    /* check the username to be able to give sensible error message */
+    ret = sysdb_getgrnam_sync(tctx, tctx->ev, tctx->sysdb,
+                              tctx->octx->name, tctx->local,
+                              &tctx->octx);
+    if (ret != EOK) {
+        ERROR("Cannot find group in local domain, "
+              "modifying groups is allowed only in local domain\n");
+        goto fini;
+    }
+
 
     tctx->octx->gid = pc_gid;
 
@@ -134,6 +145,14 @@ int main(int argc, const char **argv)
             ERROR("Member groups must be in the same domain as parent group\n");
             goto fini;
         }
+
+        /* Check group names in the LOCAL domain */
+        ret = check_group_names(tctx, tctx->octx->addgroups, &badgroup);
+        if (ret != EOK) {
+            ERROR("Cannot find group %s in local domain, "
+                  "only groups in local domain are allowed\n", badgroup);
+            goto fini;
+        }
     }
 
     if (rmgroups) {
@@ -150,6 +169,14 @@ int main(int argc, const char **argv)
             ERROR("Member groups must be in the same domain as parent group\n");
             goto fini;
         }
+
+        /* Check group names in the LOCAL domain */
+        ret = check_group_names(tctx, tctx->octx->rmgroups, &badgroup);
+        if (ret != EOK) {
+            ERROR("Cannot find group %s in local domain, "
+                  "only groups in local domain are allowed\n", badgroup);
+            goto fini;
+        }
     }
 
     if (id_in_range(tctx->octx->gid, tctx->octx->domain) != EOK) {
diff --git a/server/tools/sss_sync_ops.c b/server/tools/sss_sync_ops.c
index 68fe73e..2eb14a7 100644
--- a/server/tools/sss_sync_ops.c
+++ b/server/tools/sss_sync_ops.c
@@ -44,6 +44,7 @@
 } while(0)
 
 struct sync_op_res {
+    struct ops_ctx *data;
     int error;
     bool done;
 };
@@ -1546,3 +1547,181 @@ static void end_transaction_done(struct tevent_req *req)
     talloc_zfree(req);
 }
 
+/*
+ * getpwnam, getgrnam and friends
+ */
+static void sss_getpwnam_done(void *ptr, int status,
+                              struct ldb_result *lrs);
+
+int sysdb_getpwnam_sync(TALLOC_CTX *mem_ctx,
+                        struct tevent_context *ev,
+                        struct sysdb_ctx *sysdb,
+                        const char *name,
+                        struct sss_domain_info *domain,
+                        struct ops_ctx **out)
+{
+    int ret;
+    struct sync_op_res *res = NULL;
+
+    res = talloc_zero(mem_ctx, struct sync_op_res);
+    if (!res) {
+        return ENOMEM;
+    }
+
+    if (out == NULL) {
+        DEBUG(1, ("NULL passed for storage pointer\n"));
+        return EINVAL;
+    }
+    res->data = *out;
+
+    ret = sysdb_getpwnam(mem_ctx,
+                         sysdb,
+                         domain,
+                         name,
+                         sss_getpwnam_done,
+                         res);
+
+    SYNC_LOOP(res, ret);
+
+    talloc_free(res);
+    return ret;
+}
+
+static void sss_getpwnam_done(void *ptr, int status,
+                              struct ldb_result *lrs)
+{
+    struct sync_op_res *res = talloc_get_type(ptr, struct sync_op_res );
+    const char *str;
+
+    res->done = true;
+
+    if (status != LDB_SUCCESS) {
+        res->error = status;
+        return;
+    }
+
+    switch (lrs->count) {
+        case 0:
+            DEBUG(1, ("No result for sysdb_getpwnam call\n"));
+            res->error = ENOENT;
+            break;
+
+        case 1:
+            res->error = EOK;
+            /* fill ops_ctx */
+            res->data->uid = ldb_msg_find_attr_as_uint64(lrs->msgs[0],
+                                                         SYSDB_UIDNUM, 0);
+
+            res->data->gid = ldb_msg_find_attr_as_uint64(lrs->msgs[0],
+                                                         SYSDB_GIDNUM, 0);
+
+            str = ldb_msg_find_attr_as_string(lrs->msgs[0],
+                                              SYSDB_NAME, NULL);
+            res->data->name = discard_const_p(char, str);
+
+            str = ldb_msg_find_attr_as_string(lrs->msgs[0],
+                                              SYSDB_GECOS, NULL);
+            res->data->gecos = discard_const_p(char, str);
+
+            str = ldb_msg_find_attr_as_string(lrs->msgs[0],
+                                              SYSDB_HOMEDIR, NULL);
+            res->data->home = discard_const_p(char, str);
+
+            str = ldb_msg_find_attr_as_string(lrs->msgs[0],
+                                              SYSDB_SHELL, NULL);
+            res->data->shell = discard_const_p(char, str);
+
+            str = ldb_msg_find_attr_as_string(lrs->msgs[0],
+                                              SYSDB_DISABLED, NULL);
+            if (str == NULL) {
+                res->data->lock = DO_UNLOCK;
+            } else {
+                if (strcasecmp(str, "true") == 0) {
+                    res->data->lock = DO_LOCK;
+                } else if (strcasecmp(str, "false") == 0) {
+                    res->data->lock = DO_UNLOCK;
+                } else { /* Invalid value */
+                    DEBUG(2, ("Invalid value for %s attribute: %s\n",
+                              SYSDB_DISABLED, str ? str : "NULL"));
+                    res->error = EIO;
+                    return;
+                }
+            }
+            break;
+
+        default:
+            DEBUG(1, ("More than one result for sysdb_getpwnam call\n"));
+            res->error = EINVAL;
+            break;
+    }
+}
+
+static void sss_getgrnam_done(void *ptr, int status,
+                              struct ldb_result *lrs);
+
+int sysdb_getgrnam_sync(TALLOC_CTX *mem_ctx,
+                        struct tevent_context *ev,
+                        struct sysdb_ctx *sysdb,
+                        const char *name,
+                        struct sss_domain_info *domain,
+                        struct ops_ctx **out)
+{
+    int ret;
+    struct sync_op_res *res = NULL;
+
+    res = talloc_zero(mem_ctx, struct sync_op_res);
+    if (!res) {
+        return ENOMEM;
+    }
+
+    if (out == NULL) {
+        DEBUG(1, ("NULL passed for storage pointer\n"));
+        return EINVAL;
+    }
+    res->data = *out;
+
+    ret = sysdb_getgrnam(mem_ctx,
+                         sysdb,
+                         domain,
+                         name,
+                         sss_getgrnam_done,
+                         res);
+
+    SYNC_LOOP(res, ret);
+
+    talloc_free(res);
+    return ret;
+}
+
+static void sss_getgrnam_done(void *ptr, int status,
+                              struct ldb_result *lrs)
+{
+    struct sync_op_res *res = talloc_get_type(ptr, struct sync_op_res );
+    const char *str;
+
+    res->done = true;
+
+    if (status != LDB_SUCCESS) {
+        res->error = status;
+        return;
+    }
+
+    switch (lrs->count) {
+        case 0:
+            DEBUG(1, ("No result for sysdb_getgrnam call\n"));
+            res->error = ENOENT;
+            break;
+
+            /* sysdb_getgrnam also returns members */
+        default:
+            res->error = EOK;
+            /* fill ops_ctx */
+            res->data->gid = ldb_msg_find_attr_as_uint64(lrs->msgs[0],
+                                                         SYSDB_GIDNUM, 0);
+            str = ldb_msg_find_attr_as_string(lrs->msgs[0],
+                                              SYSDB_NAME, NULL);
+            res->data->name = discard_const_p(char, str);
+            break;
+    }
+}
+
diff --git a/server/tools/sss_sync_ops.h b/server/tools/sss_sync_ops.h
index c99b9b9..3988992 100644
--- a/server/tools/sss_sync_ops.h
+++ b/server/tools/sss_sync_ops.h
@@ -86,5 +86,19 @@ int groupmod(TALLOC_CTX *mem_ctx,
 void start_transaction(struct tools_ctx *tctx);
 void end_transaction(struct tools_ctx *tctx);
 
+int sysdb_getpwnam_sync(TALLOC_CTX *mem_ctx,
+                        struct tevent_context *ev,
+                        struct sysdb_ctx *sysdb,
+                        const char *name,
+                        struct sss_domain_info *domain,
+                        struct ops_ctx **out);
+
+int sysdb_getgrnam_sync(TALLOC_CTX *mem_ctx,
+                        struct tevent_context *ev,
+                        struct sysdb_ctx *sysdb,
+                        const char *name,
+                        struct sss_domain_info *domain,
+                        struct ops_ctx **out);
+
 #endif /* __SSS_OPS_H__ */
 
diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c
index 07e741e..4e1505d 100644
--- a/server/tools/sss_useradd.c
+++ b/server/tools/sss_useradd.c
@@ -131,6 +131,7 @@ int main(int argc, const char **argv)
     poptContext pc = NULL;
     struct tools_ctx *tctx = NULL;
     char *groups = NULL;
+    char *badgroup = NULL;
     int ret;
 
     debug_prg_name = argv[0];
@@ -204,6 +205,13 @@ int main(int argc, const char **argv)
             ERROR("Groups must be in the same domain as user\n");
             goto fini;
         }
+
+        /* Check group names in the LOCAL domain */
+        ret = check_group_names(tctx, tctx->octx->addgroups, &badgroup);
+        if (ret != EOK) {
+            ERROR("Cannot find group %s in local domain\n", badgroup);
+            goto fini;
+        }
     }
 
     /* Same as shadow-utils useradd, -g can specify gid or group name */
@@ -257,7 +265,7 @@ done:
     if (tctx->error) {
         switch (tctx->error) {
             case EEXIST:
-                ERROR("A user with the same name or UID already exists\n");
+                ERROR("A user or group with the same name or UID already exists\n");
                 break;
 
             default:
diff --git a/server/tools/sss_userdel.c b/server/tools/sss_userdel.c
index 8c7c7bd..d14ef3d 100644
--- a/server/tools/sss_userdel.c
+++ b/server/tools/sss_userdel.c
@@ -23,8 +23,6 @@
 #include <stdlib.h>
 #include <talloc.h>
 #include <popt.h>
-#include <pwd.h>
-#include <unistd.h>
 
 #include "db/sysdb.h"
 #include "util/util.h"
@@ -35,7 +33,6 @@ int main(int argc, const char **argv)
 {
     int ret = EXIT_SUCCESS;
     struct tools_ctx *tctx = NULL;
-    struct passwd *pwd_info;
     const char *pc_username = NULL;
 
     int pc_debug = 0;
@@ -93,18 +90,6 @@ int main(int argc, const char **argv)
         goto fini;
     }
 
-    /* arguments processed, go on to actual work */
-    pwd_info = getpwnam(tctx->octx->name);
-    if (pwd_info) {
-        tctx->octx->uid = pwd_info->pw_uid;
-    }
-
-    if (id_in_range(tctx->octx->uid, tctx->octx->domain) != EOK) {
-        ERROR("The selected UID is outside the allowed range\n");
-        ret = EXIT_FAILURE;
-        goto fini;
-    }
-
     start_transaction(tctx);
     if (tctx->error != EOK) {
         goto done;
@@ -128,7 +113,8 @@ done:
         DEBUG(1, ("sysdb operation failed (%d)[%s]\n", ret, strerror(ret)));
         switch (ret) {
             case ENOENT:
-                ERROR("No such user\n");
+                ERROR("No such user in local domain. "
+                      "Removing users only allowed in local domain.\n");
                 break;
 
             default:
diff --git a/server/tools/sss_usermod.c b/server/tools/sss_usermod.c
index 2c2b80e..ea1095c 100644
--- a/server/tools/sss_usermod.c
+++ b/server/tools/sss_usermod.c
@@ -60,6 +60,7 @@ int main(int argc, const char **argv)
     int ret;
     const char *pc_username = NULL;
     struct tools_ctx *tctx = NULL;
+    char *badgroup = NULL;
 
     debug_prg_name = argv[0];
 
@@ -133,6 +134,15 @@ int main(int argc, const char **argv)
         ret = EXIT_FAILURE;
         goto fini;
     }
+    /* check the username to be able to give sensible error message */
+    ret = sysdb_getpwnam_sync(tctx, tctx->ev, tctx->sysdb,
+                              tctx->octx->name, tctx->local,
+                              &tctx->octx);
+    if (ret != EOK) {
+        ERROR("Cannot find user in local domain, "
+              "modifying users is allowed only in local domain\n");
+        goto fini;
+    }
 
     if (id_in_range(tctx->octx->uid, tctx->octx->domain) != EOK) {
         ERROR("The selected UID is outside the allowed range\n");
@@ -154,6 +164,14 @@ int main(int argc, const char **argv)
             ERROR("Groups must be in the same domain as user\n");
             goto fini;
         }
+
+        /* Check group names in the LOCAL domain */
+        ret = check_group_names(tctx, tctx->octx->addgroups, &badgroup);
+        if (ret != EOK) {
+            ERROR("Cannot find group %s in local domain, "
+                  "only groups in local domain are allowed\n", badgroup);
+            goto fini;
+        }
     }
 
     if (rmgroups) {
@@ -170,6 +188,14 @@ int main(int argc, const char **argv)
             ERROR("Groups must be in the same domain as user\n");
             goto fini;
         }
+
+        /* Check group names in the LOCAL domain */
+        ret = check_group_names(tctx, tctx->octx->rmgroups, &badgroup);
+        if (ret != EOK) {
+            ERROR("Cannot find group %s in local domain, "
+                  "only groups in local domain are allowed\n", badgroup);
+            goto fini;
+        }
     }
 
     tctx->octx->gecos = pc_gecos;
@@ -205,7 +231,7 @@ done:
                 break;
 
             case EFAULT:
-                ERROR("Could not modify user - check if username is correct\n");
+                ERROR("Could not modify user - user already member of groups?\n");
                 break;
 
             default:
diff --git a/server/tools/tools_util.c b/server/tools/tools_util.c
index 7772172..bc6b76f 100644
--- a/server/tools/tools_util.c
+++ b/server/tools/tools_util.c
@@ -191,6 +191,37 @@ int parse_name_domain(struct tools_ctx *tctx,
     return EOK;
 }
 
+int check_group_names(struct tools_ctx *tctx,
+                      char **grouplist,
+                      char **badgroup)
+{
+    int ret;
+    int i;
+    struct ops_ctx *groupinfo;
+
+    groupinfo = talloc_zero(tctx, struct ops_ctx);
+    if (!groupinfo) {
+        return ENOMEM;
+    }
+
+    for (i=0; grouplist[i]; ++i) {
+        ret = sysdb_getgrnam_sync(tctx,
+                                  tctx->ev,
+                                  tctx->sysdb,
+                                  grouplist[i],
+                                  tctx->local,
+                                  &groupinfo);
+        if (ret) {
+            DEBUG(6, ("Cannot find group %s, ret: %d\n", grouplist[i], ret));
+            break;
+        }
+    }
+
+    talloc_zfree(groupinfo);
+    *badgroup = grouplist[i];
+    return ret;
+}
+
 int id_in_range(uint32_t id,
                 struct sss_domain_info *dom)
 {
diff --git a/server/tools/tools_util.h b/server/tools/tools_util.h
index c062dec..a56fc5e 100644
--- a/server/tools/tools_util.h
+++ b/server/tools/tools_util.h
@@ -72,4 +72,8 @@ int parse_groups(TALLOC_CTX *mem_ctx,
 int parse_group_name_domain(struct tools_ctx *tctx,
                             char **groups);
 
+int check_group_names(struct tools_ctx *tctx,
+                      char **grouplist,
+                      char **badgroup);
+
 #endif  /* __TOOLS_UTIL_H__ */
-- 
1.6.2.5

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to