summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Bokovoy <abokovoy@redhat.com>2015-12-23 15:04:40 +0200
committerAlexander Bokovoy <abokovoy@redhat.com>2015-12-23 16:30:16 +0200
commit2135375fa15cc992ed5b07781028440ce6220858 (patch)
treecf3dabc89df22d61c4b31c57cac07063512b8776
parent38fc0024c2669006a4d71a722a75cf2aeeb3e4bf (diff)
downloadslapi-nis-2135375fa15cc992ed5b07781028440ce6220858.tar.gz
slapi-nis-2135375fa15cc992ed5b07781028440ce6220858.tar.xz
slapi-nis-2135375fa15cc992ed5b07781028440ce6220858.zip
slapi-nis: add support to resolve external members of IPA groupsexternalmembers
FreeIPA allows to include external (non-LDAP) members into POSIX groups. To define external members, an attribute ipaExternalMember is set to the list of references to external members. Currently both FreeIPA and SSSD support only references done with SIDs (Security Identifiers) from the forests trusted by FreeIPA. Resolving external members of FreeIPA groups requires resolving SIDs to user and group names. However, since this resolution is already implemented by SSSD for the group in question, slapi-nis can use the fact that there is non-empty ipaExternalMember attribute's value to trigger lookup of the FreeIPA group via SSSD and then copy over memberUid attribute value set. This logic requires that ipaExternalMember attribute value is present in the entry to be put into the map cache. Thus, an additional configuration is needed for the groups container: schema-compat-entry-attribute: ipaexternalmember=%deref_r("member","ipaexternalmember") Note that resolving external members of IPA groups requires to use version of slapi-nis that populates the map cache after LDAP server startup, as SSSD needs to talk back to the LDAP server in the process of resolving external group members and that is not possible at the time when slapi-nis plugin starts up as the LDAP server is not yet listenting for incoming connections at that point.
-rw-r--r--src/back-sch.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/back-sch.c b/src/back-sch.c
index 98542c5..d1998d7 100644
--- a/src/back-sch.c
+++ b/src/back-sch.c
@@ -419,6 +419,67 @@ backend_set_operational_attributes(Slapi_Entry *e,
}
}
+#ifdef USE_NSSWITCH
+#define IPA_ATTR_EXTERNAL_MEMBER "ipaExternalMember"
+static void
+backend_set_process_external_members(Slapi_PBlock *pb,
+ Slapi_Entry *e,
+ struct plugin_state *state,
+ struct backend_set_data *data)
+{
+ Slapi_Attr *attr = NULL;
+ Slapi_ValueSet *valueset;
+ bool_t is_attr_exists, is_group_exists;
+ struct backend_staged_search staged = {0, };
+ struct backend_search_cbdata cbdata = {0, };
+
+ is_attr_exists = slapi_entry_attr_find(e, IPA_ATTR_EXTERNAL_MEMBER, &attr) == 0;
+
+ if (!is_attr_exists || attr == NULL) {
+ return;
+ }
+
+ /* There are external members in this entry, do group lookup via SSSD
+ * and update entry's memberUid attribute */
+
+ staged.name = slapi_entry_attr_get_charptr(e, "cn");
+ staged.type = SCH_NSSWITCH_GROUP;
+ staged.search_members = FALSE;
+ staged.is_id = FALSE;
+ staged.is_sid = FALSE;
+ staged.container_sdn = slapi_sdn_get_dn(data->container_sdn);
+ staged.entries = NULL;
+ staged.count = 0;
+ cbdata.nsswitch_buffer_len = MAX(16384, MAX(sysconf(_SC_GETPW_R_SIZE_MAX), sysconf(_SC_GETGR_R_SIZE_MAX)));
+ cbdata.nsswitch_buffer = malloc(cbdata.nsswitch_buffer_len);
+ cbdata.state = state;
+ cbdata.staged = &staged;
+
+ is_group_exists = backend_retrieve_from_nsswitch(&staged, &cbdata);
+ if (is_group_exists && staged.entries != NULL && staged.entries[0] != NULL) {
+ attr = NULL;
+ if (slapi_entry_attr_find(staged.entries[0], "memberUid", &attr) == 0) {
+ (void)slapi_attr_get_valueset(attr, &valueset);
+ if (slapi_entry_attr_find(e, "memberUid", &attr) == 0) {
+ slapi_attr_set_valueset(attr, valueset);
+ } else {
+ slapi_entry_add_valueset(e, "memberUid", valueset);
+ slapi_valueset_free(valueset);
+ }
+ }
+ slapi_entry_free(staged.entries[0]);
+ }
+
+ if (staged.entries != NULL) {
+ free(staged.entries);
+ }
+
+ (void)slapi_entry_attr_delete(e, IPA_ATTR_EXTERNAL_MEMBER);
+ free(cbdata.nsswitch_buffer);
+ slapi_ch_free_string(&staged.name);
+}
+#endif
+
/* Given a map-entry directory entry, determine a key, a value, and extra data
* to be stored in the map cache, and add them to the map cache. */
static void
@@ -613,6 +674,9 @@ backend_set_entry_from(Slapi_PBlock *pb, enum backend_entry_source source,
slapi_entry_add_string(entry,
"objectClass", "extensibleObject");
}
+#ifdef USE_NSSWITCH
+ backend_set_process_external_members(pb, entry, data->common.state, data);
+#endif
/* Clean up the entry by doing a round trip through the LDIF parser. */
ldif = slapi_entry2str(entry, &len);
slapi_entry_free(entry);