Resolves: upstream#2653 - Group renaming issue when "id_provider = ldap" is set.

Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
This commit is contained in:
Fabiano Fidêncio 2018-04-27 21:58:17 +02:00
parent 209701ef7f
commit 2dd8451396
10 changed files with 1309 additions and 0 deletions

View File

@ -0,0 +1,177 @@
From d1f38315fa7f8c9d3392af0feb32afc56a0f6c4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Fri, 16 Feb 2018 13:55:53 +0100
Subject: [PATCH] NSS: Add InvalidateGroupById handler
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
There are some situations where, from the backend, the NSS responder
will have to be notified to invalidate a group.
In order to achieve this in a clean way, let's add the
InvalidateGroupById handler and make use of it later in this very same
series.
Related:
https://pagure.io/SSSD/sssd/issue/2653
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 851d31264c826d7e1bca38bb6d49e66b446707e7)
---
src/responder/nss/nss_iface.c | 16 ++++++++++++++
src/responder/nss/nss_iface.xml | 3 +++
src/responder/nss/nss_iface_generated.c | 38 +++++++++++++++++++++++++++++++++
src/responder/nss/nss_iface_generated.h | 5 +++++
4 files changed, 62 insertions(+)
diff --git a/src/responder/nss/nss_iface.c b/src/responder/nss/nss_iface.c
index 415af9550..805e4fcdf 100644
--- a/src/responder/nss/nss_iface.c
+++ b/src/responder/nss/nss_iface.c
@@ -199,12 +199,28 @@ int nss_memorycache_update_initgroups(struct sbus_request *sbus_req,
return iface_nss_memorycache_UpdateInitgroups_finish(sbus_req);
}
+int nss_memorycache_invalidate_group_by_id(struct sbus_request *sbus_req,
+ void *data,
+ gid_t gid)
+{
+ struct resp_ctx *rctx = talloc_get_type(data, struct resp_ctx);
+ struct nss_ctx *nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx);
+
+ DEBUG(SSSDBG_TRACE_LIBS,
+ "Invalidating group %"PRIu32" from memory cache\n", gid);
+
+ sss_mmap_cache_gr_invalidate_gid(nctx->grp_mc_ctx, gid);
+
+ return iface_nss_memorycache_InvalidateGroupById_finish(sbus_req);
+}
+
struct iface_nss_memorycache iface_nss_memorycache = {
{ &iface_nss_memorycache_meta, 0 },
.UpdateInitgroups = nss_memorycache_update_initgroups,
.InvalidateAllUsers = nss_memorycache_invalidate_users,
.InvalidateAllGroups = nss_memorycache_invalidate_groups,
.InvalidateAllInitgroups = nss_memorycache_invalidate_initgroups,
+ .InvalidateGroupById = nss_memorycache_invalidate_group_by_id,
};
static struct sbus_iface_map iface_map[] = {
diff --git a/src/responder/nss/nss_iface.xml b/src/responder/nss/nss_iface.xml
index 27aae0197..4d8cf14f9 100644
--- a/src/responder/nss/nss_iface.xml
+++ b/src/responder/nss/nss_iface.xml
@@ -14,5 +14,8 @@
</method>
<method name="InvalidateAllInitgroups">
</method>
+ <method name="InvalidateGroupById">
+ <arg name="gid" type="u" direction="in" />
+ </method>
</interface>
</node>
diff --git a/src/responder/nss/nss_iface_generated.c b/src/responder/nss/nss_iface_generated.c
index 4a8b704da..8d5a4584b 100644
--- a/src/responder/nss/nss_iface_generated.c
+++ b/src/responder/nss/nss_iface_generated.c
@@ -12,6 +12,9 @@
/* invokes a handler with a 'ssau' DBus signature */
static int invoke_ssau_method(struct sbus_request *dbus_req, void *function_ptr);
+/* invokes a handler with a 'u' DBus signature */
+static int invoke_u_method(struct sbus_request *dbus_req, void *function_ptr);
+
/* arguments for org.freedesktop.sssd.nss.MemoryCache.UpdateInitgroups */
const struct sbus_arg_meta iface_nss_memorycache_UpdateInitgroups__in[] = {
{ "user", "s" },
@@ -44,6 +47,18 @@ int iface_nss_memorycache_InvalidateAllInitgroups_finish(struct sbus_request *re
DBUS_TYPE_INVALID);
}
+/* arguments for org.freedesktop.sssd.nss.MemoryCache.InvalidateGroupById */
+const struct sbus_arg_meta iface_nss_memorycache_InvalidateGroupById__in[] = {
+ { "gid", "u" },
+ { NULL, }
+};
+
+int iface_nss_memorycache_InvalidateGroupById_finish(struct sbus_request *req)
+{
+ return sbus_request_return_and_finish(req,
+ DBUS_TYPE_INVALID);
+}
+
/* methods for org.freedesktop.sssd.nss.MemoryCache */
const struct sbus_method_meta iface_nss_memorycache__methods[] = {
{
@@ -74,6 +89,13 @@ const struct sbus_method_meta iface_nss_memorycache__methods[] = {
offsetof(struct iface_nss_memorycache, InvalidateAllInitgroups),
NULL, /* no invoker */
},
+ {
+ "InvalidateGroupById", /* name */
+ iface_nss_memorycache_InvalidateGroupById__in,
+ NULL, /* no out_args */
+ offsetof(struct iface_nss_memorycache, InvalidateGroupById),
+ invoke_u_method,
+ },
{ NULL, }
};
@@ -86,6 +108,22 @@ const struct sbus_interface_meta iface_nss_memorycache_meta = {
sbus_invoke_get_all, /* GetAll invoker */
};
+/* invokes a handler with a 'u' DBus signature */
+static int invoke_u_method(struct sbus_request *dbus_req, void *function_ptr)
+{
+ uint32_t arg_0;
+ int (*handler)(struct sbus_request *, void *, uint32_t) = function_ptr;
+
+ if (!sbus_request_parse_or_finish(dbus_req,
+ DBUS_TYPE_UINT32, &arg_0,
+ DBUS_TYPE_INVALID)) {
+ return EOK; /* request handled */
+ }
+
+ return (handler)(dbus_req, dbus_req->intf->handler_data,
+ arg_0);
+}
+
/* invokes a handler with a 'ssau' DBus signature */
static int invoke_ssau_method(struct sbus_request *dbus_req, void *function_ptr)
{
diff --git a/src/responder/nss/nss_iface_generated.h b/src/responder/nss/nss_iface_generated.h
index 11fac7916..27a6d0853 100644
--- a/src/responder/nss/nss_iface_generated.h
+++ b/src/responder/nss/nss_iface_generated.h
@@ -18,6 +18,7 @@
#define IFACE_NSS_MEMORYCACHE_INVALIDATEALLUSERS "InvalidateAllUsers"
#define IFACE_NSS_MEMORYCACHE_INVALIDATEALLGROUPS "InvalidateAllGroups"
#define IFACE_NSS_MEMORYCACHE_INVALIDATEALLINITGROUPS "InvalidateAllInitgroups"
+#define IFACE_NSS_MEMORYCACHE_INVALIDATEGROUPBYID "InvalidateGroupById"
/* ------------------------------------------------------------------------
* DBus handlers
@@ -44,6 +45,7 @@ struct iface_nss_memorycache {
int (*InvalidateAllUsers)(struct sbus_request *req, void *data);
int (*InvalidateAllGroups)(struct sbus_request *req, void *data);
int (*InvalidateAllInitgroups)(struct sbus_request *req, void *data);
+ int (*InvalidateGroupById)(struct sbus_request *req, void *data, uint32_t arg_gid);
};
/* finish function for UpdateInitgroups */
@@ -58,6 +60,9 @@ int iface_nss_memorycache_InvalidateAllGroups_finish(struct sbus_request *req);
/* finish function for InvalidateAllInitgroups */
int iface_nss_memorycache_InvalidateAllInitgroups_finish(struct sbus_request *req);
+/* finish function for InvalidateGroupById */
+int iface_nss_memorycache_InvalidateGroupById_finish(struct sbus_request *req);
+
/* ------------------------------------------------------------------------
* DBus Interface Metadata
*
--
2.14.3

View File

@ -0,0 +1,91 @@
From efaabeae96f76036bbe06122f7fbf70a66d26c56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Mon, 19 Feb 2018 08:42:10 +0100
Subject: [PATCH] DP: Add dp_sbus_invalidate_group_memcache()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This function will be called from the data provider to the NSS
responder, which will invalidate a group in the memcache.
Related:
https://pagure.io/SSSD/sssd/issue/2653
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 709c42f0cabc96d0e0edf72753a0967593206ff4)
---
src/providers/data_provider/dp.h | 2 ++
src/providers/data_provider/dp_resp_client.c | 45 ++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/src/providers/data_provider/dp.h b/src/providers/data_provider/dp.h
index ceb49da53..e8b2f9c8f 100644
--- a/src/providers/data_provider/dp.h
+++ b/src/providers/data_provider/dp.h
@@ -179,6 +179,8 @@ void dp_sbus_reset_groups_ncache(struct data_provider *provider,
void dp_sbus_reset_users_memcache(struct data_provider *provider);
void dp_sbus_reset_groups_memcache(struct data_provider *provider);
void dp_sbus_reset_initgr_memcache(struct data_provider *provider);
+void dp_sbus_invalidate_group_memcache(struct data_provider *provider,
+ gid_t gid);
/*
* A dummy handler for DPM_ACCT_DOMAIN_HANDLER.
diff --git a/src/providers/data_provider/dp_resp_client.c b/src/providers/data_provider/dp_resp_client.c
index 5735188a6..a61f7c59d 100644
--- a/src/providers/data_provider/dp_resp_client.c
+++ b/src/providers/data_provider/dp_resp_client.c
@@ -189,3 +189,48 @@ void dp_sbus_reset_initgr_memcache(struct data_provider *provider)
return dp_sbus_reset_memcache(provider,
IFACE_NSS_MEMORYCACHE_INVALIDATEALLINITGROUPS);
}
+
+void dp_sbus_invalidate_group_memcache(struct data_provider *provider,
+ gid_t gid)
+{
+ struct dp_client *dp_cli;
+ DBusMessage *msg;
+ dbus_bool_t dbret;
+
+ if (provider == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "No provider pointer\n");
+ return;
+ }
+
+ dp_cli = provider->clients[DPC_NSS];
+ if (dp_cli == NULL) {
+ return;
+ }
+
+ msg = dbus_message_new_method_call(NULL,
+ NSS_MEMORYCACHE_PATH,
+ IFACE_NSS_MEMORYCACHE,
+ IFACE_NSS_MEMORYCACHE_INVALIDATEGROUPBYID);
+ if (msg == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory?!\n");
+ return;
+ }
+
+ dbret = dbus_message_append_args(msg,
+ DBUS_TYPE_UINT32, &gid,
+ DBUS_TYPE_INVALID);
+ if (!dbret) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory?!\n");
+ dbus_message_unref(msg);
+ return;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Ordering NSS responder to invalidate the group %"PRIu32" \n",
+ gid);
+
+ sbus_conn_send_reply(dp_client_conn(dp_cli), msg);
+ dbus_message_unref(msg);
+
+ return;
+}
--
2.14.3

View File

@ -0,0 +1,49 @@
From 454f493664bf117c27634e6efe33ebe7d5a85c56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Mon, 19 Feb 2018 08:29:36 +0100
Subject: [PATCH] ERRORS: Add ERR_GID_DUPLICATED
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This new error will be returned from sysdb_add_incomplete_group()
when renaming a group which will case gid collision.
Related:
https://pagure.io/SSSD/sssd/issue/2653
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit ccd349f0274217e1f0cc118e3a6045e2235ce420)
---
src/util/util_errors.c | 1 +
src/util/util_errors.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index 39ce3d7dc..e2bb2a014 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -118,6 +118,7 @@ struct err_string error_to_str[] = {
{ "GetAccountDomain() not supported" }, /* ERR_GET_ACCT_DOM_NOT_SUPPORTED */
{ "The last GetAccountDomain() result is still valid" }, /* ERR_GET_ACCT_DOM_CACHED */
{ "ID is outside the allowed range" }, /* ERR_ID_OUTSIDE_RANGE */
+ { "Group ID is duplicated" }, /* ERR_GID_DUPLICATED */
{ "ERR_LAST" } /* ERR_LAST */
};
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index ad4dad5f8..49501727d 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -140,6 +140,7 @@ enum sssd_errors {
ERR_GET_ACCT_DOM_NOT_SUPPORTED,
ERR_GET_ACCT_DOM_CACHED,
ERR_ID_OUTSIDE_RANGE,
+ ERR_GID_DUPLICATED,
ERR_LAST /* ALWAYS LAST */
};
--
2.14.3

View File

@ -0,0 +1,380 @@
From f60c77df9b7162f46d8639f940d5df31f64f5815 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Mon, 9 Apr 2018 12:36:45 +0200
Subject: [PATCH] LDAP: Augment the sdap_opts structure with a data provider
pointer
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In order to be able to use the Data Provider methods from the SDAP code
to e.g. invalidate memcache when needed, add a new field to the
sdap_options structure with the data_provider structure pointer.
Fill the pointer value for all LDAP-based providers.
Related:
https://pagure.io/SSSD/sssd/issue/2653
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
(cherry picked from commit d2633d922eeed68f92be4248b9172b928c189920)
---
src/providers/ad/ad_common.c | 18 +++++++++++++-----
src/providers/ad/ad_common.h | 4 ++++
src/providers/ad/ad_init.c | 5 ++++-
src/providers/ad/ad_subdomains.c | 8 ++++++--
src/providers/ipa/ipa_common.c | 2 ++
src/providers/ipa/ipa_common.h | 1 +
src/providers/ipa/ipa_init.c | 5 ++++-
src/providers/ipa/ipa_subdomains_server.c | 2 ++
src/providers/ldap/ldap_common.h | 1 +
src/providers/ldap/ldap_init.c | 3 ++-
src/providers/ldap/ldap_options.c | 2 ++
src/providers/ldap/sdap.h | 1 +
src/tests/cmocka/common_mock_sdap.c | 2 +-
src/tests/cmocka/test_ad_common.c | 3 +++
14 files changed, 46 insertions(+), 11 deletions(-)
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 2a1647173..d92c68e6f 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -35,7 +35,8 @@ static errno_t ad_set_sdap_options(struct ad_options *ad_opts,
struct sdap_options *id_opts);
static struct sdap_options *
-ad_create_default_sdap_options(TALLOC_CTX *mem_ctx)
+ad_create_default_sdap_options(TALLOC_CTX *mem_ctx,
+ struct data_provider *dp)
{
struct sdap_options *id_opts;
errno_t ret;
@@ -44,6 +45,7 @@ ad_create_default_sdap_options(TALLOC_CTX *mem_ctx)
if (!id_opts) {
return NULL;
}
+ id_opts->dp = dp;
ret = dp_copy_defaults(id_opts,
ad_def_ldap_opts,
@@ -112,6 +114,7 @@ static errno_t
ad_create_sdap_options(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sdap_options **_id_opts)
{
struct sdap_options *id_opts;
@@ -119,7 +122,7 @@ ad_create_sdap_options(TALLOC_CTX *mem_ctx,
if (cdb == NULL || conf_path == NULL) {
/* Fallback to defaults if there is no confdb */
- id_opts = ad_create_default_sdap_options(mem_ctx);
+ id_opts = ad_create_default_sdap_options(mem_ctx, dp);
if (id_opts == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to initialize default sdap options\n");
@@ -220,6 +223,7 @@ struct ad_options *
ad_create_options(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sss_domain_info *subdom)
{
struct ad_options *ad_options;
@@ -252,6 +256,7 @@ ad_create_options(TALLOC_CTX *mem_ctx,
ret = ad_create_sdap_options(ad_options,
cdb,
conf_path,
+ dp,
&ad_options->id);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD LDAP options\n");
@@ -304,6 +309,7 @@ struct ad_options *
ad_create_2way_trust_options(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
const char *realm,
struct sss_domain_info *subdom,
const char *hostname,
@@ -315,7 +321,7 @@ ad_create_2way_trust_options(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_TRACE_FUNC, "2way trust is defined to domain '%s'\n",
subdom->name);
- ad_options = ad_create_options(mem_ctx, cdb, conf_path, subdom);
+ ad_options = ad_create_options(mem_ctx, cdb, conf_path, dp, subdom);
if (ad_options == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "ad_create_options failed\n");
return NULL;
@@ -343,6 +349,7 @@ struct ad_options *
ad_create_1way_trust_options(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
const char *subdom_conf_path,
+ struct data_provider *dp,
struct sss_domain_info *subdom,
const char *hostname,
const char *keytab,
@@ -355,7 +362,7 @@ ad_create_1way_trust_options(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_TRACE_FUNC, "1way trust is defined to domain '%s'\n",
subdom->name);
- ad_options = ad_create_options(mem_ctx, cdb, subdom_conf_path, subdom);
+ ad_options = ad_create_options(mem_ctx, cdb, subdom_conf_path, dp, subdom);
if (ad_options == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "ad_create_options failed\n");
return NULL;
@@ -1056,12 +1063,13 @@ errno_t
ad_get_id_options(struct ad_options *ad_opts,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sdap_options **_opts)
{
struct sdap_options *id_opts;
errno_t ret;
- ret = ad_create_sdap_options(ad_opts, cdb, conf_path, &id_opts);
+ ret = ad_create_sdap_options(ad_opts, cdb, conf_path, dp, &id_opts);
if (ret != EOK) {
return ENOMEM;
}
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index 931aafc6c..6eb2ba7e9 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -112,11 +112,13 @@ ad_get_common_options(TALLOC_CTX *mem_ctx,
struct ad_options *ad_create_options(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sss_domain_info *subdom);
struct ad_options *ad_create_2way_trust_options(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
const char *realm,
struct sss_domain_info *subdom,
const char *hostname,
@@ -125,6 +127,7 @@ struct ad_options *ad_create_2way_trust_options(TALLOC_CTX *mem_ctx,
struct ad_options *ad_create_1way_trust_options(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sss_domain_info *subdom,
const char *hostname,
const char *keytab,
@@ -147,6 +150,7 @@ errno_t
ad_get_id_options(struct ad_options *ad_opts,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sdap_options **_opts);
errno_t
ad_get_autofs_options(struct ad_options *ad_opts,
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index 8c485a7c2..b19624782 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -453,7 +453,10 @@ errno_t sssm_ad_init(TALLOC_CTX *mem_ctx,
init_ctx->options->id_ctx = init_ctx->id_ctx;
- ret = ad_get_id_options(init_ctx->options, be_ctx->cdb, be_ctx->conf_path,
+ ret = ad_get_id_options(init_ctx->options,
+ be_ctx->cdb,
+ be_ctx->conf_path,
+ be_ctx->provider,
&init_ctx->id_ctx->sdap_id_ctx->opts);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init AD id options\n");
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index bd94ba8ea..74b9f0751 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -265,8 +265,12 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
return ENOMEM;
}
- ad_options = ad_create_2way_trust_options(id_ctx, be_ctx->cdb,
- subdom_conf_path, realm, subdom,
+ ad_options = ad_create_2way_trust_options(id_ctx,
+ be_ctx->cdb,
+ subdom_conf_path,
+ be_ctx->provider,
+ realm,
+ subdom,
hostname, keytab);
talloc_free(subdom_conf_path);
if (ad_options == NULL) {
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 2b81d7f3f..87ed96767 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -171,6 +171,7 @@ static errno_t ipa_parse_search_base(TALLOC_CTX *mem_ctx,
int ipa_get_id_options(struct ipa_options *ipa_opts,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sdap_options **_opts)
{
TALLOC_CTX *tmpctx;
@@ -190,6 +191,7 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
ret = ENOMEM;
goto done;
}
+ ipa_opts->id->dp = dp;
ret = sdap_domain_add(ipa_opts->id,
ipa_opts->id_ctx->sdap_id_ctx->be->domain,
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 3a1259ccd..725e0e937 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -235,6 +235,7 @@ int ipa_get_options(TALLOC_CTX *memctx,
int ipa_get_id_options(struct ipa_options *ipa_opts,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sdap_options **_opts);
int ipa_get_auth_options(struct ipa_options *ipa_opts,
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index cd2227896..931145985 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -161,7 +161,10 @@ static errno_t ipa_init_id_ctx(TALLOC_CTX *mem_ctx,
ipa_id_ctx->sdap_id_ctx = sdap_id_ctx;
ipa_options->id_ctx = ipa_id_ctx;
- ret = ipa_get_id_options(ipa_options, be_ctx->cdb, be_ctx->conf_path,
+ ret = ipa_get_id_options(ipa_options,
+ be_ctx->cdb,
+ be_ctx->conf_path,
+ be_ctx->provider,
&sdap_id_ctx->opts);
if (ret != EOK) {
goto done;
diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
index d670a156b..1e53e7a95 100644
--- a/src/providers/ipa/ipa_subdomains_server.c
+++ b/src/providers/ipa/ipa_subdomains_server.c
@@ -148,6 +148,7 @@ ipa_create_1way_trust_ctx(struct ipa_id_ctx *id_ctx,
ad_options = ad_create_1way_trust_options(id_ctx,
be_ctx->cdb,
subdom_conf_path,
+ be_ctx->provider,
subdom,
id_ctx->server_mode->hostname,
keytab,
@@ -186,6 +187,7 @@ static struct ad_options *ipa_ad_options_new(struct be_ctx *be_ctx,
ad_options = ad_create_2way_trust_options(id_ctx,
be_ctx->cdb,
subdom_conf_path,
+ be_ctx->provider,
id_ctx->server_mode->realm,
subdom,
id_ctx->server_mode->hostname,
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 44dbc3fb0..548f0f985 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -193,6 +193,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
struct sss_domain_info *dom,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sdap_options **_opts);
int ldap_get_sudo_options(struct confdb_ctx *cdb,
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index 83075b5d3..44b3e9ab3 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -458,7 +458,8 @@ errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx,
/* Always initialize options since it is needed everywhere. */
ret = ldap_get_options(init_ctx, be_ctx->domain, be_ctx->cdb,
- be_ctx->conf_path, &init_ctx->options);
+ be_ctx->conf_path, be_ctx->provider,
+ &init_ctx->options);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize LDAP options "
"[%d]: %s\n", ret, sss_strerror(ret));
diff --git a/src/providers/ldap/ldap_options.c b/src/providers/ldap/ldap_options.c
index ccc1a2c5b..0b79715d2 100644
--- a/src/providers/ldap/ldap_options.c
+++ b/src/providers/ldap/ldap_options.c
@@ -27,6 +27,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
struct sss_domain_info *dom,
struct confdb_ctx *cdb,
const char *conf_path,
+ struct data_provider *dp,
struct sdap_options **_opts)
{
struct sdap_attr_map *default_attr_map;
@@ -57,6 +58,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
opts = talloc_zero(memctx, struct sdap_options);
if (!opts) return ENOMEM;
+ opts->dp = dp;
ret = sdap_domain_add(opts, dom, NULL);
if (ret != EOK) {
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index ecf9c4d2e..e892c4071 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -465,6 +465,7 @@ struct sdap_certmap_ctx;
struct sdap_options {
struct dp_option *basic;
+ struct data_provider *dp;
struct sdap_attr_map *gen_map;
struct sdap_attr_map *user_map;
size_t user_map_cnt;
diff --git a/src/tests/cmocka/common_mock_sdap.c b/src/tests/cmocka/common_mock_sdap.c
index cef321613..fa4787c4b 100644
--- a/src/tests/cmocka/common_mock_sdap.c
+++ b/src/tests/cmocka/common_mock_sdap.c
@@ -48,7 +48,7 @@ struct sdap_options *mock_sdap_options_ldap(TALLOC_CTX *mem_ctx,
struct sdap_options *opts = NULL;
errno_t ret;
- ret = ldap_get_options(mem_ctx, domain, confdb_ctx, conf_path, &opts);
+ ret = ldap_get_options(mem_ctx, domain, confdb_ctx, conf_path, NULL, &opts);
if (ret != EOK) {
return NULL;
}
diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c
index 94f351e19..39ebbc633 100644
--- a/src/tests/cmocka/test_ad_common.c
+++ b/src/tests/cmocka/test_ad_common.c
@@ -449,6 +449,7 @@ static void test_ad_create_1way_trust_options(void **state)
test_ctx->ad_ctx,
NULL,
NULL,
+ NULL,
test_ctx->subdom,
ONEWAY_HOST_NAME,
ONEWAY_KEYTAB_PATH,
@@ -515,6 +516,7 @@ static void test_ad_create_2way_trust_options(void **state)
test_ctx->ad_ctx,
NULL,
NULL,
+ NULL,
REALMNAME,
test_ctx->subdom,
HOST_NAME,
@@ -585,6 +587,7 @@ test_ldap_conn_setup(void **state)
ad_ctx,
NULL,
NULL,
+ NULL,
REALMNAME,
test_ctx->subdom,
HOST_NAME,
--
2.14.3

View File

@ -0,0 +1,95 @@
From 87a0027c7dbc54422ac519ef8eef0323baff4b60 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Mon, 19 Feb 2018 12:43:06 +0100
Subject: [PATCH] SDAP: Add sdap_handle_id_collision_for_incomplete_groups()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This newly added function is a helper to properly hadle group
id-collisions when renaming incomplete groups and it does:
- Deletes the group from sysdb
- Adds the new incomplete group
- Notifies the NSS responder that the entry also has to be deleted from
the memory cache
This function will be called from
sdap_ad_save_group_membership_with_idmapping() and from
sdap_add_incomplete_groups().
Related:
https://pagure.io/SSSD/sssd/issue/2653
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit a537df2ea99acb0181dc360ddf9a60b69c16faf0)
---
src/providers/ldap/sdap_async.h | 11 ++++++++++
src/providers/ldap/sdap_async_initgroups.c | 34 ++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 40da81fb9..6ca3ed8d8 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -412,4 +412,15 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
errno_t
sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req);
+errno_t
+sdap_handle_id_collision_for_incomplete_groups(struct data_provider *dp,
+ struct sss_domain_info *domain,
+ const char *name,
+ gid_t gid,
+ const char *original_dn,
+ const char *sid_str,
+ const char *uuid,
+ bool posix,
+ time_t now);
+
#endif /* _SDAP_ASYNC_H_ */
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index 326294a1c..34747be59 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -3543,3 +3543,37 @@ errno_t get_sysdb_grouplist_dn(TALLOC_CTX *mem_ctx,
return get_sysdb_grouplist_ex(mem_ctx, sysdb, domain,
name, grouplist, true);
}
+
+errno_t
+sdap_handle_id_collision_for_incomplete_groups(struct data_provider *dp,
+ struct sss_domain_info *domain,
+ const char *name,
+ gid_t gid,
+ const char *original_dn,
+ const char *sid_str,
+ const char *uuid,
+ bool posix,
+ time_t now)
+{
+ errno_t ret;
+
+ ret = sysdb_delete_group(domain, NULL, gid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Due to an id collision, the new group with gid [\"%"PRIu32"\"] "
+ "will not be added as the old group (with the same gid) could "
+ "not be removed from the sysdb!",
+ gid);
+ return ret;
+ }
+
+ ret = sysdb_add_incomplete_group(domain, name, gid, original_dn, sid_str,
+ uuid, posix, now);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ dp_sbus_invalidate_group_memcache(dp, gid);
+
+ return EOK;
+}
--
2.14.3

View File

@ -0,0 +1,129 @@
From de891b231464f10ce029593d7ee2ebb401e8a0b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Mon, 19 Feb 2018 12:51:57 +0100
Subject: [PATCH] SDAP: Properly handle group id-collision when renaming
incomplete groups
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Resolves:
https://pagure.io/SSSD/sssd/issue/2653
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit a2e743cd23e8e2033340612c77a8dbb8ef48c1e1)
---
src/providers/ad/ad_pac.c | 3 +++
src/providers/ldap/sdap_async_ad.h | 1 +
src/providers/ldap/sdap_async_initgroups.c | 13 +++++++++++++
src/providers/ldap/sdap_async_initgroups_ad.c | 15 +++++++++++++++
4 files changed, 32 insertions(+)
diff --git a/src/providers/ad/ad_pac.c b/src/providers/ad/ad_pac.c
index 6b47462cf..1a344725f 100644
--- a/src/providers/ad/ad_pac.c
+++ b/src/providers/ad/ad_pac.c
@@ -434,6 +434,7 @@ struct ad_handle_pac_initgr_state {
const char *err;
int dp_error;
int sdap_ret;
+ struct sdap_options *opts;
size_t num_missing_sids;
char **missing_sids;
@@ -471,6 +472,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx,
return NULL;
}
state->user_dom = sdom->dom;
+ state->opts = id_ctx->opts;
/* The following variables are currently unused because no sub-request
* returns any of them. But they are needed to allow the same signature as
@@ -514,6 +516,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_TRACE_ALL, "Running PAC processing with id-mapping.\n");
ret = sdap_ad_save_group_membership_with_idmapping(state->username,
+ state->opts,
sdom->dom,
id_ctx->opts->idmap_ctx,
num_sids, group_sids);
diff --git a/src/providers/ldap/sdap_async_ad.h b/src/providers/ldap/sdap_async_ad.h
index 950f5a030..a5f47a1a9 100644
--- a/src/providers/ldap/sdap_async_ad.h
+++ b/src/providers/ldap/sdap_async_ad.h
@@ -25,6 +25,7 @@
#define SDAP_ASYNC_AD_H_
errno_t sdap_ad_save_group_membership_with_idmapping(const char *username,
+ struct sdap_options *opts,
struct sss_domain_info *user_dom,
struct sdap_idmap_ctx *idmap_ctx,
size_t num_sids,
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index 34747be59..03f6de01a 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -225,6 +225,19 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
ret = sysdb_add_incomplete_group(domain, groupname, gid,
original_dn, sid_str,
uuid, posix, now);
+ if (ret == ERR_GID_DUPLICATED) {
+ /* In case o group id-collision, do:
+ * - Delete the group from sysdb
+ * - Add the new incomplete group
+ * - Notify the NSS responder that the entry has also to be
+ * removed from the memory cache
+ */
+ ret = sdap_handle_id_collision_for_incomplete_groups(
+ opts->dp, domain, groupname, gid,
+ original_dn, sid_str, uuid, posix,
+ now);
+ }
+
if (ret != EOK) {
goto done;
}
diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
index 30f1d3db2..eab103652 100644
--- a/src/providers/ldap/sdap_async_initgroups_ad.c
+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
@@ -836,6 +836,7 @@ sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq)
}
errno_t sdap_ad_save_group_membership_with_idmapping(const char *username,
+ struct sdap_options *opts,
struct sss_domain_info *user_dom,
struct sdap_idmap_ctx *idmap_ctx,
size_t num_sids,
@@ -921,6 +922,19 @@ errno_t sdap_ad_save_group_membership_with_idmapping(const char *username,
ret = sysdb_add_incomplete_group(domain, name, gid,
NULL, sid, NULL, false, now);
+ if (ret == ERR_GID_DUPLICATED) {
+ /* In case o group id-collision, do:
+ * - Delete the group from sysdb
+ * - Add the new incomplete group
+ * - Notify the NSS responder that the entry has also to be
+ * removed from the memory cache
+ */
+ ret = sdap_handle_id_collision_for_incomplete_groups(
+ idmap_ctx->id_ctx->be->provider,
+ domain, name, gid, NULL, sid, NULL,
+ false, now);
+ }
+
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Could not create incomplete "
"group: [%s]\n", strerror(ret));
@@ -992,6 +1006,7 @@ static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq)
}
ret = sdap_ad_save_group_membership_with_idmapping(state->username,
+ state->opts,
state->domain,
state->idmap_ctx,
num_sids,
--
2.14.3

View File

@ -0,0 +1,64 @@
From 5da97dcfb8499348080b5c7a3980c704294f22fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Mon, 19 Feb 2018 08:53:56 +0100
Subject: [PATCH] SYSDB_OPS: Error out on id-collision when adding an
incomplete group
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This situation can be hit when renaming a group. For now, let's just
error this out so the caller can handle it properly on its own layer.
Related:
https://pagure.io/SSSD/sssd/issue/2653
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 514b2be089bfd0e2702d7e9ab883ab071a61b719)
---
src/db/sysdb_ops.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 5d3cf643d..de4fdb592 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -2377,12 +2377,34 @@ int sysdb_add_incomplete_group(struct sss_domain_info *domain,
TALLOC_CTX *tmp_ctx;
int ret;
struct sysdb_attrs *attrs;
+ struct ldb_message *msg;
+ const char *previous = NULL;
+ const char *group_attrs[] = { SYSDB_SID_STR, SYSDB_UUID, SYSDB_ORIG_DN, NULL };
+ const char *values[] = { sid_str, uuid, original_dn, NULL };
+ bool same = false;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
return ENOMEM;
}
+ ret = sysdb_search_group_by_gid(tmp_ctx, domain, gid, group_attrs, &msg);
+ if (ret == EOK) {
+ for (int i = 0; !same && group_attrs[i] != NULL; i++) {
+ previous = ldb_msg_find_attr_as_string(msg,
+ group_attrs[i],
+ NULL);
+ if (previous != NULL && values[i] != NULL) {
+ same = strcmp(previous, values[i]) == 0;
+ }
+ }
+ }
+
+ if (same) {
+ ret = ERR_GID_DUPLICATED;
+ goto done;
+ }
+
/* try to add the group */
ret = sysdb_add_basic_group(domain, name, gid);
if (ret) goto done;
--
2.14.3

View File

@ -0,0 +1,194 @@
From ead866b198034c0b3101732e09a5524d0182d1cb Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Mon, 19 Feb 2018 18:26:05 +0100
Subject: [PATCH] TESTS: Add an integration test for renaming incomplete groups
during initgroups
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
As we implemented the group renaming heuristics to rename only if we can
use another "hint" like the original DN or the SID to know the group is
the same, this patch adds two tests (positive and negative) to make sure
a group with a totally different RDN and hence different originalDN
cannot be renamed but a group whose name changed but the RDN stays the
same can be renamed.
Related:
https://pagure.io/SSSD/sssd/issue/3282
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
(cherry picked from commit 35d6fb7cabd6183252fd29b29aaf66264dca9135)
---
src/tests/intg/test_ldap.py | 149 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 147 insertions(+), 2 deletions(-)
diff --git a/src/tests/intg/test_ldap.py b/src/tests/intg/test_ldap.py
index db3253858..98b6349a8 100644
--- a/src/tests/intg/test_ldap.py
+++ b/src/tests/intg/test_ldap.py
@@ -94,10 +94,11 @@ def create_ldap_cleanup(request, ldap_conn, ent_list=None):
request.addfinalizer(lambda: cleanup_ldap_entries(ldap_conn, ent_list))
-def create_ldap_fixture(request, ldap_conn, ent_list=None):
+def create_ldap_fixture(request, ldap_conn, ent_list=None, cleanup=True):
"""Add LDAP entries and add teardown for removing them"""
create_ldap_entries(ldap_conn, ent_list)
- create_ldap_cleanup(request, ldap_conn, ent_list)
+ if cleanup:
+ create_ldap_cleanup(request, ldap_conn, ent_list)
SCHEMA_RFC2307 = "rfc2307"
@@ -1437,3 +1438,147 @@ def test_ldap_auto_private_groups_direct_no_gid(ldap_conn, mpg_setup_no_gid):
", ".join(["%s" % s for s in sorted(gids)]),
", ".join(["%s" % s for s in sorted(user1_expected_gids)])
)
+
+
+def rename_setup_no_cleanup(request, ldap_conn, cleanup_ent=None):
+ ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
+ ent_list.add_user("user1", 1001, 2001)
+ ent_list.add_group_bis("user1_private", 2001)
+
+ ent_list.add_user("user2", 1002, 2002)
+ ent_list.add_group_bis("user2_private", 2002)
+
+ ent_list.add_group_bis("group1", 2015, ["user1", "user2"])
+
+ if cleanup_ent is None:
+ create_ldap_fixture(request, ldap_conn, ent_list)
+ else:
+ # Since the entries were renamed, we need to clean up
+ # the renamed entries..
+ create_ldap_fixture(request, ldap_conn, ent_list, cleanup=False)
+ create_ldap_cleanup(request, ldap_conn, None)
+
+
+@pytest.fixture
+def rename_setup_cleanup(request, ldap_conn):
+ cleanup_ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
+ cleanup_ent_list.add_user("user1", 1001, 2001)
+ cleanup_ent_list.add_group_bis("new_user1_private", 2001)
+
+ cleanup_ent_list.add_user("user2", 1002, 2002)
+ cleanup_ent_list.add_group_bis("new_user2_private", 2002)
+
+ cleanup_ent_list.add_group_bis("new_group1", 2015, ["user1", "user2"])
+
+ rename_setup_no_cleanup(request, ldap_conn, cleanup_ent_list)
+
+ conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS)
+ create_conf_fixture(request, conf)
+ create_sssd_fixture(request)
+ return None
+
+
+@pytest.fixture
+def rename_setup_with_name(request, ldap_conn):
+ rename_setup_no_cleanup(request, ldap_conn)
+
+ conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS) + \
+ unindent("""
+ [nss]
+ [domain/LDAP]
+ ldap_group_name = name
+ timeout = 3000
+ """).format(**locals())
+ create_conf_fixture(request, conf)
+ create_sssd_fixture(request)
+ return None
+
+
+def test_rename_incomplete_group_same_dn(ldap_conn, rename_setup_with_name):
+ """
+ Test that if a group's name attribute changes, but the DN stays the same,
+ the incomplete group object will be renamed.
+
+ Because the RDN attribute must be present in the entry, we add another
+ attribute "name" that is purposefully different from the CN and make
+ sure the group names are reflected in name
+
+ Regression test for https://pagure.io/SSSD/sssd/issue/3282
+ """
+ pvt_dn1 = 'cn=user1_private,ou=Groups,' + ldap_conn.ds_inst.base_dn
+ pvt_dn2 = 'cn=user2_private,ou=Groups,' + ldap_conn.ds_inst.base_dn
+ group1_dn = 'cn=group1,ou=Groups,' + ldap_conn.ds_inst.base_dn
+
+ # Add the name we want for both private and secondary group
+ old = {'name': []}
+ new = {'name': [b"user1_group1"]}
+ ldif = ldap.modlist.modifyModlist(old, new)
+ ldap_conn.modify_s(group1_dn, ldif)
+
+ new = {'name': [b"pvt_user1"]}
+ ldif = ldap.modlist.modifyModlist(old, new)
+ ldap_conn.modify_s(pvt_dn1, ldif)
+
+ new = {'name': [b"pvt_user2"]}
+ ldif = ldap.modlist.modifyModlist(old, new)
+ ldap_conn.modify_s(pvt_dn2, ldif)
+
+ # Make sure the old name shows up in the id output
+ (res, errno, grp_list) = sssd_id.get_user_groups("user1")
+ assert res == sssd_id.NssReturnCode.SUCCESS, \
+ "Could not find groups for user1, %d" % errno
+
+ assert sorted(grp_list) == sorted(["pvt_user1", "user1_group1"])
+
+ # Rename the group by changing the cn attribute, but keep the DN the same
+ old = {'name': [b"user1_group1"]}
+ new = {'name': [b"new_user1_group1"]}
+ ldif = ldap.modlist.modifyModlist(old, new)
+ ldap_conn.modify_s(group1_dn, ldif)
+
+ (res, errno, grp_list) = sssd_id.get_user_groups("user2")
+ assert res == sssd_id.NssReturnCode.SUCCESS, \
+ "Could not find groups for user2, %d" % errno
+
+ assert sorted(grp_list) == sorted(["pvt_user2", "new_user1_group1"])
+
+ (res, errno, grp_list) = sssd_id.get_user_groups("user1")
+ assert res == sssd_id.NssReturnCode.SUCCESS, \
+ "Could not find groups for user1, %d" % errno
+
+ assert sorted(grp_list) == sorted(["pvt_user1", "new_user1_group1"])
+
+
+def test_rename_incomplete_group_rdn_changed(ldap_conn, rename_setup_cleanup):
+ """
+ Test that if a group's name attribute changes, and the DN changes with
+ the RDN. Then adding the second group will fail because we can't tell if
+ there are two duplicate groups in LDAP when saving the group or if the
+ group was renamed.
+
+ Please note that with many directories (AD, IPA), the code can rely on
+ other heuristics (SID, UUID) to find out the group is in fact the same.
+
+ Regression test for https://pagure.io/SSSD/sssd/issue/3282
+ """
+ pvt_dn = 'cn=user1_private,ou=Groups,' + ldap_conn.ds_inst.base_dn
+ group1_dn = 'cn=group1,ou=Groups,' + ldap_conn.ds_inst.base_dn
+
+ # Make sure the old name shows up in the id output
+ (res, errno, grp_list) = sssd_id.get_user_groups("user1")
+ assert res == sssd_id.NssReturnCode.SUCCESS, \
+ "Could not find groups for user1, %d" % errno
+
+ assert sorted(grp_list) == sorted(["user1_private", "group1"])
+
+ # Rename the groups, changing the RDN
+ ldap_conn.rename_s(group1_dn, "cn=new_group1")
+ ldap_conn.rename_s(pvt_dn, "cn=new_user1_private")
+
+ (res, errno, grp_list) = sssd_id.get_user_groups("user2")
+ assert res == sssd_id.NssReturnCode.SUCCESS, \
+ "Could not find groups for user2, %d" % errno
+
+ # The initgroups succeeds, but because saving the new group fails,
+ # SSSD will revert to the cache contents and return what's in the cache
+ assert sorted(grp_list) == sorted(["user2_private", "group1"])
--
2.14.3

View File

@ -0,0 +1,119 @@
From 0a367914b87ef56dd4d5d56778e5770d1201f255 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Mon, 16 Apr 2018 20:29:28 +0200
Subject: [PATCH] SYSDB: sysdb_add_incomplete_group now returns EEXIST with a
duplicate GID
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Related:
https://pagure.io/SSSD/sssd/issue/2653
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
(cherry picked from commit ba2d5f7a0adefb017d3f85203d715b725ca8810f)
---
src/db/sysdb_ops.c | 13 ++++++++++---
src/tests/sysdb-tests.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index de4fdb592..93b967e75 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -2398,10 +2398,17 @@ int sysdb_add_incomplete_group(struct sss_domain_info *domain,
same = strcmp(previous, values[i]) == 0;
}
}
- }
- if (same) {
- ret = ERR_GID_DUPLICATED;
+ if (same == true) {
+ DEBUG(SSSDBG_TRACE_LIBS,
+ "The group with GID [%"SPRIgid"] was renamed\n", gid);
+ ret = ERR_GID_DUPLICATED;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Another group with GID [%"SPRIgid"] already exists\n", gid);
+ ret = EEXIST;
goto done;
}
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 32b8ca856..416dedb5e 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -989,6 +989,50 @@ START_TEST (test_sysdb_add_incomplete_group)
}
END_TEST
+START_TEST (test_sysdb_incomplete_group_rename)
+{
+ struct sysdb_test_ctx *test_ctx;
+ int ret;
+
+ ret = setup_sysdb_tests(&test_ctx);
+ if (ret != EOK) {
+ fail("Could not set up the test");
+ return;
+ }
+
+ ret = sysdb_add_incomplete_group(test_ctx->domain, "incomplete_group",
+ 20000, NULL,
+ "S-1-5-21-123-456-789-111",
+ NULL, true, 0);
+ fail_unless(ret == EOK,
+ "sysdb_add_incomplete_group error [%d][%s]",
+ ret, strerror(ret));
+
+ /* Adding a group with the same GID and all the other characteristics uknown should fail */
+ ret = sysdb_add_incomplete_group(test_ctx->domain, "incomplete_group_new",
+ 20000, NULL, NULL, NULL, true, 0);
+ fail_unless(ret == EEXIST, "Did not caught a duplicate\n");
+
+ /* A different SID should also trigger a failure */
+ ret = sysdb_add_incomplete_group(test_ctx->domain, "incomplete_group_new",
+ 20000, NULL,
+ "S-1-5-21-123-456-789-222",
+ NULL, true, 0);
+ fail_unless(ret == EEXIST, "Did not caught a duplicate\n");
+
+ /* But if we know based on a SID that the group is in fact the same,
+ * let's just change its name
+ */
+ ret = sysdb_add_incomplete_group(test_ctx->domain, "incomplete_group_new",
+ 20000, NULL,
+ "S-1-5-21-123-456-789-111",
+ NULL, true, 0);
+ fail_unless(ret == ERR_GID_DUPLICATED,
+ "Did not catch a legitimate rename",
+ ret, strerror(ret));
+}
+END_TEST
+
START_TEST (test_sysdb_getpwnam)
{
struct sysdb_test_ctx *test_ctx;
@@ -5526,7 +5570,7 @@ START_TEST(test_sysdb_search_sid_str)
ret = setup_sysdb_tests(&test_ctx);
fail_if(ret != EOK, "Could not set up the test");
- data = test_data_new_group(test_ctx, 2900);
+ data = test_data_new_group(test_ctx, 2902);
fail_if(data == NULL);
data->sid_str = "S-1-2-3-4";
@@ -7166,6 +7210,7 @@ Suite *create_sysdb_suite(void)
tcase_add_loop_test(tc_sysdb,
test_sysdb_remove_local_group_by_gid,
28000, 28010);
+ tcase_add_test(tc_sysdb, test_sysdb_incomplete_group_rename);
/* test custom operations */
tcase_add_loop_test(tc_sysdb, test_sysdb_store_custom, 29010, 29020);
--
2.14.3

View File

@ -78,6 +78,15 @@ Patch0033: 0033-SDAP-Improve-a-DEBUG-message-about-GC-detection.patch
Patch0034: 0034-MAN-Improve-docs-about-GC-detection.patch
Patch0035: 0035-nss-idmap-do-not-set-a-limit.patch
Patch0036: 0036-nss-idmap-use-right-group-list-pointer-after-sss_get.patch
Patch0037: 0037-NSS-Add-InvalidateGroupById-handler.patch
Patch0038: 0038-DP-Add-dp_sbus_invalidate_group_memcache.patch
Patch0039: 0039-ERRORS-Add-ERR_GID_DUPLICATED.patch
Patch0040: 0040-LDAP-Augment-the-sdap_opts-structure-with-a-data-pro.patch
Patch0041: 0041-SDAP-Add-sdap_handle_id_collision_for_incomplete_gro.patch
Patch0042: 0042-SDAP-Properly-handle-group-id-collision-when-renamin.patch
Patch0043: 0043-SYSDB_OPS-Error-out-on-id-collision-when-adding-an-i.patch
Patch0044: 0044-TESTS-Add-an-integration-test-for-renaming-incomplet.patch
Patch0045: 0045-SYSDB-sysdb_add_incomplete_group-now-returns-EEXIST-.patch
Patch0502: 0502-SYSTEMD-Use-capabilities.patch
Patch0503: 0503-Disable-stopping-idle-socket-activated-responders.patch
@ -1297,6 +1306,8 @@ fi
- Improve docs/debug message about GC detection
- Resolves: upstream#3715 - ipa 389-ds-base crash in krb5-libs - k5_copy_etypes
list out of bound?
- Resolves: upstream#2653 - Group renaming issue when "id_provider = ldap" is
set.
* Fri Mar 30 2018 Fabiano Fidêncio <fidencio@fedoraproject.org> - 1.16.1-2
- Resolves: upstream#3573 - sssd won't show netgroups with blank domain