From df97525f4de20dfcde41fe8cbfbce75a697dae26 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 05 2015 16:28:17 +0000 Subject: import 389-ds-base-1.3.3.1-20.el7_1 --- diff --git a/SOURCES/0063-Ticket-48190-idm-ipa-389-ds-base-entry-cache-converg.patch b/SOURCES/0063-Ticket-48190-idm-ipa-389-ds-base-entry-cache-converg.patch new file mode 100644 index 0000000..e98f7e6 --- /dev/null +++ b/SOURCES/0063-Ticket-48190-idm-ipa-389-ds-base-entry-cache-converg.patch @@ -0,0 +1,80 @@ +From 82d69a381183cf5125ba8d4afdfd12c65544e348 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Sun, 31 May 2015 17:08:29 -0700 +Subject: [PATCH 63/72] Ticket #48190 - idm/ipa 389-ds-base entry cache + converges to 500 KB in dblayer_is_cachesize_sane + +Description: This issue was introduced by the fix for Ticket 47499 +commit 1e035d1111f6abcb87e760a2b9e41fa9e05a7ebd. + +The function dblayer_is_cachesize_sane was originally implemented for +db cache to check if the given db cache size is larger than the available +memory or not. The function resets the size to the available memory size +if it is larger. Also, considering the extra metadata size needed for the +db cache, it multiplies by 0.8 every time it starts the server. It is not +needed even for the db cache. The code is old and we don't have to save +the memory there. Thus, this patch removes the resetting code. + +https://fedorahosted.org/389/ticket/48190 + +Reviewed by mreynolds@redhat.com (Thank you, Mark!!) + +(cherry picked from commit bf9ef718cfd48c26eaf11662f522451d866e7681) +--- + ldap/servers/slapd/back-ldbm/dblayer.c | 7 ------- + ldap/servers/slapd/back-ldbm/ldbm_instance_config.c | 6 ++++-- + 2 files changed, 4 insertions(+), 9 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c +index 2524355..d3deff8 100644 +--- a/ldap/servers/slapd/back-ldbm/dblayer.c ++++ b/ldap/servers/slapd/back-ldbm/dblayer.c +@@ -1116,13 +1116,6 @@ int dblayer_is_cachesize_sane(size_t *cachesize) + if (!issane) { + *cachesize = (size_t)((pages - procpages) * pagesize); + } +- /* We now compensate for DB's own compensation for metadata size +- * They increase the actual cache size by 25%, but only for sizes +- * less than 500Meg. +- */ +- if (*cachesize < 500*MEGABYTE) { +- *cachesize = (size_t)((double)*cachesize * (double)0.8); +- } + + return issane; + } +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c +index 9b93f9a..f75ca97 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c +@@ -121,11 +121,12 @@ ldbm_instance_config_cachememsize_set(void *arg, void *value, char *errorbuf, in + ldbm_instance *inst = (ldbm_instance *) arg; + int retval = LDAP_SUCCESS; + size_t val = (size_t) value; ++ size_t chkval = val; + + /* Do whatever we can to make sure the data is ok. */ + + if (apply) { +- if (!dblayer_is_cachesize_sane(&val)){ ++ if (!dblayer_is_cachesize_sane(&chkval)){ + PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, + "Error: cachememsize value is too large."); + LDAPDebug( LDAP_DEBUG_ANY,"Error: cachememsize value is too large.\n", +@@ -152,11 +153,12 @@ ldbm_instance_config_dncachememsize_set(void *arg, void *value, char *errorbuf, + ldbm_instance *inst = (ldbm_instance *) arg; + int retval = LDAP_SUCCESS; + size_t val = (size_t)value; ++ size_t chkval = val; + + /* Do whatever we can to make sure the data is ok. */ + + if (apply) { +- if (!dblayer_is_cachesize_sane(&val)){ ++ if (!dblayer_is_cachesize_sane(&chkval)){ + PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, + "Error: dncachememsize value is too large."); + LDAPDebug( LDAP_DEBUG_ANY,"Error: dncachememsize value is too large.\n", +-- +1.9.3 + diff --git a/SOURCES/0064-Ticket-48146-async-simple-paged-results-issue.patch b/SOURCES/0064-Ticket-48146-async-simple-paged-results-issue.patch new file mode 100644 index 0000000..6027eef --- /dev/null +++ b/SOURCES/0064-Ticket-48146-async-simple-paged-results-issue.patch @@ -0,0 +1,159 @@ +From 577fa6ada5d860e5ed7291aff2e41938ca92793b Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Sun, 26 Apr 2015 14:46:44 -0700 +Subject: [PATCH 64/72] Ticket #48146 - async simple paged results issue + +Description: When the last page of the single paged results is returned, +the search results structure is freed in the simple paged results code +(in op_shared_search). The search results structure is stashed in the +simple paged results object across the pages. The free and the clean up +of the stashed address should have been atomic, but it was not. + +https://fedorahosted.org/389/ticket/48146 + +Reviewed by mreynolds@redhat.com (Thank you, Mark!!) + +(cherry picked from commit 947477f2e2367337a8c220d8c9d03a62bf1bbf1c) +(cherry picked from commit ec8801a69adbe2f502513fabcbb79bc5e38bf197) +--- + ldap/servers/slapd/opshared.c | 18 +++++++----------- + ldap/servers/slapd/pagedresults.c | 36 +++++++++++------------------------- + 2 files changed, 18 insertions(+), 36 deletions(-) + +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index ebd4fdf..e7cee8a 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -881,7 +881,10 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr); + if (PAGEDRESULTS_SEARCH_END == pr_stat) { + if (sr) { /* in case a left over sr is found, clean it up */ ++ PR_Lock(pb->pb_conn->c_mutex); ++ pagedresults_set_search_result(pb->pb_conn, operation, NULL, 1, pr_idx); + be->be_search_results_release(&sr); ++ PR_Unlock(pb->pb_conn->c_mutex); + } + if (NULL == next_be) { + /* no more entries && no more backends */ +@@ -897,17 +900,10 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate); + pagedresults_lock(pb->pb_conn, pr_idx); + if ((pagedresults_set_current_be(pb->pb_conn, be, pr_idx) < 0) || +- (pagedresults_set_search_result(pb->pb_conn, operation, +- sr, 0, pr_idx) < 0) || +- (pagedresults_set_search_result_count(pb->pb_conn, operation, +- curr_search_count, +- pr_idx) < 0) || +- (pagedresults_set_search_result_set_size_estimate(pb->pb_conn, +- operation, +- estimate, +- pr_idx) < 0) || +- (pagedresults_set_with_sort(pb->pb_conn, operation, +- with_sort, pr_idx) < 0)) { ++ (pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx) < 0) || ++ (pagedresults_set_search_result_count(pb->pb_conn, operation, curr_search_count, pr_idx) < 0) || ++ (pagedresults_set_search_result_set_size_estimate(pb->pb_conn, operation, estimate, pr_idx) < 0) || ++ (pagedresults_set_with_sort(pb->pb_conn, operation, with_sort, pr_idx) < 0)) { + pagedresults_unlock(pb->pb_conn, pr_idx); + goto free_and_return; + } +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index d589708..e61c000 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -100,26 +100,20 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + ber_free(ber, 1); + if ( cookie.bv_len <= 0 ) { + int i; +- int maxlen; + /* first time? */ +- maxlen = conn->c_pagedresults.prl_maxlen; ++ int maxlen = conn->c_pagedresults.prl_maxlen; + if (conn->c_pagedresults.prl_count == maxlen) { + if (0 == maxlen) { /* first time */ + conn->c_pagedresults.prl_maxlen = 1; +- conn->c_pagedresults.prl_list = +- (PagedResults *)slapi_ch_calloc(1, +- sizeof(PagedResults)); ++ conn->c_pagedresults.prl_list = (PagedResults *)slapi_ch_calloc(1, sizeof(PagedResults)); + } else { + /* new max length */ + conn->c_pagedresults.prl_maxlen *= 2; +- conn->c_pagedresults.prl_list = +- (PagedResults *)slapi_ch_realloc( ++ conn->c_pagedresults.prl_list = (PagedResults *)slapi_ch_realloc( + (char *)conn->c_pagedresults.prl_list, +- sizeof(PagedResults) * +- conn->c_pagedresults.prl_maxlen); ++ sizeof(PagedResults) * conn->c_pagedresults.prl_maxlen); + /* initialze newly allocated area */ +- memset(conn->c_pagedresults.prl_list + maxlen, '\0', +- sizeof(PagedResults) * maxlen); ++ memset(conn->c_pagedresults.prl_list + maxlen, '\0', sizeof(PagedResults) * maxlen); + } + *index = maxlen; /* the first position in the new area */ + } else { +@@ -276,8 +270,8 @@ pagedresults_free_one( Connection *conn, Operation *op, int index ) + prp->pr_current_be->be_search_results_release && + prp->pr_search_result_set) { + prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set)); +- prp->pr_current_be = NULL; + } ++ prp->pr_current_be = NULL; + if (prp->pr_mutex) { + /* pr_mutex is reused; back it up and reset it. */ + prmutex = prp->pr_mutex; +@@ -314,8 +308,8 @@ pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ) + prp->pr_current_be->be_search_results_release && + prp->pr_search_result_set) { + prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set)); +- prp->pr_current_be = NULL; + } ++ prp->pr_current_be = NULL; + prp->pr_flags |= CONN_FLAG_PAGEDRESULTS_ABANDONED; + prp->pr_flags &= ~CONN_FLAG_PAGEDRESULTS_PROCESSING; + conn->c_pagedresults.prl_count--; +@@ -404,16 +398,8 @@ pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, + if (conn && (index > -1)) { + if (!locked) PR_Lock(conn->c_mutex); + if (index < conn->c_pagedresults.prl_maxlen) { +- if (sr) { /* set */ +- if (NULL == +- conn->c_pagedresults.prl_list[index].pr_search_result_set) { +- conn->c_pagedresults.prl_list[index].pr_search_result_set = sr; +- rc = 0; +- } +- } else { /* reset */ +- conn->c_pagedresults.prl_list[index].pr_search_result_set = sr; +- rc = 0; +- } ++ conn->c_pagedresults.prl_list[index].pr_search_result_set = sr; ++ rc = 0; + } + if (!locked) PR_Unlock(conn->c_mutex); + } +@@ -732,9 +718,9 @@ pagedresults_cleanup(Connection *conn, int needlock) + if (prp->pr_current_be && prp->pr_search_result_set && + prp->pr_current_be->be_search_results_release) { + prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set)); +- prp->pr_current_be = NULL; + rc = 1; + } ++ prp->pr_current_be = NULL; + if (prp->pr_mutex) { + PR_DestroyLock(prp->pr_mutex); + } +@@ -780,9 +766,9 @@ pagedresults_cleanup_all(Connection *conn, int needlock) + if (prp->pr_current_be && prp->pr_search_result_set && + prp->pr_current_be->be_search_results_release) { + prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set)); +- prp->pr_current_be = NULL; + rc = 1; + } ++ prp->pr_current_be = NULL; + } + slapi_ch_free((void **)&conn->c_pagedresults.prl_list); + conn->c_pagedresults.prl_maxlen = 0; +-- +1.9.3 + diff --git a/SOURCES/0065-Ticket-48146-async-simple-paged-results-issue-log-pr.patch b/SOURCES/0065-Ticket-48146-async-simple-paged-results-issue-log-pr.patch new file mode 100644 index 0000000..e07e791 --- /dev/null +++ b/SOURCES/0065-Ticket-48146-async-simple-paged-results-issue-log-pr.patch @@ -0,0 +1,74 @@ +From 01fb4193778aa165070c3a8b4fe2c48e83ce3828 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 1 May 2015 10:50:39 -0700 +Subject: [PATCH 65/72] Ticket #48146 - async simple paged results issue; log + pr index + +Description: When the request is a simple paged results search, + log pr index in the access log. +Sample access log for "getent netgroup ": + [..] conn=23 op=521 SRCH base="cn=accounts,dc=testrelm,dc=test" scope=2 filter="(&(|(memberOf=ipaUniqueID=3036b6a0-ee18-11e4-b7dd-00215e2032c0,cn=ng,cn=alt,dc=testrelm,dc=test))(objectClass=ipaHost))" attrs="objectClass cn fqdn serverHostName memberOf ipaSshPubKey ipaUniqueID" + [..] conn=23 op=521 RESULT err=0 tag=101 nentries=200 etime=0 notes=P pr_idx=3 + +https://fedorahosted.org/389/ticket/48146 + +Reviewed by rmeggins@redhat.com (Thanks, Rich!!) + +(cherry picked from commit 9eb20d89755160aa916544c7cfce0ad066e538f7) +--- + ldap/servers/slapd/result.c | 32 +++++++++++++++++++++++++++++++- + 1 file changed, 31 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c +index 2198337..226f01c 100644 +--- a/ldap/servers/slapd/result.c ++++ b/ldap/servers/slapd/result.c +@@ -1961,6 +1961,9 @@ log_result( Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentrie + CSN *operationcsn = NULL; + char csn_str[CSN_STRSIZE + 5]; + char etime[ETIME_BUFSIZ]; ++ int pr_idx = -1; ++ ++ slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx); + + internal_op = operation_is_flag_set( op, OP_FLAG_INTERNAL ); + +@@ -2054,7 +2057,34 @@ log_result( Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentrie + } + slapi_ch_free((void**)&dn); + } else { +- if ( !internal_op ) ++ if (pr_idx > -1) ++ { ++ if ( !internal_op ) ++ { ++ slapi_log_access( LDAP_DEBUG_STATS, ++ "conn=%" NSPRIu64 " op=%d RESULT err=%d" ++ " tag=%" BERTAG_T " nentries=%d etime=%s%s%s" ++ " pr_idx=%d\n", ++ op->o_connid, ++ op->o_opid, ++ err, tag, nentries, ++ etime, ++ notes_str, csn_str, pr_idx ); ++ } ++ else ++ { ++ slapi_log_access( LDAP_DEBUG_ARGS, ++ "conn=%s op=%d RESULT err=%d" ++ " tag=%" BERTAG_T " nentries=%d etime=%s%s%s" ++ " pr_idx=%d\n", ++ LOG_INTERNAL_OP_CON_ID, ++ LOG_INTERNAL_OP_OP_ID, ++ err, tag, nentries, ++ etime, ++ notes_str, csn_str, pr_idx ); ++ } ++ } ++ else if ( !internal_op ) + { + slapi_log_access( LDAP_DEBUG_STATS, + "conn=%" NSPRIu64 " op=%d RESULT err=%d" +-- +1.9.3 + diff --git a/SOURCES/0066-Ticket-48146-async-simple-paged-results-issue-need-t.patch b/SOURCES/0066-Ticket-48146-async-simple-paged-results-issue-need-t.patch new file mode 100644 index 0000000..4b7aec6 --- /dev/null +++ b/SOURCES/0066-Ticket-48146-async-simple-paged-results-issue-need-t.patch @@ -0,0 +1,183 @@ +From 39e430f55e61605d27849c0f17e37e046cbbda72 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 1 May 2015 12:01:13 -0700 +Subject: [PATCH 66/72] Ticket #48146 - async simple paged results issue; need + to close a small window for a pr index competed among multiple threads. + +Description: If multiple async simple paged results requests come in via one +connection simultaneously, the same slot in the paged results array in the +connection could be shared. If one of them has to do paging, the search +request object stashed in the paged result array slot could be freed by the +other request if it has the shorter life cycle. + +These 3 reqs use the same paged results array slot. +req0: <--------------><----x +page1 page2 +req1: <-----> +req2: <-------> +frees search result object of req0 + +Reviewed by rmeggins@redhat.com (Thank you, Rich!!) + +(cherry picked from commit 3cf85d1ad6cbc0feac5578dee5ce259c0f65055f) +--- + ldap/servers/slapd/opshared.c | 93 +++++++++++++++++++-------------------- + ldap/servers/slapd/pagedresults.c | 3 +- + ldap/servers/slapd/proto-slap.h | 2 +- + 3 files changed, 49 insertions(+), 49 deletions(-) + +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index e7cee8a..430b0c6 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -408,6 +408,51 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + */ + operation_set_target_spec (pb->pb_op, basesdn); + ++ if (be_name == NULL) ++ { ++ /* no specific backend was requested, use the mapping tree ++ */ ++ err_code = slapi_mapping_tree_select_all(pb, be_list, referral_list, errorbuf); ++ if (((err_code != LDAP_SUCCESS) && (err_code != LDAP_OPERATIONS_ERROR) && (err_code != LDAP_REFERRAL)) ++ || ((err_code == LDAP_OPERATIONS_ERROR) && (be_list[0] == NULL))) ++ { ++ send_ldap_result(pb, err_code, NULL, errorbuf, 0, NULL); ++ rc = -1; ++ goto free_and_return; ++ } ++ if (be_list[0] != NULL) ++ { ++ index = 0; ++ if (pr_be) { /* PAGED RESULT: be is found from the previous paging. */ ++ /* move the index in the be_list which matches pr_be */ ++ while (be_list[index] && be_list[index+1] && pr_be != be_list[index]) ++ index++; ++ } else { ++ while (be_list[index] && be_list[index+1]) ++ index++; ++ } ++ /* "be" is either pr_be or the last backend */ ++ be = be_list[index]; ++ } ++ else ++ be = pr_be?pr_be:NULL; ++ } ++ else ++ { ++ /* specific backend be_name was requested, use slapi_be_select_by_instance_name ++ */ ++ if (pr_be) { ++ be_single = be = pr_be; ++ } else { ++ be_single = be = slapi_be_select_by_instance_name(be_name); ++ } ++ if (be_single) ++ slapi_be_Rlock(be_single); ++ be_list[0] = NULL; ++ referral_list[0] = NULL; ++ referral = NULL; ++ } ++ + /* this is time to check if mapping tree specific control + * was used to specify that we want to parse only + * one backend +@@ -478,8 +523,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + if ( slapi_control_present (ctrlp, LDAP_CONTROL_PAGEDRESULTS, + &ctl_value, &iscritical) ) + { +- rc = pagedresults_parse_control_value(pb, ctl_value, +- &pagesize, &pr_idx); ++ rc = pagedresults_parse_control_value(pb, ctl_value, &pagesize, &pr_idx, be); + /* Let's set pr_idx even if it fails; in case, pr_idx == -1. */ + slapi_pblock_set(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx); + if ((LDAP_SUCCESS == rc) || +@@ -520,51 +564,6 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + } + } + +- if (be_name == NULL) +- { +- /* no specific backend was requested, use the mapping tree +- */ +- err_code = slapi_mapping_tree_select_all(pb, be_list, referral_list, errorbuf); +- if (((err_code != LDAP_SUCCESS) && (err_code != LDAP_OPERATIONS_ERROR) && (err_code != LDAP_REFERRAL)) +- || ((err_code == LDAP_OPERATIONS_ERROR) && (be_list[0] == NULL))) +- { +- send_ldap_result(pb, err_code, NULL, errorbuf, 0, NULL); +- rc = -1; +- goto free_and_return; +- } +- if (be_list[0] != NULL) +- { +- index = 0; +- if (pr_be) { /* PAGED RESULT: be is found from the previous paging. */ +- /* move the index in the be_list which matches pr_be */ +- while (be_list[index] && be_list[index+1] && pr_be != be_list[index]) +- index++; +- } else { +- while (be_list[index] && be_list[index+1]) +- index++; +- } +- /* "be" is either pr_be or the last backend */ +- be = be_list[index]; +- } +- else +- be = pr_be?pr_be:NULL; +- } +- else +- { +- /* specific backend be_name was requested, use slapi_be_select_by_instance_name +- */ +- if (pr_be) { +- be_single = be = pr_be; +- } else { +- be_single = be = slapi_be_select_by_instance_name(be_name); +- } +- if (be_single) +- slapi_be_Rlock(be_single); +- be_list[0] = NULL; +- referral_list[0] = NULL; +- referral = NULL; +- } +- + slapi_pblock_set(pb, SLAPI_BACKEND_COUNT, &index); + + if (be) +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index e61c000..a3a5fc4 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -58,7 +58,7 @@ + int + pagedresults_parse_control_value( Slapi_PBlock *pb, + struct berval *psbvp, ber_int_t *pagesize, +- int *index ) ++ int *index, Slapi_Backend *be ) + { + int rc = LDAP_SUCCESS; + struct berval cookie = {0}; +@@ -119,6 +119,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + } else { + for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { + if (!conn->c_pagedresults.prl_list[i].pr_current_be) { ++ conn->c_pagedresults.prl_list[i].pr_current_be = be; + *index = i; + break; + } +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index c987b4a..80504b2 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -1467,7 +1467,7 @@ int slapd_do_all_nss_ssl_init(int slapd_exemode, int importexport_encrypt, + * pagedresults.c + */ + int pagedresults_parse_control_value(Slapi_PBlock *pb, struct berval *psbvp, +- ber_int_t *pagesize, int *index); ++ ber_int_t *pagesize, int *index, Slapi_Backend *be); + void pagedresults_set_response_control(Slapi_PBlock *pb, int iscritical, + ber_int_t estimate, + int curr_search_count, int index); +-- +1.9.3 + diff --git a/SOURCES/0067-Ticket-48146-async-simple-paged-results-issue.patch b/SOURCES/0067-Ticket-48146-async-simple-paged-results-issue.patch new file mode 100644 index 0000000..a89acd4 --- /dev/null +++ b/SOURCES/0067-Ticket-48146-async-simple-paged-results-issue.patch @@ -0,0 +1,42 @@ +From 3e34dcaf4899a5379d40d80f2eee7821b2604702 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 4 May 2015 14:06:43 -0700 +Subject: [PATCH 67/72] Ticket #48146 - async simple paged results issue + +Description: Invalid index could cause Invalid read. + +https://fedorahosted.org/389/ticket/48146 +(cherry picked from commit 8e21bfbe4fcac79cf39e5c6b579c4bc88e05257e) +--- + ldap/servers/slapd/pagedresults.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index a3a5fc4..327da54 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -138,6 +138,13 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + memcpy(ptr, cookie.bv_val, cookie.bv_len); + *(ptr+cookie.bv_len) = '\0'; + *index = strtol(ptr, NULL, 10); ++ if (conn->c_pagedresults.prl_maxlen <= *index) { ++ rc = LDAP_PROTOCOL_ERROR; ++ LDAPDebug1Arg(LDAP_DEBUG_ANY, ++ "pagedresults_parse_control_value: invalid cookie: %d\n", ++ *index); ++ goto bail; ++ } + slapi_ch_free_string(&ptr); + prp = conn->c_pagedresults.prl_list + *index; + if (!(prp->pr_search_result_set)) { /* freed and reused for the next backend. */ +@@ -162,6 +169,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + "pagedresults_parse_control_value: invalid cookie: %d\n", + *index); + } ++bail: + PR_Unlock(conn->c_mutex); + + LDAPDebug1Arg(LDAP_DEBUG_TRACE, +-- +1.9.3 + diff --git a/SOURCES/0068-Ticket-48146-async-simple-paged-results-issue.patch b/SOURCES/0068-Ticket-48146-async-simple-paged-results-issue.patch new file mode 100644 index 0000000..8feeef8 --- /dev/null +++ b/SOURCES/0068-Ticket-48146-async-simple-paged-results-issue.patch @@ -0,0 +1,160 @@ +From ef82e8471b3bc171ae99ffd753937b55aa0e6e2f Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 26 May 2015 10:41:03 -0700 +Subject: [PATCH 68/72] Ticket #48146 - async simple paged results issue + +Description: commit 5060d11f5039efa8534a8b65392ac6e10cbd2168 introduced +a regression. Handling backend "be" should be done after checking OID +MTN_CONTROL_USE_ONE_BACKEND_EXT_OID in the request control. + +https://fedorahosted.org/389/ticket/48146 + +Reviewed by mreynolds@redhat.com (Thank you, Mark!!) + +(cherry picked from commit bd2c0d0b6a499d7f91a36e8a9feb83e4fbd3dac5) +(cherry picked from commit 0c7b38abfb4c5c02286efd5e698616534a798993) +--- + ldap/servers/slapd/opshared.c | 108 ++++++++++++++++++++++-------------------- + 1 file changed, 57 insertions(+), 51 deletions(-) + +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index 430b0c6..ff67a9b 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -408,57 +408,12 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + */ + operation_set_target_spec (pb->pb_op, basesdn); + +- if (be_name == NULL) +- { +- /* no specific backend was requested, use the mapping tree +- */ +- err_code = slapi_mapping_tree_select_all(pb, be_list, referral_list, errorbuf); +- if (((err_code != LDAP_SUCCESS) && (err_code != LDAP_OPERATIONS_ERROR) && (err_code != LDAP_REFERRAL)) +- || ((err_code == LDAP_OPERATIONS_ERROR) && (be_list[0] == NULL))) +- { +- send_ldap_result(pb, err_code, NULL, errorbuf, 0, NULL); +- rc = -1; +- goto free_and_return; +- } +- if (be_list[0] != NULL) +- { +- index = 0; +- if (pr_be) { /* PAGED RESULT: be is found from the previous paging. */ +- /* move the index in the be_list which matches pr_be */ +- while (be_list[index] && be_list[index+1] && pr_be != be_list[index]) +- index++; +- } else { +- while (be_list[index] && be_list[index+1]) +- index++; +- } +- /* "be" is either pr_be or the last backend */ +- be = be_list[index]; +- } +- else +- be = pr_be?pr_be:NULL; +- } +- else +- { +- /* specific backend be_name was requested, use slapi_be_select_by_instance_name +- */ +- if (pr_be) { +- be_single = be = pr_be; +- } else { +- be_single = be = slapi_be_select_by_instance_name(be_name); +- } +- if (be_single) +- slapi_be_Rlock(be_single); +- be_list[0] = NULL; +- referral_list[0] = NULL; +- referral = NULL; +- } +- +- /* this is time to check if mapping tree specific control +- * was used to specify that we want to parse only +- * one backend ++ /* ++ * this is time to check if mapping tree specific control was used to ++ * specify that we want to parse only one backend. + */ + slapi_pblock_get(pb, SLAPI_REQCONTROLS, &ctrlp); +- if (NULL != ctrlp) ++ if (ctrlp) + { + if (slapi_control_present(ctrlp, MTN_CONTROL_USE_ONE_BACKEND_EXT_OID, + &ctl_value, &iscritical)) +@@ -513,7 +468,57 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + } + } + } ++ } ++ ++ if (be_name == NULL) ++ { ++ /* no specific backend was requested, use the mapping tree ++ */ ++ err_code = slapi_mapping_tree_select_all(pb, be_list, referral_list, errorbuf); ++ if (((err_code != LDAP_SUCCESS) && (err_code != LDAP_OPERATIONS_ERROR) && (err_code != LDAP_REFERRAL)) ++ || ((err_code == LDAP_OPERATIONS_ERROR) && (be_list[0] == NULL))) ++ { ++ send_ldap_result(pb, err_code, NULL, errorbuf, 0, NULL); ++ rc = -1; ++ goto free_and_return; ++ } ++ if (be_list[0] != NULL) ++ { ++ index = 0; ++ if (pr_be) { /* PAGED RESULT: be is found from the previous paging. */ ++ /* move the index in the be_list which matches pr_be */ ++ while (be_list[index] && be_list[index+1] && pr_be != be_list[index]) ++ index++; ++ } else { ++ while (be_list[index] && be_list[index+1]) ++ index++; ++ } ++ /* "be" is either pr_be or the last backend */ ++ be = be_list[index]; ++ } ++ else ++ be = pr_be?pr_be:NULL; ++ } ++ else ++ { ++ /* specific backend be_name was requested, use slapi_be_select_by_instance_name ++ */ ++ if (pr_be) { ++ be_single = be = pr_be; ++ } else { ++ be_single = be = slapi_be_select_by_instance_name(be_name); ++ } ++ if (be_single) { ++ slapi_be_Rlock(be_single); ++ } ++ be_list[0] = NULL; ++ referral_list[0] = NULL; ++ referral = NULL; ++ } + ++ /* Handle the rest of the controls. */ ++ if (ctrlp) ++ { + if ( slapi_control_present (ctrlp, LDAP_CONTROL_GET_EFFECTIVE_RIGHTS, + &ctl_value, &iscritical) ) + { +@@ -1024,10 +1029,11 @@ next_be: + } + + free_and_return: +- if ((be_list[0] != NULL) || (referral_list[0] != NULL)) ++ if ((be_list[0] != NULL) || (referral_list[0] != NULL)) { + slapi_mapping_tree_free_all(be_list, referral_list); +- else if (be_single) ++ } else if (be_single) { + slapi_be_Unlock(be_single); ++ } + + free_and_return_nolock: + slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc); +-- +1.9.3 + diff --git a/SOURCES/0069-Ticket-48146-async-simple-paged-results-issue.patch b/SOURCES/0069-Ticket-48146-async-simple-paged-results-issue.patch new file mode 100644 index 0000000..110279e --- /dev/null +++ b/SOURCES/0069-Ticket-48146-async-simple-paged-results-issue.patch @@ -0,0 +1,157 @@ +From 2c5b4ef85d492732050f3bec57eec1b7afbb1120 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Sat, 30 May 2015 16:44:14 -0700 +Subject: [PATCH 69/72] Ticket #48146 - async simple paged results issue + +Description: commit 5e9c4f1f09596dd076a6c3a0bb419580e8fd705e broke the +CI test case ticket47824_test.py. + +If the simple paged results search is operated on a backend having one +or more sub-backends underneath, it fails to pick up the next sub-back +ends, but repeats the search on the parent backend. The problem was +fixed. + +https://fedorahosted.org/389/ticket/48146 + +Reviewed by mreynolds@redhat.com (Thank you, Mark!!) + +(cherry picked from commit 03d3455dfbe84f034a234df2ebd8cfdd7ad15f48) +(cherry picked from commit f6fe5bfe4c1fb1402af789a0f935c765c299d103) +--- + ldap/servers/slapd/opshared.c | 87 ++++++++++++++++++++----------------------- + 1 file changed, 41 insertions(+), 46 deletions(-) + +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index ff67a9b..5dff42f 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -470,46 +470,31 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + } + } + +- if (be_name == NULL) +- { +- /* no specific backend was requested, use the mapping tree +- */ +- err_code = slapi_mapping_tree_select_all(pb, be_list, referral_list, errorbuf); +- if (((err_code != LDAP_SUCCESS) && (err_code != LDAP_OPERATIONS_ERROR) && (err_code != LDAP_REFERRAL)) +- || ((err_code == LDAP_OPERATIONS_ERROR) && (be_list[0] == NULL))) +- { +- send_ldap_result(pb, err_code, NULL, errorbuf, 0, NULL); +- rc = -1; +- goto free_and_return; +- } +- if (be_list[0] != NULL) +- { +- index = 0; +- if (pr_be) { /* PAGED RESULT: be is found from the previous paging. */ +- /* move the index in the be_list which matches pr_be */ +- while (be_list[index] && be_list[index+1] && pr_be != be_list[index]) +- index++; ++ if (be_name == NULL) { ++ /* no specific backend was requested, use the mapping tree ++ */ ++ err_code = slapi_mapping_tree_select_all(pb, be_list, referral_list, errorbuf); ++ if (((err_code != LDAP_SUCCESS) && (err_code != LDAP_OPERATIONS_ERROR) && (err_code != LDAP_REFERRAL)) ++ || ((err_code == LDAP_OPERATIONS_ERROR) && (be_list[0] == NULL))) { ++ send_ldap_result(pb, err_code, NULL, errorbuf, 0, NULL); ++ rc = -1; ++ goto free_and_return; ++ } ++ if (be_list[0] != NULL) { ++ index = 0; ++ while (be_list[index] && be_list[index+1]) { ++ index++; ++ } ++ be = be_list[index]; + } else { +- while (be_list[index] && be_list[index+1]) +- index++; ++ be = NULL; + } +- /* "be" is either pr_be or the last backend */ +- be = be_list[index]; +- } +- else +- be = pr_be?pr_be:NULL; +- } +- else +- { ++ } else { + /* specific backend be_name was requested, use slapi_be_select_by_instance_name + */ +- if (pr_be) { +- be_single = be = pr_be; +- } else { +- be_single = be = slapi_be_select_by_instance_name(be_name); +- } ++ be_single = be = slapi_be_select_by_instance_name(be_name); + if (be_single) { +- slapi_be_Rlock(be_single); ++ slapi_be_Rlock(be_single); + } + be_list[0] = NULL; + referral_list[0] = NULL; +@@ -528,6 +513,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + if ( slapi_control_present (ctrlp, LDAP_CONTROL_PAGEDRESULTS, + &ctl_value, &iscritical) ) + { ++ /* be is set only when this request is new. otherwise, prev be is honored. */ + rc = pagedresults_parse_control_value(pb, ctl_value, &pagesize, &pr_idx, be); + /* Let's set pr_idx even if it fails; in case, pr_idx == -1. */ + slapi_pblock_set(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx); +@@ -536,13 +522,24 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED; + op_set_pagedresults(operation); + pr_be = pagedresults_get_current_be(pb->pb_conn, pr_idx); +- pr_search_result = pagedresults_get_search_result(pb->pb_conn, +- operation, +- pr_idx); +- estimate = +- pagedresults_get_search_result_set_size_estimate(pb->pb_conn, +- operation, +- pr_idx); ++ if (be_name) { ++ if (pr_be != be_single) { ++ slapi_be_Unlock(be_single); ++ be_single = be = pr_be; ++ slapi_be_Rlock(be_single); ++ } ++ } else if (be_list[0]) { ++ if (pr_be) { /* PAGED RESULT: be is found from the previous paging. */ ++ /* move the index in the be_list which matches pr_be */ ++ index = 0; ++ while (be_list[index] && be_list[index+1] && pr_be != be_list[index]) { ++ index++; ++ } ++ be = be_list[index]; ++ } ++ } ++ pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, pr_idx); ++ estimate = pagedresults_get_search_result_set_size_estimate(pb->pb_conn, operation, pr_idx); + if (pagedresults_get_unindexed(pb->pb_conn, operation, pr_idx)) { + opnote |= SLAPI_OP_NOTE_UNINDEXED; + } +@@ -687,7 +684,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + * change ONE-LEVEL searches to BASE + */ + +- /* that's mean we only support one suffix per backend */ ++ /* that means we only support one suffix per backend */ + be_suffix = slapi_be_getsuffix(be, 0); + + if (be_list[0] == NULL) +@@ -711,9 +708,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + * In async paged result case, the search result might be released + * by other theads. We need to double check it in the locked region. + */ +- pr_search_result = pagedresults_get_search_result(pb->pb_conn, +- operation, +- pr_idx); ++ pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, pr_idx); + if (pr_search_result) { + slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result ); + rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat); +-- +1.9.3 + diff --git a/SOURCES/0070-Ticket-48192-Individual-abandoned-simple-paged-resul.patch b/SOURCES/0070-Ticket-48192-Individual-abandoned-simple-paged-resul.patch new file mode 100644 index 0000000..dfb25f9 --- /dev/null +++ b/SOURCES/0070-Ticket-48192-Individual-abandoned-simple-paged-resul.patch @@ -0,0 +1,321 @@ +From 810e825adebf9f1669bab9f61831f158e0c2f941 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 4 Jun 2015 16:27:05 -0700 +Subject: [PATCH 70/72] Ticket #48192 - Individual abandoned simple paged + results request has no chance to be cleaned up + +Description: When allocating a slot in simple paged results array stashed +in a connection in pagedresults_parse_control_value, a new code is added +to scan the array if the existing slot is timed out or not. If it is, the +slot is released and a search results is released if it is attached. + +Also, if a request is abandoned, instead of returning a valid cookie, it +changed to return an empty cookie to inform the client the request was not +successfully completed. + +https://fedorahosted.org/389/ticket/48192 + +Reviewed by rmeggins@redhat.com (Thank you, Rich!!) + +(cherry picked from commit f3c3125fc9fd4dc1cbd41027d6442cb525efd014) +(cherry picked from commit 97c707df4e11936202310e99bcf5f45d15b49f0f) +--- + ldap/servers/slapd/opshared.c | 41 +++++++------- + ldap/servers/slapd/pagedresults.c | 110 ++++++++++++++++++++++++-------------- + 2 files changed, 89 insertions(+), 62 deletions(-) + +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index 5dff42f..9cf431c 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -517,8 +517,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + rc = pagedresults_parse_control_value(pb, ctl_value, &pagesize, &pr_idx, be); + /* Let's set pr_idx even if it fails; in case, pr_idx == -1. */ + slapi_pblock_set(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx); +- if ((LDAP_SUCCESS == rc) || +- (LDAP_CANCELLED == rc) || (0 == pagesize)) { ++ if ((LDAP_SUCCESS == rc) || (LDAP_CANCELLED == rc) || (0 == pagesize)) { + unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED; + op_set_pagedresults(operation); + pr_be = pagedresults_get_current_be(pb->pb_conn, pr_idx); +@@ -545,9 +544,8 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + } + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); + if ((LDAP_CANCELLED == rc) || (0 == pagesize)) { +- /* paged-results-request was abandoned */ +- pagedresults_set_response_control(pb, 0, estimate, +- curr_search_count, pr_idx); ++ /* paged-results-request was abandoned; making an empty cookie. */ ++ pagedresults_set_response_control(pb, 0, estimate, -1, pr_idx); + send_ldap_result(pb, 0, NULL, + "Simple Paged Results Search abandoned", + 0, NULL); +@@ -574,10 +572,21 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + + /* adjust time and size limits */ + compute_limits (pb); +- +- /* call the pre-search plugins. if they succeed, call the backend +- search function. then call the post-search plugins. */ + ++ /* set the timelimit to clean up the too-long-lived-paged results requests */ ++ if (op_is_pagedresults(operation)) { ++ time_t optime, time_up; ++ int tlimit; ++ slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit ); ++ slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime ); ++ time_up = (tlimit==-1 ? -1 : optime + tlimit); /* -1: no time limit */ ++ pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, time_up, pr_idx); ++ } ++ ++ /* ++ * call the pre-search plugins. if they succeed, call the backend ++ * search function. then call the post-search plugins. ++ */ + /* ONREPL - should regular plugin be called for internal searches ? */ + if (plugin_call_plugins(pb, SLAPI_PLUGIN_PRE_SEARCH_FN) == 0) + { +@@ -642,16 +651,6 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + } + } + +- /* set the timelimit to clean up the too-long-lived-paged results requests */ +- if (op_is_pagedresults(operation)) { +- time_t optime, time_up; +- int tlimit; +- slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit ); +- slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime ); +- time_up = (tlimit==-1 ? -1 : optime + tlimit); /* -1: no time limit */ +- pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, time_up, pr_idx); +- } +- + /* PAR: now filters have been rewritten, we can assign plugins to work on them */ + index_subsys_assign_filter_decoders(pb); + +@@ -880,10 +879,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr); + if (PAGEDRESULTS_SEARCH_END == pr_stat) { + if (sr) { /* in case a left over sr is found, clean it up */ +- PR_Lock(pb->pb_conn->c_mutex); +- pagedresults_set_search_result(pb->pb_conn, operation, NULL, 1, pr_idx); +- be->be_search_results_release(&sr); +- PR_Unlock(pb->pb_conn->c_mutex); ++ pagedresults_free_one(pb->pb_conn, operation, pr_idx); + } + if (NULL == next_be) { + /* no more entries && no more backends */ +@@ -1306,7 +1302,6 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, + operation_out_of_disk_space(); + } + pr_stat = PAGEDRESULTS_SEARCH_END; +- pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, 0, pr_idx); + rval = -1; + done = 1; + continue; +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index 327da54..402dd10 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -41,6 +41,27 @@ + + #include "slap.h" + ++/* helper function to clean up one prp slot */ ++static void ++_pr_cleanup_one_slot(PagedResults *prp) ++{ ++ PRLock *prmutex = NULL; ++ if (!prp) { ++ return; ++ } ++ if (prp->pr_current_be && prp->pr_current_be->be_search_results_release) { ++ /* sr is left; release it. */ ++ prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set)); ++ } ++ /* clean up the slot */ ++ if (prp->pr_mutex) { ++ /* pr_mutex is reused; back it up and reset it. */ ++ prmutex = prp->pr_mutex; ++ } ++ memset(prp, '\0', sizeof(PagedResults)); ++ prp->pr_mutex = prmutex; ++} ++ + /* + * Parse the value from an LDAPv3 "Simple Paged Results" control. They look + * like this: +@@ -65,6 +86,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + Connection *conn = pb->pb_conn; + Operation *op = pb->pb_op; + BerElement *ber = NULL; ++ PagedResults *prp = NULL; + + LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_parse_control_value\n"); + if ( NULL == conn || NULL == op || NULL == pagesize || NULL == index ) { +@@ -117,13 +139,31 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + } + *index = maxlen; /* the first position in the new area */ + } else { +- for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { +- if (!conn->c_pagedresults.prl_list[i].pr_current_be) { +- conn->c_pagedresults.prl_list[i].pr_current_be = be; ++ time_t ctime = current_time(); ++ prp = conn->c_pagedresults.prl_list; ++ for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) { ++ if (!prp->pr_current_be) { /* unused slot; take it */ ++ prp->pr_current_be = be; ++ *index = i; ++ break; ++ } else if (((prp->pr_timelimit > 0) && (ctime < prp->pr_timelimit)) || /* timelimit exceeded */ ++ (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) /* abandoned */) { ++ _pr_cleanup_one_slot(prp); ++ conn->c_pagedresults.prl_count--; ++ prp->pr_current_be = be; + *index = i; + break; + } + } ++ /* cleaning up the rest of the timedout if any */ ++ for (++i; i < conn->c_pagedresults.prl_maxlen; i++, prp++) { ++ if (prp->pr_current_be && ++ (((prp->pr_timelimit > 0) && (ctime < prp->pr_timelimit)) || /* timelimit exceeded */ ++ (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED)) /* abandoned */) { ++ _pr_cleanup_one_slot(prp); ++ conn->c_pagedresults.prl_count--; ++ } ++ } + } + if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen) && + !conn->c_pagedresults.prl_list[*index].pr_mutex) { +@@ -131,7 +171,6 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + } + conn->c_pagedresults.prl_count++; + } else { +- PagedResults *prp = NULL; + /* Repeated paged results request. + * PagedResults is already allocated. */ + char *ptr = slapi_ch_malloc(cookie.bv_len + 1); +@@ -156,8 +195,10 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + slapi_ch_free((void **)&cookie.bv_val); + + if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) { +- if (conn->c_pagedresults.prl_list[*index].pr_flags & +- CONN_FLAG_PAGEDRESULTS_ABANDONED) { ++ if (conn->c_pagedresults.prl_list[*index].pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) { ++ /* repeated case? */ ++ prp = conn->c_pagedresults.prl_list + *index; ++ _pr_cleanup_one_slot(prp); + rc = LDAP_CANCELLED; + } else { + /* Need to keep the latest msgid to prepare for the abandon. */ +@@ -273,20 +314,8 @@ pagedresults_free_one( Connection *conn, Operation *op, int index ) + "conn=%d paged requests list count is %d\n", + conn->c_connid, conn->c_pagedresults.prl_count); + } else if (index < conn->c_pagedresults.prl_maxlen) { +- PRLock *prmutex = NULL; + PagedResults *prp = conn->c_pagedresults.prl_list + index; +- if (prp && prp->pr_current_be && +- prp->pr_current_be->be_search_results_release && +- prp->pr_search_result_set) { +- prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set)); +- } +- prp->pr_current_be = NULL; +- if (prp->pr_mutex) { +- /* pr_mutex is reused; back it up and reset it. */ +- prmutex = prp->pr_mutex; +- } +- memset(prp, '\0', sizeof(PagedResults)); +- prp->pr_mutex = prmutex; ++ _pr_cleanup_one_slot(prp); + conn->c_pagedresults.prl_count--; + rc = 0; + } +@@ -309,7 +338,7 @@ pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ) + ; /* Not a paged result. */ + } else { + LDAPDebug1Arg(LDAP_DEBUG_TRACE, +- "--> pagedresults_free_one: msgid=%d\n", msgid); ++ "--> pagedresults_free_one_msgid_nolock: msgid=%d\n", msgid); + for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { + if (conn->c_pagedresults.prl_list[i].pr_msgid == msgid) { + PagedResults *prp = conn->c_pagedresults.prl_list + i; +@@ -318,16 +347,14 @@ pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ) + prp->pr_search_result_set) { + prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set)); + } +- prp->pr_current_be = NULL; + prp->pr_flags |= CONN_FLAG_PAGEDRESULTS_ABANDONED; + prp->pr_flags &= ~CONN_FLAG_PAGEDRESULTS_PROCESSING; +- conn->c_pagedresults.prl_count--; + rc = 0; + break; + } + } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, +- "<-- pagedresults_free_one: %d\n", rc); ++ "<-- pagedresults_free_one_msgid_nolock: %d\n", rc); + } + } + +@@ -845,37 +872,42 @@ pagedresults_reset_processing(Connection *conn, int index) + } + #endif + +-/* Are all the paged results requests timed out? */ ++/* ++ * This timedout is mainly for an end user leaves a commandline untouched ++ * for a long time. This should not affect a permanent connection which ++ * manages multiple simple paged results requests over the connection. ++ * ++ * [rule] ++ * If there is just one slot and it's timed out, we return it is timedout. ++ * If there are multiple slots, the connection may be a permanent one. ++ * Do not return timed out here. But let the next request take care the ++ * timedout slot(s). ++ */ + int + pagedresults_is_timedout_nolock(Connection *conn) + { +- int i; + PagedResults *prp = NULL; + time_t ctime; +- int rc = 0; + + LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_is_timedout\n"); + +- if (NULL == conn || 0 == conn->c_pagedresults.prl_count) { +- LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: -\n"); +- return rc; ++ if (!conn || (0 == conn->c_pagedresults.prl_maxlen)) { ++ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: false\n"); ++ return 0; + } + + ctime = current_time(); +- for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { +- prp = conn->c_pagedresults.prl_list + i; ++ prp = conn->c_pagedresults.prl_list; ++ if (prp && (1 == conn->c_pagedresults.prl_maxlen)) { + if (prp->pr_current_be && (prp->pr_timelimit > 0)) { +- if (ctime < prp->pr_timelimit) { +- LDAPDebug0Args(LDAP_DEBUG_TRACE, +- "<-- pagedresults_is_timedout: 0\n"); +- return 0; /* at least, one request is not timed out. */ +- } else { +- rc = 1; /* possibly timed out */ ++ if (ctime > prp->pr_timelimit) { ++ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: true\n"); ++ return 1; + } + } + } +- LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: 1\n"); +- return rc; /* all requests are timed out. */ ++ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_is_timedout: false\n"); ++ return 0; + } + + /* reset all timeout */ +-- +1.9.3 + diff --git a/SOURCES/0071-Ticket-48192-Individual-abandoned-simple-paged-resul.patch b/SOURCES/0071-Ticket-48192-Individual-abandoned-simple-paged-resul.patch new file mode 100644 index 0000000..7e126e2 --- /dev/null +++ b/SOURCES/0071-Ticket-48192-Individual-abandoned-simple-paged-resul.patch @@ -0,0 +1,42 @@ +From aa6561d02969ce1db1a50da2b8af8679f6aeca69 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 5 Jun 2015 10:13:17 -0700 +Subject: [PATCH 71/72] Ticket #48192 - Individual abandoned simple paged + results request has no chance to be cleaned up + +Description: Checking the cookie value passed by the client was not +sufficient. The negative value check was missing, which lead to +the simple paged results array out of bounds. Plus, a minor memory +leak was fixed. Thanks to Thierry Bordaz for his reviews! + +https://fedorahosted.org/389/ticket/48192 +(cherry picked from commit 298371d372678cf553594ae73ae57a6ea35358bf) +(cherry picked from commit 7718eb6a6714d1a284c3c706e621a7eb0ca5655a) +--- + ldap/servers/slapd/pagedresults.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index 402dd10..2e70e19 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -177,14 +177,14 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + memcpy(ptr, cookie.bv_val, cookie.bv_len); + *(ptr+cookie.bv_len) = '\0'; + *index = strtol(ptr, NULL, 10); +- if (conn->c_pagedresults.prl_maxlen <= *index) { ++ slapi_ch_free_string(&ptr); ++ if ((conn->c_pagedresults.prl_maxlen <= *index) || (*index < 0)){ + rc = LDAP_PROTOCOL_ERROR; + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "pagedresults_parse_control_value: invalid cookie: %d\n", + *index); + goto bail; + } +- slapi_ch_free_string(&ptr); + prp = conn->c_pagedresults.prl_list + *index; + if (!(prp->pr_search_result_set)) { /* freed and reused for the next backend. */ + conn->c_pagedresults.prl_count++; +-- +1.9.3 + diff --git a/SOURCES/0072-Ticket-48192-Individual-abandoned-simple-paged-resul.patch b/SOURCES/0072-Ticket-48192-Individual-abandoned-simple-paged-resul.patch new file mode 100644 index 0000000..5ea6c6c --- /dev/null +++ b/SOURCES/0072-Ticket-48192-Individual-abandoned-simple-paged-resul.patch @@ -0,0 +1,314 @@ +From 504609eadf933c726d829e1532dbe525ab71d1b2 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 9 Jun 2015 10:02:02 -0700 +Subject: [PATCH 72/72] Ticket #48192 - Individual abandoned simple paged + results request has no chance to be cleaned up + +Description: When a simple paged results is abandoned immediately and +asynchronously just after the request, the abandon request has a chance +to be handled before the simple paged results control is received and +processed. In the case, the search could be executed and the search +result structure could be leaked. + +This patch adds more abandon checks. In op_shared_search, after the +send_results_ext call, if the SLAPI_OP_STATUS_ABANDONED bit is set in +the status in the operation object, it cleans up the search results +again, which gives the second chance. + +https://fedorahosted.org/389/ticket/48192 + +Reviewed by tbordaz@redhat.com (Thank you so much, Thierry!!) + +(cherry picked from commit 1d18dd0107d48ac1d79f7c9988adf18b0905bbdb) +(cherry picked from commit 798eae4f2240a5b47963a2bb09a2a17acfc488ec) +--- + ldap/servers/slapd/abandon.c | 10 +++--- + ldap/servers/slapd/back-ldbm/ldbm_search.c | 13 ++++++-- + ldap/servers/slapd/opshared.c | 36 +++++++++++++-------- + ldap/servers/slapd/pagedresults.c | 52 +++++++++++++++++------------- + ldap/servers/slapd/proto-slap.h | 2 +- + 5 files changed, 69 insertions(+), 44 deletions(-) + +diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c +index 6b4bbf2..d80087e 100644 +--- a/ldap/servers/slapd/abandon.c ++++ b/ldap/servers/slapd/abandon.c +@@ -132,8 +132,7 @@ do_abandon( Slapi_PBlock *pb ) + } + + operation_set_abandoned_op (pb->pb_op, o->o_abandoned_op); +- if ( plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_ABANDON_FN ) +- == 0 ) { ++ if ( plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_ABANDON_FN ) == 0 ) { + int rc = 0; + + if ( o->o_status != SLAPI_OP_STATUS_RESULT_SENT ) { +@@ -148,14 +147,13 @@ do_abandon( Slapi_PBlock *pb ) + suppressed_by_plugin = 1; + } + } else { +- LDAPDebug( LDAP_DEBUG_TRACE, "do_abandon: op not found\n", 0, 0, +- 0 ); ++ LDAPDebug0Args(LDAP_DEBUG_TRACE, "do_abandon: op not found\n"); + } + + if ( 0 == pagedresults_free_one_msgid_nolock(pb->pb_conn, id) ) { + slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 +- " op=%d ABANDON targetop=Simple Paged Results\n", +- (long long unsigned int)pb->pb_conn->c_connid, pb->pb_op->o_opid ); ++ " op=%d ABANDON targetop=Simple Paged Results msgid=%d\n", ++ (long long unsigned int)pb->pb_conn->c_connid, pb->pb_op->o_opid, id ); + } else if ( NULL == o ) { + slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d ABANDON" + " targetop=NOTFOUND msgid=%d\n", +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c +index e1951a0..c6c5735 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c +@@ -1817,12 +1817,21 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + } + } + } ++ /* check for the final abandon */ ++ if (slapi_op_abandoned(pb)) { ++ slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate ); ++ if ( use_extension ) { ++ slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL ); ++ } ++ slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL ); ++ delete_search_result_set(pb, &sr); ++ rc = SLAPI_FAIL_GENERAL; ++ } + + bail: +- if(rc){ ++ if (rc && op) { + op->o_reverse_search_state = 0; + } +- + return rc; + } + +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index 9cf431c..4be5366 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -748,7 +748,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + pagedresults_unlock(pb->pb_conn, pr_idx); + if (next_be) { + /* no more entries, but at least another backend */ +- if (pagedresults_set_current_be(pb->pb_conn, next_be, pr_idx) < 0) { ++ if (pagedresults_set_current_be(pb->pb_conn, next_be, pr_idx, 0) < 0) { + goto free_and_return; + } + } +@@ -878,23 +878,23 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + curr_search_count = pnentries; + slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr); + if (PAGEDRESULTS_SEARCH_END == pr_stat) { +- if (sr) { /* in case a left over sr is found, clean it up */ +- pagedresults_free_one(pb->pb_conn, operation, pr_idx); +- } ++ /* no more entries, but at least another backend */ ++ PR_Lock(pb->pb_conn->c_mutex); ++ pagedresults_set_search_result(pb->pb_conn, operation, NULL, 1, pr_idx); ++ be->be_search_results_release(&sr); ++ rc = pagedresults_set_current_be(pb->pb_conn, next_be, pr_idx, 1); ++ PR_Unlock(pb->pb_conn->c_mutex); + if (NULL == next_be) { +- /* no more entries && no more backends */ +- curr_search_count = -1; +- } else { +- /* no more entries, but at least another backend */ +- if (pagedresults_set_current_be(pb->pb_conn, next_be, pr_idx) < 0) { ++ /* no more entries && no more backends */ ++ curr_search_count = -1; ++ } else if (rc < 0) { + goto free_and_return; +- } + } + } else { + curr_search_count = pnentries; + slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate); + pagedresults_lock(pb->pb_conn, pr_idx); +- if ((pagedresults_set_current_be(pb->pb_conn, be, pr_idx) < 0) || ++ if ((pagedresults_set_current_be(pb->pb_conn, be, pr_idx, 0) < 0) || + (pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx) < 0) || + (pagedresults_set_search_result_count(pb->pb_conn, operation, curr_search_count, pr_idx) < 0) || + (pagedresults_set_search_result_set_size_estimate(pb->pb_conn, operation, estimate, pr_idx) < 0) || +@@ -904,10 +904,20 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + } + pagedresults_unlock(pb->pb_conn, pr_idx); + } +- pagedresults_set_response_control(pb, 0, estimate, +- curr_search_count, pr_idx); + slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL ); + next_be = NULL; /* to break the loop */ ++ if (operation->o_status & SLAPI_OP_STATUS_ABANDONED) { ++ /* It turned out this search was abandoned. */ ++ PR_Lock(pb->pb_conn->c_mutex); ++ pagedresults_free_one_msgid_nolock( pb->pb_conn, operation->o_msgid); ++ PR_Unlock(pb->pb_conn->c_mutex); ++ /* paged-results-request was abandoned; making an empty cookie. */ ++ pagedresults_set_response_control(pb, 0, estimate, -1, pr_idx); ++ send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL); ++ rc = LDAP_SUCCESS; ++ goto free_and_return; ++ } ++ pagedresults_set_response_control(pb, 0, estimate, curr_search_count, pr_idx); + if (curr_search_count == -1) { + pagedresults_free_one(pb->pb_conn, operation, pr_idx); + } +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index 2e70e19..a7fe2cd 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -87,6 +87,8 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + Operation *op = pb->pb_op; + BerElement *ber = NULL; + PagedResults *prp = NULL; ++ time_t ctime = current_time(); ++ int i; + + LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_parse_control_value\n"); + if ( NULL == conn || NULL == op || NULL == pagesize || NULL == index ) { +@@ -121,7 +123,6 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + /* the ber encoding is no longer needed */ + ber_free(ber, 1); + if ( cookie.bv_len <= 0 ) { +- int i; + /* first time? */ + int maxlen = conn->c_pagedresults.prl_maxlen; + if (conn->c_pagedresults.prl_count == maxlen) { +@@ -138,15 +139,16 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + memset(conn->c_pagedresults.prl_list + maxlen, '\0', sizeof(PagedResults) * maxlen); + } + *index = maxlen; /* the first position in the new area */ ++ prp = conn->c_pagedresults.prl_list + *index; ++ prp->pr_current_be = be; + } else { +- time_t ctime = current_time(); + prp = conn->c_pagedresults.prl_list; + for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) { + if (!prp->pr_current_be) { /* unused slot; take it */ + prp->pr_current_be = be; + *index = i; + break; +- } else if (((prp->pr_timelimit > 0) && (ctime < prp->pr_timelimit)) || /* timelimit exceeded */ ++ } else if (((prp->pr_timelimit > 0) && (ctime > prp->pr_timelimit)) || /* timelimit exceeded */ + (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) /* abandoned */) { + _pr_cleanup_one_slot(prp); + conn->c_pagedresults.prl_count--; +@@ -155,15 +157,6 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + break; + } + } +- /* cleaning up the rest of the timedout if any */ +- for (++i; i < conn->c_pagedresults.prl_maxlen; i++, prp++) { +- if (prp->pr_current_be && +- (((prp->pr_timelimit > 0) && (ctime < prp->pr_timelimit)) || /* timelimit exceeded */ +- (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED)) /* abandoned */) { +- _pr_cleanup_one_slot(prp); +- conn->c_pagedresults.prl_count--; +- } +- } + } + if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen) && + !conn->c_pagedresults.prl_list[*index].pr_mutex) { +@@ -181,8 +174,8 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + if ((conn->c_pagedresults.prl_maxlen <= *index) || (*index < 0)){ + rc = LDAP_PROTOCOL_ERROR; + LDAPDebug1Arg(LDAP_DEBUG_ANY, +- "pagedresults_parse_control_value: invalid cookie: %d\n", +- *index); ++ "pagedresults_parse_control_value: invalid cookie: %d\n", *index); ++ *index = -1; /* index is invalid. reinitializing it. */ + goto bail; + } + prp = conn->c_pagedresults.prl_list + *index; +@@ -206,11 +199,24 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + } + } else { + rc = LDAP_PROTOCOL_ERROR; +- LDAPDebug1Arg(LDAP_DEBUG_ANY, +- "pagedresults_parse_control_value: invalid cookie: %d\n", +- *index); ++ LDAPDebug1Arg(LDAP_DEBUG_ANY, "pagedresults_parse_control_value: invalid cookie: %d\n", *index); + } + bail: ++ /* cleaning up the rest of the timedout or abandoned if any */ ++ prp = conn->c_pagedresults.prl_list; ++ for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) { ++ if (prp->pr_current_be && ++ (((prp->pr_timelimit > 0) && (ctime > prp->pr_timelimit)) || /* timelimit exceeded */ ++ (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED)) /* abandoned */) { ++ _pr_cleanup_one_slot(prp); ++ conn->c_pagedresults.prl_count--; ++ if (i == *index) { ++ /* registered slot is expired and cleaned up. return cancelled. */ ++ *index = -1; ++ rc = LDAP_CANCELLED; ++ } ++ } ++ } + PR_Unlock(conn->c_mutex); + + LDAPDebug1Arg(LDAP_DEBUG_TRACE, +@@ -326,7 +332,9 @@ pagedresults_free_one( Connection *conn, Operation *op, int index ) + return rc; + } + +-/* Used for abandoning */ ++/* ++ * Used for abandoning - conn->c_mutex is already locked in do_abandone. ++ */ + int + pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ) + { +@@ -334,7 +342,7 @@ pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ) + int i; + + if (conn && (msgid > -1)) { +- if (conn->c_pagedresults.prl_count <= 0) { ++ if (conn->c_pagedresults.prl_maxlen <= 0) { + ; /* Not a paged result. */ + } else { + LDAPDebug1Arg(LDAP_DEBUG_TRACE, +@@ -381,18 +389,18 @@ pagedresults_get_current_be(Connection *conn, int index) + } + + int +-pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index) ++pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index, int nolock) + { + int rc = -1; + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_set_current_be: idx=%d\n", index); + if (conn && (index > -1)) { +- PR_Lock(conn->c_mutex); ++ if (!nolock) PR_Lock(conn->c_mutex); + if (index < conn->c_pagedresults.prl_maxlen) { + conn->c_pagedresults.prl_list[index].pr_current_be = be; + } +- PR_Unlock(conn->c_mutex); + rc = 0; ++ if (!nolock) PR_Unlock(conn->c_mutex); + } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "<-- pagedresults_set_current_be: %d\n", rc); +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index 80504b2..c5c412d 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -1472,7 +1472,7 @@ void pagedresults_set_response_control(Slapi_PBlock *pb, int iscritical, + ber_int_t estimate, + int curr_search_count, int index); + Slapi_Backend *pagedresults_get_current_be(Connection *conn, int index); +-int pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index); ++int pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index, int nolock); + void *pagedresults_get_search_result(Connection *conn, Operation *op, + int index); + int pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, +-- +1.9.3 + diff --git a/SOURCES/0073-Ticket-48194-nsSSL3Ciphers-preference-not-enforced-s.patch b/SOURCES/0073-Ticket-48194-nsSSL3Ciphers-preference-not-enforced-s.patch new file mode 100644 index 0000000..8e2ba49 --- /dev/null +++ b/SOURCES/0073-Ticket-48194-nsSSL3Ciphers-preference-not-enforced-s.patch @@ -0,0 +1,176 @@ +From 413ac674d497a981b30bdc81b47ea2bb3e14ad57 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 11 Jun 2015 22:25:14 -0700 +Subject: [PATCH] Ticket #48194 - nsSSL3Ciphers preference not enforced server + side + +Description: The fix for ticket 47838 accidentally changed the timing +of setting default cipher preferences and creating a sslSocket which +broke setting the default preferences to each sslSocket. + +https://fedorahosted.org/389/ticket/48194 + +Reviewed by rmeggins@redhat.com (Thank you, Rich!!) + +(cherry picked from commit 53c9c4e84e3bcbc40de87b1e7cf7634d14599e1c) +(cherry picked from commit 99109e38ca671951c50724018fce71e2e362f0ff) +--- + ldap/servers/slapd/ssl.c | 97 +++++++++++++++++++++++++----------------------- + 1 file changed, 50 insertions(+), 47 deletions(-) + +diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c +index 6b51e0c..36a4788 100644 +--- a/ldap/servers/slapd/ssl.c ++++ b/ldap/servers/slapd/ssl.c +@@ -1342,9 +1342,6 @@ slapd_ssl_init() + freeConfigEntry( &entry ); + } + +- /* ugaston- Cipher preferences must be set before any sslSocket is created +- * for such sockets to take preferences into account. +- */ + freeConfigEntry( &entry ); + + /* Introduce a way of knowing whether slapd_ssl_init has +@@ -1590,6 +1587,45 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + + errorbuf[0] = '\0'; + ++ /* ++ * Cipher preferences must be set before any sslSocket is created ++ * for such sockets to take preferences into account. ++ */ ++ getConfigEntry(configDN, &e); ++ if (e == NULL) { ++ slapd_SSL_warn("Security Initialization: Failed get config entry %s", configDN); ++ return 1; ++ } ++ val = slapi_entry_attr_get_charptr(e, "allowWeakCipher"); ++ if (val) { ++ if (!PL_strcasecmp(val, "off") || !PL_strcasecmp(val, "false") || ++ !PL_strcmp(val, "0") || !PL_strcasecmp(val, "no")) { ++ allowweakcipher = CIPHER_SET_DISALLOWWEAKCIPHER; ++ } else if (!PL_strcasecmp(val, "on") || !PL_strcasecmp(val, "true") || ++ !PL_strcmp(val, "1") || !PL_strcasecmp(val, "yes")) { ++ allowweakcipher = CIPHER_SET_ALLOWWEAKCIPHER; ++ } else { ++ slapd_SSL_warn("The value of allowWeakCipher \"%s\" in %s is invalid.", ++ "Ignoring it and set it to default.", val, configDN); ++ } ++ } ++ slapi_ch_free((void **) &val); ++ ++ /* Set SSL cipher preferences */ ++ *cipher_string = 0; ++ if(ciphers && (*ciphers) && PL_strcmp(ciphers, "blank")) ++ PL_strncpyz(cipher_string, ciphers, sizeof(cipher_string)); ++ slapi_ch_free((void **) &ciphers); ++ ++ if ( NULL != (val = _conf_setciphers(cipher_string, allowweakcipher)) ) { ++ errorCode = PR_GetError(); ++ slapd_SSL_warn("Security Initialization: Failed to set SSL cipher " ++ "preference information: %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", ++ val, errorCode, slapd_pr_strerror(errorCode)); ++ slapi_ch_free((void **) &val); ++ } ++ freeConfigEntry(&e); ++ + /* Import pr fd into SSL */ + pr_sock = SSL_ImportFD( NULL, sock ); + if( pr_sock == (PRFileDesc *)NULL ) { +@@ -1632,8 +1668,6 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + slapd_pk11_setSlotPWValues(slot, 0, 0); + } + +- +- + /* + * Now, get the complete list of cipher families. Each family + * has a token name and personality name which we'll use to find +@@ -1816,9 +1850,8 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + "out of disk space! Make more room in /tmp " + "and try again. (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", + errorCode, slapd_pr_strerror(errorCode)); +- } +- else { +- slapd_SSL_error("Config of server nonce cache failed (error %d - %s)", ++ } else { ++ slapd_SSL_error("Config of server nonce cache failed (error %d - %s)", + errorCode, slapd_pr_strerror(errorCode)); + } + return rv; +@@ -1985,36 +2018,6 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + #if !defined(NSS_TLS10) /* NSS_TLS11 or newer */ + } + #endif +- val = slapi_entry_attr_get_charptr(e, "allowWeakCipher"); +- if (val) { +- if (!PL_strcasecmp(val, "off") || !PL_strcasecmp(val, "false") || +- !PL_strcmp(val, "0") || !PL_strcasecmp(val, "no")) { +- allowweakcipher = CIPHER_SET_DISALLOWWEAKCIPHER; +- } else if (!PL_strcasecmp(val, "on") || !PL_strcasecmp(val, "true") || +- !PL_strcmp(val, "1") || !PL_strcasecmp(val, "yes")) { +- allowweakcipher = CIPHER_SET_ALLOWWEAKCIPHER; +- } else { +- slapd_SSL_warn("The value of allowWeakCipher \"%s\" in %s is invalid.", +- "Ignoring it and set it to default.", val, configDN); +- } +- } +- slapi_ch_free((void **) &val); +- +- /* Set SSL cipher preferences */ +- *cipher_string = 0; +- if(ciphers && (*ciphers) && PL_strcmp(ciphers, "blank")) +- PL_strncpyz(cipher_string, ciphers, sizeof(cipher_string)); +- slapi_ch_free((void **) &ciphers); +- +- if ( NULL != (val = _conf_setciphers(cipher_string, allowweakcipher)) ) { +- errorCode = PR_GetError(); +- slapd_SSL_warn("Security Initialization: Failed to set SSL cipher " +- "preference information: %s (" SLAPI_COMPONENT_NAME_NSPR " error %d - %s)", +- val, errorCode, slapd_pr_strerror(errorCode)); +- rv = 3; +- slapi_ch_free((void **) &val); +- } +- + freeConfigEntry( &e ); + + if(( slapd_SSLclientAuth = config_get_SSLclientAuth()) != SLAPD_SSLCLIENTAUTH_OFF ) { +@@ -2059,17 +2062,17 @@ slapd_ssl_init2(PRFileDesc **fd, int startTLS) + /* richm 20020227 + To do LDAP client SSL init, we need to do + +- static void +- ldapssl_basic_init( void ) +- { +- PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); ++ static void ++ ldapssl_basic_init( void ) ++ { ++ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); + +- PR_SetConcurrency( 4 ); +- } ++ PR_SetConcurrency( 4 ); ++ } + NSS_Init(certdbpath); + SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE); +- SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE); +- s = NSS_SetDomesticPolicy(); ++ SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE); ++ s = NSS_SetDomesticPolicy(); + We already do pr_init, we don't need pr_setconcurrency, we already do nss_init and the rest + + */ +@@ -2095,7 +2098,7 @@ slapd_SSL_client_auth (LDAP* ld) + char **family; + char *personality = NULL; + char *activation = NULL; +- char *cipher = NULL; ++ char *cipher = NULL; + + for (family = family_list; *family; family++) { + getConfigEntry( *family, &entry ); +-- +1.9.3 + diff --git a/SOURCES/0074-Ticket-48192-Individual-abandoned-simple-paged-resul.patch b/SOURCES/0074-Ticket-48192-Individual-abandoned-simple-paged-resul.patch new file mode 100644 index 0000000..959a784 --- /dev/null +++ b/SOURCES/0074-Ticket-48192-Individual-abandoned-simple-paged-resul.patch @@ -0,0 +1,147 @@ +From 22b0f8f0de1ee208a8c06c171bc2069da0adcc87 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 6 Jul 2015 14:06:11 -0700 +Subject: [PATCH] Ticket #48192 - Individual abandoned simple paged results + request has no chance to be cleaned up + +Description: There was a small window that the search on the next page +after the previous page abandoned referred the cleaned up simple paged +object. + +This patch introduces a pagedresults_is_abandoned helper function to +check the simple paged results was abandoned or not with some improvements +based upon the comments by rmeggins@redhat.com (Thank you!!): +1) adding locking when getting a simplepaged object in pagedresults_is_ + abandoned_or_notavailable as well as in pagedresults_{un}lock. +2) sending "Simple Paged Results Search abandoned" if the previous page + with the same cookie in the same connection was abandoned. + +https://fedorahosted.org/389/ticket/48192 + +Reviewed by rmeggins@redhat.com (Thank you, Rich!!) + +(cherry picked from commit e4d83c91fc88fcf9e6c823c608c629ac10e362f8) +(cherry picked from commit b513a502250f93cfb43df000c2140b27c4ef0d39) +(cherry picked from commit 7b17c488de280f29264920b4e53dce862ed5b7e4) +--- + ldap/servers/slapd/opshared.c | 22 ++++++++++++++++------ + ldap/servers/slapd/pagedresults.c | 24 +++++++++++++++++++++++- + ldap/servers/slapd/proto-slap.h | 1 + + 3 files changed, 40 insertions(+), 7 deletions(-) + +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index 4be5366..1bad7ef 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -709,12 +709,20 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + */ + pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, pr_idx); + if (pr_search_result) { +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result ); +- rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat); ++ if (pagedresults_is_abandoned_or_notavailable(pb->pb_conn, pr_idx)) { ++ pagedresults_unlock(pb->pb_conn, pr_idx); ++ /* Previous operation was abandoned and the simplepaged object is not in use. */ ++ send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL); ++ rc = LDAP_SUCCESS; ++ goto free_and_return; ++ } else { ++ slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result ); ++ rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat); + +- /* search result could be reset in the backend/dse */ +- slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr); +- pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx); ++ /* search result could be reset in the backend/dse */ ++ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr); ++ pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx); ++ } + } else { + pr_stat = PAGEDRESULTS_SEARCH_END; + } +@@ -744,7 +752,9 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + if (PAGEDRESULTS_SEARCH_END == pr_stat) { + pagedresults_lock(pb->pb_conn, pr_idx); + slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL); +- pagedresults_free_one(pb->pb_conn, operation, pr_idx); ++ if (!pagedresults_is_abandoned_or_notavailable(pb->pb_conn, pr_idx)) { ++ pagedresults_free_one(pb->pb_conn, operation, pr_idx); ++ } + pagedresults_unlock(pb->pb_conn, pr_idx); + if (next_be) { + /* no more entries, but at least another backend */ +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index a7fe2cd..010e5c1 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -890,6 +890,8 @@ pagedresults_reset_processing(Connection *conn, int index) + * If there are multiple slots, the connection may be a permanent one. + * Do not return timed out here. But let the next request take care the + * timedout slot(s). ++ * ++ * must be called within conn->c_mutex + */ + int + pagedresults_is_timedout_nolock(Connection *conn) +@@ -918,7 +920,10 @@ pagedresults_is_timedout_nolock(Connection *conn) + return 0; + } + +-/* reset all timeout */ ++/* ++ * reset all timeout ++ * must be called within conn->c_mutex ++ */ + int + pagedresults_reset_timedout_nolock(Connection *conn) + { +@@ -981,7 +986,9 @@ pagedresults_lock( Connection *conn, int index ) + if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) { + return; + } ++ PR_Lock(conn->c_mutex); + prp = conn->c_pagedresults.prl_list + index; ++ PR_Unlock(conn->c_mutex); + if (prp->pr_mutex) { + PR_Lock(prp->pr_mutex); + } +@@ -995,9 +1002,24 @@ pagedresults_unlock( Connection *conn, int index ) + if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) { + return; + } ++ PR_Lock(conn->c_mutex); + prp = conn->c_pagedresults.prl_list + index; ++ PR_Unlock(conn->c_mutex); + if (prp->pr_mutex) { + PR_Unlock(prp->pr_mutex); + } + return; + } ++ ++int ++pagedresults_is_abandoned_or_notavailable( Connection *conn, int index ) ++{ ++ PagedResults *prp; ++ if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) { ++ return 1; /* not abandoned, but do not want to proceed paged results op. */ ++ } ++ PR_Lock(conn->c_mutex); ++ prp = conn->c_pagedresults.prl_list + index; ++ PR_Unlock(conn->c_mutex); ++ return prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED; ++} +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index c5c412d..4c0d1ce 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -1515,6 +1515,7 @@ int pagedresults_cleanup_all(Connection *conn, int needlock); + void op_set_pagedresults(Operation *op); + void pagedresults_lock(Connection *conn, int index); + void pagedresults_unlock(Connection *conn, int index); ++int pagedresults_is_abandoned_or_notavailable(Connection *conn, int index); + + /* + * sort.c +-- +1.9.3 + diff --git a/SOURCES/0075-Ticket-48223-Winsync-fails-when-AD-users-have-multip.patch b/SOURCES/0075-Ticket-48223-Winsync-fails-when-AD-users-have-multip.patch new file mode 100644 index 0000000..97aef2a --- /dev/null +++ b/SOURCES/0075-Ticket-48223-Winsync-fails-when-AD-users-have-multip.patch @@ -0,0 +1,78 @@ +From 8eef70242e661d55cdc0fae7f5328c780ec6d60a Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 13 Jul 2015 17:51:01 -0700 +Subject: [PATCH] Ticket #48223 - Winsync fails when AD users have multiple + spaces (two)inside the value of the rdn attribute + +Description: When the dirsync search returns a remote entry, winsync +search the entry with DN to retrieve the whole attribute value pairs. +The DN used for the search was normalized which replaced multiple white- +spaces with one in the DN. This patch does not used the normalized DN, +but the same DN given by AD. + +The DN normalization behaviour was introduced to fix a ticket #529 - +dn normalization must handle multiple space characters in attributes. + +Added additional debugging to get the info which entry failed to sync. + +https://fedorahosted.org/389/ticket/48223 + +Reviewed by rmeggins@redhat.com (Thank you, Rich!!) + +(cherry picked from commit 2c484cc6e89e473bced0e9b25dd6e68d53024bb3) +(cherry picked from commit 69fd1f188105b2c3ca1bee04b05909e53c980b34) +(cherry picked from commit 8622b69a733a6126414876f11ab627211cb3bd06) +--- + ldap/servers/plugins/posix-winsync/posix-group-func.c | 2 +- + ldap/servers/plugins/replication/windows_protocol_util.c | 11 +++++++---- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-func.c b/ldap/servers/plugins/posix-winsync/posix-group-func.c +index 5f841e5..a497f3f 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-func.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-func.c +@@ -95,7 +95,7 @@ getEntry(const char *udn, char **attrs) + } + else { + slapi_log_error(SLAPI_LOG_FATAL, POSIX_WINSYNC_PLUGIN_NAME, +- "getEntry: error searching for uid: %d\n", rc); ++ "getEntry: error searching for uid %s: %d\n", udn, rc); + } + + return NULL; +diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c +index dabc936..ca79021 100644 +--- a/ldap/servers/plugins/replication/windows_protocol_util.c ++++ b/ldap/servers/plugins/replication/windows_protocol_util.c +@@ -3244,7 +3244,7 @@ windows_get_remote_entry (Private_Repl_Protocol *prp, const Slapi_DN* remote_dn, + const char *searchbase = NULL; + Slapi_Entry *found_entry = NULL; + +- searchbase = slapi_sdn_get_dn(remote_dn); ++ searchbase = slapi_sdn_get_udn(remote_dn); + cres = windows_search_entry_ext(prp->conn, (char*)searchbase, filter, &found_entry, NULL, LDAP_SCOPE_BASE); + if (cres) + { +@@ -5904,13 +5904,16 @@ retry: + remote_entry = NULL; + } else + { +- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s: windows_process_dirsync_entry: failed to fetch inbound entry.\n",agmt_get_long_name(prp->agmt)); ++ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, ++ "%s: windows_process_dirsync_entry: failed to fetch inbound entry %s.\n", ++ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(slapi_entry_get_sdn_const(e))); + } + slapi_entry_free(local_entry); + if (rc) { + /* Something bad happened */ +- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"%s: windows_process_dirsync_entry: failed to update inbound entry for %s.\n",agmt_get_long_name(prp->agmt), +- slapi_sdn_get_dn(slapi_entry_get_sdn_const(e))); ++ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, ++ "%s: windows_process_dirsync_entry: failed to update inbound entry for %s.\n", ++ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(slapi_entry_get_sdn_const(e))); + } + } else + { +-- +1.9.3 + diff --git a/SPECS/389-ds-base.spec b/SPECS/389-ds-base.spec index 25d46e8..9a9aba4 100644 --- a/SPECS/389-ds-base.spec +++ b/SPECS/389-ds-base.spec @@ -25,7 +25,7 @@ Summary: 389 Directory Server (base) Name: 389-ds-base Version: 1.3.3.1 -Release: %{?relprefix}16%{?prerel}%{?dist} +Release: %{?relprefix}20%{?prerel}%{?dist} License: GPLv2 with exceptions URL: http://port389.org/ Group: System Environment/Daemons @@ -177,6 +177,19 @@ Patch59: 0059-Ticket-47988-Schema-learning-mechanism-in-replicatio.patc Patch60: 0060-Ticket-47988-Schema-learning-mechanism-in-replicatio.patch Patch61: 0061-Ticket-48005-ns-slapd-crash-in-shutdown-phase.patch Patch62: 0062-CVE-2015-1854-389ds-base-access-control-bypass-with-.patch +Patch63: 0063-Ticket-48190-idm-ipa-389-ds-base-entry-cache-converg.patch +Patch64: 0064-Ticket-48146-async-simple-paged-results-issue.patch +Patch65: 0065-Ticket-48146-async-simple-paged-results-issue-log-pr.patch +Patch66: 0066-Ticket-48146-async-simple-paged-results-issue-need-t.patch +Patch67: 0067-Ticket-48146-async-simple-paged-results-issue.patch +Patch68: 0068-Ticket-48146-async-simple-paged-results-issue.patch +Patch69: 0069-Ticket-48146-async-simple-paged-results-issue.patch +Patch70: 0070-Ticket-48192-Individual-abandoned-simple-paged-resul.patch +Patch71: 0071-Ticket-48192-Individual-abandoned-simple-paged-resul.patch +Patch72: 0072-Ticket-48192-Individual-abandoned-simple-paged-resul.patch +Patch73: 0073-Ticket-48194-nsSSL3Ciphers-preference-not-enforced-s.patch +Patch74: 0074-Ticket-48192-Individual-abandoned-simple-paged-resul.patch +Patch75: 0075-Ticket-48223-Winsync-fails-when-AD-users-have-multip.patch %description 389 Directory Server is an LDAPv3 compliant server. The base package includes @@ -290,6 +303,19 @@ cp %{SOURCE2} README.devel %patch60 -p1 %patch61 -p1 %patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +%patch73 -p1 +%patch74 -p1 +%patch75 -p1 %build %if %{use_openldap} @@ -450,6 +476,23 @@ fi %{_libdir}/%{pkgname}/libns-dshttpd.so* %changelog +* Thu Jul 16 2015 Noriko Hosoi - 1.3.3.1-20 +- release 1.3.3.1-20 +- Resolves: bug 1243718 - Winsync fails when AD users have multiple spaces (two)inside the value of the rdn attribute (DS 48223) + +* Mon Jul 6 2015 Noriko Hosoi - 1.3.3.1-19 +- release 1.3.3.1-19 +- Resolves: bug 1230037 - async simple paged results issue (DS 48192) + +* Tue Jun 16 2015 Noriko Hosoi - 1.3.3.1-18 +- release 1.3.3.1-18 +- Resolves: bug 1232100 - CVE-2015-3230 389-ds-base: nsSSL3Ciphers preference not enforced server side (DS 48194) + +* Wed Jun 10 2015 Noriko Hosoi - 1.3.3.1-17 +- release 1.3.3.1-17 +- Resolves: bug 1230038 - idm/ipa 389-ds-base entry cache converges to 500 KB in dblayer_is_cachesize_sane (DS 48190) +- Resolves: bug 1230037 - async simple paged results issue (DS 48146, DS 48192) + * Tue Apr 21 2015 Noriko Hosoi - 1.3.3.1-16 - release 1.3.3.1-16 - Resolves: bug 1212894 - CVE-2015-1854 389ds-base: access control bypass with modrdn