summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-03-09 20:34:44 -0400
committerSimo Sorce <ssorce@redhat.com>2009-03-09 20:34:44 -0400
commit92bb11b3570c0ce1de84824d9697fa45422feb0b (patch)
tree3834cc0b59f463ce92ebc963c419e6352b7991fc /server
parent5ea221d5325a2b60ec872a3864953178c8b593a0 (diff)
downloadsssd-92bb11b3570c0ce1de84824d9697fa45422feb0b.tar.gz
sssd-92bb11b3570c0ce1de84824d9697fa45422feb0b.tar.xz
sssd-92bb11b3570c0ce1de84824d9697fa45422feb0b.zip
Move MPG checks within sysdb.
This allows to perform checks and modifications in one transaction. Uses configuration stored in confdb to determins if a domain uses MPGs.
Diffstat (limited to 'server')
-rw-r--r--server/db/sysdb.h25
-rw-r--r--server/db/sysdb_ops.c196
-rw-r--r--server/tools/sss_groupadd.c8
-rw-r--r--server/tools/sss_useradd.c8
-rw-r--r--server/tools/tools_util.c98
-rw-r--r--server/tools/tools_util.h2
6 files changed, 199 insertions, 138 deletions
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index c278e64cb..e7da90b0e 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -65,20 +65,25 @@
#define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)"
-#define SYSDB_PWNAM_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_NAME"=%s))"
-#define SYSDB_PWUID_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_UIDNUM"=%lu))"
-#define SYSDB_PWENT_FILTER "(objectclass="SYSDB_USER_CLASS")"
+#define SYSDB_UC "objectclass="SYSDB_USER_CLASS
+#define SYSDB_GC "objectclass="SYSDB_GROUP_CLASS
-#define SYSDB_GRNAM_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_NAME"=%s))"
-#define SYSDB_GRNA2_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_MEMBEROF"=%s))"
-#define SYSDB_GRGID_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_GIDNUM"=%lu))"
-#define SYSDB_GRENT_FILTER "(objectclass="SYSDB_GROUP_CLASS")"
+#define SYSDB_PWNAM_FILTER "(&("SYSDB_UC")("SYSDB_NAME"=%s))"
+#define SYSDB_PWUID_FILTER "(&("SYSDB_UC")("SYSDB_UIDNUM"=%lu))"
+#define SYSDB_PWENT_FILTER "("SYSDB_UC")"
-#define SYSDB_INITGR_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_GIDNUM"=*))"
+#define SYSDB_GRNAM_FILTER "(&("SYSDB_GC")("SYSDB_NAME"=%s))"
+#define SYSDB_GRNA2_FILTER "(&("SYSDB_UC")("SYSDB_MEMBEROF"=%s))"
+#define SYSDB_GRGID_FILTER "(&("SYSDB_GC")("SYSDB_GIDNUM"=%lu))"
+#define SYSDB_GRENT_FILTER "("SYSDB_GC")"
-#define SYSDB_INITGR_LEGACY_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_LEGACY_MEMBER"=%s))"
+#define SYSDB_INITGR_FILTER "(&("SYSDB_GC")("SYSDB_GIDNUM"=*))"
-#define SYSDB_GETCACHED_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_LAST_LOGIN">=%lu))"
+#define SYSDB_INITGR_LEGACY_FILTER "(&("SYSDB_GC")("SYSDB_LEGACY_MEMBER"=%s))"
+
+#define SYSDB_GETCACHED_FILTER "(&"SYSDB_UC")("SYSDB_LAST_LOGIN">=%lu))"
+
+#define SYSDB_CHECK_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_NAME"=%s))"
#define SYSDB_PW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
SYSDB_GIDNUM, SYSDB_FULLNAME, \
diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c
index 9ea2a0aa5..0d20d7b32 100644
--- a/server/db/sysdb_ops.c
+++ b/server/db/sysdb_ops.c
@@ -753,6 +753,108 @@ static int nextid_callback(struct ldb_request *req, struct ldb_reply *rep)
return LDB_SUCCESS;
}
+struct check_name_ctx {
+ struct sysdb_req *sysreq;
+
+ sysdb_callback_t fn;
+ void *pvt;
+
+ struct ldb_result *res;
+};
+
+static int check_name_callback(struct ldb_request *req, struct ldb_reply *rep);
+
+int sysdb_check_name_unique(struct sysdb_req *sysreq,
+ struct sss_domain_info *domain,
+ TALLOC_CTX *mem_ctx, const char *name,
+ sysdb_callback_t fn, void *pvt)
+{
+ static const char *attrs[] = { SYSDB_NAME, NULL };
+ struct check_name_ctx *cnctx;
+ struct sysdb_ctx *ctx;
+ struct ldb_dn *base_dn;
+ struct ldb_request *req;
+ char *filter;
+ int ret;
+
+ if (!sysdb_req_check_running(sysreq)) {
+ DEBUG(2, ("Invalid request! Not running at this time.\n"));
+ return EINVAL;
+ }
+
+ ctx = sysdb_req_get_ctx(sysreq);
+
+ cnctx = talloc_zero(mem_ctx, struct check_name_ctx);
+ if (!cnctx) return ENOMEM;
+
+ cnctx->sysreq = sysreq;
+ cnctx->fn = fn;
+ cnctx->pvt = pvt;
+
+ base_dn = sysdb_domain_dn(ctx, cnctx, domain->name);
+ if (!base_dn) return ENOMEM;
+
+ filter = talloc_asprintf(cnctx, SYSDB_CHECK_FILTER, name);
+ if (!filter) return ENOMEM;
+
+ cnctx->res = talloc_zero(cnctx, struct ldb_result);
+ if (!cnctx->res) return ENOMEM;
+
+ ret = ldb_build_search_req(&req, ctx->ldb, mem_ctx,
+ base_dn, LDB_SCOPE_SUBTREE,
+ filter, attrs, NULL,
+ cnctx, check_name_callback, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
+ return sysdb_error_to_errno(ret);
+ }
+
+ ret = ldb_request(ctx->ldb, req);
+ if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+
+ return EOK;
+}
+
+static int check_name_callback(struct ldb_request *req, struct ldb_reply *rep)
+{
+ struct check_name_ctx *cnctx;
+ struct sysdb_ctx *ctx;
+
+ cnctx = talloc_get_type(req->context, struct check_name_ctx);
+ ctx = sysdb_req_get_ctx(cnctx->sysreq);
+
+ if (!rep) {
+ return_error(cnctx, EIO);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (rep->error != LDB_SUCCESS) {
+ return_error(cnctx, sysdb_error_to_errno(rep->error));
+ return rep->error;
+ }
+
+ switch (rep->type) {
+ case LDB_REPLY_ENTRY:
+
+ /* one found, that means name is not available */
+ /* return EEXIST */
+ return_error(cnctx, EEXIST);
+ return LDB_ERR_ENTRY_ALREADY_EXISTS;
+ break;
+
+ case LDB_REPLY_DONE:
+
+ return_done(cnctx);
+ break;
+
+ default:
+ return_error(cnctx, EINVAL);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return LDB_SUCCESS;
+}
+
struct user_add_ctx {
struct sysdb_req *sysreq;
@@ -769,6 +871,8 @@ struct user_add_ctx {
struct next_id id;
};
+static void user_check_callback(void *pvt, int error, struct ldb_result *res);
+static int user_add_id(struct user_add_ctx *user_ctx);
static void user_add_id_callback(void *pvt, int error, struct ldb_result *res);
static int user_add_call(struct user_add_ctx *user_ctx);
@@ -786,6 +890,13 @@ int sysdb_add_user(struct sysdb_req *sysreq,
return EINVAL;
}
+ if ((uid == 0 || gid == 0) && (uid != 0 || gid != 0)) {
+ /* you either set both or neither, we will not guess only one */
+ DEBUG(1, ("You have to either specify both uid and gid or neither"
+ " (preferred) [passed in uid=%u, gid =%u]\n", uid, gid));
+ return EINVAL;
+ }
+
user_ctx = talloc(sysreq, struct user_add_ctx);
if (!user_ctx) return ENOMEM;
@@ -803,17 +914,42 @@ int sysdb_add_user(struct sysdb_req *sysreq,
user_ctx->homedir = homedir;
user_ctx->shell = shell;
- if (uid == 0 && gid == 0) {
- /* Must generate uid/gid pair */
- return sysdb_get_next_available_id(sysreq, domain, &(user_ctx->id),
- user_add_id_callback, user_ctx);
+ if (domain->mpg) {
+ /* if the domain is mpg we need to check we do not have there are no
+ * name conflicts */
+
+ return sysdb_check_name_unique(sysreq, domain, user_ctx, name,
+ user_check_callback, user_ctx);
}
- if (uid == 0 || gid == 0) {
- /* you either set both or neither, we will not guess only one */
- DEBUG(1, ("You have to either specify both uid and gid or neither"
- " (preferred) [passed in uid=%u, gid =%u]\n", uid, gid));
- return EINVAL;
+ return user_add_id(user_ctx);
+}
+
+static void user_check_callback(void *pvt, int error, struct ldb_result *res)
+{
+ struct user_add_ctx *user_ctx;
+ int ret;
+
+ user_ctx = talloc_get_type(pvt, struct user_add_ctx);
+ if (error != EOK) {
+ return_error(user_ctx->cbctx, error);
+ return;
+ }
+
+ ret = user_add_id(user_ctx);
+ if (ret != EOK) {
+ return_error(user_ctx->cbctx, ret);
+ }
+}
+
+static int user_add_id(struct user_add_ctx *user_ctx)
+{
+ if (user_ctx->uid == 0 && user_ctx->gid == 0) {
+ /* Must generate uid/gid pair */
+ return sysdb_get_next_available_id(user_ctx->sysreq,
+ user_ctx->domain,
+ &(user_ctx->id),
+ user_add_id_callback, user_ctx);
}
return user_add_call(user_ctx);
@@ -835,7 +971,9 @@ static void user_add_id_callback(void *pvt, int error, struct ldb_result *res)
user_ctx->gid = user_ctx->id.id;
ret = user_add_call(user_ctx);
- if (ret != EOK) return_error(user_ctx->cbctx, ret);
+ if (ret != EOK) {
+ return_error(user_ctx->cbctx, ret);
+ }
}
static int user_add_call(struct user_add_ctx *user_ctx)
@@ -920,6 +1058,8 @@ struct group_add_ctx {
struct next_id id;
};
+static void group_check_callback(void *pvt, int error, struct ldb_result *res);
+static int group_add_id(struct group_add_ctx *group_ctx);
static void group_add_id_callback(void *pvt, int error, struct ldb_result *res);
static int group_add_call(struct group_add_ctx *group_ctx);
@@ -948,9 +1088,41 @@ int sysdb_add_group(struct sysdb_req *sysreq,
group_ctx->name = name;
group_ctx->gid = gid;
- if (gid == 0) {
+ if (domain->mpg) {
+ /* if the domain is mpg we need to check we do not have there are no
+ * name conflicts */
+
+ return sysdb_check_name_unique(sysreq, domain, group_ctx, name,
+ group_check_callback, group_ctx);
+ }
+
+ return group_add_id(group_ctx);
+}
+
+static void group_check_callback(void *pvt, int error, struct ldb_result *res)
+{
+ struct group_add_ctx *group_ctx;
+ int ret;
+
+ group_ctx = talloc_get_type(pvt, struct group_add_ctx);
+ if (error != EOK) {
+ return_error(group_ctx->cbctx, error);
+ return;
+ }
+
+ ret = group_add_id(group_ctx);
+ if (ret != EOK) {
+ return_error(group_ctx->cbctx, ret);
+ }
+}
+
+static int group_add_id(struct group_add_ctx *group_ctx)
+{
+ if (group_ctx->gid == 0) {
/* Must generate uid/gid pair */
- return sysdb_get_next_available_id(sysreq, domain, &(group_ctx->id),
+ return sysdb_get_next_available_id(group_ctx->sysreq,
+ group_ctx->domain,
+ &(group_ctx->id),
group_add_id_callback, group_ctx);
}
diff --git a/server/tools/sss_groupadd.c b/server/tools/sss_groupadd.c
index e36e220fe..5363dbbaf 100644
--- a/server/tools/sss_groupadd.c
+++ b/server/tools/sss_groupadd.c
@@ -135,14 +135,6 @@ int main(int argc, const char **argv)
goto fini;
}
- /* Check MPG constraints */
- ret = check_group_name_unique(ctx, group_ctx->groupname);
- if(ret != EOK) {
- DEBUG(1, ("Could not add group - name not unique\n"));
- ret = EXIT_FAILURE;
- goto fini;
- }
-
/* add_group */
ret = sysdb_transaction(ctx, ctx->sysdb, add_group, group_ctx);
if(ret != EOK) {
diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c
index 710ed207f..7bad83786 100644
--- a/server/tools/sss_useradd.c
+++ b/server/tools/sss_useradd.c
@@ -338,14 +338,6 @@ int main(int argc, const char **argv)
goto fini;
}
- /* Check MPG constraints */
- ret = check_user_name_unique(ctx, user_ctx->username);
- if (ret != EOK) {
- DEBUG(0, ("Could not add user - name not unique\n"));
- ret = EXIT_FAILURE;
- goto fini;
- }
-
/* useradd */
ret = sysdb_transaction(ctx, ctx->sysdb, add_user, user_ctx);
if (ret != EOK) {
diff --git a/server/tools/tools_util.c b/server/tools/tools_util.c
index daf9b41f4..a3669001f 100644
--- a/server/tools/tools_util.c
+++ b/server/tools/tools_util.c
@@ -28,104 +28,6 @@
#include "db/sysdb.h"
#include "tools/tools_util.h"
-/* Even in LOCAL database, we must enforce MPG. That means enforcing the following rules:
- *
- * 1. Users and groups must share the same name space. There can never be
- * a real group that has the same name of a real user.
- * 2. Users and Groups must share the same ID space a group can never have
- * a gidNumber that is numerically equal to a uidNumber Otherwise the
- * user MPG will conflict with said group.
- */
-
-struct ucheck {
- bool done;
- bool dup;
- int error;
-};
-
-void check_unique_callback(void *ptr, int error, struct ldb_result *res)
-{
- struct ucheck *data = talloc_get_type(ptr, struct ucheck);
-
- data->done = true;
-
- if (error) {
- data->error = error;
- }
-
- if (res->count != 0) {
- data->dup = true;
- }
-}
-
-int check_user_name_unique(struct tools_ctx *ctx, const char *name)
-{
- struct ucheck *data;
- int ret = EOK;
-
- data = talloc_zero(NULL, struct ucheck);
- if (!data) return ENOMEM;
-
- ret = sysdb_getgrnam(data, ctx->sysdb,
- "LOCAL", name, false,
- check_unique_callback, data);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_getgrnam failed: %d\n", ret));
- goto done;
- }
-
- while (!data->done) {
- tevent_loop_once(ctx->ev);
- }
-
- if (data->error) {
- ret = data->error;
- goto done;
- }
-
- if (data->dup) {
- ret = EEXIST;
- }
-
-done:
- talloc_free(data);
- return ret;
-}
-
-int check_group_name_unique(struct tools_ctx *ctx, const char *name)
-{
- struct ucheck *data;
- int ret;
-
- data = talloc_zero(NULL, struct ucheck);
- if (!data) return ENOMEM;
-
- ret = sysdb_getpwnam(data, ctx->sysdb,
- "LOCAL", name, false,
- check_unique_callback, data);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_getgrnam failed: %d\n", ret));
- goto done;
- }
-
- while (!data->done) {
- tevent_loop_once(ctx->ev);
- }
-
- if (data->error) {
- ret = data->error;
- goto done;
- }
-
- if (data->dup) {
- ret = EEXIST;
- }
-
-done:
- talloc_free(data);
- return ret;
-}
-
int setup_db(struct tools_ctx **tools_ctx)
{
TALLOC_CTX *tmp_ctx;
diff --git a/server/tools/tools_util.h b/server/tools/tools_util.h
index d8edd4930..4a32e9c73 100644
--- a/server/tools/tools_util.h
+++ b/server/tools/tools_util.h
@@ -12,8 +12,6 @@ struct tools_ctx {
struct btreemap *domains;
};
-int check_user_name_unique(struct tools_ctx *ctx, const char *name);
-int check_group_name_unique(struct tools_ctx *ctx, const char *name);
int setup_db(struct tools_ctx **ctx);
void usage(poptContext pc, const char *error);