summaryrefslogtreecommitdiff
path: root/server/db
diff options
context:
space:
mode:
Diffstat (limited to 'server/db')
-rw-r--r--server/db/sysdb.h25
-rw-r--r--server/db/sysdb_ops.c196
2 files changed, 199 insertions, 22 deletions
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index c278e64c..e7da90b0 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 9ea2a0aa..0d20d7b3 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);
}