diff --git a/SOURCES/slapi-nis-extmem-0005-slapi-nis-populate-data-trees-asynchronously-after-L.patch b/SOURCES/slapi-nis-extmem-0005-slapi-nis-populate-data-trees-asynchronously-after-L.patch new file mode 100644 index 0000000..eafbedd --- /dev/null +++ b/SOURCES/slapi-nis-extmem-0005-slapi-nis-populate-data-trees-asynchronously-after-L.patch @@ -0,0 +1,207 @@ +From 2df48b57adb666112cab22e62750dd984fc7450a Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Wed, 23 Dec 2015 14:57:03 +0200 +Subject: [PATCH 05/12] slapi-nis: populate data trees asynchronously after + LDAP server startup + +Currently slapi-nis design assumes the map cache is populated by +scanning the original trees on plugin start up. This has few +consequences: + - LDAP server cannot serve LDAP clients until all plugins are + initialized + + - slapi-nis cannot ask SSSD to resolve external identities at + this point as SSSD will need to talk to the LDAP server which + is at this point not listening for connections. SSSD will put + whole IPA domain into offline and always will respond + with negative result + +To solve these issues, schedule tree scan after LDAP server startup. +The problem here is that it is not possible to reliably detect when +389-ds starts to listen to the incoming connections. However, it is +possible to schedule an event into 389-ds event queue that will run +shortly after start of the event loop. Given that the call back function +which is registered to be called is called within the event loop thread, +one can fire off another thread and wait in the thread function some +time until the LDAP server is ready for connections. + +The time interval is something that would depend on a specific +deployment profile but experiments show that having 5 seconds delay +should be enough as event queue is created just before starting the +listeners. +--- + src/back-shr.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++--------- + src/plug-sch.c | 4 +-- + 2 files changed, 96 insertions(+), 18 deletions(-) + +diff --git a/src/back-shr.c b/src/back-shr.c +index c68640a..36ecc0b 100644 +--- a/src/back-shr.c ++++ b/src/back-shr.c +@@ -664,40 +664,56 @@ backend_shr_get_vattr_sdnlist(struct plugin_state *state, + return ret; + } + +-/* Scan for the list of configured groups and sets. */ +-void +-backend_shr_startup(struct plugin_state *state, +- Slapi_PBlock *parent_pb, +- const char *filter) ++struct backend_shr_data_init_cbdata { ++ Slapi_PBlock *parent_pb; ++ struct plugin_state *state; ++ const char *filter; ++}; ++ ++#define PLUGIN_SCAN_DELAY 5 ++ ++static void ++backend_shr_data_initialize_thread_cb(void *arg) + { +- Slapi_PBlock *pb; ++ struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg; ++ Slapi_PBlock *pb = NULL; + struct backend_set_config_entry_add_cbdata set_cbdata; ++ int result = 0; ++ if (cbdata == NULL) { ++ return; ++ } ++ ++ /* Scan may require consulting SSSD for external identities ++ * therefore, we need to make sure the scan starts after ns-slapd ++ * started to serve LDAP clients. There is no a signal for this, ++ * so we just wait some time. */ ++ DS_Sleep(PR_SecondsToInterval(PLUGIN_SCAN_DELAY)); + +- backend_update_params(parent_pb, state); ++ backend_update_params(cbdata->parent_pb, cbdata->state); + + slapi_log_error(SLAPI_LOG_PLUGIN, +- state->plugin_desc->spd_id, ++ cbdata->state->plugin_desc->spd_id, + "searching under \"%s\" for configuration\n", +- state->plugin_base); +- pb = wrap_pblock_new(parent_pb); ++ cbdata->state->plugin_base); ++ pb = wrap_pblock_new(cbdata->parent_pb); + slapi_search_internal_set_pb(pb, +- state->plugin_base, ++ cbdata->state->plugin_base, + LDAP_SCOPE_ONELEVEL, +- filter, ++ cbdata->filter, + NULL, FALSE, + NULL, + NULL, +- state->plugin_identity, ++ cbdata->state->plugin_identity, + 0); + if (map_wrlock() != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, +- state->plugin_desc->spd_id, ++ cbdata->state->plugin_desc->spd_id, + "failed to search under \"%s\" for " + "configuration: failed to acquire a lock\n", +- state->plugin_base); ++ cbdata->state->plugin_base); + goto done_with_lock; + } +- set_cbdata.state = state; ++ set_cbdata.state = cbdata->state; + set_cbdata.pb = pb; + slapi_search_internal_callback_pb(pb, &set_cbdata, + NULL, +@@ -706,6 +722,68 @@ backend_shr_startup(struct plugin_state *state, + map_unlock(); + done_with_lock: + slapi_pblock_destroy(pb); ++ if (cbdata) { ++ slapi_ch_free((void**)&cbdata); ++ } ++} ++ ++static void ++backend_shr_data_initialize_thread(time_t when, void *arg) ++{ ++ struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg; ++ PRThread *thread = NULL; ++ ++ /* start data import as a separate thread */ ++ thread = PR_CreateThread(PR_USER_THREAD, backend_shr_data_initialize_thread_cb, ++ (void *)arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, ++ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE); ++ if (thread == NULL) { ++ slapi_log_error(SLAPI_LOG_FATAL, ++ cbdata->state->plugin_desc->spd_id, ++ "unable to create compatibility tree scan thread!\n"); ++ } else { ++ slapi_log_error(SLAPI_LOG_FATAL, ++ cbdata->state->plugin_desc->spd_id, ++ "%s tree scan will start in about %d seconds!\n", ++ cbdata->state->plugin_desc->spd_id, PLUGIN_SCAN_DELAY); ++ } ++ ++} ++ ++/* Scan for the list of configured groups and sets. */ ++void ++backend_shr_startup(struct plugin_state *state, ++ Slapi_PBlock *parent_pb, ++ const char *filter) ++{ ++ struct backend_shr_data_init_cbdata *cbdata = NULL; ++ ++ cbdata = (struct backend_shr_data_init_cbdata *) ++ slapi_ch_malloc(sizeof(struct backend_shr_data_init_cbdata)); ++ ++ if (cbdata == NULL) { ++ slapi_log_error(SLAPI_LOG_FATAL, ++ state->plugin_desc->spd_id, ++ "failed to create a task for populating " ++ "compatibility tree\n"); ++ return; ++ } ++ ++ cbdata->state = state; ++ cbdata->parent_pb = parent_pb; ++ cbdata->filter = filter; ++ ++ /* Schedule running a callback that will create a thread */ ++ slapi_eq_once(backend_shr_data_initialize_thread, ++ cbdata, PR_SecondsToInterval(PLUGIN_SCAN_DELAY)); ++ ++ slapi_log_error(SLAPI_LOG_FATAL, ++ cbdata->state->plugin_desc->spd_id, ++ "scheduled %s tree scan in about %d seconds after the server startup!\n", ++ state->plugin_desc->spd_id, PLUGIN_SCAN_DELAY); ++ ++ return; ++ + } + + /* Process a set configuration directory entry. Pull out the group and set +diff --git a/src/plug-sch.c b/src/plug-sch.c +index f132e6d..95a4fd8 100644 +--- a/src/plug-sch.c ++++ b/src/plug-sch.c +@@ -109,8 +109,6 @@ plugin_startup(Slapi_PBlock *pb) + state->plugin_base ? "\"" : "", + state->plugin_base ? state->plugin_base : "NULL", + state->plugin_base ? "\"" : ""); +- /* Populate the tree of fake entries. */ +- backend_startup(pb, state); + state->pam_lock = wrap_new_rwlock(); + backend_nss_init_context((struct nss_ops_ctx**) &state->nss_context); + if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) && +@@ -123,6 +121,8 @@ plugin_startup(Slapi_PBlock *pb) + wrap_rwlock_wrlock(state->cached_entries_lock); + state->cached_entries = PL_NewHashTable(0, PL_HashString, PL_CompareStrings, PL_CompareValues, 0, 0); + wrap_rwlock_unlock(state->cached_entries_lock); ++ /* Populate the tree of fake entries. */ ++ backend_startup(pb, state); + /* Note that the plugin is ready to go. */ + slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id, + "plugin startup completed\n"); +-- +2.5.0 + diff --git a/SOURCES/slapi-nis-extmem-0006-nss-force-lower-case-for-memberUid-attribute-as-per-.patch b/SOURCES/slapi-nis-extmem-0006-nss-force-lower-case-for-memberUid-attribute-as-per-.patch new file mode 100644 index 0000000..efdacae --- /dev/null +++ b/SOURCES/slapi-nis-extmem-0006-nss-force-lower-case-for-memberUid-attribute-as-per-.patch @@ -0,0 +1,84 @@ +From 52beb5e79905712a8aaabf19e52e654fc4648a94 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Fri, 15 Jan 2016 16:16:00 +0200 +Subject: [PATCH 06/12] nss: force lower case for memberUid attribute as per + RFC2307 + +When memberUid attribute is generated, it has to be normalized or +otherwise searches for members against groups in compat tree will fail. +slapi-nis already normalizes elements of a search filter that mention +memberUid attribute values but the original memberUid value should be +normalized as well. +--- + src/back-sch-nss.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/src/back-sch-nss.c b/src/back-sch-nss.c +index 16d4164..702590c 100644 +--- a/src/back-sch-nss.c ++++ b/src/back-sch-nss.c +@@ -246,8 +246,8 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd, + return NULL; + } + +- dn = backend_build_dn("uid", pwd->pw_name, container_sdn); +- if (dn == NULL) { ++ name = (char *) slapi_utf8StrToLower((unsigned char *) pwd->pw_name); ++ if (name == NULL) { + slapi_log_error(SLAPI_LOG_FATAL, + cbdata->state->plugin_desc->spd_id, + "error building DN for uid=%s,%s skipping\n", +@@ -256,12 +256,22 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd, + return NULL; + } + ++ dn = backend_build_dn("uid", name, container_sdn); ++ if (dn == NULL) { ++ slapi_log_error(SLAPI_LOG_FATAL, ++ cbdata->state->plugin_desc->spd_id, ++ "error building DN for uid=%s,%s skipping\n", ++ name, container_sdn); ++ slapi_entry_free(entry); ++ return NULL; ++ } ++ + slapi_entry_add_string(entry, + "objectClass", "top"); + slapi_entry_add_string(entry, + "objectClass", "posixAccount"); + slapi_entry_add_string(entry, +- "uid", pwd->pw_name); ++ "uid", name); + slapi_entry_attr_set_uint(entry, + "uidNumber", pwd->pw_uid); + slapi_entry_attr_set_uint(entry, +@@ -286,6 +296,7 @@ backend_make_user_entry_from_nsswitch_passwd(struct passwd *pwd, + } + + slapi_entry_set_dn(entry, dn); ++ slapi_ch_free_string(&name); + + #ifdef HAVE_SSS_NSS_IDMAP + rc = sss_nss_getsidbyid(pwd->pw_uid, &sid_str, &id_type); +@@ -520,6 +531,7 @@ backend_make_group_entry_from_nsswitch_group(struct group *grp, + Slapi_Entry *entry; + int rc, i; + char *dn = NULL; ++ char *name = NULL; + #ifdef HAVE_SSS_NSS_IDMAP + enum sss_id_type id_type; + char *sid_str; +@@ -551,7 +563,9 @@ backend_make_group_entry_from_nsswitch_group(struct group *grp, + + if (grp->gr_mem) { + for (i=0; grp->gr_mem[i]; i++) { +- slapi_entry_add_string(entry, "memberUid", grp->gr_mem[i]); ++ name = (char *) slapi_utf8StrToLower((unsigned char*) grp->gr_mem[i]); ++ slapi_entry_add_string(entry, "memberUid", name); ++ slapi_ch_free_string(&name); + } + } + +-- +2.5.0 + diff --git a/SOURCES/slapi-nis-extmem-0007-slapi-nis-add-support-to-resolve-external-members-of.patch b/SOURCES/slapi-nis-extmem-0007-slapi-nis-add-support-to-resolve-external-members-of.patch new file mode 100644 index 0000000..6ddaa28 --- /dev/null +++ b/SOURCES/slapi-nis-extmem-0007-slapi-nis-add-support-to-resolve-external-members-of.patch @@ -0,0 +1,195 @@ +From d1b87904462e890a855ac9d3b68ed02e089450d8 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Wed, 23 Dec 2015 15:04:40 +0200 +Subject: [PATCH 07/12] slapi-nis: add support to resolve external members of + IPA groups + +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. +--- + doc/ipa/sch-ipa.txt | 15 +++++++ + src/back-sch.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 127 insertions(+) + +diff --git a/doc/ipa/sch-ipa.txt b/doc/ipa/sch-ipa.txt +index 106e6cc..eb6238a 100644 +--- a/doc/ipa/sch-ipa.txt ++++ b/doc/ipa/sch-ipa.txt +@@ -81,6 +81,21 @@ and groups from trusted domains. No additional configuration is needed. + ipa-adtrust-install, however, will not set the minimal numeric id for user or + group. + ++Additionally, group area configuration should include following two attributes to ++allow resolving external members of IPA groups: ++ ++schema-compat-entry-attribute: ipaexternalmember=%deref_r("member","ipaexternalmember") ++schema-compat-entry-attribute: objectclass=ipaexternalgroup ++ ++When 'ipaExternalMember' attribute is present in the group entry generated by ++Schema Compatibility plugin, the plugin will attempt to retrieve the group ++members from SSSD daemon. If group has non-empty list of members, these new ++members will replace the original ones as they will include both IPA and external ++group members. ++ ++SSSD greater than 1.13.3 is required to produce correct behavior due to bug ++https://fedorahosted.org/sssd/ticket/2522 ++ + == Authentication of the trusted domains' users == + + When the Schema Compatibility Plugin is configured to expose users from trusted +diff --git a/src/back-sch.c b/src/back-sch.c +index 98542c5..04fe667 100644 +--- a/src/back-sch.c ++++ b/src/back-sch.c +@@ -419,6 +419,115 @@ backend_set_operational_attributes(Slapi_Entry *e, + } + } + ++#ifdef USE_NSSWITCH ++#define IPA_ATTR_EXTERNAL_MEMBER "ipaExternalMember" ++#define IPA_ATTR_MEMBERUID "memberUid" ++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 = NULL; ++ bool_t is_attr_exists, is_group_exists; ++ struct backend_staged_search staged = {0, }; ++ struct backend_search_cbdata cbdata = {0, }; ++ char *plugin_id = state->plugin_desc->spd_id; ++ ++ 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 = (char*) 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; ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, ++ "refreshing group membership for group \"%s\"\n", staged.name); ++ ++ do { ++ /* This group must exist because it exists in the original tree ++ * but as dirsrv was restarted, SSSD might still consider its domain offline. */ ++ is_group_exists = backend_retrieve_from_nsswitch(&staged, &cbdata); ++ if (!is_group_exists) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, ++ "group \"%s\" does not exist because SSSD is offline.", ++ staged.name); ++ if (state->ready_to_serve == 0) { ++ /* Only wait for SSSD when we populate the original set */ ++ slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, ++ "waiting for SSSD to become online..."); ++ DS_Sleep(PR_SecondsToInterval(35)); ++ } else { ++ break; ++ } ++ } ++ } while (!is_group_exists); ++ ++ if (staged.entries != NULL && staged.entries[0] != NULL) { ++ attr = NULL; ++ if (slapi_entry_attr_find(staged.entries[0], IPA_ATTR_MEMBERUID, &attr) == 0) { ++#if 0 ++ /* Debug output of original and updated memberUid values */ ++ char **ary1, **ary2; ++ ary1 = slapi_entry_attr_get_charray(e, "memberUid"); ++ ary2 = slapi_entry_attr_get_charray(staged.entries[0], "memberUid"); ++ ++ slapi_log_error(SLAPI_LOG_FATAL, plugin_id, ++ "original group \"%s\":\n", staged.name); ++ for (int i = 0; ary1 && ary1[i] != NULL; ++i) { ++ slapi_log_error(SLAPI_LOG_FATAL, plugin_id, ++ "\t> %s\n", ary1[i]); ++ } ++ slapi_log_error(SLAPI_LOG_FATAL, plugin_id, ++ "new group \"%s\":\n", staged.name); ++ for (int i = 0; ary2 && ary2[i] != NULL; ++i) { ++ slapi_log_error(SLAPI_LOG_FATAL, plugin_id, ++ "\t> %s\n", ary2[i]); ++ } ++ slapi_ch_array_free(ary2); ++ slapi_ch_array_free(ary1); ++#endif ++ ++ (void)slapi_attr_get_valueset(attr, &valueset); ++ ++ if (slapi_entry_attr_find(e, IPA_ATTR_MEMBERUID, &attr) == 0) { ++ (void) slapi_entry_attr_delete(e, IPA_ATTR_MEMBERUID); ++ } ++ (void) slapi_entry_add_valueset(e, IPA_ATTR_MEMBERUID, valueset); ++ slapi_valueset_free(valueset); ++ } else { ++ slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, ++ "group \"%s\" doesn't have memberUid attribute\n", staged.name); ++ } ++ 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 +722,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); +-- +2.5.0 + diff --git a/SOURCES/slapi-nis-extmem-0008-slapi-nis-process-requests-only-when-initialization-.patch b/SOURCES/slapi-nis-extmem-0008-slapi-nis-process-requests-only-when-initialization-.patch new file mode 100644 index 0000000..ec47383 --- /dev/null +++ b/SOURCES/slapi-nis-extmem-0008-slapi-nis-process-requests-only-when-initialization-.patch @@ -0,0 +1,150 @@ +From 594fcb2320033d01cfe2b8121793d431d1017987 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Fri, 15 Jan 2016 16:39:12 +0200 +Subject: [PATCH 08/12] slapi-nis: process requests only when initialization + completed + +Initializing map cache may take time. Skip slapi-nis lookups untli +the map cache is ready. +--- + src/back-sch.c | 23 ++++++++++++++++++++++- + src/back-shr.c | 20 ++++++++++++++++++++ + src/plugin.h | 1 + + 3 files changed, 43 insertions(+), 1 deletion(-) + +diff --git a/src/back-sch.c b/src/back-sch.c +index 04fe667..871734c 100644 +--- a/src/back-sch.c ++++ b/src/back-sch.c +@@ -1609,7 +1609,7 @@ backend_search_cb(Slapi_PBlock *pb) + { + struct backend_search_cbdata cbdata; + struct backend_staged_search *staged, *next; +- int i; ++ int i, isroot; + + if (wrap_get_call_level() > 0) { + return 0; +@@ -1621,6 +1621,19 @@ backend_search_cb(Slapi_PBlock *pb) + /* The plugin was not actually started. */ + return 0; + } ++ if (cbdata.state->ready_to_serve == 0) { ++ /* No data to serve yet */ ++ return 0; ++ } ++ ++ slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot); ++ ++ if (slapi_op_internal(pb) || (slapi_is_ldapi_conn(pb) && isroot)) { ++ /* The plugin should not engage in internal searches of other ++ * plugins or ldapi+cn=DM */ ++ return 0; ++ } ++ + slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &cbdata.target); + slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &cbdata.scope); + slapi_pblock_get(pb, SLAPI_SEARCH_SIZELIMIT, &cbdata.sizelimit); +@@ -2018,6 +2031,10 @@ backend_write_cb(Slapi_PBlock *pb, struct plugin_state *state) + if (wrap_get_call_level() > 0) { + return 0; + } ++ if (state->ready_to_serve == 0) { ++ /* No data to serve yet */ ++ return 0; ++ } + + wrap_inc_call_level(); + if (map_rdlock() == 0) { +@@ -2125,6 +2142,10 @@ backend_bind_cb(Slapi_PBlock *pb) + } + + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); ++ if (state->ready_to_serve == 0) { ++ /* No data to serve yet */ ++ return 0; ++ } + /* The code below handles three separate facts: + * 1. For NSSWITCH-discovered users PAM is responsible for authentication. + * We want to run PAM auth without any slapi-nis lock taken to avoid +diff --git a/src/back-shr.c b/src/back-shr.c +index 36ecc0b..131365d 100644 +--- a/src/back-shr.c ++++ b/src/back-shr.c +@@ -725,6 +725,8 @@ done_with_lock: + if (cbdata) { + slapi_ch_free((void**)&cbdata); + } ++ ++ PR_AtomicSet(&state->ready_to_serve, 1); + } + + static void +@@ -769,6 +771,7 @@ backend_shr_startup(struct plugin_state *state, + return; + } + ++ PR_AtomicSet(&state->ready_to_serve, 0); + cbdata->state = state; + cbdata->parent_pb = parent_pb; + cbdata->filter = filter; +@@ -1798,6 +1801,11 @@ backend_shr_add_cb(Slapi_PBlock *pb) + /* The plugin was not actually started. */ + return 0; + } ++ if (cbdata.state->ready_to_serve == 0) { ++ /* No data yet, ignore */ ++ return 0; ++ } ++ + slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e); + slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); + slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &rc); +@@ -2208,6 +2216,10 @@ backend_shr_modify_cb(Slapi_PBlock *pb) + /* The plugin was not actually started. */ + return 0; + } ++ if (cbdata.state->ready_to_serve == 0) { ++ /* No data yet, ignore */ ++ return 0; ++ } + slapi_pblock_get(pb, SLAPI_MODIFY_TARGET, &dn); + slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &cbdata.mods); + slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e_pre); +@@ -2410,6 +2422,10 @@ backend_shr_modrdn_cb(Slapi_PBlock *pb) + /* The plugin was not actually started. */ + return 0; + } ++ if (cbdata.state->ready_to_serve == 0) { ++ /* No data yet, ignore */ ++ return 0; ++ } + slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e_pre); + slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e_post); + +@@ -2549,6 +2565,10 @@ backend_shr_delete_cb(Slapi_PBlock *pb) + /* The plugin was not actually started. */ + return 0; + } ++ if (cbdata.state->ready_to_serve == 0) { ++ /* No data yet, ignore */ ++ return 0; ++ } + slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e); + slapi_pblock_get(pb, SLAPI_DELETE_TARGET, &dn); + slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &rc); +diff --git a/src/plugin.h b/src/plugin.h +index 429e291..7a89ac7 100644 +--- a/src/plugin.h ++++ b/src/plugin.h +@@ -33,6 +33,7 @@ struct plugin_state { + Slapi_ComponentId *plugin_identity; + Slapi_PluginDesc *plugin_desc; + unsigned int use_be_txns: 1; ++ PRInt32 ready_to_serve; + + /* NIS-specific data. */ + struct wrapped_thread *tid; +-- +2.5.0 + diff --git a/SOURCES/slapi-nis-extmem-0009-slapi-nis-serialize-map-cache-initialization.patch b/SOURCES/slapi-nis-extmem-0009-slapi-nis-serialize-map-cache-initialization.patch new file mode 100644 index 0000000..85544b9 --- /dev/null +++ b/SOURCES/slapi-nis-extmem-0009-slapi-nis-serialize-map-cache-initialization.patch @@ -0,0 +1,105 @@ +From 3aaf4941fc17df388c43776eda6d41f62017a143 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Fri, 15 Jan 2016 17:17:23 +0200 +Subject: [PATCH 09/12] slapi-nis: serialize map cache initialization + +Serialize process of initiliazing map cache to avoid locking the +directory server backends. +--- + src/back-shr.c | 55 +++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 18 deletions(-) + +diff --git a/src/back-shr.c b/src/back-shr.c +index 131365d..0157582 100644 +--- a/src/back-shr.c ++++ b/src/back-shr.c +@@ -678,49 +678,68 @@ backend_shr_data_initialize_thread_cb(void *arg) + struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg; + Slapi_PBlock *pb = NULL; + struct backend_set_config_entry_add_cbdata set_cbdata; +- int result = 0; ++ int result = 0, i = 0; ++ Slapi_Entry **entries = NULL; ++ struct plugin_state *state = NULL; ++ + if (cbdata == NULL) { + return; + } + ++ state = cbdata->state; ++ + /* Scan may require consulting SSSD for external identities + * therefore, we need to make sure the scan starts after ns-slapd + * started to serve LDAP clients. There is no a signal for this, + * so we just wait some time. */ + DS_Sleep(PR_SecondsToInterval(PLUGIN_SCAN_DELAY)); + +- backend_update_params(cbdata->parent_pb, cbdata->state); ++ backend_update_params(cbdata->parent_pb, state); + + slapi_log_error(SLAPI_LOG_PLUGIN, +- cbdata->state->plugin_desc->spd_id, ++ state->plugin_desc->spd_id, + "searching under \"%s\" for configuration\n", +- cbdata->state->plugin_base); ++ state->plugin_base); + pb = wrap_pblock_new(cbdata->parent_pb); + slapi_search_internal_set_pb(pb, +- cbdata->state->plugin_base, ++ state->plugin_base, + LDAP_SCOPE_ONELEVEL, + cbdata->filter, + NULL, FALSE, + NULL, + NULL, +- cbdata->state->plugin_identity, ++ state->plugin_identity, + 0); +- if (map_wrlock() != 0) { +- slapi_log_error(SLAPI_LOG_PLUGIN, +- cbdata->state->plugin_desc->spd_id, ++ wrap_inc_call_level(); ++ set_cbdata.state = state; ++ set_cbdata.pb = pb; ++ ++ /* Do a search and collect found entries to avoid locking the backends */ ++ if (slapi_search_internal_pb(pb) == 0) { ++ if (map_wrlock() != 0) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, ++ state->plugin_desc->spd_id, + "failed to search under \"%s\" for " + "configuration: failed to acquire a lock\n", +- cbdata->state->plugin_base); +- goto done_with_lock; ++ state->plugin_base); ++ goto done_with_lock; ++ } ++ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result); ++ if (result == 0) { ++ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); ++ for (i = 0; entries[i] != NULL; i++) { ++ backend_set_config_entry_add_cb(entries[i], &set_cbdata); ++ } ++ } ++ map_unlock(); ++ slapi_free_search_results_internal(pb); + } +- set_cbdata.state = cbdata->state; +- set_cbdata.pb = pb; +- slapi_search_internal_callback_pb(pb, &set_cbdata, +- NULL, +- backend_set_config_entry_add_cb, +- NULL); +- map_unlock(); ++ slapi_log_error(SLAPI_LOG_FATAL, ++ state->plugin_desc->spd_id, ++ "Finished plugin initialization.\n"); ++ + done_with_lock: ++ wrap_dec_call_level(); + slapi_pblock_destroy(pb); + if (cbdata) { + slapi_ch_free((void**)&cbdata); +-- +2.5.0 + diff --git a/SOURCES/slapi-nis-extmem-0010-nis-lock-out-accounts-if-nsAccountLock-is-TRUE.patch b/SOURCES/slapi-nis-extmem-0010-nis-lock-out-accounts-if-nsAccountLock-is-TRUE.patch new file mode 100644 index 0000000..0c125c3 --- /dev/null +++ b/SOURCES/slapi-nis-extmem-0010-nis-lock-out-accounts-if-nsAccountLock-is-TRUE.patch @@ -0,0 +1,80 @@ +From 5eaad9c4c218d9a59f6930a29f5bee54235c4fab Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Tue, 19 Jan 2016 07:37:46 +0200 +Subject: [PATCH 10/12] nis: lock out accounts if nsAccountLock is TRUE + +Add a rule that adds two bang characters in front of the password. + +When the password algorithm is defined as CRYPT and NIS is used to +authenticate users on other systems, there is no way to disable or lock +accounts. Traditional convention has been to put two bang (exclamation) +characters in front of the password, creating an impossible password +hash. This effectively locks the user account, preventing +authentication. + +All UNIX systems agree that for encrypted passwords presence of a +character which cannot be part of CRYPT password scheme renders +impossible to login to system with such password. However, not all +systems have meaning of locked accounts and even how these locked +accounts express themselves. + +There is certain controversy in what could be used to indicate locked +accounts: + - GNU/Linux systems expect '!' as first character of the password field + - FreeBSD expects '*LOCKED*' string at start of the password field + - Various Solaris versions expect '*LOCK*' string at start of the + password field + - NetBSD has no meaning of locked passwords via content of password field + +Given that it is impossible to serve NIS maps with encrypted passwords +in a different way to different clients, standardize on '!!' scheme as +traditional among UNIX administrators. + +Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1298478 +--- + src/defs-nis.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/defs-nis.c b/src/defs-nis.c +index 3d2b9e9..ad0e7dc 100644 +--- a/src/defs-nis.c ++++ b/src/defs-nis.c +@@ -52,17 +52,17 @@ static struct configuration { + {"passwd.byname", config_exact, FALSE, NULL, + "(objectClass=posixAccount)", + "%{uid}", NULL, +- "%{uid}:%ifeq(\"objectClass\",\"shadowAccount\",\"x\",\"%regsubi(\\\"%{userPassword}\\\",\\\"^\\\\\\\\{CRYPT\\\\\\\\}(..*)\\\",\\\"%1\\\",\\\"*\\\")\"):%regmatch(\"%{uidNumber}\",\"[0-9]+\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-" _PATH_BSHELL "}", NULL, ++ "%{uid}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%ifeq(\"objectClass\",\"shadowAccount\",\"x\",\"%regsubi(\\\"%{userPassword}\\\",\\\"^\\\\\\\\{CRYPT\\\\\\\\}(..*)\\\",\\\"%1\\\",\\\"*\\\")\"):%regmatch(\"%{uidNumber}\",\"[0-9]+\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-" _PATH_BSHELL "}", NULL, + ":\r\n"}, + {"passwd.byuid", config_exact, FALSE, NULL, + "(objectClass=posixAccount)", + "%{uidNumber}", NULL, +- "%{uid}:%ifeq(\"objectClass\",\"shadowAccount\",\"x\",\"%regsubi(\\\"%{userPassword}\\\",\\\"^\\\\\\\\{CRYPT\\\\\\\\}(..*)\\\",\\\"%1\\\",\\\"*\\\")\"):%regmatch(\"%{uidNumber}\",\"[0-9]+\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-" _PATH_BSHELL "}", NULL, ++ "%{uid}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%ifeq(\"objectClass\",\"shadowAccount\",\"x\",\"%regsubi(\\\"%{userPassword}\\\",\\\"^\\\\\\\\{CRYPT\\\\\\\\}(..*)\\\",\\\"%1\\\",\\\"*\\\")\"):%regmatch(\"%{uidNumber}\",\"[0-9]+\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%{gecos:-%{cn:-}}:%{homeDirectory:-/}:%{loginShell:-" _PATH_BSHELL "}", NULL, + ":\r\n"}, + {"shadow.byname", config_exact, TRUE, NULL, + "(objectClass=shadowAccount)", + "%{uid}", NULL, +- "%{uid}:%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{shadowLastChange:-}:%{shadowMin:-}:%{shadowMax:-}:%{shadowWarning:-}:%{shadowInactive:-}:%{shadowExpire:-}:%{shadowFlag:-}", NULL, ++ "%{uid}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{shadowLastChange:-}:%{shadowMin:-}:%{shadowMax:-}:%{shadowWarning:-}:%{shadowInactive:-}:%{shadowExpire:-}:%{shadowFlag:-}", NULL, + ":\r\n"}, + {"passwd.adjunct.byname", config_exact, TRUE, NULL, + "(objectClass=shadowAccount)", +@@ -72,12 +72,12 @@ static struct configuration { + {"group.byname", config_exact, FALSE, NULL, + "(objectClass=posixGroup)", + "%{cn}", NULL, +- "%{cn}:%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%merge(\",\",\"%{memberUid}\",\"%deref_r(\\\"member\\\",\\\"uid\\\")\",\"%deref_r(\\\"uniqueMember\\\",\\\"uid\\\")\")", NULL, ++ "%{cn}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%regmatch(\"%{gidNumber}\",\"[0-9]+\"):%merge(\",\",\"%{memberUid}\",\"%deref_r(\\\"member\\\",\\\"uid\\\")\",\"%deref_r(\\\"uniqueMember\\\",\\\"uid\\\")\")", NULL, + ":,\r\n"}, + {"group.bygid", config_exact, FALSE, NULL, + "(objectClass=posixGroup)", + "%{gidNumber}", NULL, +- "%{cn}:%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{gidNumber}:%merge(\",\",\"%{memberUid}\",\"%deref_r(\\\"member\\\",\\\"uid\\\")\",\"%deref_r(\\\"uniqueMember\\\",\\\"uid\\\")\")", NULL, ++ "%{cn}:%ifeq(\"nsAccountLock\",\"TRUE\",\"!!\",\"\")%regsubi(\"%{userPassword}\",\"^\\\\{CRYPT\\\\}(..*)\",\"%1\",\"*\"):%{gidNumber}:%merge(\",\",\"%{memberUid}\",\"%deref_r(\\\"member\\\",\\\"uid\\\")\",\"%deref_r(\\\"uniqueMember\\\",\\\"uid\\\")\")", NULL, + ":,\r\n"}, + {"netgroup", config_exact, FALSE, NULL, + "(objectClass=nisNetgroup)", +-- +2.5.0 + diff --git a/SOURCES/slapi-nis-extmem-0011-idviews-bind-with-original-DN-if-ID-view-does-not-ov.patch b/SOURCES/slapi-nis-extmem-0011-idviews-bind-with-original-DN-if-ID-view-does-not-ov.patch new file mode 100644 index 0000000..302beba --- /dev/null +++ b/SOURCES/slapi-nis-extmem-0011-idviews-bind-with-original-DN-if-ID-view-does-not-ov.patch @@ -0,0 +1,117 @@ +From 00468e8eebd455ab4e41d4d86772fb5f8a745d0a Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Thu, 21 Jan 2016 19:16:30 +0200 +Subject: [PATCH 11/12] idviews: bind with original DN if ID view does not + override uid attribute + +With ID Views in FreeIPA one can override different kinds of attributes, +including the uid. When uid attribute is overriden, LDAP BINDs with +DNs using new (overridden) uid are properly modified to reference the +original (non-overridden) object. + +However, when uid attribute is not overridden, slapi-nis did mistakenly +avoided to build a reference to the original object without ID view. +This resulted in inability to do LDAP BIND as overriden DN with original +uid attribute. + +Fix the issue by always processing a DN after removing ID view reference +from it, whether RDN value (uid) was replaced or not. + +Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1301300 +--- + src/back-sch-idview.c | 4 ++-- + src/back-sch.c | 24 ++++++++++++------------ + 2 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/src/back-sch-idview.c b/src/back-sch-idview.c +index 8ffab91..8842906 100644 +--- a/src/back-sch-idview.c ++++ b/src/back-sch-idview.c +@@ -311,7 +311,7 @@ idview_replace_bval_by_override(const char *bval_usage, const char *attr_name, + } + + attr_val = slapi_value_new_berval(bval); +- slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id, ++ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, + "Searching for an override of the %s %s with %s=%*s from the overrides\n.", + bval_usage, attr_name, attr_name, (int) bval->bv_len, bval->bv_val); + +@@ -347,7 +347,7 @@ idview_replace_bval_by_override(const char *bval_usage, const char *attr_name, + slapi_ber_bvdone(bval); + slapi_ber_bvcpy(bval, slapi_value_get_berval(anchor_val)); + anchor_override_found = TRUE; +- slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id, ++ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, + "Overriding the %s %s with %s=%*s from the override %s\n.", + bval_usage, attr_name, IPA_IDVIEWS_ATTR_ANCHORUUID, + (int) bval->bv_len, bval->bv_val, +diff --git a/src/back-sch.c b/src/back-sch.c +index 871734c..9a0e96b 100644 +--- a/src/back-sch.c ++++ b/src/back-sch.c +@@ -465,13 +465,13 @@ backend_set_process_external_members(Slapi_PBlock *pb, + * but as dirsrv was restarted, SSSD might still consider its domain offline. */ + is_group_exists = backend_retrieve_from_nsswitch(&staged, &cbdata); + if (!is_group_exists) { +- slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, +- "group \"%s\" does not exist because SSSD is offline.", ++ slapi_log_error(SLAPI_LOG_FATAL, plugin_id, ++ "group \"%s\" does not exist because SSSD is offline.\n", + staged.name); + if (state->ready_to_serve == 0) { + /* Only wait for SSSD when we populate the original set */ +- slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id, +- "waiting for SSSD to become online..."); ++ slapi_log_error(SLAPI_LOG_FATAL, plugin_id, ++ "waiting for SSSD to become online...\n"); + DS_Sleep(PR_SecondsToInterval(35)); + } else { + break; +@@ -1609,15 +1609,15 @@ backend_search_cb(Slapi_PBlock *pb) + { + struct backend_search_cbdata cbdata; + struct backend_staged_search *staged, *next; +- int i, isroot; ++ int i, isroot, ret; + + if (wrap_get_call_level() > 0) { + return 0; + } + memset(&cbdata, 0, sizeof(cbdata)); + cbdata.pb = pb; +- slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); +- if (cbdata.state->plugin_base == NULL) { ++ ret = slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); ++ if ((ret == -1) || (cbdata.state->plugin_base == NULL)) { + /* The plugin was not actually started. */ + return 0; + } +@@ -1626,9 +1626,9 @@ backend_search_cb(Slapi_PBlock *pb) + return 0; + } + +- slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot); ++ ret = slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot); + +- if (slapi_op_internal(pb) || (slapi_is_ldapi_conn(pb) && isroot)) { ++ if ((ret == -1) || (slapi_op_internal(pb) || (slapi_is_ldapi_conn(pb) && isroot))) { + /* The plugin should not engage in internal searches of other + * plugins or ldapi+cn=DM */ + return 0; +@@ -1959,10 +1959,10 @@ backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char ** + if (res == 1) { + slapi_rdn_remove_index(rdn, 1); + slapi_rdn_add(rdn, "uid", bval.bv_val); +- slapi_sdn_free(&cbdata.target_dn); +- cbdata.target_dn = slapi_sdn_set_rdn(scbdata.target_dn, rdn); +- map_data_foreach_map(cbdata.state, NULL, backend_locate_cb, &cbdata); + } ++ slapi_sdn_free(&cbdata.target_dn); ++ cbdata.target_dn = slapi_sdn_set_rdn(scbdata.target_dn, rdn); ++ map_data_foreach_map(cbdata.state, NULL, backend_locate_cb, &cbdata); + slapi_ber_bvdone(&bval); + slapi_rdn_free(&rdn); + idview_free_overrides(&scbdata); +-- +2.5.0 + diff --git a/SOURCES/slapi-nis-priming-0001-wrap-add-wrapped-mutex-support.patch b/SOURCES/slapi-nis-priming-0001-wrap-add-wrapped-mutex-support.patch new file mode 100644 index 0000000..2b5f6fc --- /dev/null +++ b/SOURCES/slapi-nis-priming-0001-wrap-add-wrapped-mutex-support.patch @@ -0,0 +1,145 @@ +From 43ea9a5c6cf7f2022f1e586bb4514564fd7826cb Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Tue, 26 Apr 2016 12:44:56 +0300 +Subject: [PATCH 1/4] wrap: add wrapped mutex support + +--- + src/wrap.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/wrap.h | 6 +++++ + 2 files changed, 96 insertions(+) + +diff --git a/src/wrap.c b/src/wrap.c +index c89638f..f8056a4 100644 +--- a/src/wrap.c ++++ b/src/wrap.c +@@ -79,6 +79,18 @@ struct wrapped_rwlock { + #endif + }; + ++struct wrapped_mutex { ++#if defined(USE_SLAPI_LOCKS) ++ Slapi_Mutex *mutex; ++#elif defined(USE_PTHREAD_LOCKS) ++ pthread_mutex_t mutex; ++#elif defined(USE_NSPR_LOCKS) ++ PRLock *mutex; ++#else ++#error "Unknown thread-safe locking model!" ++#endif ++}; ++ + #ifdef USE_NSPR_THREADS + static void + wrap_pthread_starter(void *p) +@@ -169,6 +181,84 @@ wrap_thread_stopfd(struct wrapped_thread *t) + return ret; + } + ++struct wrapped_mutex * ++wrap_new_mutex(void) ++{ ++ struct wrapped_mutex *mutex; ++ mutex = malloc(sizeof(*mutex)); ++ if (mutex == NULL) { ++ return NULL; ++ } ++#ifdef USE_SLAPI_LOCKS ++ mutex->mutex = slapi_new_mutex(); ++ if (mutex->mutex == NULL) { ++ free(mutex); ++ return NULL; ++ } ++#endif ++#ifdef USE_PTHREAD_LOCKS ++ if (pthread_mutex_init(&mutex->mutex, NULL) != 0) { ++ free(mutex); ++ return NULL; ++ } ++#endif ++#ifdef USE_NSPR_LOCKS ++ mutex->mutex = PR_NewLock(); ++ if (mutex->mutex == NULL) { ++ free(mutex); ++ return NULL; ++ } ++#endif ++ return mutex; ++} ++ ++void ++wrap_free_mutex(struct wrapped_mutex *mutex) ++{ ++#ifdef USE_SLAPI_LOCKS ++ slapi_destroy_mutex(mutex->mutex); ++#endif ++#ifdef USE_PTHREAD_LOCKS ++ pthread_mutex_destroy(&mutex->mutex); ++#endif ++#ifdef USE_NSPR_LOCKS ++ PR_DestroyLock(mutex->mutex); ++#endif ++ free(mutex); ++} ++ ++int ++wrap_mutex_lock(struct wrapped_mutex *mutex) ++{ ++#ifdef USE_SLAPI_LOCKS ++ slapi_lock_mutex(mutex->mutex); ++ return 0; ++#endif ++#ifdef USE_PTHREAD_LOCKS ++ return pthread_mutex_lock(&mutex->mutex); ++#endif ++#ifdef USE_NSPR_LOCKS ++ PR_Lock(mutex->mutex); ++ return 0; ++#endif ++} ++ ++int ++wrap_mutex_unlock(struct wrapped_mutex *mutex) ++{ ++#ifdef USE_SLAPI_LOCKS ++ return slapi_unlock_mutex(mutex->mutex); ++#endif ++#ifdef USE_PTHREAD_LOCKS ++ return pthread_mutex_unlock(&mutex->mutex); ++#endif ++#ifdef USE_NSPR_LOCKS ++ PR_Unlock(mutex->mutex); ++ return 0; ++#endif ++} ++ ++ + struct wrapped_rwlock * + wrap_new_rwlock(void) + { +diff --git a/src/wrap.h b/src/wrap.h +index 71bd326..2b797f7 100644 +--- a/src/wrap.h ++++ b/src/wrap.h +@@ -23,6 +23,7 @@ + #define wrap_h + + struct wrapped_thread; ++struct wrapped_mutex; + struct wrapped_rwlock; + + struct wrapped_thread * wrap_start_thread(void * (*fn)(struct wrapped_thread *), +@@ -31,6 +32,11 @@ void *wrap_stop_thread(struct wrapped_thread *t); + void *wrap_thread_arg(struct wrapped_thread *t); + int wrap_thread_stopfd(struct wrapped_thread *t); + ++struct wrapped_mutex *wrap_new_mutex(void); ++void wrap_free_mutex(struct wrapped_mutex *mutex); ++int wrap_mutex_lock(struct wrapped_mutex *mutex); ++int wrap_mutex_unlock(struct wrapped_mutex *mutex); ++ + struct wrapped_rwlock *wrap_new_rwlock(void); + void wrap_free_rwlock(struct wrapped_rwlock *rwlock); + int wrap_rwlock_rdlock(struct wrapped_rwlock *rwlock); +-- +2.7.4 + diff --git a/SOURCES/slapi-nis-priming-0002-backend-support-backend-shutdown-for-priming-thread-.patch b/SOURCES/slapi-nis-priming-0002-backend-support-backend-shutdown-for-priming-thread-.patch new file mode 100644 index 0000000..22550e0 --- /dev/null +++ b/SOURCES/slapi-nis-priming-0002-backend-support-backend-shutdown-for-priming-thread-.patch @@ -0,0 +1,268 @@ +From c5e89132f2ee017aa026f7b8009a2976b627fa3a Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Tue, 26 Apr 2016 13:00:44 +0300 +Subject: [PATCH 2/4] backend: support backend shutdown for priming thread + cancellation + +Launching a separate thread to populate map cache has a side effect that +the thread could be scheduled to execute over a shutdown time. If LDAP server +received the request to shutdown, we need to stop processing the +original source and shut the priming thread. + +Resolves: rhbz#1327197 +--- + src/back-shr.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++---------- + src/back-shr.h | 1 + + src/backend.h | 1 + + src/plugin.h | 3 ++ + 4 files changed, 92 insertions(+), 17 deletions(-) + +diff --git a/src/back-shr.c b/src/back-shr.c +index 0157582..7842e05 100644 +--- a/src/back-shr.c ++++ b/src/back-shr.c +@@ -665,25 +665,34 @@ backend_shr_get_vattr_sdnlist(struct plugin_state *state, + } + + struct backend_shr_data_init_cbdata { +- Slapi_PBlock *parent_pb; + struct plugin_state *state; + const char *filter; + }; + + #define PLUGIN_SCAN_DELAY 5 + +-static void +-backend_shr_data_initialize_thread_cb(void *arg) ++static void * ++backend_shr_data_initialize_thread_cb(struct wrapped_thread *t) + { +- struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg; ++ struct backend_shr_data_init_cbdata *cbdata = wrap_thread_arg(t); + Slapi_PBlock *pb = NULL; + struct backend_set_config_entry_add_cbdata set_cbdata; + int result = 0, i = 0; + Slapi_Entry **entries = NULL; + struct plugin_state *state = NULL; + ++ /* We have to be cautious here as the thread can be executed after ++ * the plugin received a shutdown request, thus a number of checks here. */ ++ if (slapi_is_shutting_down()) { ++ return NULL; ++ } ++ + if (cbdata == NULL) { +- return; ++ return NULL; ++ } ++ ++ if ((cbdata->state == NULL) || (cbdata->state->plugin_base == NULL)) { ++ return NULL; + } + + state = cbdata->state; +@@ -694,13 +703,23 @@ backend_shr_data_initialize_thread_cb(void *arg) + * so we just wait some time. */ + DS_Sleep(PR_SecondsToInterval(PLUGIN_SCAN_DELAY)); + +- backend_update_params(cbdata->parent_pb, state); ++ if (slapi_is_shutting_down()) { ++ return NULL; ++ } ++ ++ if (state->plugin_base == NULL) { ++ return NULL; ++ } ++ ++ pb = wrap_pblock_new(NULL); ++ backend_update_params(pb, state); ++ slapi_pblock_destroy(pb); + + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "searching under \"%s\" for configuration\n", + state->plugin_base); +- pb = wrap_pblock_new(cbdata->parent_pb); ++ pb = wrap_pblock_new(NULL); + slapi_search_internal_set_pb(pb, + state->plugin_base, + LDAP_SCOPE_ONELEVEL, +@@ -717,10 +736,10 @@ backend_shr_data_initialize_thread_cb(void *arg) + /* Do a search and collect found entries to avoid locking the backends */ + if (slapi_search_internal_pb(pb) == 0) { + if (map_wrlock() != 0) { +- slapi_log_error(SLAPI_LOG_PLUGIN, ++ slapi_log_error(SLAPI_LOG_FATAL, + state->plugin_desc->spd_id, + "failed to search under \"%s\" for " +- "configuration: failed to acquire a lock\n", ++ "configuration: failed to acquire a write lock to a map\n", + state->plugin_base); + goto done_with_lock; + } +@@ -728,6 +747,11 @@ backend_shr_data_initialize_thread_cb(void *arg) + if (result == 0) { + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); + for (i = 0; entries[i] != NULL; i++) { ++ /* We may be scheduled to run over shutdown time, exit early */ ++ if (slapi_is_shutting_down()) { ++ map_unlock(); ++ goto done_with_lock; ++ } + backend_set_config_entry_add_cb(entries[i], &set_cbdata); + } + } +@@ -746,6 +770,7 @@ done_with_lock: + } + + PR_AtomicSet(&state->ready_to_serve, 1); ++ return NULL; + } + + static void +@@ -754,11 +779,28 @@ backend_shr_data_initialize_thread(time_t when, void *arg) + struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg; + PRThread *thread = NULL; + +- /* start data import as a separate thread */ +- thread = PR_CreateThread(PR_USER_THREAD, backend_shr_data_initialize_thread_cb, +- (void *)arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, +- PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE); +- if (thread == NULL) { ++ if (slapi_is_shutting_down()) { ++ return; ++ } ++ ++ if (cbdata->state->priming_mutex == NULL) { ++ /* This mutex is allocated at plugin startup ++ * Without this mutex we can not enforce that shutdown wait for priming completion ++ * This is better to skip the priming ++ */ ++ slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id, "priming_mutex not initialized. Priming fails\n"); ++ return; ++ } ++ wrap_mutex_lock(cbdata->state->priming_mutex); ++ ++ if (!cbdata->state->start_priming_thread) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id, ++ "Likely a shutdown occurred before we started \n"); ++ goto done; ++ } ++ ++ cbdata->state->priming_tid = wrap_start_thread(&backend_shr_data_initialize_thread_cb, arg); ++ if (cbdata->state->priming_tid == NULL) { + slapi_log_error(SLAPI_LOG_FATAL, + cbdata->state->plugin_desc->spd_id, + "unable to create compatibility tree scan thread!\n"); +@@ -769,6 +811,8 @@ backend_shr_data_initialize_thread(time_t when, void *arg) + cbdata->state->plugin_desc->spd_id, PLUGIN_SCAN_DELAY); + } + ++done: ++ wrap_mutex_unlock(cbdata->state->priming_mutex); + } + + /* Scan for the list of configured groups and sets. */ +@@ -779,6 +823,14 @@ backend_shr_startup(struct plugin_state *state, + { + struct backend_shr_data_init_cbdata *cbdata = NULL; + ++ if (slapi_is_shutting_down()) { ++ slapi_log_error(SLAPI_LOG_FATAL, ++ state->plugin_desc->spd_id, ++ "task for populating compatibility tree will " ++ "not be created due to upcoming server shutdown\n"); ++ return; ++ } ++ + cbdata = (struct backend_shr_data_init_cbdata *) + slapi_ch_malloc(sizeof(struct backend_shr_data_init_cbdata)); + +@@ -792,10 +844,10 @@ backend_shr_startup(struct plugin_state *state, + + PR_AtomicSet(&state->ready_to_serve, 0); + cbdata->state = state; +- cbdata->parent_pb = parent_pb; + cbdata->filter = filter; + +- /* Schedule running a callback that will create a thread */ ++ /* Schedule running a callback that will create a thread ++ * but make sure it is called a first thing when event loop is created */ + slapi_eq_once(backend_shr_data_initialize_thread, + cbdata, PR_SecondsToInterval(PLUGIN_SCAN_DELAY)); + +@@ -808,6 +860,24 @@ backend_shr_startup(struct plugin_state *state, + + } + ++void ++backend_shr_shutdown(struct plugin_state *state) ++{ ++ /* Make sure the priming thread is stopped or will not start ++ * Note: priming_mutex will not be freed because the priming thread ++ * may access it independently of the server/plugin shutdown ++ */ ++ wrap_mutex_lock(state->priming_mutex); ++ state->start_priming_thread = 0; /* prevent spawing of priming thread */ ++ if (state->priming_tid == NULL) { ++ /* priming thread has not yet started or failed to start */ ++ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, ++ "At shutdown, priming thread not yet started or failed to start\n"); ++ } else { ++ wrap_stop_thread(state->priming_tid); ++ } ++ wrap_mutex_unlock(state->priming_mutex); ++} + /* Process a set configuration directory entry. Pull out the group and set + * names which are specified in the entry and delete each in turn. */ + int +@@ -2336,7 +2406,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb) + backend_set_config_entry_add_cb(cbdata.e_post, &set_cbdata); + } + /* Lastly, if the entry is our own entry, re-read parameters. */ +- sdn = slapi_sdn_new_dn_byref(cbdata.state->plugin_base); ++ sdn = slapi_sdn_new_dn_byval(cbdata.state->plugin_base); + if (sdn != NULL) { + if ((strcmp(slapi_entry_get_ndn(cbdata.e_pre), + slapi_sdn_get_ndn(sdn)) == 0) || +diff --git a/src/back-shr.h b/src/back-shr.h +index 44c25fe..2caea5d 100644 +--- a/src/back-shr.h ++++ b/src/back-shr.h +@@ -39,6 +39,7 @@ void backend_shr_free_sdnlist(const Slapi_DN **sdnlist); + + void backend_shr_startup(struct plugin_state *state, + Slapi_PBlock *pb, const char *set_filter); ++void backend_shr_shutdown(struct plugin_state *state); + int backend_shr_betxn_postop_init(Slapi_PBlock *pb, + struct plugin_state *state); + int backend_shr_postop_init(Slapi_PBlock *pb, struct plugin_state *state); +diff --git a/src/backend.h b/src/backend.h +index 7974aae..4608d2d 100644 +--- a/src/backend.h ++++ b/src/backend.h +@@ -58,6 +58,7 @@ struct backend_shr_set_data { + + /* Startup/initialization functions called through the map. */ + void backend_startup(struct slapi_pblock *pb, struct plugin_state *state); ++void backend_shutdown(struct plugin_state *state); + int backend_init_preop(struct slapi_pblock *pb, struct plugin_state *state); + int backend_init_betxn_preop(struct slapi_pblock *pb, + struct plugin_state *state); +diff --git a/src/plugin.h b/src/plugin.h +index 7a89ac7..56d672f 100644 +--- a/src/plugin.h ++++ b/src/plugin.h +@@ -34,6 +34,9 @@ struct plugin_state { + Slapi_PluginDesc *plugin_desc; + unsigned int use_be_txns: 1; + PRInt32 ready_to_serve; ++ struct wrapped_mutex *priming_mutex; ++ unsigned int start_priming_thread: 1; /* flag to allow spawning of the priming thread */ ++ struct wrapped_thread *priming_tid; /* priming thread pid. use to join */ + + /* NIS-specific data. */ + struct wrapped_thread *tid; +-- +2.7.4 + diff --git a/SOURCES/slapi-nis-priming-0003-nis-add-backend-shutdown-support-to-stop-priming-thr.patch b/SOURCES/slapi-nis-priming-0003-nis-add-backend-shutdown-support-to-stop-priming-thr.patch new file mode 100644 index 0000000..f3122b8 --- /dev/null +++ b/SOURCES/slapi-nis-priming-0003-nis-add-backend-shutdown-support-to-stop-priming-thr.patch @@ -0,0 +1,92 @@ +From 63212ccae673e46334b874688741bf96d996fd36 Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Tue, 26 Apr 2016 13:17:03 +0300 +Subject: [PATCH 3/4] nis: add backend shutdown support to stop priming thread + +Resolves: rhbz#1327197 +--- + src/back-nis.c | 6 ++++++ + src/plug-nis.c | 34 +++++++++++++++++++++++++++------- + 2 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/src/back-nis.c b/src/back-nis.c +index b9379c0..7fb191d 100644 +--- a/src/back-nis.c ++++ b/src/back-nis.c +@@ -1021,6 +1021,12 @@ backend_startup(Slapi_PBlock *pb, struct plugin_state *state) + backend_shr_startup(state, pb, NIS_MAP_CONFIGURATION_FILTER); + } + ++void ++backend_shutdown(struct plugin_state *state) ++{ ++ backend_shr_shutdown(state); ++} ++ + /* Set up our post-op callbacks. */ + #ifdef SLAPI_NIS_SUPPORT_BE_TXNS + int +diff --git a/src/plug-nis.c b/src/plug-nis.c +index a1bdf89..ee90c37 100644 +--- a/src/plug-nis.c ++++ b/src/plug-nis.c +@@ -81,14 +81,31 @@ plugin_startup(Slapi_PBlock *pb) + struct plugin_state *state; + const char *pname; + int i, protocol; ++ Slapi_DN *pluginsdn = NULL; ++ + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); +- slapi_pblock_get(pb, SLAPI_TARGET_DN, &state->plugin_base); +- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, +- "configuration entry is %s%s%s\n", +- state->plugin_base ? "\"" : "", +- state->plugin_base ? state->plugin_base : "NULL", +- state->plugin_base ? "\"" : ""); ++ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &pluginsdn); ++ /* plugin base need to be duplicated because it will be destroyed ++ * when pblock is destroyed but we need to use it in a separate thread */ ++ if (NULL == pluginsdn || 0 == slapi_sdn_get_ndn_len(pluginsdn)) { ++ slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id, ++ "nis plugin_startup: unable to retrieve plugin DN\n"); ++ return -1; ++ ++ } else { ++ state->plugin_base = slapi_ch_strdup(slapi_sdn_get_dn(pluginsdn)); ++ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, ++ "configuration entry is %s%s%s\n", ++ state->plugin_base ? "\"" : "", ++ state->plugin_base ? state->plugin_base : "NULL", ++ state->plugin_base ? "\"" : ""); ++ } ++ + /* Populate the maps and data. */ ++ if (state->priming_mutex == NULL) { ++ state->priming_mutex = wrap_new_mutex(); ++ state->start_priming_thread = 1; ++ } + backend_startup(pb, state); + /* Start a new listening thread to handle incoming traffic. */ + state->tid = wrap_start_thread(&dispatch_thread, state); +@@ -177,6 +194,7 @@ plugin_shutdown(Slapi_PBlock *pb) + struct plugin_state *state; + int i, protocol; + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); ++ backend_shutdown(state); + for (i = 0; i < state->n_listeners; i++) { + if (state->pmap_client_socket != -1) { + switch (state->listener[i].type) { +@@ -217,7 +235,9 @@ plugin_shutdown(Slapi_PBlock *pb) + #ifdef HAVE_TCPD_H + free(state->request_info); + #endif +- state->plugin_base = NULL; ++ if (state->plugin_base != NULL) { ++ slapi_ch_free((void **)&state->plugin_base); ++ } + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "plugin shutdown completed\n"); + return 0; +-- +2.7.4 + diff --git a/SOURCES/slapi-nis-priming-0004-schema-compat-add-backend-shutdown-support-for-primi.patch b/SOURCES/slapi-nis-priming-0004-schema-compat-add-backend-shutdown-support-for-primi.patch new file mode 100644 index 0000000..7772689 --- /dev/null +++ b/SOURCES/slapi-nis-priming-0004-schema-compat-add-backend-shutdown-support-for-primi.patch @@ -0,0 +1,99 @@ +From 02e32192779994cab254c548291c24d89429b335 Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Tue, 26 Apr 2016 13:17:46 +0300 +Subject: [PATCH 4/4] schema-compat: add backend shutdown support for priming + thread + +Resolves: rhbz#1327197 +--- + src/back-sch.c | 6 ++++++ + src/plug-sch.c | 34 +++++++++++++++++++++++++++------- + 2 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/src/back-sch.c b/src/back-sch.c +index 9a0e96b..32b1d9e 100644 +--- a/src/back-sch.c ++++ b/src/back-sch.c +@@ -2280,6 +2280,12 @@ backend_startup(Slapi_PBlock *pb, struct plugin_state *state) + backend_shr_startup(state, pb, SCH_CONTAINER_CONFIGURATION_FILTER); + } + ++void ++backend_shutdown(struct plugin_state *state) ++{ ++ backend_shr_shutdown(state); ++} ++ + int + backend_init_preop(Slapi_PBlock *pb, struct plugin_state *state) + { +diff --git a/src/plug-sch.c b/src/plug-sch.c +index 95a4fd8..7af8480 100644 +--- a/src/plug-sch.c ++++ b/src/plug-sch.c +@@ -102,13 +102,26 @@ plugin_startup(Slapi_PBlock *pb) + /* Populate the maps and data. */ + struct plugin_state *state; + Slapi_Entry *plugin_entry = NULL; ++ Slapi_DN *pluginsdn = NULL; ++ + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); +- slapi_pblock_get(pb, SLAPI_TARGET_DN, &state->plugin_base); +- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, +- "configuration entry is %s%s%s\n", +- state->plugin_base ? "\"" : "", +- state->plugin_base ? state->plugin_base : "NULL", +- state->plugin_base ? "\"" : ""); ++ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &pluginsdn); ++ /* plugin base need to be duplicated because it will be destroyed ++ * when pblock is destroyed but we need to use it in a separate thread */ ++ if (NULL == pluginsdn || 0 == slapi_sdn_get_ndn_len(pluginsdn)) { ++ slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id, ++ "scheman compat plugin_startup: unable to retrieve plugin DN\n"); ++ return -1; ++ ++ } else { ++ state->plugin_base = slapi_ch_strdup(slapi_sdn_get_dn(pluginsdn)); ++ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, ++ "configuration entry is %s%s%s\n", ++ state->plugin_base ? "\"" : "", ++ state->plugin_base ? state->plugin_base : "NULL", ++ state->plugin_base ? "\"" : ""); ++ } ++ + state->pam_lock = wrap_new_rwlock(); + backend_nss_init_context((struct nss_ops_ctx**) &state->nss_context); + if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) && +@@ -122,6 +135,10 @@ plugin_startup(Slapi_PBlock *pb) + state->cached_entries = PL_NewHashTable(0, PL_HashString, PL_CompareStrings, PL_CompareValues, 0, 0); + wrap_rwlock_unlock(state->cached_entries_lock); + /* Populate the tree of fake entries. */ ++ if (state->priming_mutex == NULL) { ++ state->priming_mutex = wrap_new_mutex(); ++ state->start_priming_thread = 1; ++ } + backend_startup(pb, state); + /* Note that the plugin is ready to go. */ + slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id, +@@ -147,6 +164,7 @@ plugin_shutdown(Slapi_PBlock *pb) + { + struct plugin_state *state; + slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state); ++ backend_shutdown(state); + map_done(state); + wrap_free_rwlock(state->pam_lock); + state->pam_lock = NULL; +@@ -160,7 +178,9 @@ plugin_shutdown(Slapi_PBlock *pb) + wrap_free_rwlock(state->cached_entries_lock); + state->cached_entries_lock = NULL; + } +- state->plugin_base = NULL; ++ if (state->plugin_base != NULL) { ++ slapi_ch_free((void **)&state->plugin_base); ++ } + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "plugin shutdown completed\n"); + return 0; +-- +2.7.4 + diff --git a/SPECS/slapi-nis.spec b/SPECS/slapi-nis.spec index 140a4f5..ca37210 100644 --- a/SPECS/slapi-nis.spec +++ b/SPECS/slapi-nis.spec @@ -11,7 +11,7 @@ Name: slapi-nis Version: 0.54 -Release: 6%{?dist} +Release: 9%{?dist} Summary: NIS Server and Schema Compatibility plugins for Directory Server Group: System Environment/Daemons License: GPLv2 @@ -27,6 +27,17 @@ Patch5: slapi-nis-nss-Make-sure-default-buffer-for-nsswitch-operations-i Patch6: slapi-nis-don-t-search-in-SSSD-when-memberUid-has-no.patch Patch7: slapi-nis-delay-sending-responses-from-compat-tree-a.patch Patch8: slapi-nis-fix-processing-of-ID-views.patch +Patch15: slapi-nis-extmem-0005-slapi-nis-populate-data-trees-asynchronously-after-L.patch +Patch16: slapi-nis-extmem-0006-nss-force-lower-case-for-memberUid-attribute-as-per-.patch +Patch17: slapi-nis-extmem-0007-slapi-nis-add-support-to-resolve-external-members-of.patch +Patch18: slapi-nis-extmem-0008-slapi-nis-process-requests-only-when-initialization-.patch +Patch19: slapi-nis-extmem-0009-slapi-nis-serialize-map-cache-initialization.patch +Patch20: slapi-nis-extmem-0010-nis-lock-out-accounts-if-nsAccountLock-is-TRUE.patch +Patch21: slapi-nis-extmem-0011-idviews-bind-with-original-DN-if-ID-view-does-not-ov.patch +Patch22: slapi-nis-priming-0001-wrap-add-wrapped-mutex-support.patch +Patch23: slapi-nis-priming-0002-backend-support-backend-shutdown-for-priming-thread-.patch +Patch24: slapi-nis-priming-0003-nis-add-backend-shutdown-support-to-stop-priming-thr.patch +Patch25: slapi-nis-priming-0004-schema-compat-add-backend-shutdown-support-for-primi.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: 389-ds-base-devel, %{ldap_impl}-devel @@ -74,6 +85,22 @@ for attributes from multiple entries in the tree. %patch6 -p1 %patch7 -p1 %patch8 -p1 +# patchset for "External membership of IPA groups" +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +# "Lock out NIS entries with nsAccountLock set to TRUE" +%patch20 -p1 +# "Support bind with non-overridden uid rdn" +%patch21 -p1 +# "Wait for priming thread join on shutdown" +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 + %build %configure --disable-static --with-tcp-wrappers --with-ldap=%{ldap_impl} \ --with-nsswitch --with-pam --with-pam-service=system-auth \ @@ -103,6 +130,18 @@ rm -rf $RPM_BUILD_ROOT %{_sbindir}/nisserver-plugin-defs %changelog +* Tue Apr 26 2016 Alexander Bokovoy - 0.54-9 +- Reworked priming thread shutdown support +- Resolves: #1327197 + +* Fri Apr 15 2016 Alexander Bokovoy - 0.54-8 +- Wait for priming thread to finish before shutdown +- Resolves: #1327197 + +* Tue Feb 23 2016 Alexander Bokovoy - 0.54-7 +- Resolves: #1311257 +- Resolves: #1311012 + * Fri Nov 13 2015 Alexander Bokovoy - 0.54-6 - delay sending responses from compat tree after map cache search - Resolves: #1281748 @@ -115,6 +154,7 @@ rm -rf $RPM_BUILD_ROOT * Wed Jul 15 2015 Alexander Bokovoy - 0.54-4 - Fix CVE-2015-0283 for RHEL 7.2 + - Resolves: #1202996 * Wed Mar 18 2015 Alexander Bokovoy - 0.54-3