From dc8c345aafdce027e11e93c1bcecc7676bccc6aa Mon Sep 17 00:00:00 2001 From: Kimpe Andy Date: Jun 08 2024 21:20:32 +0000 Subject: Update branch c6 source file extract 389-ds-base-1.2.11.15-95.el6_9.src.rpm --- diff --git a/0000-Trac-Ticket-340-Change-on-SLAPI_MODRDN_NEWSUPERIOR-i.patch b/0000-Trac-Ticket-340-Change-on-SLAPI_MODRDN_NEWSUPERIOR-i.patch new file mode 100644 index 0000000..925cfb6 --- /dev/null +++ b/0000-Trac-Ticket-340-Change-on-SLAPI_MODRDN_NEWSUPERIOR-i.patch @@ -0,0 +1,376 @@ +From 7399cbd53d6289df592d3414a84972eacb4dc97d Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 21 Sep 2012 12:35:18 -0700 +Subject: [PATCH 0/5] Trac Ticket #340 - Change on SLAPI_MODRDN_NEWSUPERIOR is + not evaluated in acl + +https://fedorahosted.org/389/ticket/340 + +Bug Description: When modrdn operation was executed, only newrdn +change was passed to the acl plugin. Also, the change was used +only for the acl search, but not for the acl target in the items +in the acl cache. + +Fix Description: This patch also passes the newsuperior update +to the acl plugin. And the modrdn updates are applied to the +acl target in the acl cache. +(cherry picked from commit 5beb93d42efb807838c09c5fab898876876f8d09) +--- + ldap/servers/plugins/acl/acl.c | 77 ++++++++++++++++++++++------------ + ldap/servers/plugins/acl/acl.h | 5 +- + ldap/servers/plugins/acl/aclgroup.c | 2 +- + ldap/servers/plugins/acl/acllist.c | 48 +++++++++++++--------- + ldap/servers/slapd/dn.c | 2 +- + ldap/servers/slapd/plugin_acl.c | 30 ++++++++++---- + 6 files changed, 106 insertions(+), 58 deletions(-) + +diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c +index 15e474e..3389404 100644 +--- a/ldap/servers/plugins/acl/acl.c ++++ b/ldap/servers/plugins/acl/acl.c +@@ -170,9 +170,9 @@ acl_access_allowed_modrdn( + * Test if have access to make the first rdn of dn in entry e. + */ + +-static int check_rdn_access( Slapi_PBlock *pb, Slapi_Entry *e, const char *dn, +- int access) { +- ++static int ++check_rdn_access( Slapi_PBlock *pb, Slapi_Entry *e, const char *dn, int access) ++{ + char **dns; + char **rdns; + int retCode = LDAP_INSUFFICIENT_ACCESS; +@@ -655,7 +655,8 @@ cleanup_and_ret: + + } + +-static void print_access_control_summary( char *source, int ret_val, char *clientDn, ++static void ++print_access_control_summary( char *source, int ret_val, char *clientDn, + struct acl_pblock *aclpb, + char *right, + char *attr, +@@ -1524,11 +1525,12 @@ acl_check_mods( + * + **************************************************************************/ + extern void +-acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change) ++acl_modified (Slapi_PBlock *pb, int optype, Slapi_DN *e_sdn, void *change) + { + struct berval **bvalue; + char **value; + int rv=0; /* returned value */ ++ const char* n_dn; + char* new_RDN; + char* parent_DN; + char* new_DN; +@@ -1537,10 +1539,12 @@ acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change) + int j; + Slapi_Attr *attr = NULL; + Slapi_Entry *e = NULL; +- Slapi_DN *e_sdn; + aclUserGroup *ugroup = NULL; + +- e_sdn = slapi_sdn_new_normdn_byval ( n_dn ); ++ if (NULL == e_sdn) { ++ return; ++ } ++ n_dn = slapi_sdn_get_dn(e_sdn); + /* Before we proceed, Let's first check if we are changing any groups. + ** If we are, then we need to change the signature + */ +@@ -1768,45 +1772,64 @@ acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change) + } + + break; +- }/* case op is modify*/ ++ }/* case op is modify*/ + +- case SLAPI_OPERATION_MODRDN: +- +- new_RDN = (char*) change; +- slapi_log_error (SLAPI_LOG_ACL, plugin_name, +- "acl_modified (MODRDN %s => \"%s\"\n", +- n_dn, new_RDN); ++ case SLAPI_OPERATION_MODRDN: ++ { ++ char **rdn_parent; ++ rdn_parent = (char **)change; ++ new_RDN = rdn_parent[0]; ++ parent_DN = rdn_parent[1]; + + /* compute new_DN: */ +- parent_DN = slapi_dn_parent (n_dn); +- if (parent_DN == NULL) { +- new_DN = new_RDN; ++ if (NULL == parent_DN) { ++ parent_DN = slapi_dn_parent(n_dn); ++ } ++ if (NULL == parent_DN) { ++ if (NULL == new_RDN) { ++ slapi_log_error (SLAPI_LOG_ACL, plugin_name, ++ "acl_modified (MODRDN %s => \"no change\"\n", ++ n_dn); ++ break; ++ } else { ++ new_DN = new_RDN; ++ } + } else { +- new_DN = slapi_create_dn_string("%s,%s", new_RDN, parent_DN); ++ if (NULL == new_RDN) { ++ Slapi_RDN *rdn= slapi_rdn_new(); ++ slapi_sdn_get_rdn(e_sdn, rdn); ++ new_DN = slapi_create_dn_string("%s,%s", slapi_rdn_get_rdn(rdn), ++ parent_DN); ++ slapi_rdn_free(&rdn); ++ } else { ++ new_DN = slapi_create_dn_string("%s,%s", new_RDN, parent_DN); ++ } + } ++ slapi_log_error (SLAPI_LOG_ACL, plugin_name, ++ "acl_modified (MODRDN %s => \"%s\"\n", n_dn, new_RDN); + + /* Change the acls */ +- acllist_acicache_WRITE_LOCK(); ++ acllist_acicache_WRITE_LOCK(); + /* acllist_moddn_aci_needsLock expects normalized new_DN, + * which is no need to be case-ignored */ + acllist_moddn_aci_needsLock ( e_sdn, new_DN ); + acllist_acicache_WRITE_UNLOCK(); + + /* deallocat the parent_DN */ +- if (parent_DN != NULL) { +- slapi_ch_free ( (void **) &new_DN ); +- slapi_ch_free ( (void **) &parent_DN ); ++ if (parent_DN != NULL) { ++ slapi_ch_free_string(&new_DN); ++ if (parent_DN != rdn_parent[1]) { ++ slapi_ch_free_string(&parent_DN); ++ } + } + break; +- +- default: ++ } /* case op is modrdn */ ++ default: + /* print ERROR */ + break; + } /*optype switch */ +- +- slapi_sdn_free ( &e_sdn ); +- + } ++ + /*************************************************************************** + * + * acl__scan_for_acis +diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h +index 4fa3e3f..28c38e7 100644 +--- a/ldap/servers/plugins/acl/acl.h ++++ b/ldap/servers/plugins/acl/acl.h +@@ -796,7 +796,8 @@ int acl_read_access_allowed_on_attr ( Slapi_PBlock *pb, Slapi_Entry *e, char + struct berval *val, int access); + void acl_set_acllist (Slapi_PBlock *pb, int scope, char *base); + void acl_gen_err_msg(int access, char *edn, char *attr, char **errbuf); +-void acl_modified ( Slapi_PBlock *pb, int optype, char *dn, void *change); ++void acl_modified (Slapi_PBlock *pb, int optype, Slapi_DN *e_sdn, void *change); ++ + int acl_access_allowed_disjoint_resource( Slapi_PBlock *pb, Slapi_Entry *e, + char *attr, struct berval *val, int access ); + int acl_access_allowed_main ( Slapi_PBlock *pb, Slapi_Entry *e, char **attrs, +@@ -866,7 +867,7 @@ void acllist_print_tree ( Avlnode *root, int *depth, char *start, char *side); + AciContainer *acllist_get_aciContainer_new ( ); + void acllist_done_aciContainer ( AciContainer *); + +-aclUserGroup* aclg_find_userGroup (char *n_dn); ++aclUserGroup* aclg_find_userGroup (const char *n_dn); + void aclg_regen_ugroup_signature( aclUserGroup *ugroup); + void aclg_markUgroupForRemoval ( aclUserGroup *u_group ); + void aclg_reader_incr_ugroup_refcnt(aclUserGroup* u_group); +diff --git a/ldap/servers/plugins/acl/aclgroup.c b/ldap/servers/plugins/acl/aclgroup.c +index c694293..2231304 100644 +--- a/ldap/servers/plugins/acl/aclgroup.c ++++ b/ldap/servers/plugins/acl/aclgroup.c +@@ -213,7 +213,7 @@ aclg_reset_userGroup ( struct acl_pblock *aclpb ) + */ + + aclUserGroup* +-aclg_find_userGroup(char *n_dn) ++aclg_find_userGroup(const char *n_dn) + { + aclUserGroup *u_group = NULL; + int i; +diff --git a/ldap/servers/plugins/acl/acllist.c b/ldap/servers/plugins/acl/acllist.c +index 9b5363a..e8198af 100644 +--- a/ldap/servers/plugins/acl/acllist.c ++++ b/ldap/servers/plugins/acl/acllist.c +@@ -600,7 +600,6 @@ void + acllist_init_scan (Slapi_PBlock *pb, int scope, const char *base) + { + Acl_PBlock *aclpb; +- int i; + AciContainer *root; + char *basedn = NULL; + int index; +@@ -671,11 +670,6 @@ acllist_init_scan (Slapi_PBlock *pb, int scope, const char *base) + aclpb->aclpb_state &= ~ACLPB_SEARCH_BASED_ON_LIST ; + + acllist_acicache_READ_UNLOCK(); +- +- i = 0; +- while ( i < aclpb_max_selected_acls && aclpb->aclpb_base_handles_index[i] != -1 ) { +- i++; +- } + } + + /* +@@ -893,34 +887,50 @@ acllist_acicache_WRITE_LOCK( ) + int + acllist_moddn_aci_needsLock ( Slapi_DN *oldsdn, char *newdn ) + { +- +- + AciContainer *aciListHead; + AciContainer *head; ++ aci_t *acip; ++ const char *oldndn; + + /* first get the container */ + + aciListHead = acllist_get_aciContainer_new ( ); + slapi_sdn_free(&aciListHead->acic_sdn); +- aciListHead->acic_sdn = oldsdn; +- ++ aciListHead->acic_sdn = oldsdn; + + if ( NULL == (head = (AciContainer *) avl_find( acllistRoot, aciListHead, +- (IFP) __acllist_aciContainer_node_cmp ) ) ) { ++ (IFP) __acllist_aciContainer_node_cmp ) ) ) { + + slapi_log_error ( SLAPI_PLUGIN_ACL, plugin_name, +- "Can't find the acl in the tree for moddn operation:olddn%s\n", +- slapi_sdn_get_ndn ( oldsdn )); ++ "Can't find the acl in the tree for moddn operation:olddn%s\n", ++ slapi_sdn_get_ndn ( oldsdn )); + aciListHead->acic_sdn = NULL; + __acllist_free_aciContainer ( &aciListHead ); +- return 1; ++ return 1; + } + +- +- /* Now set the new DN */ +- slapi_sdn_done ( head->acic_sdn ); +- slapi_sdn_set_normdn_byval ( head->acic_sdn, newdn ); +- ++ /* Now set the new DN */ ++ slapi_sdn_set_normdn_byval(head->acic_sdn, newdn); ++ ++ /* If necessary, reset the target DNs, as well. */ ++ oldndn = slapi_sdn_get_ndn(oldsdn); ++ for (acip = head->acic_list; acip; acip = acip->aci_next) { ++ const char *ndn = slapi_sdn_get_ndn(acip->aci_sdn); ++ char *p = PL_strstr(ndn, oldndn); ++ if (p) { ++ if (p == ndn) { ++ /* target dn is identical, replace it with new DN*/ ++ slapi_sdn_set_normdn_byval(acip->aci_sdn, newdn); ++ } else { ++ /* target dn is a descendent of olddn, merge it with new DN*/ ++ char *mynewdn; ++ *p = '\0'; ++ mynewdn = slapi_ch_smprintf("%s%s", ndn, newdn); ++ slapi_sdn_set_normdn_passin(acip->aci_sdn, mynewdn); ++ } ++ } ++ } ++ + aciListHead->acic_sdn = NULL; + __acllist_free_aciContainer ( &aciListHead ); + +diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c +index 568871f..35c0700 100644 +--- a/ldap/servers/slapd/dn.c ++++ b/ldap/servers/slapd/dn.c +@@ -2037,7 +2037,7 @@ slapi_sdn_set_normdn_byval(Slapi_DN *sdn, const char *normdn) + slapi_sdn_done(sdn); + sdn->flag = slapi_setbit_uchar(sdn->flag, FLAG_DN); + if(normdn == NULL) { +- sdn->dn = slapi_ch_strdup(normdn); ++ sdn->dn = NULL; + sdn->ndn_len = 0; + } else { + sdn->dn = slapi_ch_strdup(normdn); +diff --git a/ldap/servers/slapd/plugin_acl.c b/ldap/servers/slapd/plugin_acl.c +index b878156..3bc3f21 100644 +--- a/ldap/servers/slapd/plugin_acl.c ++++ b/ldap/servers/slapd/plugin_acl.c +@@ -134,11 +134,10 @@ int + plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype ) + { + struct slapdplugin *p; +- char *dn; + int rc = 0; +- void *change = NULL; +- Slapi_Entry *te = NULL; +- Slapi_DN *sdn = NULL; ++ void *change = NULL; ++ Slapi_Entry *te = NULL; ++ Slapi_DN *sdn = NULL; + Operation *operation; + + slapi_pblock_get (pb, SLAPI_OPERATION, &operation); +@@ -146,7 +145,7 @@ plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype ) + (void)slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ); + + switch ( optype ) { +- case SLAPI_OPERATION_MODIFY: ++ case SLAPI_OPERATION_MODIFY: + (void)slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &change ); + break; + case SLAPI_OPERATION_ADD: +@@ -158,11 +157,27 @@ plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype ) + } + break; + case SLAPI_OPERATION_MODRDN: ++ { ++ void *mychange[2]; ++ char *newrdn = NULL; ++ Slapi_DN *psdn = NULL; ++ char *pdn = NULL; ++ + /* newrdn: "change" is normalized but not case-ignored */ + /* The acl plugin expects normalized newrdn, but no need to be case- + * ignored. */ +- (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &change ); ++ (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn ); ++ (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &psdn ); ++ if (psdn) { ++ pdn = (char *)slapi_sdn_get_dn(psdn); ++ } else { ++ (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR, &pdn ); ++ } ++ mychange[0] = newrdn; ++ mychange[1] = pdn; ++ change = mychange; + break; ++ } + } + + if (NULL == sdn) { +@@ -172,10 +187,9 @@ plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype ) + } + + /* call the global plugins first and then the backend specific */ +- dn = (char*)slapi_sdn_get_ndn(sdn); /* jcm - Had to cast away const */ + for ( p = get_plugin_list(PLUGIN_LIST_ACL); p != NULL; p = p->plg_next ) { + if (plugin_invoke_plugin_sdn(p, SLAPI_PLUGIN_ACL_MODS_UPDATE, pb, sdn)){ +- rc = (*p->plg_acl_mods_update)(pb, optype, dn, change ); ++ rc = (*p->plg_acl_mods_update)(pb, optype, sdn, change ); + if ( rc != LDAP_SUCCESS ) break; + } + } +-- +1.7.7.6 + diff --git a/0001-Ticket-478-passwordTrackUpdateTime-stops-working-wit.patch b/0001-Ticket-478-passwordTrackUpdateTime-stops-working-wit.patch new file mode 100644 index 0000000..185b552 --- /dev/null +++ b/0001-Ticket-478-passwordTrackUpdateTime-stops-working-wit.patch @@ -0,0 +1,66 @@ +From 009fd8c21bb8226766fd84e477fae032ab1741c5 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 28 Sep 2012 15:00:20 -0400 +Subject: [PATCH 1/5] Ticket 478 - passwordTrackUpdateTime stops working with + subtree password policies + +Bug Description: If you create a subtree/user password policy passwordTrackUpdateTime + is not checked, bascially turning it off regardless of the setting in + cn=config. + +Fix Description: Added a check for passwordTrackUpdateTime in new_passwordPolicy(). Also + added this attribute to the schema so you can manually add it to subtree/user + password policies. + +https://fedorahosted.org/389/ticket/478 + +Reviewed by: Noriko(Thanks!) +(cherry picked from commit 7ba65b0022b9ecb40baaffbcef8130527028ed8b) +--- + ldap/schema/02common.ldif | 3 ++- + ldap/servers/slapd/pw.c | 5 ++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif +index c209615..c6cc6b8 100644 +--- a/ldap/schema/02common.ldif ++++ b/ldap/schema/02common.ldif +@@ -94,6 +94,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2080 NAME ( 'passwordMin8bit' 'pwdMin8bi + attributeTypes: ( 2.16.840.1.113730.3.1.2081 NAME ( 'passwordMaxRepeats' 'pwdMaxRepeats' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.2082 NAME ( 'passwordMinCategories' 'pwdMinCategories' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.2083 NAME ( 'passwordMinTokenLength' 'pwdMinTokenLength' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2140 NAME ( 'passwordTrackUpdateTime' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.198 NAME 'memberURL' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.199 NAME 'memberCertificateDescription' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.207 NAME 'vlvBase' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape Directory Server' ) +@@ -163,7 +164,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.7 NAME 'nsLicenseUser' DESC 'Netscape def + objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' DESC 'LDAP changelog objectclass' SUP top MUST ( targetdn $ changeTime $ changenumber $ changeType ) MAY ( changes $ newrdn $ deleteoldrdn $ newsuperior ) X-ORIGIN 'Changelog Internet Draft' ) + objectClasses: ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'LDAP referrals objectclass' SUP top MAY ( ref ) X-ORIGIN 'LDAPv3 referrals Internet Draft' ) + objectClasses: ( 2.16.840.1.113730.3.2.12 NAME 'passwordObject' DESC 'Netscape defined password policy objectclass' SUP top MAY ( pwdpolicysubentry $ passwordExpirationTime $ passwordExpWarned $ passwordRetryCount $ retryCountResetTime $ accountUnlockTime $ passwordHistory $ passwordAllowChangeTime $ passwordGraceUserTime ) X-ORIGIN 'Netscape Directory Server' ) +-objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength ) X-ORIGIN 'Netscape Directory Server' ) ++objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.30 NAME 'glue' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.32 NAME 'netscapeMachineData' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.38 NAME 'vlvSearch' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ vlvBase $ vlvScope $ vlvFilter ) MAY ( multiLineDescription ) X-ORIGIN 'Netscape Directory Server' ) +diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c +index 93fc899..6f3d436 100644 +--- a/ldap/servers/slapd/pw.c ++++ b/ldap/servers/slapd/pw.c +@@ -1625,10 +1625,13 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn) + "--local policy entry not found\n", dn); + goto done; + } +- ++ + /* set the default passwordLegacyPolicy setting */ + pwdpolicy->pw_is_legacy = 1; + ++ /* set passwordTrackUpdateTime */ ++ pwdpolicy->pw_track_update_time = slapdFrontendConfig->pw_policy.pw_track_update_time; ++ + for (slapi_entry_first_attr(pw_entry, &attr); attr; + slapi_entry_next_attr(pw_entry, attr, &attr)) + { +-- +1.7.7.6 + diff --git a/0002-Bug-863576-Dirsrv-deadlock-locking-up-IPA.patch b/0002-Bug-863576-Dirsrv-deadlock-locking-up-IPA.patch new file mode 100644 index 0000000..f385f56 --- /dev/null +++ b/0002-Bug-863576-Dirsrv-deadlock-locking-up-IPA.patch @@ -0,0 +1,307 @@ +From 4d825079a9bb622211d3709ea2496f533b8e51d1 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 5 Oct 2012 17:56:22 -0700 +Subject: [PATCH 2/5] Bug 863576 - Dirsrv deadlock locking up IPA + +https://bugzilla.redhat.com/show_bug.cgi?id=863576 + +Bug Description: Abandon of a Simple Paged Results request causes +the self deadlock. When abandoning a simple paged result request, +the mutex for the connection object c_mutex is locked in do_abandon. +But to free a pagedresult massage id, pagedresults_free_one_msgid +called from do_abandon tries to acquire lock on c_mutex again. +The NSPR lock function PR_Lock is not self re-entrant. Thus the +server hangs there due to the self-deadlock. + +Fix Description: This patch is removing to call PR_Lock(c_mutex) +in pagedresults_free_one_msgid and renamed it to pagedresults_free_ +one_msgid_nolock. To maintain the consistency, "_nolock" is added +to other pagedresults apis which do not call PR_Lock in it. +Also, stricter locking on c_mutex is being added to pagedresults_ +parse_control_value to protect the pagedresults related field in +the connection object. +(cherry picked from commit c19bb9dd1e95ee98a53a06f3d7eefb4dce5bc0ef) +--- + ldap/servers/slapd/abandon.c | 2 +- + ldap/servers/slapd/connection.c | 4 +- + ldap/servers/slapd/daemon.c | 2 +- + ldap/servers/slapd/pagedresults.c | 130 +++++++++++++++++++------------------ + ldap/servers/slapd/proto-slap.h | 8 +- + 5 files changed, 74 insertions(+), 72 deletions(-) + +diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c +index 4f00da9..094ae95 100644 +--- a/ldap/servers/slapd/abandon.c ++++ b/ldap/servers/slapd/abandon.c +@@ -153,7 +153,7 @@ do_abandon( Slapi_PBlock *pb ) + } + + if ( op_is_pagedresults(o) ) { +- if ( 0 == pagedresults_free_one_msgid(pb->pb_conn, id) ) { ++ 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", + pb->pb_conn->c_connid, pb->pb_op->o_opid ); +diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c +index 9e43104..a3b1df5 100644 +--- a/ldap/servers/slapd/connection.c ++++ b/ldap/servers/slapd/connection.c +@@ -2094,7 +2094,7 @@ void connection_enter_leave_turbo(Connection *conn, int current_turbo_flag, int + PR_Lock(conn->c_mutex); + /* We can already be in turbo mode, or not */ + current_mode = current_turbo_flag; +- if (pagedresults_in_use(conn)) { ++ if (pagedresults_in_use_nolock(conn)) { + /* PAGED_RESULTS does not need turbo mode */ + new_mode = 0; + } else if (conn->c_private->operation_rate == 0) { +@@ -2780,7 +2780,7 @@ disconnect_server_nomutex( Connection *conn, PRUint64 opconnid, int opid, PRErro + connection_abandon_operations( conn ); + /* needed here to ensure simple paged results timeout properly and + * don't impact subsequent ops */ +- pagedresults_reset_timedout(conn); ++ pagedresults_reset_timedout_nolock(conn); + + if (! config_check_referral_mode()) { + /* +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index 597e131..b611f5c 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -1693,7 +1693,7 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps + { + int add_fd = 1; + /* check timeout for PAGED RESULTS */ +- if (pagedresults_is_timedout(c)) ++ if (pagedresults_is_timedout_nolock(c)) + { + /* Exceeded the timelimit; disconnect the client */ + disconnect_server_nomutex(c, c->c_connid, -1, +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index ea7de14..d445c06 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -64,6 +64,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + struct berval cookie = {0}; + Connection *conn = pb->pb_conn; + Operation *op = pb->pb_op; ++ BerElement *ber = NULL; + + LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_parse_control_value\n"); + if ( NULL == conn || NULL == op || NULL == pagesize || NULL == index ) { +@@ -76,70 +77,71 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + + if ( psbvp->bv_len == 0 || psbvp->bv_val == NULL ) + { +- rc = LDAP_PROTOCOL_ERROR; ++ LDAPDebug0Args(LDAP_DEBUG_ANY, ++ "<-- pagedresults_parse_control_value: no control value\n"); ++ return LDAP_PROTOCOL_ERROR; + } +- else ++ ber = ber_init( psbvp ); ++ if ( ber == NULL ) + { +- BerElement *ber = ber_init( psbvp ); +- if ( ber == NULL ) +- { +- rc = LDAP_OPERATIONS_ERROR; +- } +- else +- { +- if ( ber_scanf( ber, "{io}", pagesize, &cookie ) == LBER_ERROR ) +- { +- rc = LDAP_PROTOCOL_ERROR; ++ LDAPDebug0Args(LDAP_DEBUG_ANY, ++ "<-- pagedresults_parse_control_value: no control value\n"); ++ return LDAP_PROTOCOL_ERROR; ++ } ++ if ( ber_scanf( ber, "{io}", pagesize, &cookie ) == LBER_ERROR ) ++ { ++ LDAPDebug0Args(LDAP_DEBUG_ANY, ++ "<-- pagedresults_parse_control_value: corrupted control value\n"); ++ return LDAP_PROTOCOL_ERROR; ++ } ++ ++ PR_Lock(conn->c_mutex); ++ /* the ber encoding is no longer needed */ ++ ber_free(ber, 1); ++ if ( cookie.bv_len <= 0 ) { ++ int i; ++ int maxlen; ++ /* first time? */ ++ 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)); ++ } else { ++ /* new max length */ ++ conn->c_pagedresults.prl_maxlen *= 2; ++ conn->c_pagedresults.prl_list = ++ (PagedResults *)slapi_ch_realloc( ++ (char *)conn->c_pagedresults.prl_list, ++ sizeof(PagedResults) * ++ conn->c_pagedresults.prl_maxlen); ++ /* initialze newly allocated area */ ++ memset(conn->c_pagedresults.prl_list + maxlen, '\0', ++ sizeof(PagedResults) * maxlen); + } +- /* the ber encoding is no longer needed */ +- ber_free(ber, 1); +- if ( cookie.bv_len <= 0 ) { +- int i; +- int maxlen; +- /* first time? */ +- PR_Lock(conn->c_mutex); +- 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)); +- } else { +- /* new max length */ +- conn->c_pagedresults.prl_maxlen *= 2; +- conn->c_pagedresults.prl_list = +- (PagedResults *)slapi_ch_realloc( +- (char *)conn->c_pagedresults.prl_list, +- sizeof(PagedResults) * +- conn->c_pagedresults.prl_maxlen); +- /* initialze newly allocated area */ +- memset(conn->c_pagedresults.prl_list + maxlen, '\0', +- sizeof(PagedResults) * maxlen); +- } +- *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) { +- *index = i; +- break; +- } +- } ++ *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) { ++ *index = i; ++ break; + } +- conn->c_pagedresults.prl_count++; +- PR_Unlock(conn->c_mutex); +- } else { +- /* Repeated paged results request. +- * PagedResults is already allocated. */ +- char *ptr = slapi_ch_malloc(cookie.bv_len + 1); +- memcpy(ptr, cookie.bv_val, cookie.bv_len); +- *(ptr+cookie.bv_len) = '\0'; +- *index = strtol(ptr, NULL, 10); +- slapi_ch_free_string(&ptr); + } +- slapi_ch_free((void **)&cookie.bv_val); + } ++ conn->c_pagedresults.prl_count++; ++ } else { ++ /* Repeated paged results request. ++ * PagedResults is already allocated. */ ++ char *ptr = slapi_ch_malloc(cookie.bv_len + 1); ++ memcpy(ptr, cookie.bv_val, cookie.bv_len); ++ *(ptr+cookie.bv_len) = '\0'; ++ *index = strtol(ptr, NULL, 10); ++ slapi_ch_free_string(&ptr); + } ++ slapi_ch_free((void **)&cookie.bv_val); ++ + if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) { + /* Need to keep the latest msgid to prepare for the abandon. */ + conn->c_pagedresults.prl_list[*index].pr_msgid = op->o_msgid; +@@ -149,6 +151,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + "pagedresults_parse_control_value: invalid cookie: %d\n", + *index); + } ++ PR_Unlock(conn->c_mutex); + + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "<-- pagedresults_parse_control_value: idx %d\n", *index); +@@ -261,7 +264,7 @@ pagedresults_free_one( Connection *conn, int index ) + } + + int +-pagedresults_free_one_msgid( Connection *conn, ber_int_t msgid ) ++pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ) + { + int rc = -1; + int i; +@@ -269,9 +272,9 @@ pagedresults_free_one_msgid( Connection *conn, ber_int_t msgid ) + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_free_one: msgid=%d\n", msgid); + if (conn && (msgid > -1)) { +- PR_Lock(conn->c_mutex); + if (conn->c_pagedresults.prl_count <= 0) { +- LDAPDebug2Args(LDAP_DEBUG_TRACE, "pagedresults_free_one_msgid: " ++ LDAPDebug2Args(LDAP_DEBUG_TRACE, ++ "pagedresults_free_one_msgid_nolock: " + "conn=%d paged requests list count is %d\n", + conn->c_connid, conn->c_pagedresults.prl_count); + } else { +@@ -285,7 +288,6 @@ pagedresults_free_one_msgid( Connection *conn, ber_int_t msgid ) + } + } + } +- PR_Unlock(conn->c_mutex); + } + + LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_free_one: %d\n", rc); +@@ -720,7 +722,7 @@ pagedresults_reset_processing(Connection *conn, int index) + + /* Are all the paged results requests timed out? */ + int +-pagedresults_is_timedout(Connection *conn) ++pagedresults_is_timedout_nolock(Connection *conn) + { + int i; + PagedResults *prp = NULL; +@@ -753,7 +755,7 @@ pagedresults_is_timedout(Connection *conn) + + /* reset all timeout */ + int +-pagedresults_reset_timedout(Connection *conn) ++pagedresults_reset_timedout_nolock(Connection *conn) + { + int i; + PagedResults *prp = NULL; +@@ -773,7 +775,7 @@ pagedresults_reset_timedout(Connection *conn) + + /* paged results requests are in progress. */ + int +-pagedresults_in_use(Connection *conn) ++pagedresults_in_use_nolock(Connection *conn) + { + LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_in_use\n"); + if (NULL == conn) { +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index 1b62c13..7e438b7 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -1421,11 +1421,11 @@ int pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index); + int pagedresults_cleanup(Connection *conn, int needlock); + int pagedresults_check_or_set_processing(Connection *conn, int index); + int pagedresults_reset_processing(Connection *conn, int index); +-int pagedresults_is_timedout(Connection *conn); +-int pagedresults_reset_timedout(Connection *conn); +-int pagedresults_in_use(Connection *conn); ++int pagedresults_is_timedout_nolock(Connection *conn); ++int pagedresults_reset_timedout_nolock(Connection *conn); ++int pagedresults_in_use_nolock(Connection *conn); + int pagedresults_free_one(Connection *conn, int index); +-int pagedresults_free_one_msgid( Connection *conn, ber_int_t msgid ); ++int pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ); + int op_is_pagedresults(Operation *op); + int pagedresults_cleanup_all(Connection *conn, int needlock); + void op_set_pagedresults(Operation *op); +-- +1.7.7.6 + diff --git a/0003-Ticket-446-anonymous-limits-are-being-applied-to-dir.patch b/0003-Ticket-446-anonymous-limits-are-being-applied-to-dir.patch new file mode 100644 index 0000000..ddb6501 --- /dev/null +++ b/0003-Ticket-446-anonymous-limits-are-being-applied-to-dir.patch @@ -0,0 +1,55 @@ +From 3e9a21ae4e41f1680fc899795f272f80c2d9aef9 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 9 Oct 2012 12:59:48 -0400 +Subject: [PATCH 3/5] Ticket #446 - anonymous limits are being applied to + directory manager + +Bug Description: If you set "anonymous limits" they are incorrectly applied + to the root DN + +Fix Description: When a connection is first accepted we set the anonymous limits + before we process the bind, because there might not be a bind operation. + However, we fail to clear out the resouce limits if the bind DN is + the root dn. + +https://fedorahosted.org/389/ticket/446 + +Reviewed by: richm(Thanks!) +(cherry picked from commit 53e16eda8e2a82a45deb39129bbe839beb036c70) +--- + ldap/servers/slapd/pblock.c | 6 ++++-- + 1 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c +index baee7a7..33559a7 100644 +--- a/ldap/servers/slapd/pblock.c ++++ b/ldap/servers/slapd/pblock.c +@@ -3639,7 +3639,7 @@ bind_credentials_set_nolock( Connection *conn, char *authtype, char *normdn, + { + /* clear credentials */ + bind_credentials_clear( conn, PR_FALSE /* conn is already locked */, +- ( extauthtype != NULL ) /* clear external creds. if requested */ ); ++ ( extauthtype != NULL ) /* clear external creds. if requested */ ); + + /* set primary credentials */ + slapi_ch_free((void**)&conn->c_authtype); +@@ -3657,7 +3657,6 @@ bind_credentials_set_nolock( Connection *conn, char *authtype, char *normdn, + conn->c_client_cert = clientcert; + } + +- + /* notify binder-based resource limit subsystem about the change in DN */ + if ( !conn->c_isroot ) + { +@@ -3681,5 +3680,8 @@ bind_credentials_set_nolock( Connection *conn, char *authtype, char *normdn, + + slapi_ch_free_string( &anon_dn ); + } ++ } else { ++ /* For root dn clear about the resource limits */ ++ reslimit_update_from_entry( conn, NULL ); + } + } +-- +1.7.7.6 + diff --git a/0004-Ticket-481-expand-nested-posix-groups.patch b/0004-Ticket-481-expand-nested-posix-groups.patch new file mode 100644 index 0000000..28660ee --- /dev/null +++ b/0004-Ticket-481-expand-nested-posix-groups.patch @@ -0,0 +1,1728 @@ +From 54431eb9e2438a838904a6d4846c45131b937cd0 Mon Sep 17 00:00:00 2001 +From: Ken Rossato +Date: Mon, 24 Sep 2012 19:52:09 -0400 +Subject: [PATCH 4/5] Ticket #481 - expand nested posix groups + +Description: Add ability to populate memberuid dynamically to +reflect nested grouping. +(cherry picked from commit b9eeb2e1a8e688dfec753e8965d0e5aeb119e638) +--- + Makefile.am | 1 + + Makefile.in | 1 + + ldap/ldif/50posix-winsync-plugin.ldif | 1 + + ldap/schema/60posix-winsync-plugin.ldif | 44 + + .../plugins/posix-winsync/posix-group-func.c | 846 ++++++++++++++++---- + .../plugins/posix-winsync/posix-group-task.c | 249 +++++-- + .../plugins/posix-winsync/posix-winsync-config.c | 16 + + ldap/servers/plugins/posix-winsync/posix-winsync.c | 72 ++- + .../plugins/posix-winsync/posix-wsp-ident.h | 4 +- + 9 files changed, 1008 insertions(+), 226 deletions(-) + create mode 100644 ldap/schema/60posix-winsync-plugin.ldif + +diff --git a/Makefile.am b/Makefile.am +index c5c4080..507a2d6 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -299,6 +299,7 @@ schema_DATA = $(srcdir)/ldap/schema/00core.ldif \ + $(srcdir)/ldap/schema/50ns-value.ldif \ + $(srcdir)/ldap/schema/50ns-web.ldif \ + $(srcdir)/ldap/schema/60pam-plugin.ldif \ ++ $(srcdir)/ldap/schema/60posix-winsync-plugin.ldif \ + $(srcdir)/ldap/schema/60autofs.ldif \ + $(srcdir)/ldap/schema/60eduperson.ldif \ + $(srcdir)/ldap/schema/60mozilla.ldif \ +diff --git a/Makefile.in b/Makefile.in +index 3777829..f105932 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -1527,6 +1527,7 @@ schema_DATA = $(srcdir)/ldap/schema/00core.ldif \ + $(srcdir)/ldap/schema/50ns-value.ldif \ + $(srcdir)/ldap/schema/50ns-web.ldif \ + $(srcdir)/ldap/schema/60pam-plugin.ldif \ ++ $(srcdir)/ldap/schema/60posix-winsync-plugin.ldif \ + $(srcdir)/ldap/schema/60autofs.ldif \ + $(srcdir)/ldap/schema/60eduperson.ldif \ + $(srcdir)/ldap/schema/60mozilla.ldif \ +diff --git a/ldap/ldif/50posix-winsync-plugin.ldif b/ldap/ldif/50posix-winsync-plugin.ldif +index de8c432..17dc243 100644 +--- a/ldap/ldif/50posix-winsync-plugin.ldif ++++ b/ldap/ldif/50posix-winsync-plugin.ldif +@@ -10,6 +10,7 @@ nsslapd-pluginenabled: off + nsslapd-plugin-depends-on-type: database + posixWinsyncMsSFUSchema: false + posixWinsyncMapMemberUID: true ++posixWinsyncMapNestedGrouping: false + posixWinsyncCreateMemberOfTask: false + posixWinsyncLowerCaseUID: false + nsslapd-pluginprecedence: 25 +diff --git a/ldap/schema/60posix-winsync-plugin.ldif b/ldap/schema/60posix-winsync-plugin.ldif +new file mode 100644 +index 0000000..8d9a72e +--- /dev/null ++++ b/ldap/schema/60posix-winsync-plugin.ldif +@@ -0,0 +1,44 @@ ++# ++# BEGIN COPYRIGHT BLOCK ++# This Program is free software; you can redistribute it and/or modify it under ++# the terms of the GNU General Public License as published by the Free Software ++# Foundation; version 2 of the License. ++# ++# This Program is distributed in the hope that it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple ++# Place, Suite 330, Boston, MA 02111-1307 USA. ++# ++# In addition, as a special exception, Red Hat, Inc. gives You the additional ++# right to link the code of this Program with code not covered under the GNU ++# General Public License ("Non-GPL Code") and to distribute linked combinations ++# including the two, subject to the limitations in this paragraph. Non-GPL Code ++# permitted under this exception must only link to the code of this Program ++# through those well defined interfaces identified in the file named EXCEPTION ++# found in the source code files (the "Approved Interfaces"). The files of ++# Non-GPL Code may instantiate templates or use macros or inline functions from ++# the Approved Interfaces without causing the resulting work to be covered by ++# the GNU General Public License. Only Red Hat, Inc. may make changes or ++# additions to the list of Approved Interfaces. You must obey the GNU General ++# Public License in all respects for all of the Program code and other code used ++# in conjunction with the Program except the Non-GPL Code covered by this ++# exception. If you modify this file, you may extend this exception to your ++# version of the file, but you are not obligated to do so. If you do not wish to ++# provide this exception without modification, you must delete this exception ++# statement from your version and license this file solely under the GPL without ++# exception. ++# ++# ++# Copyright (C) 2005 Red Hat, Inc. ++# All rights reserved. ++# END COPYRIGHT BLOCK ++# ++# ++# Schema for representing internal dynamically-generated group members ++# ++dn: cn=schema ++attributeTypes: ( 2.16.840.1.113730.3.1.2141 NAME 'dsOnlyMemberUid' DESC 'Elements from a memberuid attribute created to reflect dynamic group membership' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Red Hat Directory Server' ) ++objectClasses: ( 2.16.840.1.113730.3.2.326 NAME 'dynamicGroup' DESC 'Group containing internal dynamically-generated members' SUP posixGroup AUXILIARY MAY ( dsOnlyMemberUid ) X-ORIGIN 'Red Hat Directory Server' ) +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-func.c b/ldap/servers/plugins/posix-winsync/posix-group-func.c +index 1403a89..66b9272 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-func.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-func.c +@@ -18,11 +18,14 @@ + $Id: posix-group-func.c 28 2011-05-13 14:35:29Z grzemba $ + */ + #include "slapi-plugin.h" ++#include "slapi-private.h" + + #include + #include + #include "posix-wsp-ident.h" + ++#define MAX_RECURSION_DEPTH (5) ++ + Slapi_Value ** + valueset_get_valuearray(const Slapi_ValueSet *vs); /* stolen from proto-slap.h */ + static PRMonitor *memberuid_operation_lock = 0; +@@ -45,58 +48,100 @@ memberUidLockInit() + return (memberuid_operation_lock = PR_NewMonitor()) != NULL; + } + ++void ++addDynamicGroupIfNecessary(Slapi_Entry *entry, Slapi_Mods *smods) { ++ Slapi_Attr *oc_attr = NULL; ++ Slapi_Value *voc = slapi_value_new(); ++ ++ slapi_value_init_string(voc, "dynamicGroup"); ++ slapi_entry_attr_find(entry, "objectClass", &oc_attr); ++ ++ if (slapi_attr_value_find(oc_attr, slapi_value_get_berval(voc)) != 0) { ++ if (smods) { ++ slapi_mods_add_string(smods, LDAP_MOD_ADD, "objectClass", "dynamicGroup"); ++ } ++ else { ++ smods = slapi_mods_new(); ++ slapi_mods_add_string(smods, LDAP_MOD_ADD, "objectClass", "dynamicGroup"); ++ ++ Slapi_PBlock *mod_pb = slapi_pblock_new(); ++ slapi_modify_internal_set_pb_ext(mod_pb, slapi_entry_get_sdn(entry), slapi_mods_get_ldapmods_passout(smods), 0, 0, ++ posix_winsync_get_plugin_identity(), 0); ++ slapi_modify_internal_pb(mod_pb); ++ slapi_pblock_destroy(mod_pb); ++ ++ slapi_mods_free(&smods); ++ } ++ } ++ ++ slapi_value_free(&voc); ++} ++ ++Slapi_Entry * ++getEntry(const char *udn, char **attrs) ++{ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "getEntry: search %s\n", udn); ++ ++ Slapi_DN *udn_sdn = slapi_sdn_new_dn_byval(udn); ++ Slapi_Entry *result = NULL; ++ int rc = slapi_search_internal_get_entry(udn_sdn, attrs, &result, posix_winsync_get_plugin_identity()); ++ slapi_sdn_free(&udn_sdn); ++ ++ if (rc == 0) { ++ if (result != NULL) { ++ return result; /* Must be freed */ ++ } ++ else { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getEntry: %s not found\n", udn); ++ } ++ } ++ else { ++ slapi_log_error(SLAPI_LOG_FATAL, POSIX_WINSYNC_PLUGIN_NAME, ++ "getEntry: error searching for uid: %d", rc); ++ } ++ ++ return NULL; ++} ++ + /* search the user with DN udn and returns uid*/ + char * + searchUid(const char *udn) + { +- Slapi_PBlock *int_search_pb = slapi_pblock_new(); +- Slapi_Entry **entries = NULL; +- char *attrs[] = { "uid", NULL }; ++ char *attrs[] = { "uid", "objectclass", NULL }; ++ Slapi_Entry *entry = getEntry(udn, ++ /* "(|(objectclass=posixAccount)(objectclass=ldapsubentry))", */ ++ attrs); + char *uid = NULL; + +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "search Uid: search %s\n", udn); ++ if (entry) { ++ Slapi_Attr *attr = NULL; ++ Slapi_Value *v = NULL; + +- slapi_search_internal_set_pb(int_search_pb, udn, LDAP_SCOPE_BASE, +- "(|(objectclass=posixAccount)(objectclass=ldapsubentry))", attrs, +- 0 /* attrsonly */, NULL /* controls */, NULL /* uniqueid */, +- posix_winsync_get_plugin_identity(), 0 /* actions */); +- if (slapi_search_internal_pb(int_search_pb)) { +- /* get result and log an error */ +- int res = 0; +- slapi_pblock_get(int_search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res); +- slapi_log_error(SLAPI_LOG_FATAL, POSIX_WINSYNC_PLUGIN_NAME, +- "searchUid: error searching for uid: %d", res); +- } else { +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "searchUid: searched %s\n", +- udn); +- slapi_pblock_get(int_search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); +- if (NULL != entries && NULL != entries[0]) { +- Slapi_Attr *attr = NULL; +- Slapi_Value *v = NULL; ++ if (slapi_entry_attr_find(entry, "uid", &attr) == 0 && hasObjectClass(entry, "posixAccount")) { ++ slapi_attr_first_value(attr, &v); ++ uid = slapi_ch_strdup(slapi_value_get_string(v)); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "searchUid: return uid %s\n", uid); ++ } else { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "searchUid: uid in %s not found\n", udn); ++ } + +- if (slapi_entry_attr_find(entries[0], "uid", &attr) == 0) { +- slapi_attr_first_value(attr, &v); +- uid = slapi_ch_strdup(slapi_value_get_string(v)); +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "searchUid: return uid %s\n", uid); +- /* slapi_value_free(&v); */ +- } else { +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "searchUid: uid in %s not found\n", udn); +- } +- slapi_free_search_results_internal(int_search_pb); +- slapi_pblock_destroy(int_search_pb); +- if (uid && posix_winsync_config_get_lowercase()) { +- return slapi_dn_ignore_case(uid); +- } +- return uid; ++ if (uid && posix_winsync_config_get_lowercase()) { ++ uid = slapi_dn_ignore_case(uid); + } ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "searchUid: About to free entry\n", udn); ++ ++ slapi_entry_free(entry); + } +- slapi_free_search_results_internal(int_search_pb); +- slapi_pblock_destroy(int_search_pb); ++ + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "searchUid: posix user %s not found\n", udn); +- return NULL; ++ "searchUid: <==\n", udn); ++ ++ return uid; + } + + int +@@ -152,6 +197,36 @@ uid_in_set(const char* uid, char **uids) + return false; + } + ++int ++uid_in_valueset(const char* uid, Slapi_ValueSet *uids) ++{ ++ int i; ++ Slapi_Value *v = NULL; ++ ++ if (uid == NULL) ++ return false; ++ for (i = slapi_valueset_first_value(uids, &v); i != -1; ++ i = slapi_valueset_next_value(uids, i, &v)) { ++ Slapi_RDN *i_rdn = NULL; ++ char *i_uid = NULL; ++ char *t = NULL; ++ ++ const char *uid_i = slapi_value_get_string(v); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "uid_in_valueset: comp %s %s \n", ++ uid, uid_i); ++ i_rdn = slapi_rdn_new_dn(uid_i); ++ if (slapi_rdn_get_first(i_rdn, &t, &i_uid) == 1) { ++ if (strncasecmp(uid, i_uid, 256) == 0) { ++ slapi_rdn_free(&i_rdn); ++ return true; ++ } ++ } ++ slapi_rdn_free(&i_rdn); ++ } ++ return false; ++} ++ + /* return 1 if smods already has the given mod - 0 otherwise */ + static int + smods_has_mod(Slapi_Mods *smods, int modtype, const char *type, const char *val) +@@ -186,7 +261,7 @@ smods_has_mod(Slapi_Mods *smods, int modtype, const char *type, const char *val) + } + + int +-isPosixGroup(Slapi_Entry *entry) ++hasObjectClass(Slapi_Entry *entry, const char *objectClass) + { + int rc = 0; + int i; +@@ -200,7 +275,7 @@ isPosixGroup(Slapi_Entry *entry) + } + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "add/mod-GroupMembership scan objectclasses\n"); ++ "Scanning objectclasses\n"); + + for ( + i = slapi_attr_first_value(obj_attr, &value); +@@ -209,22 +284,357 @@ isPosixGroup(Slapi_Entry *entry) + ) { + const char *oc = NULL; + oc = slapi_value_get_string(value); +- if (strncasecmp(oc, "posixGroup", 11) == 0) { +- return 1; /* Entry has objectclass posixGroup */ ++ if (strcasecmp(oc, objectClass) == 0) { ++ return 1; /* Entry has the desired objectclass */ ++ } ++ } ++ ++ return 0; /* Doesn't have desired objectclass */ ++} ++ ++void ++posix_winsync_foreach_parent(Slapi_Entry *entry, char **attrs, plugin_search_entry_callback callback, void *callback_data) ++{ ++ char *cookie = NULL; ++ Slapi_Backend *be = NULL; ++ ++ const char *value = slapi_entry_get_ndn(entry); ++ size_t vallen = value ? strlen(value) : 0; ++ char *filter_escaped_value = slapi_ch_calloc(sizeof(char), vallen*3+1); ++ char *filter = slapi_ch_smprintf("(uniqueMember=%s)", escape_filter_value(value, vallen, filter_escaped_value)); ++ slapi_ch_free_string(&filter_escaped_value); ++ ++ Slapi_PBlock *search_pb = slapi_pblock_new(); ++ ++ for (be = slapi_get_first_backend(&cookie); be; ++ be = slapi_get_next_backend(cookie)) { ++ const Slapi_DN *base_sdn = slapi_be_getsuffix(be, 0); ++ if (base_sdn == NULL) { ++ continue; + } ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_winsync_foreach_parent: Searching subtree %s for %s\n", ++ slapi_sdn_get_dn(base_sdn), ++ filter); ++ ++ slapi_search_internal_set_pb(search_pb, ++ slapi_sdn_get_dn(base_sdn), ++ LDAP_SCOPE_SUBTREE, ++ filter, ++ attrs, 0, NULL, NULL, ++ posix_winsync_get_plugin_identity(), 0); ++ slapi_search_internal_callback_pb(search_pb, callback_data, 0, callback, 0); ++ ++ slapi_pblock_init(search_pb); + } + +- return 0; /* Doesn't have objectclass "posixGroup" */ ++ slapi_pblock_destroy(search_pb); ++ slapi_ch_free((void**)&cookie); ++ slapi_ch_free_string(&filter); + } + +-int +-modGroupMembership(Slapi_Entry *entry, Slapi_Mods *smods, int *do_modify) ++/* Retrieve nested membership from chains of groups. ++ * Muid_vs in => any preexisting membership list ++ * out => the union of the input list and the total membership ++ * Muid_nested_vs out => the members of muid_vs "out" that weren't in muid_vs "in" ++ * deletions in => Any elements to NOT consider if members of base_sdn ++ */ ++void ++getMembershipFromDownward(Slapi_Entry *entry, Slapi_ValueSet *muid_vs, Slapi_ValueSet *muid_nested_vs, Slapi_ValueSet *deletions, const Slapi_DN *base_sdn, int depth) + { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward: ==>\n"); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward: entry name: %s\n", ++ slapi_entry_get_dn_const(entry)); ++ + int rc = 0; ++ Slapi_Attr *um_attr = NULL; /* Entry attributes uniqueMember */ ++ Slapi_Value *uid_value = NULL; /* uniqueMember attribute values */ ++ ++ if (depth >= MAX_RECURSION_DEPTH) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward: recursion limit reached: %d\n", depth); ++ return; ++ } ++ ++ rc = slapi_entry_attr_find(entry, "uniquemember", &um_attr); ++ if (rc != 0 || um_attr == NULL) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward end: attribute uniquemember not found\n"); ++ return; ++ } ++ ++ int i; ++ for (i = slapi_attr_first_value(um_attr, &uid_value); i != -1; ++ i = slapi_attr_next_value(um_attr, i, &uid_value)) { ++ ++ char *attrs[] = { "uniqueMember", "memberUid", "uid", "objectClass", NULL }; ++ const char *uid_dn = slapi_value_get_string(uid_value); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward: iterating uniqueMember: %s\n", ++ uid_dn); ++ ++ if (deletions && !slapi_sdn_compare(slapi_entry_get_sdn_const(entry), base_sdn)) { ++ if (slapi_valueset_find(um_attr, deletions, uid_value)) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward: Skipping iteration because of deletion\n"); ++ ++ continue; ++ } ++ } ++ ++ Slapi_Entry *child = getEntry(uid_dn, attrs); ++ ++ if (!child) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward end: child not found: %s\n", uid_dn); ++ } ++ else { ++ /* PosixGroups except for the top one are already fully mapped out */ ++ if ((!hasObjectClass(entry, "posixGroup") || depth == 0) && ++ (hasObjectClass(child, "ntGroup") || hasObjectClass(child, "posixGroup"))) { ++ ++ /* Recurse downward */ ++ getMembershipFromDownward(child, muid_vs, muid_nested_vs, deletions, base_sdn, depth + 1); ++ } ++ ++ if (hasObjectClass(child, "posixAccount")) { ++ Slapi_Attr *uid_attr = NULL; ++ Slapi_Value *v = NULL; ++ if (slapi_entry_attr_find(child, "uid", &uid_attr) == 0) { ++ slapi_attr_first_value(uid_attr, &v); ++ ++ if (v && !slapi_valueset_find(uid_attr, muid_vs, v)) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward: adding member: %s\n", ++ slapi_value_get_string(v)); ++ slapi_valueset_add_value(muid_vs, v); ++ slapi_valueset_add_value(muid_nested_vs, v); ++ } ++ } ++ } ++ slapi_entry_free(child); ++ } ++ } ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "getMembershipFromDownward: <==\n"); ++} ++ ++struct propogateMembershipUpwardArgs { ++ Slapi_ValueSet *muid_vs; ++ int depth; ++}; ++ ++/* Forward declaration for next function */ ++void propogateMembershipUpward(Slapi_Entry *, Slapi_ValueSet *, int); ++ ++int ++propogateMembershipUpwardCallback(Slapi_Entry *child, void *callback_data) ++{ ++ struct propogateMembershipUpwardArgs *args = (struct propogateMembershipUpwardArgs *)(callback_data); ++ propogateMembershipUpward(child, args->muid_vs, args->depth); ++ return 0; ++} ++ ++void ++propogateMembershipUpward(Slapi_Entry *entry, Slapi_ValueSet *muid_vs, int depth) ++{ ++ if (depth >= MAX_RECURSION_DEPTH) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateMembershipUpward: recursion limit reached: %d\n", depth); ++ return; ++ } ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateMembershipUpward: ==>\n"); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateMembershipUpward: entry name: %s\n", ++ slapi_entry_get_dn_const(entry)); ++ ++ Slapi_ValueSet *muid_here_vs = NULL; ++ Slapi_ValueSet *muid_upward_vs = NULL; ++ ++ /* Get the memberUids at this location, and figure out local changes to memberUid (if any) ++ * and changes to send upward. ++ */ ++ if (depth > 0 && hasObjectClass(entry, "posixGroup")) { ++ int addDynamicGroup = 0; ++ Slapi_Attr *muid_old_attr = NULL; ++ Slapi_ValueSet *muid_old_vs = NULL; ++ int rc = slapi_entry_attr_find(entry, "memberUid", &muid_old_attr); ++ if (rc != 0 || muid_old_attr == NULL) { /* Found no memberUid list, so create */ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateMembershipUpward: no attribute memberUid\n"); ++ ++ /* There's no values from this entry to add */ ++ muid_upward_vs = muid_vs; ++ muid_here_vs = muid_vs; ++ } ++ else { ++ /* Eliminate duplicates */ ++ muid_upward_vs = slapi_valueset_new(); ++ muid_here_vs = slapi_valueset_new(); ++ ++ slapi_valueset_set_valueset(muid_upward_vs, muid_old_vs); ++ ++ slapi_attr_get_valueset(muid_old_attr, &muid_old_vs); ++ int i = 0; ++ Slapi_Value *v = NULL; ++ for (i = slapi_valueset_first_value(muid_vs, &v); i != -1; ++ i = slapi_valueset_next_value(muid_vs, i, &v)) { ++ ++ if (!slapi_valueset_find(muid_old_attr, muid_old_vs, v)) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateMembershipUpward: adding %s to set\n", ++ slapi_value_get_string(v)); ++ ++ addDynamicGroup = 1; ++ slapi_valueset_add_value(muid_here_vs, v); ++ slapi_valueset_add_value(muid_upward_vs, v); ++ } ++ } ++ } ++ ++ /* Update this group's membership */ ++ slapi_entry_add_valueset(entry, "memberUid", muid_here_vs); ++ if (addDynamicGroup) { ++ addDynamicGroupIfNecessary(entry, NULL); ++ slapi_entry_add_valueset(entry, "dsOnlyMemberUid", muid_here_vs); ++ } ++ } ++ else { ++ muid_upward_vs = muid_vs; ++ } ++ ++ /* Find groups containing this one, recurse ++ */ ++ char *attrs[] = {"memberUid", "objectClass", NULL}; ++ struct propogateMembershipUpwardArgs data = {muid_upward_vs, depth + 1}; ++ ++ posix_winsync_foreach_parent(entry, attrs, propogateMembershipUpwardCallback, &data); ++ ++/* Cleanup */ ++ if (muid_here_vs && muid_here_vs != muid_vs) { ++ slapi_valueset_free(muid_here_vs); muid_here_vs = NULL; ++ } ++ if (muid_upward_vs && muid_upward_vs != muid_vs) { ++ slapi_valueset_free(muid_upward_vs); muid_upward_vs = NULL; ++ } + ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateMembershipUpward: <==\n"); ++} ++ ++struct propogateDeletionsUpwardArgs { ++ const Slapi_DN *base_sdn; ++ Slapi_ValueSet *smod_deluids; ++ Slapi_ValueSet *del_nested_vs; ++ int depth; ++}; ++ ++/* Forward declaration for next function */ ++void propogateDeletionsUpward(Slapi_Entry *, const Slapi_DN *, Slapi_ValueSet*, Slapi_ValueSet *, int); ++ ++int ++propogateDeletionsUpwardCallback(Slapi_Entry *entry, void *callback_data) ++{ ++ struct propogateDeletionsUpwardArgs *args = (struct propogateDeletionsUpwardArgs *)(callback_data); ++ propogateDeletionsUpward(entry, args->base_sdn, args->smod_deluids, args->del_nested_vs, args->depth); ++} ++ ++void ++propogateDeletionsUpward(Slapi_Entry *entry, const Slapi_DN *base_sdn, Slapi_ValueSet *smod_deluids, Slapi_ValueSet *del_nested_vs, int depth) ++{ ++ if (smod_deluids == NULL) return; ++ ++ if (depth >= MAX_RECURSION_DEPTH) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateDeletionsUpward: recursion limit reached: %d\n", depth); ++ return; ++ } ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateDeletionsUpward: ==>\n"); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateDeletionsUpward: entry name: %s\n", ++ slapi_entry_get_dn_const(entry)); ++ ++ char *attrs[] = { "uniqueMember", "memberUid", "objectClass", NULL }; ++ struct propogateDeletionsUpwardArgs data = {base_sdn, smod_deluids, del_nested_vs, depth + 1}; ++ posix_winsync_foreach_parent(entry, attrs, propogateDeletionsUpwardCallback, &data); ++ ++ Slapi_Attr *muid_attr = NULL; ++ int rc = slapi_entry_attr_find(entry, "dsOnlyMemberUid", &muid_attr); ++ ++ if (rc == 0 && muid_attr != NULL) { ++ ++ Slapi_ValueSet *muid_vs = slapi_valueset_new(); ++ Slapi_ValueSet *muid_nested_vs = slapi_valueset_new(); ++ Slapi_ValueSet *muid_deletions_vs = slapi_valueset_new(); ++ ++ getMembershipFromDownward(entry, muid_vs, muid_nested_vs, smod_deluids, base_sdn, 0); ++ ++ int i; ++ Slapi_Value *v; ++ for (i = slapi_attr_first_value(muid_attr, &v); i != -1; ++ i = slapi_attr_next_value(muid_attr, i, &v)) { ++ if (!slapi_valueset_find(muid_attr, muid_vs, v)) { ++ const char *uid = slapi_value_get_string(v); ++ if (depth == 0 && !uid_in_valueset(uid, smod_deluids)) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateDeletionsUpward: Adding deletion to modlist: %s\n", ++ slapi_value_get_string(v)); ++ slapi_valueset_add_value(del_nested_vs, v); ++ } ++ else if (depth > 0) { ++ slapi_valueset_add_value(muid_deletions_vs, v); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateDeletionsUpward: Adding deletion to deletion list: %s\n", ++ slapi_value_get_string(v)); ++ } ++ } ++ } ++ ++ if (depth > 0) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateDeletionsUpward: executing deletion list\n"); ++ ++ Slapi_Mods *smods = slapi_mods_new(); ++ slapi_mods_add_mod_values(smods, LDAP_MOD_DELETE, "memberuid", valueset_get_valuearray(muid_deletions_vs)); ++ slapi_mods_add_mod_values(smods, LDAP_MOD_DELETE, "dsonlymemberuid", valueset_get_valuearray(muid_deletions_vs)); ++ ++ Slapi_PBlock *mod_pb = slapi_pblock_new(); ++ slapi_modify_internal_set_pb_ext(mod_pb, slapi_entry_get_sdn(entry), slapi_mods_get_ldapmods_passout(smods), 0, 0, ++ posix_winsync_get_plugin_identity(), 0); ++ slapi_modify_internal_pb(mod_pb); ++ slapi_pblock_destroy(mod_pb); ++ ++ slapi_mods_free(&smods); ++ } ++ ++ slapi_valueset_free(muid_vs); muid_vs = NULL; ++ slapi_valueset_free(muid_nested_vs); muid_nested_vs = NULL; ++ slapi_valueset_free(muid_deletions_vs); muid_deletions_vs = NULL; ++ } ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "propogateDeletionsUpward: <==\n"); ++} ++ ++int ++modGroupMembership(Slapi_Entry *entry, Slapi_Mods *smods, int *do_modify) ++{ + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "modGroupMembership: ==>\n"); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "modGroupMembership: Modding %s\n", ++ slapi_entry_get_dn_const(entry)); + +- if (!isPosixGroup(entry)) { ++ int posixGroup = hasObjectClass(entry, "posixGroup"); ++ ++ if (!(posixGroup || hasObjectClass(entry, "ntGroup"))) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "modGroupMembership end: Not a posixGroup or ntGroup\n"); + return 0; + } + +@@ -232,7 +642,7 @@ modGroupMembership(Slapi_Entry *entry, Slapi_Mods *smods, int *do_modify) + Slapi_Mod *nextMod = slapi_mod_new(); + int del_mod = 0; /* Bool: was there a delete mod? */ + char **smod_adduids = NULL; +- char **smod_deluids = NULL; ++ Slapi_ValueSet *smod_deluids = NULL; + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, + "modGroupMembership: posixGroup -> look for uniquemember\n"); +@@ -243,15 +653,20 @@ modGroupMembership(Slapi_Entry *entry, Slapi_Mods *smods, int *do_modify) + if (slapi_attr_types_equivalent(slapi_mod_get_type(smod), "uniqueMember")) { + struct berval *bv; + ++ int current_del_mod = SLAPI_IS_MOD_DELETE(slapi_mod_get_operation(smod)); ++ if (current_del_mod) { ++ del_mod = 1; ++ } ++ + for (bv = slapi_mod_get_first_value(smod); bv; + bv = slapi_mod_get_next_value(smod)) { + Slapi_Value *sv = slapi_value_new(); + + slapi_value_init_berval(sv, bv); /* copies bv_val */ +- if (SLAPI_IS_MOD_DELETE(slapi_mod_get_operation(smod))) { +- del_mod = 1; +- slapi_ch_array_add(&smod_deluids, +- slapi_ch_strdup(slapi_value_get_string(sv))); ++ if (current_del_mod) { ++ if (!smod_deluids) smod_deluids = slapi_valueset_new(); ++ ++ slapi_valueset_add_value(smod_deluids, sv); + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, + "modGroupMembership: add to deluids %s\n", + bv->bv_val); +@@ -268,60 +683,67 @@ modGroupMembership(Slapi_Entry *entry, Slapi_Mods *smods, int *do_modify) + } + slapi_mod_free(&nextMod); + +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "modGroupMembership: entry is posixGroup\n"); +- +- Slapi_Attr * muid_attr = NULL; /* Entry attributes */ ++ int muid_rc = 0; ++ Slapi_Attr * muid_attr = NULL; /* Entry attributes */ ++ Slapi_ValueSet *muid_vs = NULL; + Slapi_Value * uid_value = NULL; /* Attribute values */ + +- char **adduids = NULL; +- char **moduids = NULL; +- char **deluids = NULL; +- int doModify = false; ++ Slapi_ValueSet *adduids = slapi_valueset_new(); ++ Slapi_ValueSet *add_nested_vs = slapi_valueset_new(); ++ Slapi_ValueSet *deluids = slapi_valueset_new(); ++ Slapi_ValueSet *del_nested_vs = slapi_valueset_new(); ++ ++ const Slapi_DN *base_sdn = slapi_entry_get_sdn_const(entry); ++ + int j = 0; + + if (del_mod || smod_deluids != NULL) { + do { /* Create a context to "break" from */ +- Slapi_Attr * mu_attr = NULL; /* Entry attributes */ +- rc = slapi_entry_attr_find(entry, "memberUid", &mu_attr); +- if (rc != 0 || mu_attr == NULL) { +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "modGroupMembership end: attribute memberUid not found\n"); +- break; +- } +- /* found attribute uniquemember */ ++ muid_rc = slapi_entry_attr_find(entry, "memberUid", &muid_attr); ++ + if (smod_deluids == NULL) { /* deletion of the last value, deletes the Attribut from entry complete, this operation has no value, so we must look by self */ + Slapi_Attr * um_attr = NULL; /* Entry attributes */ + Slapi_Value * uid_dn_value = NULL; /* Attribute values */ + int rc = slapi_entry_attr_find(entry, "uniquemember", &um_attr); ++ + if (rc != 0 || um_attr == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, + "modGroupMembership end: attribute uniquemember not found\n"); + break; + } +- /* found attribute uniquemember */ +- /* ...loop for value... */ +- for (j = slapi_attr_first_value(um_attr, &uid_dn_value); j != -1; +- j = slapi_attr_next_value(um_attr, j, &uid_dn_value)) { +- slapi_ch_array_add(&smod_deluids, +- slapi_ch_strdup(slapi_value_get_string(uid_dn_value))); +- } ++ ++ slapi_attr_get_valueset(um_attr, &smod_deluids); + } +- /* ...loop for value... */ +- for (j = slapi_attr_first_value(mu_attr, &uid_value); j != -1; +- j = slapi_attr_next_value(mu_attr, j, &uid_value)) { +- /* remove from uniquemember: remove from memberUid also */ +- const char *uid = NULL; ++ if (muid_rc != 0 || muid_attr == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "modGroupMembership: test dellist \n"); +- uid = slapi_value_get_string(uid_value); +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "modGroupMembership: test dellist %s\n", uid); +- if (uid_in_set(uid, smod_deluids)) { +- slapi_ch_array_add(&deluids, slapi_ch_strdup(uid)); ++ "modGroupMembership end: attribute memberUid not found\n"); ++ } ++ else if (posix_winsync_config_get_mapMemberUid()) { ++ /* ...loop for value... */ ++ for (j = slapi_attr_first_value(muid_attr, &uid_value); j != -1; ++ j = slapi_attr_next_value(muid_attr, j, &uid_value)) { ++ /* remove from uniquemember: remove from memberUid also */ ++ const char *uid = NULL; + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "modGroupMembership: add to dellist %s\n", uid); +- doModify = true; ++ "modGroupMembership: test dellist \n"); ++ uid = slapi_value_get_string(uid_value); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "modGroupMembership: test dellist %s\n", uid); ++ if (uid_in_valueset(uid, smod_deluids)) { ++ slapi_valueset_add_value(deluids, uid_value); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "modGroupMembership: add to dellist %s\n", uid); ++ } ++ } ++ } ++ ++ if (posix_winsync_config_get_mapNestedGrouping()) { ++ propogateDeletionsUpward(entry, base_sdn, smod_deluids, del_nested_vs, 0); ++ int i; ++ Slapi_Value *v; ++ for (i = slapi_valueset_first_value(del_nested_vs, &v); i != -1; ++ i = slapi_valueset_next_value(del_nested_vs, i, &v)) { ++ slapi_valueset_add_value(deluids, v); + } + } + } while (false); +@@ -331,93 +753,176 @@ modGroupMembership(Slapi_Entry *entry, Slapi_Mods *smods, int *do_modify) + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, + "modGroupMembership: posixGroup -> look for uniquemember\n"); +- /* found attribute uniquemember */ +- for (j = 0; smod_adduids[j]; j++) { +- static char *uid = NULL; + +- uid_dn = smod_adduids[j]; +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "modGroupMembership: perform user %s\n", uid_dn); ++ if (muid_rc == 0 && muid_attr == NULL) { ++ muid_rc = slapi_entry_attr_find(entry, "memberUid", &muid_attr); ++ } ++ if (muid_rc == 0 && muid_attr != NULL) { ++ slapi_attr_get_valueset(muid_attr, &muid_vs); ++ } ++ else { ++ muid_vs = slapi_valueset_new(); ++ } + +- uid = searchUid(uid_dn); ++ if (posix_winsync_config_get_mapMemberUid()) { ++ for (j = 0; smod_adduids[j]; j++) { ++ static char *uid = NULL; + +- if (uid == NULL) { ++ uid_dn = smod_adduids[j]; + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "modGroupMembership: uid not found for %s, cannot do anything\n", +- uid_dn); /* member on longer on server, do nothing */ +- } else { +- rc |= slapi_entry_attr_find(entry, "memberUid", &muid_attr); +- if (rc != 0 || muid_attr == NULL) { /* Found no memberUid list, so create */ ++ "modGroupMembership: perform user %s\n", uid_dn); ++ ++ uid = searchUid(uid_dn); ++ ++ if (uid == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "modGroupMembership: no attribute memberUid, add with %s \n", +- uid_dn); +- slapi_ch_array_add(&adduids, uid); +- uid = NULL; /* adduids now owns uid */ +- doModify = true; +- } else { /* Found a memberUid list, so modify */ +- Slapi_ValueSet *vs = NULL; ++ "modGroupMembership: uid not found for %s, cannot do anything\n", ++ uid_dn); /* member on longer on server, do nothing */ ++ } else { + Slapi_Value *v = slapi_value_new(); +- + slapi_value_init_string_passin(v, uid); +- slapi_attr_get_valueset(muid_attr, &vs); +- if (slapi_valueset_find(muid_attr, vs, v) != NULL) { /* already exist, all ok */ ++ ++ if (muid_rc == 0 && muid_attr != NULL && ++ slapi_valueset_find(muid_attr, muid_vs, v) != NULL) { ++ + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, + "modGroupMembership: uid found in memberuid list %s nothing to do\n", + uid); +- } else { +- slapi_ch_array_add(&moduids, uid); ++ } ++ else { ++ slapi_valueset_add_value(adduids, v); ++ slapi_valueset_add_value(muid_vs, v); + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, + "modGroupMembership: add to modlist %s\n", uid); +- uid = NULL; /* adduids now owns uid */ +- /* have to clear out v otherwise slapi_value_free will also free uid */ +- slapi_value_init_berval(v, NULL); +- doModify = true; + } ++ + slapi_value_free(&v); /* also frees uid since it was a passin */ +- slapi_valueset_free(vs); vs = NULL; + } + } + } ++ ++ if (posix_winsync_config_get_mapNestedGrouping()) { ++ ++ for (j = 0; smod_adduids[j]; ++j) { ++ char *attrs[] = { "uniqueMember", "memberUid", "uid", "objectClass", NULL }; ++ Slapi_Entry *child = getEntry(smod_adduids[j], attrs); ++ ++ if (child) { ++ if (hasObjectClass(child, "ntGroup") || hasObjectClass(child, "posixGroup")) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "modGroupMembership: Found mod to add group, adding membership: %s\n", ++ smod_adduids[j]); ++ Slapi_ValueSet *muid_tempnested = slapi_valueset_new(); ++ getMembershipFromDownward(child, muid_vs, add_nested_vs, smod_deluids, base_sdn, 0); ++ ++ slapi_valueset_free(muid_tempnested); muid_tempnested = NULL; ++ } ++ } ++ else { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "modGroupMembership: entry not found for dn: %s\n", ++ smod_adduids[j]); ++ } ++ } ++ ++ getMembershipFromDownward(entry, muid_vs, add_nested_vs, smod_deluids, base_sdn, 0); ++ int i = 0; ++ Slapi_Value *v = NULL; ++ for (i = slapi_valueset_first_value(add_nested_vs, &v); i != -1; ++ i = slapi_valueset_next_value(add_nested_vs, i, &v)) { ++ slapi_valueset_add_value(adduids, v); ++ } ++ ++ propogateMembershipUpward(entry, adduids, 0); ++ } + } +- if (doModify) { ++ if (posixGroup) { ++ int addDynamicGroup = 0; + int i; +- for (i = 0; adduids && adduids[i]; i++) { +- if (!smods_has_mod(smods, LDAP_MOD_ADD, "memberUid", adduids[i])) { +- slapi_mods_add_string(smods, LDAP_MOD_ADD, "memberUid", adduids[i]); ++ Slapi_Value *v; ++ for (i = slapi_valueset_first_value(adduids, &v); i != -1; ++ i = slapi_valueset_next_value(adduids, i, &v)){ ++ const char *muid = slapi_value_get_string(v); ++ if (!smods_has_mod(smods, LDAP_MOD_ADD, "memberUid", muid)) { ++ *do_modify = 1; ++ slapi_mods_add_string(smods, LDAP_MOD_ADD, "memberUid", muid); ++ } ++ } ++ for (i = slapi_valueset_first_value(add_nested_vs, &v); i != -1; ++ i = slapi_valueset_next_value(add_nested_vs, i, &v)) { ++ const char *muid = slapi_value_get_string(v); ++ if (!smods_has_mod(smods, LDAP_MOD_ADD, "dsOnlyMemberUid", muid)) { ++ addDynamicGroup = 1; ++ *do_modify = 1; ++ slapi_mods_add_string(smods, LDAP_MOD_ADD, "dsOnlyMemberUid", muid); + } + } +- for (i = 0; moduids && moduids[i]; i++) { +- if (!smods_has_mod(smods, LDAP_MOD_ADD, "memberUid", moduids[i])) { +- slapi_mods_add_string(smods, LDAP_MOD_ADD, "memberUid", moduids[i]); ++ for (i = slapi_valueset_first_value(deluids, &v); i != -1; ++ i = slapi_valueset_next_value(deluids, i, &v)){ ++ const char *muid = slapi_value_get_string(v); ++ if (!smods_has_mod(smods, LDAP_MOD_DELETE, "memberUid", muid)) { ++ *do_modify = 1; ++ slapi_mods_add_string(smods, LDAP_MOD_DELETE, "memberUid", muid); + } + } +- for (i = 0; deluids && deluids[i]; i++) { +- if (!smods_has_mod(smods, LDAP_MOD_DELETE, "memberUid", deluids[i])) { +- slapi_mods_add_string(smods, LDAP_MOD_DELETE, "memberUid", deluids[i]); ++ for (i = slapi_valueset_first_value(del_nested_vs, &v); i != -1; ++ i = slapi_valueset_next_value(del_nested_vs, i, &v)){ ++ const char *muid = slapi_value_get_string(v); ++ if (!smods_has_mod(smods, LDAP_MOD_DELETE, "dsOnlyMemberUid", muid)) { ++ *do_modify = 1; ++ slapi_mods_add_string(smods, LDAP_MOD_DELETE, "dsOnlyMemberUid", muid); + } + } ++ if (addDynamicGroup) { ++ addDynamicGroupIfNecessary(entry, smods); ++ } + + if (slapi_is_loglevel_set(SLAPI_LOG_PLUGIN)) + slapi_mods_dump(smods, "memberUid - mods dump"); +- *do_modify = 1; + posix_winsync_config_set_MOFTaskCreated(); + } + slapi_ch_array_free(smod_adduids); + smod_adduids = NULL; +- slapi_ch_array_free(adduids); +- adduids = NULL; +- slapi_ch_array_free(smod_deluids); ++ if (smod_deluids) slapi_valueset_free(smod_deluids); + smod_deluids = NULL; +- slapi_ch_array_free(deluids); ++ ++ slapi_valueset_free(adduids); ++ adduids = NULL; ++ slapi_valueset_free(deluids); + deluids = NULL; +- slapi_ch_array_free(moduids); +- moduids = NULL; ++ ++ slapi_valueset_free(add_nested_vs); add_nested_vs = NULL; ++ slapi_valueset_free(del_nested_vs); del_nested_vs = NULL; ++ ++ if (muid_vs) { ++ slapi_valueset_free(muid_vs); muid_vs = NULL; ++ } + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "modGroupMembership: <==\n"); + return 0; + } + + int ++addUserToGroupMembership(Slapi_Entry *entry) ++{ ++ Slapi_Attr *uid_attr = NULL; ++ Slapi_Value *v = NULL; ++ Slapi_ValueSet *muid_vs = slapi_valueset_new(); ++ ++ if (slapi_entry_attr_find(entry, "uid", &uid_attr) == 0) { ++ slapi_attr_first_value(uid_attr, &v); ++ ++ if (v) { ++ slapi_valueset_add_value(muid_vs, v); ++ } ++ } ++ ++ propogateMembershipUpward(entry, muid_vs, 0); ++ ++ slapi_valueset_free(muid_vs); muid_vs = NULL; ++} ++ ++int + addGroupMembership(Slapi_Entry *entry, Slapi_Entry *ad_entry) + { + int rc = 0; +@@ -425,7 +930,11 @@ addGroupMembership(Slapi_Entry *entry, Slapi_Entry *ad_entry) + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "addGroupMembership: ==>\n"); + +- if(!isPosixGroup(entry)) { ++ int posixGroup = hasObjectClass(entry, "posixGroup"); ++ ++ if(!(posixGroup || hasObjectClass(entry, "ntGroup"))) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "addGroupMembership: didn't find posixGroup or ntGroup objectclass\n"); + return 0; + } + +@@ -448,34 +957,55 @@ addGroupMembership(Slapi_Entry *entry, Slapi_Entry *ad_entry) + if (rc != 0 || muid_attr == NULL) { /* Found no memberUid list, so create */ + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, + "addGroupMembership: no attribute memberUid\n"); ++ muid_attr = NULL; + } + newvs = slapi_valueset_new(); + /* ...loop for value... */ +- for (i = slapi_attr_first_value(um_attr, &uid_value); i != -1; +- i = slapi_attr_next_value(um_attr, i, &uid_value)) { +- const char *uid_dn = NULL; +- static char *uid = NULL; +- Slapi_Value *v = NULL; ++ if (posix_winsync_config_get_mapMemberUid()) { ++ for (i = slapi_attr_first_value(um_attr, &uid_value); i != -1; ++ i = slapi_attr_next_value(um_attr, i, &uid_value)) { ++ const char *uid_dn = NULL; ++ static char *uid = NULL; ++ Slapi_Value *v = NULL; + +- uid_dn = slapi_value_get_string(uid_value); +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "addGroupMembership: perform member %s\n", uid_dn); +- uid = searchUid(uid_dn); +- if (uid == NULL) { ++ uid_dn = slapi_value_get_string(uid_value); + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "addGroupMembership: uid not found for %s, cannot do anything\n", +- uid_dn); /* member on longer on server, do nothing */ +- } else { +- v = slapi_value_new_string(uid); +- slapi_ch_free_string(&uid); +- if (slapi_attr_value_find(muid_attr, slapi_value_get_berval(v)) != 0) { +- slapi_valueset_add_value(newvs, v); ++ "addGroupMembership: perform member %s\n", uid_dn); ++ uid = searchUid(uid_dn); ++ if (uid == NULL) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "addGroupMembership: uid not found for %s, cannot do anything\n", ++ uid_dn); /* member on longer on server, do nothing */ ++ } else { ++ v = slapi_value_new_string(uid); ++ slapi_ch_free_string(&uid); ++ if (slapi_attr_value_find(muid_attr, slapi_value_get_berval(v)) != 0) { ++ slapi_valueset_add_value(newvs, v); ++ } ++ slapi_value_free(&v); + } +- slapi_value_free(&v); + } + } +- slapi_entry_add_valueset(entry, "memberUid", newvs); +- slapi_valueset_free(newvs); ++ ++ if (posix_winsync_config_get_mapNestedGrouping()) { ++ Slapi_ValueSet *muid_nested_vs = slapi_valueset_new(); ++ ++ getMembershipFromDownward(entry, newvs, muid_nested_vs, NULL, NULL, 0); ++ propogateMembershipUpward(entry, newvs, 0); ++ ++ if (posixGroup) { ++ addDynamicGroupIfNecessary(entry, NULL); ++ slapi_entry_add_valueset(entry, "dsOnlyMemberUid", muid_nested_vs); ++ } ++ ++ slapi_valueset_free(muid_nested_vs); muid_nested_vs = NULL; ++ } ++ ++ if (posixGroup) { ++ slapi_entry_add_valueset(entry, "memberUid", newvs); ++ } ++ ++ slapi_valueset_free(newvs); newvs = NULL; + posix_winsync_config_get_MOFTaskCreated(); + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "addGroupMembership: <==\n"); +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-task.c b/ldap/servers/plugins/posix-winsync/posix-group-task.c +index e31064c..4555f1b 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-task.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-task.c +@@ -25,11 +25,17 @@ typedef struct _cb_data + } posix_group_data_data; + */ + ++Slapi_Value ** ++valueset_get_valuearray(const Slapi_ValueSet *vs); /* stolen from proto-slap.h */ ++ + /* interface function */ + int + posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int *returncode, + char *returntext, void *arg); + ++Slapi_Entry * ++getEntry(const char *udn, char **attrs); ++ + static void + posix_group_task_destructor(Slapi_Task *task); + static void +@@ -67,6 +73,10 @@ posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int + + *returncode = LDAP_SUCCESS; + ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: ==>\n"); ++ + /* get arg(s) */ + /* default: set replication basedn */ + if ((dn = fetch_attr(e, "basedn", slapi_sdn_get_dn(posix_winsync_config_get_suffix()))) == NULL) { +@@ -75,12 +85,18 @@ posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int + goto out; + } + +- if ((filter = fetch_attr(e, "filter", "(&(objectclass=posixGroup)(uniquemember=*))")) == NULL) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: retrieved basedn: %s\n", dn); ++ ++ if ((filter = fetch_attr(e, "filter", "(objectclass=ntGroup)")) == NULL) { + *returncode = LDAP_OBJECT_CLASS_VIOLATION; + rv = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } + ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: retrieved filter: %s\n", filter); ++ + /* setup our task data */ + mytaskdata = (task_data*) slapi_ch_malloc(sizeof(task_data)); + if (mytaskdata == NULL) { +@@ -91,19 +107,41 @@ posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int + mytaskdata->dn = slapi_ch_strdup(dn); + mytaskdata->filter_str = slapi_ch_strdup(filter); + ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: task data allocated\n"); ++ + /* allocate new task now */ +- task = slapi_new_task(slapi_entry_get_ndn(e)); ++ char * ndn = slapi_entry_get_ndn(e); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: creating task object: %s\n", ++ ndn); ++ ++ task = slapi_new_task(ndn); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: task object created\n"); + + /* register our destructor for cleaning up our private data */ + slapi_task_set_destructor_fn(task, posix_group_task_destructor); + ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: task destructor set\n"); ++ + /* Stash a pointer to our data in the task */ + slapi_task_set_data(task, mytaskdata); + ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: task object initialized\n"); ++ + /* start the sample task as a separate thread */ + thread = PR_CreateThread(PR_USER_THREAD, posix_group_fixup_task_thread, (void *) task, + PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, + SLAPD_DEFAULT_THREAD_STACKSIZE); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: thread created\n"); ++ + if (thread == NULL) { + slapi_log_error(SLAPI_LOG_FATAL, POSIX_WINSYNC_PLUGIN_NAME, + "unable to create task thread!\n"); +@@ -114,7 +152,11 @@ posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int + rv = SLAPI_DSE_CALLBACK_OK; + } + +- out: return rv; ++ out: ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "posix_group_task_add: <==\n", filter); ++ ++ return rv; + } + + static void +@@ -195,86 +237,172 @@ posix_group_fix_memberuid(char *dn, char *filter_str, void *txn) + static int + posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data) + { +- int rc = 0; ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid ==>\n"); ++ cb_data *the_cb_data = (cb_data *) callback_data; ++ ++ int rc; ++ Slapi_Attr *muid_attr = NULL; ++ Slapi_Value *v = NULL; ++ ++ Slapi_Mods *smods = slapi_mods_new(); ++ + char *dn = slapi_entry_get_dn(e); + Slapi_DN *sdn = slapi_entry_get_sdn(e); + +- Slapi_Attr *obj_attr = NULL; ++/* Clean out memberuids and dsonlymemberuids without a valid referant */ ++ rc = slapi_entry_attr_find(e, "memberuid", &muid_attr); ++ if (rc == 0 && muid_attr) { ++ Slapi_PBlock *search_pb = slapi_pblock_new(); ++ ++ Slapi_Attr *dsmuid_attr = NULL; ++ Slapi_ValueSet *dsmuid_vs = NULL; ++ ++ char *attrs[] = { "uid", NULL }; ++ ++ rc = slapi_entry_attr_find(e, "dsonlymemberuid", &dsmuid_attr); ++ if (rc == 0 && dsmuid_attr) { ++ slapi_attr_get_valueset(dsmuid_attr, &dsmuid_vs); ++ } ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid scan for orphaned memberuids\n"); ++ ++ int i; ++ for (i = slapi_attr_first_value(muid_attr, &v); i != -1; ++ i = slapi_attr_next_value(muid_attr, i, &v)) { ++ const char *muid = slapi_value_get_string(v); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid iterating memberuid: %s\n", ++ muid); ++ ++ size_t vallen = muid ? strlen(muid) : 0; ++ char *filter_escaped_value = slapi_ch_calloc(sizeof(char), vallen*3+1); ++ char *filter = slapi_ch_smprintf("(uid=%s)", escape_filter_value(muid, vallen, filter_escaped_value)); ++ slapi_ch_free_string(&filter_escaped_value); ++ ++ Slapi_Entry **search_entries = NULL; ++ ++ slapi_search_internal_set_pb(search_pb, ++ the_cb_data->dn, ++ LDAP_SCOPE_SUBTREE, ++ filter, ++ attrs, 0, NULL, NULL, ++ posix_winsync_get_plugin_identity(), 0); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid searching %s with filter: %s\n", ++ the_cb_data->dn, filter); + ++ rc = slapi_search_internal_pb(search_pb); ++ ++ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &search_entries); ++ ++ if (!search_entries || !search_entries[0]) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid Adding bad memberuid %s\n", ++ slapi_value_get_string(v)); ++ ++ slapi_mods_add_string(smods, LDAP_MOD_DELETE, "memberuid", slapi_value_get_string(v)); ++ ++ if (dsmuid_vs && slapi_valueset_find(dsmuid_attr, dsmuid_vs, v)) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid Adding bad dsonlymemberuid %s\n", ++ slapi_value_get_string(v)); ++ ++ slapi_mods_add_string(smods, LDAP_MOD_DELETE, "dsonlymemberuid", slapi_value_get_string(v)); ++ } ++ } ++ ++ slapi_free_search_results_internal(search_pb); ++ slapi_pblock_init(search_pb); ++ slapi_ch_free_string(&filter); ++ } ++ ++ if (dsmuid_vs) { ++ slapi_valueset_free(dsmuid_vs); dsmuid_vs = NULL; ++ } ++ ++ slapi_pblock_destroy(search_pb); search_pb = NULL; ++ } ++ ++ /* Cleanup uniquemembers without a referent, and verify memberuid otherwise */ ++ Slapi_Attr *obj_attr = NULL; + rc = slapi_entry_attr_find(e, "uniquemember", &obj_attr); +- if (rc == 0) { /* Found uniquemember, so... */ ++ if (rc == 0 && obj_attr) { ++ int fixMembership = 0; ++ Slapi_ValueSet *bad_ums = NULL; ++ + int i; +- Slapi_Value * value = slapi_value_new(); /* new memberuid Attribute values */ +- Slapi_Value * uniqval = NULL; /* uniquemeber Attribute values */ +- Slapi_ValueSet *uids = slapi_valueset_new(); ++ Slapi_Value * uniqval = NULL; /* uniquemeber Attribute values */ + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, + "_fix_memberuid scan uniquemember, group %s\n", dn); + for (i = slapi_attr_first_value(obj_attr, &uniqval); i != -1; + i = slapi_attr_next_value(obj_attr, i, &uniqval)) { +- const char *member = NULL; +- char * uid = NULL; +- member = slapi_value_get_string(uniqval); +- /* search uid for member (DN) */ +- slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "search %s\n", member); +- if ((uid = searchUid(member)) != NULL) { +- slapi_value_set_string(value, uid); +- /* add uids ValueSet */ +- slapi_valueset_add_value(uids, value); ++ ++ const char *member = slapi_value_get_string(uniqval); ++ char *attrs[] = { "uid", "objectclass", NULL }; ++ Slapi_Entry *child = getEntry(member, attrs); ++ ++ if (!child) { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid orphaned uniquemember found: %s\n", member); ++ ++ if (strncasecmp(member, "cn=", 3) == 0) { ++ fixMembership = 1; ++ } ++ if (!bad_ums) { ++ bad_ums = slapi_valueset_new(); ++ } ++ slapi_valueset_add_value(bad_ums, uniqval); + } + } +- slapi_value_free(&value); +- +- /* If we found some posix members, replace the existing memberuid attribute +- * with the found values. */ +- if (uids && slapi_valueset_count(uids)) { +- Slapi_PBlock *mod_pb = slapi_pblock_new(); +- Slapi_Value *val = 0; +- Slapi_Mod *smod; +- LDAPMod **mods = (LDAPMod **) slapi_ch_malloc(2 * sizeof(LDAPMod *)); +- int hint = 0; +- cb_data *the_cb_data = (cb_data *) callback_data; +- +- smod = slapi_mod_new(); +- slapi_mod_init(smod, 0); +- slapi_mod_set_operation(smod, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES); +- slapi_mod_set_type(smod, "memberuid"); +- +- /* Loop through all of our values and add them to smod */ +- hint = slapi_valueset_first_value(uids, &val); +- while (val) { +- /* this makes a copy of the berval */ +- slapi_mod_add_value(smod, slapi_value_get_berval(val)); +- hint = slapi_valueset_next_value(uids, hint, &val); +- } + +- mods[0] = slapi_mod_get_ldapmod_passout(smod); +- mods[1] = 0; ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid Finishing...\n"); + +- slapi_modify_internal_set_pb_ext(mod_pb, sdn, mods, 0, 0, +- posix_winsync_get_plugin_identity(), 0); ++ if (fixMembership && posix_winsync_config_get_mapNestedGrouping()) { ++ Slapi_ValueSet *del_nested_vs = slapi_valueset_new(); + +- slapi_pblock_set(mod_pb, SLAPI_TXN, the_cb_data->txn); +- slapi_modify_internal_pb(mod_pb); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid group deleted, recalculating nesting\n"); ++ propogateDeletionsUpward(e, sdn, bad_ums, del_nested_vs, 0); + +- slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); ++ slapi_valueset_free(del_nested_vs); del_nested_vs = NULL; ++ } + +- ldap_mods_free(mods, 1); +- slapi_mod_free(&smod); +- slapi_pblock_destroy(mod_pb); +- } else { +- /* No member were found, so remove the memberuid attribute +- * from this entry. */ +- posix_group_del_memberuid_callback(e, callback_data); ++ if (bad_ums) { ++ slapi_mods_add_mod_values(smods, LDAP_MOD_DELETE, "uniquemember", valueset_get_valuearray(bad_ums)); ++ slapi_valueset_free(bad_ums); bad_ums = NULL; + } +- slapi_valueset_free(uids); + } ++ ++ Slapi_PBlock *mod_pb = slapi_pblock_new(); ++ ++ slapi_modify_internal_set_pb_ext(mod_pb, sdn, slapi_mods_get_ldapmods_passout(smods), 0, 0, ++ posix_winsync_get_plugin_identity(), 0); ++ ++ slapi_pblock_set(mod_pb, SLAPI_TXN, the_cb_data->txn); ++ slapi_modify_internal_pb(mod_pb); ++ ++ slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); ++ slapi_pblock_destroy(mod_pb); ++ ++ slapi_mods_free(&smods); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_fix_memberuid <==\n"); + return rc; + } + + static void + posix_group_fixup_task_thread(void *arg) + { ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_task_thread ==>\n"); ++ + Slapi_Task *task = (Slapi_Task *) arg; + task_data *td = NULL; + int rc = 0; +@@ -293,11 +421,18 @@ posix_group_fixup_task_thread(void *arg) + + /* release the memberOf operation lock */ + memberUidUnlock(); ++ + + slapi_task_log_notice(task, "posix_group task finished."); + slapi_task_log_status(task, "posix_group task finished."); + slapi_task_inc_progress(task); + ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_task_thread finishing\n"); ++ + /* this will queue the destruction of the task */ + slapi_task_finish(task, rc); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_task_thread <==\n"); + } +diff --git a/ldap/servers/plugins/posix-winsync/posix-winsync-config.c b/ldap/servers/plugins/posix-winsync/posix-winsync-config.c +index a2d21be..a7fd6e9 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-winsync-config.c ++++ b/ldap/servers/plugins/posix-winsync/posix-winsync-config.c +@@ -142,6 +142,12 @@ posix_winsync_config_get_msSFUSchema() + return theConfig.mssfuSchema; + } + ++PRBool ++posix_winsync_config_get_mapNestedGrouping() ++{ ++ return theConfig.mapNestedGrouping; ++} ++ + Slapi_DN * + posix_winsync_config_get_suffix() + { +@@ -182,6 +188,7 @@ posix_winsync_config(Slapi_Entry *config_e) + theConfig.lowercase = PR_FALSE; + theConfig.createMemberOfTask = PR_FALSE; + theConfig.MOFTaskCreated = PR_FALSE; ++ theConfig.mapNestedGrouping = PR_FALSE; + + posix_winsync_apply_config(NULL, NULL, config_e, &returncode, returntext, NULL); + /* config DSE must be initialized before we get here */ +@@ -224,6 +231,7 @@ posix_winsync_apply_config(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Ent + PRBool createMemberOfTask = PR_FALSE; + PRBool lowercase = PR_FALSE; + Slapi_Attr *testattr = NULL; ++ PRBool mapNestedGrouping = PR_FALSE; + + *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ + +@@ -257,6 +265,13 @@ posix_winsync_apply_config(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Ent + "_apply_config: Config paramter %s: %d\n", POSIX_WINSYNC_LOWER_CASE, + lowercase); + } ++ /* propogate memberuids in nested grouping */ ++ if (!slapi_entry_attr_find(e, POSIX_WINSYNC_MAP_NESTED_GROUPING, &testattr) && (NULL != testattr)) { ++ mapNestedGrouping = slapi_entry_attr_get_bool(e, POSIX_WINSYNC_MAP_NESTED_GROUPING); ++ slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, ++ "_apply_config: Config paramter %s: %d\n", POSIX_WINSYNC_MAP_NESTED_GROUPING, ++ mapNestedGrouping); ++ } + /* if we got here, we have valid values for everything + set the config entry */ + slapi_lock_mutex(theConfig.lock); +@@ -269,6 +284,7 @@ posix_winsync_apply_config(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Ent + theConfig.mapMemberUID = mapMemberUID; + theConfig.createMemberOfTask = createMemberOfTask; + theConfig.lowercase = lowercase; ++ theConfig.mapNestedGrouping = mapNestedGrouping; + + /* success */ + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +diff --git a/ldap/servers/plugins/posix-winsync/posix-winsync.c b/ldap/servers/plugins/posix-winsync/posix-winsync.c +index 398541d..aa292c3 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-winsync.c ++++ b/ldap/servers/plugins/posix-winsync/posix-winsync.c +@@ -68,7 +68,7 @@ + #include "posix-wsp-ident.h" + #include "posix-group-func.h" + +-#define MEMBEROFTASK "memberof task" ++#define MEMBEROFTASK "memberuid task" + Slapi_Value ** + valueset_get_valuearray(const Slapi_ValueSet *vs); /* stolen from proto-slap.h */ + void * +@@ -103,6 +103,7 @@ static windows_attribute_map user_mssfu_attribute_map[] = + { "msSFU30gecos", "gecos" }, + { NULL, NULL } }; + ++/* memberUid must be first element or fixup in pre_ad_mod/add_group is required */ + static windows_attribute_map group_attribute_map[] = { { "memberUid", "memberUid" }, + { "gidNumber", "gidNumber" }, + { NULL, NULL } }; +@@ -661,7 +662,34 @@ posix_winsync_pre_ad_mod_group_cb(void *cbdata, const Slapi_Entry *rawentry, Sla + char *ad_type = NULL; + int is_present_local; + +- slapi_attr_get_valueset(attr, &vs); ++ if (i == 0) { /* memberUid */ ++ Slapi_Attr *dsmuid_attr = NULL; ++ Slapi_Value *v = NULL; ++ slapi_entry_attr_find(ds_entry, "dsonlymemberuid", &dsmuid_attr); ++ ++ if (dsmuid_attr) { ++ Slapi_ValueSet *dsmuid_vs = NULL; ++ slapi_attr_get_valueset(dsmuid_attr, &dsmuid_vs); ++ if (dsmuid_vs) { ++ vs = slapi_valueset_new(); ++ ++ int j; ++ for (j = slapi_attr_first_value(attr, &v); j != -1; ++ j = slapi_attr_next_value(attr, i, &v)) { ++ if (!slapi_valueset_find(dsmuid_attr, dsmuid_vs, v)) { ++ slapi_valueset_add_value(vs, v); ++ } ++ } ++ ++ slapi_valueset_free(dsmuid_vs); dsmuid_vs = NULL; ++ } ++ } ++ } ++ ++ if (!vs) { ++ slapi_attr_get_valueset(attr, &vs); ++ } ++ + ad_type = slapi_ch_strdup(attr_map[i].windows_attribute_name); + slapi_entry_attr_find(ad_entry, ad_type, &ad_attr); + is_present_local = (NULL == ad_attr) ? 0 : 1; +@@ -810,6 +838,12 @@ posix_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + valueset_get_valuearray(oc_vs)); + slapi_value_free(&oc_nv); + slapi_valueset_free(oc_vs); ++ ++ if (posix_winsync_config_get_mapNestedGrouping()) { ++ memberUidLock(); ++ addUserToGroupMembership(ds_entry); ++ memberUidUnlock(); ++ } + } + } + slapi_value_free(&voc); +@@ -897,7 +931,7 @@ posix_winsync_pre_ds_mod_group_cb(void *cbdata, const Slapi_Entry *rawentry, Sla + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, + "_pre_ds_mod_group_cb present %d modify %d before\n", is_present_local, + do_modify_local); +- if (posix_winsync_config_get_mapMemberUid()) { ++ if (posix_winsync_config_get_mapMemberUid() || posix_winsync_config_get_mapNestedGrouping()) { + memberUidLock(); + modGroupMembership(ds_entry, smods, do_modify); + memberUidUnlock(); +@@ -999,6 +1033,13 @@ posix_winsync_pre_ds_add_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, + "<-- _pre_ds_add_user_cb -- adding objectclass for new entry failed %d\n", + rc); ++ else { ++ if (posix_winsync_config_get_mapNestedGrouping()) { ++ memberUidLock(); ++ addUserToGroupMembership(ds_entry); ++ memberUidUnlock(); ++ } ++ } + } + sync_acct_disable(cbdata, rawentry, ds_entry, ACCT_DISABLE_TO_DS, ds_entry, NULL, NULL); + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, "<-- _pre_ds_add_user_cb -- end\n"); +@@ -1054,14 +1095,14 @@ posix_winsync_pre_ds_add_group_cb(void *cbdata, const Slapi_Entry *rawentry, Sla + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, + "<-- _pre_ds_add_group_cb -- adding objectclass for new entry failed %d\n", + rc); +- } else { +- if (posix_winsync_config_get_mapMemberUid()) { +- memberUidLock(); +- addGroupMembership(ds_entry, ad_entry); +- memberUidUnlock(); +- } + } + } ++ if (posix_winsync_config_get_mapMemberUid() || posix_winsync_config_get_mapNestedGrouping()) { ++ memberUidLock(); ++ addGroupMembership(ds_entry, ad_entry); ++ memberUidUnlock(); ++ } ++ + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, + "<-- posix_winsync_pre_ds_add_group_cb -- end\n"); + +@@ -1274,7 +1315,7 @@ posix_winsync_end_update_cb(void *cbdata, const Slapi_DN *ds_subtree, const Slap + "--> posix_winsync_end_update_cb -- begin %d %d\n", + posix_winsync_config_get_MOFTaskCreated(), + posix_winsync_config_get_createMOFTask()); +- if (posix_winsync_config_get_MOFTaskCreated() && posix_winsync_config_get_createMOFTask()) { ++ if (1 && posix_winsync_config_get_createMOFTask()) { + /* add a task to schedule memberof Plugin for fix memebrof attributs */ + Slapi_PBlock *pb = slapi_pblock_new(); + Slapi_Entry *e_task = slapi_entry_alloc(); +@@ -1291,13 +1332,24 @@ posix_winsync_end_update_cb(void *cbdata, const Slapi_DN *ds_subtree, const Slap + posix_winsync_plugin_name, MEMBEROFTASK); + return; + } ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, ++ "--> posix_winsync_end_update_cb, init'ing task\n"); ++ + slapi_entry_init(e_task, slapi_ch_strdup(dn), NULL); + slapi_entry_add_string(e_task, "cn", slapi_ch_strdup(posix_winsync_plugin_name)); + slapi_entry_add_string(e_task, "objectClass", "extensibleObject"); + slapi_entry_add_string(e_task, "basedn", slapi_sdn_get_dn(ds_subtree)); + + slapi_add_entry_internal_set_pb(pb, e_task, NULL, posix_winsync_get_plugin_identity(), 0); ++ ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, ++ "--> posix_winsync_end_update_cb, adding task\n"); + slapi_add_internal_pb(pb); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, ++ "--> posix_winsync_end_update_cb, retrieving return code\n"); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); + if (rc != 0) { + slapi_log_error(SLAPI_LOG_FATAL, posix_winsync_plugin_name, +diff --git a/ldap/servers/plugins/posix-winsync/posix-wsp-ident.h b/ldap/servers/plugins/posix-winsync/posix-wsp-ident.h +index 43a23df..f36fe40 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-wsp-ident.h ++++ b/ldap/servers/plugins/posix-winsync/posix-wsp-ident.h +@@ -17,7 +17,7 @@ + #define POSIX_WINSYNC_MAP_MEMBERUID "posixWinsyncMapMemberUID" + #define POSIX_WINSYNC_CREATE_MEMBEROFTASK "posixWinsyncCreateMemberOfTask" + #define POSIX_WINSYNC_LOWER_CASE "posixWinsyncLowerCaseUID" +- ++#define POSIX_WINSYNC_MAP_NESTED_GROUPING "posixWinsyncMapNestedGrouping" + + void * posix_winsync_get_plugin_identity(); + +@@ -29,6 +29,7 @@ typedef struct posix_winsync_config_struct { + PRBool lowercase; /* store the uid in group memberuid in lower case */ + PRBool createMemberOfTask; /* should memberOf Plugin Task run after AD sync */ + PRBool MOFTaskCreated; ++ PRBool mapNestedGrouping; + Slapi_DN *rep_suffix; /* namingContext in DS of the replicated suffix */ + } POSIX_WinSync_Config; + +@@ -42,6 +43,7 @@ Slapi_DN *posix_winsync_config_get_suffix(); + void posix_winsync_config_reset_MOFTaskCreated(); + void posix_winsync_config_set_MOFTaskCreated(); + PRBool posix_winsync_config_get_MOFTaskCreated(); ++PRBool posix_winsync_config_get_mapNestedGrouping(); + + int posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, + Slapi_Entry *eAfter, int *returncode, char *returntext, +-- +1.7.7.6 + diff --git a/0005-Ticket-491-multimaster_extop_cleanruv-returns-wrong-.patch b/0005-Ticket-491-multimaster_extop_cleanruv-returns-wrong-.patch new file mode 100644 index 0000000..9df6271 --- /dev/null +++ b/0005-Ticket-491-multimaster_extop_cleanruv-returns-wrong-.patch @@ -0,0 +1,231 @@ +From 6a1e19821464ad599fb9b5ddf05d93d68f99ac9a Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Thu, 11 Oct 2012 11:57:24 -0600 +Subject: [PATCH 05/10] Ticket #491 - multimaster_extop_cleanruv returns wrong error codes + +https://fedorahosted.org/389/ticket/491 +Reviewed by: nhosoi (Thanks!) +Branch: rhel-6.4 +Fix Description: multimaster_extop_cleanruv must return with a code of +SLAPI_PLUGIN_EXTENDED_SENT_RESULT to tell the server that the result +has been sent - otherwise, in 1.2.10, the server will attempt to send +the result again. In 1.2.11 the result code has been changed to ignore +a subsequent attempt to send a result for the same operation, but the +function should still return the correct codes. +I also cleaned up the error codes and memory management a bit. +Platforms tested: RHEL6 x86_64, Fedora 16 +Flag Day: no +Doc impact: no +(cherry picked from commit bf54018e8ee4b355c66621ad3bfe5e59d4820170) +(cherry picked from commit 6125990c403d600a048e8d6420236f6acb58e179) +--- + ldap/servers/plugins/replication/repl_extop.c | 59 +++++++++++++----------- + 1 files changed, 32 insertions(+), 27 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c +index 1b72dfb..3a6f422 100644 +--- a/ldap/servers/plugins/replication/repl_extop.c ++++ b/ldap/servers/plugins/replication/repl_extop.c +@@ -1445,19 +1445,20 @@ free_and_return: + int + multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + { +- multimaster_mtnode_extension *mtnode_ext; ++ multimaster_mtnode_extension *mtnode_ext = NULL; ++ int release_it = 0; + PRThread *thread = NULL; + cleanruv_data *data; + Replica *r; + ReplicaId rid; +- CSN *maxcsn; +- struct berval *extop_payload; ++ CSN *maxcsn = NULL; ++ struct berval *extop_payload = NULL; + char *extop_oid; + char *repl_root; + char *payload = NULL; + char *certify_all; + char *iter; +- int rc = 0; ++ int rc = LDAP_SUCCESS; + + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload); +@@ -1495,6 +1496,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + } + if (mtnode_ext->replica){ + object_acquire (mtnode_ext->replica); ++ release_it = 1; + } else { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: replica is missing from (%s), " + "aborting operation\n",repl_root); +@@ -1518,6 +1520,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + goto out; + } + data->repl_obj = mtnode_ext->replica; /* released in replica_abort_task_thread() */ ++ release_it = 0; /* thread owns it now */ + data->replica = r; + data->task = NULL; + data->payload = slapi_ch_bvdup(extop_payload); +@@ -1539,17 +1542,20 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE); + if (thread == NULL) { +- if(mtnode_ext->replica){ +- object_release(mtnode_ext->replica); +- } + slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort cleanAllRUV task: unable to create abort " + "thread. Aborting task.\n"); ++ release_it = 1; /* have to release mtnode_ext->replica now */ + slapi_ch_free_string(&data->repl_root); + slapi_ch_free_string(&data->certify); ++ ber_bvfree(data->payload); ++ slapi_ch_free((void **)&data); + rc = LDAP_OPERATIONS_ERROR; + } + + out: ++ if (release_it && mtnode_ext && mtnode_ext->replica) { ++ object_release(mtnode_ext->replica); ++ } + slapi_ch_free_string(&payload); + + return rc; +@@ -1569,7 +1575,7 @@ out: + int + multimaster_extop_cleanruv(Slapi_PBlock *pb) + { +- multimaster_mtnode_extension *mtnode_ext; ++ multimaster_mtnode_extension *mtnode_ext = NULL; + PRThread *thread = NULL; + Replica *r = NULL; + cleanruv_data *data = NULL; +@@ -1584,7 +1590,7 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + char *iter; + int release_it = 0; + int rid = 0; +- int rc = 0; ++ int rc = LDAP_OPERATIONS_ERROR; + + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload); +@@ -1592,7 +1598,6 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + if (NULL == extop_oid || strcmp(extop_oid, REPL_CLEANRUV_OID) != 0 || + NULL == extop_payload || NULL == extop_payload->bv_val){ + /* something is wrong, error out */ +- rc = -1; + goto free_and_return; + } + /* +@@ -1600,7 +1605,6 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + */ + if(decode_cleanruv_payload(extop_payload, &payload)){ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to decode payload. Aborting ext op\n"); +- rc = -1; + goto free_and_return; + } + rid = atoi(ldap_utf8strtok_r(payload, ":", &iter)); +@@ -1613,7 +1617,7 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + */ + if(is_cleaned_rid(rid)){ + csn_free(&maxcsn); +- rc = 1; ++ rc = LDAP_SUCCESS; + goto free_and_return; + } + +@@ -1623,25 +1627,21 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to get replication node " + "from (%s), aborting operation\n", repl_root); +- rc = -1; + goto free_and_return; + } + + if (mtnode_ext->replica){ + object_acquire (mtnode_ext->replica); + release_it = 1; +- } +- if (mtnode_ext->replica == NULL){ ++ } else { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: replica is missing from (%s), " + "aborting operation\n",repl_root); +- rc = LDAP_OPERATIONS_ERROR; + goto free_and_return; + } + + r = (Replica*)object_get_data (mtnode_ext->replica); + if(r == NULL){ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: replica is NULL, aborting task\n"); +- rc = -1; + goto free_and_return; + } + +@@ -1656,7 +1656,6 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + if (data == NULL) { + slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to allocate " + "cleanruv_Data\n"); +- rc = -1; + goto free_and_return; + } + data->repl_obj = mtnode_ext->replica; +@@ -1670,9 +1669,15 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE); + if (thread == NULL) { +- rc = -1; + slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: unable to create cleanAllRUV " + "monitoring thread. Aborting task.\n"); ++ ber_bvfree(data->payload); ++ data->payload = NULL; ++ slapi_ch_free((void **)&data); ++ } else { ++ release_it = 0; /* thread will release data->repl_obj == mtnode_ext->replica */ ++ maxcsn = NULL; /* thread owns it now */ ++ rc = LDAP_SUCCESS; + } + } else { /* this is a read-only consumer */ + /* +@@ -1712,24 +1717,20 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + + /* free everything */ + object_release(ruv_obj); +- csn_free(&maxcsn); +- if (mtnode_ext->replica && release_it) +- object_release (mtnode_ext->replica); + /* + * This read-only replica has no easy way to tell when it's safe to release the rid. + * So we won't release it, not until a server restart. + */ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: You must restart the server if you want to reuse rid(%d).\n", rid); + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Successfully cleaned rid(%d).\n", rid); ++ rc = LDAP_SUCCESS; + } + + free_and_return: +- if(rc && release_it){ +- if (mtnode_ext->replica) +- object_release (mtnode_ext->replica); ++ if(release_it && mtnode_ext && mtnode_ext->replica) { ++ object_release (mtnode_ext->replica); + } +- if(rc) +- csn_free(&maxcsn); ++ csn_free(&maxcsn); + slapi_ch_free_string(&payload); + + /* +@@ -1753,6 +1754,10 @@ free_and_return: + { + ber_bvfree(resp_bval); + } ++ /* tell extendop code that we have already sent the result */ ++ rc = SLAPI_PLUGIN_EXTENDED_SENT_RESULT; ++ } else { ++ rc = LDAP_OPERATIONS_ERROR; + } + + return rc; +-- +1.7.1 + diff --git a/0006-Coverity-defects.patch b/0006-Coverity-defects.patch new file mode 100644 index 0000000..696a59b --- /dev/null +++ b/0006-Coverity-defects.patch @@ -0,0 +1,93 @@ +From 2f960e4bd658679330faa249981f1b48bc7a6e03 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Wed, 24 Oct 2012 15:27:48 -0700 +Subject: [PATCH 06/10] Coverity defects + +The commit b9eeb2e1a8e688dfec753e8965d0e5aeb119e638 for Ticket #481 +"expand nested posix groups" introduced 4 coverity defects. + +Description: +13100, 13101: Missing return statement +Fix description: addUserToGroupMembership and propogateDeletion- +UpwardCallback are declared to return an integer value, but +nothing was returned. This patch changes it to return 0. + +13102: Resource leak +Fix description: The memory of valueset muid_old_vs is internally +allocated. It was meant to be set to muid_upward_vs and freed +together when muid_upward_vs is freed. But due to the function +calling order, it was not properly set and it lost the chance to +be freed. This patch calls slapi_attr_get_valueset prior to +slapi_valueset_set_valueset and let free muid_old_vs together +with slapi_valueset_set_valueset. + +13103: Uninitialized pointer read +Fix description: Possibly uninitialized variable was passed to +a logging function slapi_log_error, but actually it was not +referred. With this patch, the variable filter is no longer to +passed to the function. +(cherry picked from commit e9941a2915ac848abe9a4afe802d0432aa0c354a) +(cherry picked from commit a57d9131f9d0ae7a5d9865dd6be7f37f26de376c) +--- + .../plugins/posix-winsync/posix-group-func.c | 8 +++++--- + .../plugins/posix-winsync/posix-group-task.c | 4 ++-- + 2 files changed, 7 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 66b9272..be3a6ec 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-func.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-func.c +@@ -473,15 +473,15 @@ propogateMembershipUpward(Slapi_Entry *entry, Slapi_ValueSet *muid_vs, int depth + muid_here_vs = muid_vs; + } + else { ++ int i = 0; ++ Slapi_Value *v = NULL; + /* Eliminate duplicates */ + muid_upward_vs = slapi_valueset_new(); + muid_here_vs = slapi_valueset_new(); + ++ slapi_attr_get_valueset(muid_old_attr, &muid_old_vs); + slapi_valueset_set_valueset(muid_upward_vs, muid_old_vs); + +- slapi_attr_get_valueset(muid_old_attr, &muid_old_vs); +- int i = 0; +- Slapi_Value *v = NULL; + for (i = slapi_valueset_first_value(muid_vs, &v); i != -1; + i = slapi_valueset_next_value(muid_vs, i, &v)) { + +@@ -542,6 +542,7 @@ propogateDeletionsUpwardCallback(Slapi_Entry *entry, void *callback_data) + { + struct propogateDeletionsUpwardArgs *args = (struct propogateDeletionsUpwardArgs *)(callback_data); + propogateDeletionsUpward(entry, args->base_sdn, args->smod_deluids, args->del_nested_vs, args->depth); ++ return 0; + } + + void +@@ -920,6 +921,7 @@ addUserToGroupMembership(Slapi_Entry *entry) + propogateMembershipUpward(entry, muid_vs, 0); + + slapi_valueset_free(muid_vs); muid_vs = NULL; ++ return 0; + } + + int +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-task.c b/ldap/servers/plugins/posix-winsync/posix-group-task.c +index 4555f1b..e5385b0 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-task.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-task.c +@@ -152,9 +152,9 @@ posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int + rv = SLAPI_DSE_CALLBACK_OK; + } + +- out: ++out: + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "posix_group_task_add: <==\n", filter); ++ "posix_group_task_add: <==\n"); + + return rv; + } +-- +1.7.1 + diff --git a/0007-Fixing-compiler-warnings-in-the-posix-winsync-plugin.patch b/0007-Fixing-compiler-warnings-in-the-posix-winsync-plugin.patch new file mode 100644 index 0000000..f2ec243 --- /dev/null +++ b/0007-Fixing-compiler-warnings-in-the-posix-winsync-plugin.patch @@ -0,0 +1,92 @@ +From 1ac087a405c11d27b1150b27d9f075b456000c50 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Wed, 24 Oct 2012 16:13:32 -0700 +Subject: [PATCH 07/10] Fixing compiler warnings in the posix-winsync plugin + +The commit b9eeb2e1a8e688dfec753e8965d0e5aeb119e638 for Ticket #481 +"expand nested posix groups" introduced these compiler warnings. + +1) posix-grou-func.c +. added missing format strings "%s" in searchUid. +. added a function declaration hasObjectClass. +. eliminated an unused variable uid_dn_value. +2) posix-group-task.c +. included "slapi-private.h" for filter_escaped_value. +(cherry picked from commit 56ebbb20fa9f8d1add75075fdf421f53ed5348f1) +--- + .../plugins/posix-winsync/posix-group-func.c | 9 +++++---- + .../plugins/posix-winsync/posix-group-func.h | 2 ++ + .../plugins/posix-winsync/posix-group-task.c | 1 + + 3 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-func.c b/ldap/servers/plugins/posix-winsync/posix-group-func.c +index be3a6ec..9ad636f 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-func.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-func.c +@@ -28,6 +28,8 @@ + + Slapi_Value ** + valueset_get_valuearray(const Slapi_ValueSet *vs); /* stolen from proto-slap.h */ ++static int hasObjectClass(Slapi_Entry *entry, const char *objectClass); ++ + static PRMonitor *memberuid_operation_lock = 0; + + void +@@ -133,13 +135,13 @@ searchUid(const char *udn) + } + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "searchUid: About to free entry\n", udn); ++ "searchUid: About to free entry (%s)\n", udn); + + slapi_entry_free(entry); + } + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +- "searchUid: <==\n", udn); ++ "searchUid(%s): <==\n", udn); + + return uid; + } +@@ -260,7 +262,7 @@ smods_has_mod(Slapi_Mods *smods, int modtype, const char *type, const char *val) + return rc; + } + +-int ++static int + hasObjectClass(Slapi_Entry *entry, const char *objectClass) + { + int rc = 0; +@@ -704,7 +706,6 @@ modGroupMembership(Slapi_Entry *entry, Slapi_Mods *smods, int *do_modify) + + if (smod_deluids == NULL) { /* deletion of the last value, deletes the Attribut from entry complete, this operation has no value, so we must look by self */ + Slapi_Attr * um_attr = NULL; /* Entry attributes */ +- Slapi_Value * uid_dn_value = NULL; /* Attribute values */ + int rc = slapi_entry_attr_find(entry, "uniquemember", &um_attr); + + if (rc != 0 || um_attr == NULL) { +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-func.h b/ldap/servers/plugins/posix-winsync/posix-group-func.h +index 9452022..0f0ae37 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-func.h ++++ b/ldap/servers/plugins/posix-winsync/posix-group-func.h +@@ -17,5 +17,7 @@ char * searchUid(const char *udn); + void memberUidLock(); + void memberUidUnlock(); + int memberUidLockInit(); ++int addUserToGroupMembership(Slapi_Entry *entry); ++void propogateDeletionsUpward(Slapi_Entry *, const Slapi_DN *, Slapi_ValueSet*, Slapi_ValueSet *, int); + + #endif +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-task.c b/ldap/servers/plugins/posix-winsync/posix-group-task.c +index e5385b0..92ac342 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-task.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-task.c +@@ -1,4 +1,5 @@ + #include "slapi-plugin.h" ++#include "slapi-private.h" + #include "nspr.h" + + #include "posix-wsp-ident.h" +-- +1.7.1 + diff --git a/0008-Trac-Ticket-494-slapd-entered-to-infinite-loop-durin.patch b/0008-Trac-Ticket-494-slapd-entered-to-infinite-loop-durin.patch new file mode 100644 index 0000000..eda5e55 --- /dev/null +++ b/0008-Trac-Ticket-494-slapd-entered-to-infinite-loop-durin.patch @@ -0,0 +1,42 @@ +From 179c018e99350c7ee051a281a3466ef46004a255 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 26 Oct 2012 10:02:38 -0700 +Subject: [PATCH 08/10] Trac Ticket #494 - slapd entered to infinite loop during new index addition + +https://fedorahosted.org/389/ticket/494 + +Bug Description: An entry which rdn is nsuniqueid=...,nsuniqueid=... +was accidentally generated. It broke the entryrdn tree and put +the reindex and export into the the infinite loop. + +Fix Description: Added an missing check if the retrieved entry is +already an tombstone or not. This tombstone is the one converted +by the entryusn plugin. Please note that replication has an urp +code which handles such conflicts. +(cherry-picked from commit b963576d2758d29e8d21297e8f763d0373895b9f) +(cherry picked from commit 31d15788d4e988646a42252f6ea351f033206a96) +--- + ldap/servers/slapd/back-ldbm/ldbm_delete.c | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +index 73c3658..528693e 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +@@ -290,6 +290,13 @@ ldbm_back_delete( Slapi_PBlock *pb ) + create_tombstone_entry = (create_tombstone_entry < 0) ? 0 : 1; + } + } ++ if (create_tombstone_entry && is_tombstone_entry) { ++ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete", ++ "Attempt to convert a tombstone entry %s to tombstone\n", dn); ++ retval = -1; ++ ldap_result_code = LDAP_UNWILLING_TO_PERFORM; ++ goto error_return; ++ } + + #if DEBUG + slapi_log_error(SLAPI_LOG_REPL, "ldbm_back_delete", +-- +1.7.1 + diff --git a/0009-Coverity-defects.patch b/0009-Coverity-defects.patch new file mode 100644 index 0000000..d87852e --- /dev/null +++ b/0009-Coverity-defects.patch @@ -0,0 +1,34 @@ +From c970af0ea2da634d5ee7562047715c94a4ab5c4e Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 26 Oct 2012 18:18:15 -0700 +Subject: [PATCH 09/10] Coverity defects + +History: +The commit b9eeb2e1a8e688dfec753e8965d0e5aeb119e638 for Ticket #481 +"expand nested posix groups" introduced 4 coverity defects. Commit for +the fixing patch e9941a2915ac848abe9a4afe802d0432aa0c354a failed to solve +13102: Resource leak. + +Fix Description: This patch explicitly calls slapi_valueset_free for +the leak reported object muid_old_vs. +(cherry picked from commit 544f027193139a109aeb14145ae1d77c4bdcc618) +(cherry picked from commit 55997a627ecf155499621b17eb7e118787536765) +--- + .../plugins/posix-winsync/posix-group-func.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-func.c b/ldap/servers/plugins/posix-winsync/posix-group-func.c +index 9ad636f..60528f5 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-func.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-func.c +@@ -497,6 +497,7 @@ propogateMembershipUpward(Slapi_Entry *entry, Slapi_ValueSet *muid_vs, int depth + slapi_valueset_add_value(muid_upward_vs, v); + } + } ++ slapi_valueset_free(muid_old_vs); + } + + /* Update this group's membership */ +-- +1.7.1 + diff --git a/0010-Trac-Ticket-498-Cannot-abaondon-simple-paged-result-.patch b/0010-Trac-Ticket-498-Cannot-abaondon-simple-paged-result-.patch new file mode 100644 index 0000000..f340d2a --- /dev/null +++ b/0010-Trac-Ticket-498-Cannot-abaondon-simple-paged-result-.patch @@ -0,0 +1,221 @@ +From 0ae7a17ae868530ae461ea70ffcead0a8a8d1880 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 29 Oct 2012 10:55:05 -0700 +Subject: [PATCH 10/10] Trac Ticket #498 - Cannot abaondon simple paged result search + +https://fedorahosted.org/389/ticket/498 + +Bug Description: The enhancement "Ticket #260 - 389 DS does not +support multiple paging controls on a single connection (commit +add880accaa28de8304da1c2c2f58fe8af002ebb)" broke the ability to +abandon the on-going simple paged result search. + +1) The abandon request expects the operation exist. When sending +an abort request, the search operation could have already finished +and the operation object has been released. + +2) Plus, request page size is 0, it should be interpreted as abandoned. + +Fix Description: +1) In do_abandon, this patch eliminates to check if the operation +is a simplepaged results oriented or not, since the operation object +is often already released. Instead, it directly checks the internal +paged results info in the connection object. + +To make sure the abandoned search won't go further, a flag value +CONN_FLAG_PAGEDRESULTS_ABANDONED is introduced. If it is set in +the pagedresults structure in the connection object, it skips any +further process of the search. + +2) This patch is adding a check if the given page size is 0 in the +simple-paged-results control or not. If it is 0, treat is as an +abandoned operation. +(cherry picked from commit 47c0d96ac28c0b1cc15e7bbb77648551c309ccf5) +(cherry picked from commit 973886082b1c695a55d503f96b2e74188cbfded6) +--- + ldap/servers/slapd/abandon.c | 10 +++----- + ldap/servers/slapd/opshared.c | 17 ++++++++++++-- + ldap/servers/slapd/pagedresults.c | 41 +++++++++++++++++++++++++----------- + ldap/servers/slapd/slap.h | 15 +++++++------ + 4 files changed, 54 insertions(+), 29 deletions(-) + +diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c +index 094ae95..9639701 100644 +--- a/ldap/servers/slapd/abandon.c ++++ b/ldap/servers/slapd/abandon.c +@@ -152,12 +152,10 @@ do_abandon( Slapi_PBlock *pb ) + 0 ); + } + +- if ( op_is_pagedresults(o) ) { +- 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", +- pb->pb_conn->c_connid, pb->pb_op->o_opid ); +- } ++ 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", ++ pb->pb_conn->c_connid, pb->pb_op->o_opid ); + } 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/opshared.c b/ldap/servers/slapd/opshared.c +index 22a3822..2701250 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -197,8 +197,8 @@ void modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods) + } + } + +- slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, +- "modifiersname", bvals); ++ slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, ++ "modifiersname", bvals); + + /* fill in modifytimestamp */ + curtime = current_time(); +@@ -461,7 +461,8 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + &pagesize, &pr_idx); + /* 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) { ++ if ((LDAP_SUCCESS == rc) || ++ (LDAP_CANCELLED == rc) || (0 == pagesize)) { + unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED; + if (pagedresults_check_or_set_processing(pb->pb_conn, pr_idx)) { + send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, +@@ -483,6 +484,16 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + opnote |= SLAPI_OP_NOTE_UNINDEXED; + } + 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); ++ send_ldap_result(pb, 0, NULL, ++ "Simple Paged Results Search abandoned", ++ 0, NULL); ++ rc = LDAP_SUCCESS; ++ goto free_and_return; ++ } + } else { + /* parse paged-results-control failed */ + if (iscritical) { /* return an error since it's critical */ +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index d445c06..9b294eb 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -143,8 +143,13 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + slapi_ch_free((void **)&cookie.bv_val); + + if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) { +- /* Need to keep the latest msgid to prepare for the abandon. */ +- conn->c_pagedresults.prl_list[*index].pr_msgid = op->o_msgid; ++ if (conn->c_pagedresults.prl_list[*index].pr_flags & ++ CONN_FLAG_PAGEDRESULTS_ABANDONED) { ++ rc = LDAP_CANCELLED; ++ } else { ++ /* Need to keep the latest msgid to prepare for the abandon. */ ++ conn->c_pagedresults.prl_list[*index].pr_msgid = op->o_msgid; ++ } + } else { + rc = LDAP_PROTOCOL_ERROR; + LDAPDebug1Arg(LDAP_DEBUG_ANY, +@@ -251,8 +256,13 @@ pagedresults_free_one( Connection *conn, 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) { +- memset(&conn->c_pagedresults.prl_list[index], +- '\0', sizeof(PagedResults)); ++ 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)); ++ } ++ memset(prp, '\0', sizeof(PagedResults)); + conn->c_pagedresults.prl_count--; + rc = 0; + } +@@ -263,34 +273,39 @@ pagedresults_free_one( Connection *conn, int index ) + return rc; + } + ++/* Used for abandoning */ + int + pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ) + { + int rc = -1; + int i; + +- LDAPDebug1Arg(LDAP_DEBUG_TRACE, +- "--> pagedresults_free_one: msgid=%d\n", msgid); + if (conn && (msgid > -1)) { + if (conn->c_pagedresults.prl_count <= 0) { +- LDAPDebug2Args(LDAP_DEBUG_TRACE, +- "pagedresults_free_one_msgid_nolock: " +- "conn=%d paged requests list count is %d\n", +- conn->c_connid, conn->c_pagedresults.prl_count); ++ ; /* Not a paged result. */ + } else { ++ LDAPDebug1Arg(LDAP_DEBUG_TRACE, ++ "--> pagedresults_free_one: msgid=%d\n", msgid); + for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { + if (conn->c_pagedresults.prl_list[i].pr_msgid == msgid) { +- memset(&conn->c_pagedresults.prl_list[i], +- '\0', sizeof(PagedResults)); ++ PagedResults *prp = conn->c_pagedresults.prl_list + i; ++ 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_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); + } + } + +- LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_free_one: %d\n", rc); + return rc; + } + +diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h +index d0f2b33..e3cbc72 100644 +--- a/ldap/servers/slapd/slap.h ++++ b/ldap/servers/slapd/slap.h +@@ -1461,16 +1461,17 @@ typedef struct conn { + * successfully completed. + */ + +-#define CONN_FLAG_PAGEDRESULTS_WITH_SORT 64 /* paged results control is +- * sent with server side sorting +- */ ++#define CONN_FLAG_PAGEDRESULTS_WITH_SORT 64/* paged results control is ++ * sent with server side sorting ++ */ + +-#define CONN_FLAG_PAGEDRESULTS_UNINDEXED 128 /* If the search is unindexed, ++#define CONN_FLAG_PAGEDRESULTS_UNINDEXED 128/* If the search is unindexed, + * store the info in c_flags + */ +-#define CONN_FLAG_PAGEDRESULTS_PROCESSING 256 /* there is an operation +- * processing a pagedresults search +- */ ++#define CONN_FLAG_PAGEDRESULTS_PROCESSING 256/* there is an operation ++ * processing a pagedresults search ++ */ ++#define CONN_FLAG_PAGEDRESULTS_ABANDONED 512/* pagedresults abandoned */ + #define CONN_GET_SORT_RESULT_CODE (-1) + + #define START_TLS_OID "1.3.6.1.4.1.1466.20037" +-- +1.7.1 + diff --git a/0011-Ticket-503-Improve-AD-version-in-winsync-log-message.patch b/0011-Ticket-503-Improve-AD-version-in-winsync-log-message.patch new file mode 100644 index 0000000..fd90767 --- /dev/null +++ b/0011-Ticket-503-Improve-AD-version-in-winsync-log-message.patch @@ -0,0 +1,34 @@ +From 90bb6b273f91e7296b7dfbe6e193b5aeabfec22d Mon Sep 17 00:00:00 2001 +From: Nathan Kinder +Date: Tue, 6 Nov 2012 07:58:58 -0800 +Subject: [PATCH 11/16] Ticket #503 - Improve AD version in winsync log + message + +When enabling replication level logging, winsync prints out what +version of Windows/AD it detects. If it detects win2k3 or later, it +prints out "detected win2k3 peer". This can be confusing if you are +running a later version, such as win2k8. The code is really trying +to detect if we can use certain operations that only started being +supported in win2k3. This patch changes the message to match this +logic by printing "detected win2k3 or later peer". +(cherry picked from commit 98b809ba580530d9418e7bbf857e1ff2b79f75c8) +--- + ldap/servers/plugins/replication/windows_connection.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c +index 0393627..105c205 100644 +--- a/ldap/servers/plugins/replication/windows_connection.c ++++ b/ldap/servers/plugins/replication/windows_connection.c +@@ -1333,7 +1333,7 @@ windows_conn_connect(Repl_Connection *conn) + if (CONN_IS_WIN2K3 == supports) + { + windows_private_set_iswin2k3(conn->agmt,1); +- LDAPDebug( LDAP_DEBUG_REPL, "windows_conn_connect : detected Win2k3 peer\n", 0, 0, 0 ); ++ LDAPDebug( LDAP_DEBUG_REPL, "windows_conn_connect : detected Win2k3 or later peer\n", 0, 0, 0 ); + } else + { + windows_private_set_iswin2k3(conn->agmt,0); +-- +1.7.11.7 + diff --git a/0012-Trac-Ticket-500-Newly-created-users-with-organizatio.patch b/0012-Trac-Ticket-500-Newly-created-users-with-organizatio.patch new file mode 100644 index 0000000..e0b59ff --- /dev/null +++ b/0012-Trac-Ticket-500-Newly-created-users-with-organizatio.patch @@ -0,0 +1,259 @@ +From eb10a9e242264fe94098743e048bfbba4fc9a422 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 13 Nov 2012 11:21:26 -0800 +Subject: [PATCH 12/16] Trac Ticket #500 - Newly created users with + organizationalPerson objectClass fails to sync from + AD to DS with missing attribute error + +https://fedorahosted.org/389/ticket/500 + +Bug description: Posix Account objectclass requires homeDirectory, +uidNumber, and gidNumber. When an AD entry has just some of these +attributes or other allow-to-have attributes, i.e., loginShell or +gecos, the entry is incompletely converted to Posix Account entry +and fails to be added due to the missing attribute error. + +Fix description: Before transforming the AD entry to the DS posix +account entry, check the required attributes first. If any of the +above 3 attributes is missing, all of the posix account related +attributes are dropped and added to the DS as a non-posix account +entry. If the PLUGIN log level is set, this type of message is +logged in the error log. +[] posix-winsync - AD entry CN=,OU=,DC=,DC= does +not have required attribute uidNumber for posixAccount objectclass. +(cherry picked from commit 19e49e69124ff19530a584f90808aa652a4c686f) +(cherry picked from commit f95bc254e3019727123068af5612058be05fb6be) +--- + ldap/servers/plugins/posix-winsync/posix-winsync.c | 129 ++++++++++++++------- + ldap/servers/slapd/mapping_tree.c | 2 +- + 2 files changed, 91 insertions(+), 40 deletions(-) + +diff --git a/ldap/servers/plugins/posix-winsync/posix-winsync.c b/ldap/servers/plugins/posix-winsync/posix-winsync.c +index aa292c3..92a3a79 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-winsync.c ++++ b/ldap/servers/plugins/posix-winsync/posix-winsync.c +@@ -86,14 +86,17 @@ typedef struct _windows_attr_map + { + char *windows_attribute_name; + char *ldap_attribute_name; ++ int isMUST; /* schema: required attribute */ + } windows_attribute_map; + +-static windows_attribute_map user_attribute_map[] = { { "unixHomeDirectory", "homeDirectory" }, +- { "loginShell", "loginShell" }, +- { "uidNumber", "uidNumber" }, +- { "gidNumber", "gidNumber" }, +- { "gecos", "gecos" }, +- { NULL, NULL } }; ++static windows_attribute_map user_attribute_map[] = { ++ { "unixHomeDirectory", "homeDirectory", 1 }, ++ { "loginShell", "loginShell", 0 }, ++ { "uidNumber", "uidNumber", 1 }, ++ { "gidNumber", "gidNumber", 1 }, ++ { "gecos", "gecos", 0 }, ++ { NULL, NULL, 0 } ++}; + + static windows_attribute_map user_mssfu_attribute_map[] = + { { "msSFU30homedirectory", "homeDirectory" }, +@@ -751,7 +754,9 @@ posix_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + int is_present_local = 0; + int do_modify_local = 0; + int rc; ++ int i; + windows_attribute_map *attr_map = user_attribute_map; ++ PRBool posixval = PR_TRUE; + + if (posix_winsync_config_get_msSFUSchema()) + attr_map = user_mssfu_attribute_map; +@@ -759,15 +764,33 @@ posix_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, + "--> _pre_ds_mod_user_cb -- begin\n"); + ++ /* check all of the required attributes are in the ad_entry: ++ * MUST (cn $ uid $ uidNumber $ gidNumber $ homeDirectory). ++ * If any of the required attributes are missing, drop them before adding ++ * the entry to the DS. */ ++ for (i = 0; attr_map[i].windows_attribute_name != NULL; i++) { ++ Slapi_Attr *pa_attr; ++ if (attr_map[i].isMUST && ++ slapi_entry_attr_find(ad_entry, ++ attr_map[i].windows_attribute_name, ++ &pa_attr)) { ++ /* required attribute does not exist */ ++ posixval = PR_FALSE; ++ slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, ++ "AD entry %s does not have required attribute %s for posixAccount objectclass.\n", ++ slapi_entry_get_dn_const(ad_entry), ++ attr_map[i].ldap_attribute_name); ++ } ++ } ++ + /* add objectclass: posixAccount, uidnumber ,gidnumber ,homeDirectory, loginshell */ + /* in the ad to ds case we have no changelog, so we have to compare the entries */ + for (rc = slapi_entry_first_attr(ad_entry, &attr); rc == 0; + rc = slapi_entry_next_attr(ad_entry, attr, &attr)) { + char *type = NULL; +- size_t i = 0; + + slapi_attr_get_type(attr, &type); +- for (; attr_map[i].windows_attribute_name != NULL; i++) { ++ for (i = 0; attr_map[i].windows_attribute_name != NULL; i++) { + if (0 == slapi_attr_type_cmp(type, attr_map[i].windows_attribute_name, + SLAPI_TYPE_CMP_SUBTYPE)) { + Slapi_Attr *local_attr = NULL; +@@ -779,7 +802,10 @@ posix_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + slapi_entry_attr_find(ds_entry, local_type, &local_attr); + is_present_local = (NULL == local_attr) ? 0 : 1; + if (is_present_local) { ++ /* DS entry has the posix attrs. ++ * I.e., it is a posix account*/ + int values_equal = 0; ++ posixval = PR_TRUE; + values_equal = attr_compare_equal(attr, local_attr); + if (!values_equal) { + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, +@@ -791,8 +817,8 @@ posix_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + valueset_get_valuearray(vs)); + *do_modify = 1; + } +- } else { +- ++ } else if (posixval) { ++ /* only if AD provides the all necessary attributes */ + slapi_mods_add_mod_values(smods, LDAP_MOD_ADD, local_type, + valueset_get_valuearray(vs)); + *do_modify = do_modify_local = 1; +@@ -804,10 +830,11 @@ posix_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + } + } + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, +- "<-- _pre_ds_mod_user_cb present %d modify %d\n", is_present_local, +- do_modify_local); ++ "<-- _pre_ds_mod_user_cb present %d modify %d isPosixaccount %s\n", ++ is_present_local, do_modify_local, ++ posixval?"yes":"no"); + +- if (!is_present_local && do_modify_local) { ++ if (!is_present_local && do_modify_local && posixval) { + Slapi_Attr *oc_attr = NULL; + Slapi_Value *voc = slapi_value_new(); + +@@ -988,8 +1015,9 @@ posix_winsync_pre_ds_add_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + { + Slapi_Attr *attr = NULL; + char *type = NULL; +- PRBool posixval = PR_FALSE; ++ PRBool posixval = PR_TRUE; + windows_attribute_map *attr_map = user_attribute_map; ++ int i = 0; + + if (posix_winsync_config_get_msSFUSchema()) + attr_map = user_mssfu_attribute_map; +@@ -998,42 +1026,65 @@ posix_winsync_pre_ds_add_user_cb(void *cbdata, const Slapi_Entry *rawentry, Slap + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, + "--> _pre_ds_add_user_cb -- begin\n"); + +- for (slapi_entry_first_attr(ad_entry, &attr); attr; slapi_entry_next_attr(ad_entry, attr, &attr)) { +- size_t i = 0; +- +- slapi_attr_get_type(attr, &type); +- if (!type) { +- continue; ++ /* check all of the required attributes are in the ad_entry: ++ * MUST (cn $ uid $ uidNumber $ gidNumber $ homeDirectory). ++ * If any of the required attributes are missing, drop them before adding ++ * the entry to the DS. */ ++ for (i = 0; attr_map[i].windows_attribute_name != NULL; i++) { ++ Slapi_Attr *pa_attr; ++ if (attr_map[i].isMUST && ++ slapi_entry_attr_find(ad_entry, ++ attr_map[i].windows_attribute_name, ++ &pa_attr)) { ++ /* required attribute does not exist */ ++ posixval = PR_FALSE; ++ slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, ++ "AD entry %s does not have required attribute %s for posixAccount objectclass.\n", ++ slapi_entry_get_dn_const(ad_entry), ++ attr_map[i].ldap_attribute_name); + } ++ } + +- slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, "--> _pre_ds_add_user_cb -- " +- "look for [%s] to new entry [%s]\n", type, slapi_entry_get_dn_const(ds_entry)); +- for (; attr_map[i].windows_attribute_name != NULL; i++) { +- if (slapi_attr_type_cmp(attr_map[i].windows_attribute_name, type, +- SLAPI_TYPE_CMP_SUBTYPE) == 0) { +- Slapi_ValueSet *svs = NULL; +- slapi_attr_get_valueset(attr, &svs); +- slapi_entry_add_valueset(ds_entry, attr_map[i].ldap_attribute_name, svs); +- slapi_valueset_free(svs); ++ /* converts the AD attributes to DS posix attribute if all the posix ++ * required attributes are available */ ++ if (posixval) { ++ int rc; ++ for (slapi_entry_first_attr(ad_entry, &attr); attr; ++ slapi_entry_next_attr(ad_entry, attr, &attr)) { + +- slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, +- "--> _pre_ds_add_user_cb -- " +- "adding val for [%s] to new entry [%s]\n", type, +- slapi_entry_get_dn_const(ds_entry)); +- posixval = PR_TRUE; ++ slapi_attr_get_type(attr, &type); ++ if (!type) { ++ continue; ++ } ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, ++ "--> _pre_ds_add_user_cb -- " ++ "look for [%s] to new entry [%s]\n", ++ type, slapi_entry_get_dn_const(ds_entry)); ++ for (i = 0; attr_map[i].windows_attribute_name != NULL; i++) { ++ if (slapi_attr_type_cmp(attr_map[i].windows_attribute_name, ++ type, SLAPI_TYPE_CMP_SUBTYPE) == 0) { ++ Slapi_ValueSet *svs = NULL; ++ slapi_attr_get_valueset(attr, &svs); ++ slapi_entry_add_valueset(ds_entry, ++ attr_map[i].ldap_attribute_name, svs); ++ slapi_valueset_free(svs); ++ ++ slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, ++ "--> _pre_ds_add_user_cb -- " ++ "adding val for [%s] to new entry [%s]\n", ++ type, slapi_entry_get_dn_const(ds_entry)); ++ } + } + } +- } +- if (posixval) { +- int rc; + rc = slapi_entry_add_string(ds_entry, "objectClass", "posixAccount"); + rc |= slapi_entry_add_string(ds_entry, "objectClass", "shadowAccount"); + rc |= slapi_entry_add_string(ds_entry, "objectClass", "inetUser"); +- if (rc != 0) ++ if (rc != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, posix_winsync_plugin_name, + "<-- _pre_ds_add_user_cb -- adding objectclass for new entry failed %d\n", + rc); +- else { ++ } else { + if (posix_winsync_config_get_mapNestedGrouping()) { + memberUidLock(); + addUserToGroupMembership(ds_entry); +diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c +index e8e414f..da8e4f3 100644 +--- a/ldap/servers/slapd/mapping_tree.c ++++ b/ldap/servers/slapd/mapping_tree.c +@@ -2451,7 +2451,7 @@ int slapi_mapping_tree_select_and_check(Slapi_PBlock *pb,char *newdn, Slapi_Back + { + ret = LDAP_AFFECTS_MULTIPLE_DSAS; + PR_snprintf(errorbuf, BUFSIZ, +- "Cannot move entries accross backends\n"); ++ "Cannot move entries across backends\n"); + goto unlock_and_return; + } + } +-- +1.7.11.7 + diff --git a/0013-Trac-Ticket-519-Search-with-a-complex-filter-includi.patch b/0013-Trac-Ticket-519-Search-with-a-complex-filter-includi.patch new file mode 100644 index 0000000..11b1f9d --- /dev/null +++ b/0013-Trac-Ticket-519-Search-with-a-complex-filter-includi.patch @@ -0,0 +1,279 @@ +From e8d103d554e3fd1c62232b404a7a68addc0809ef Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 13 Nov 2012 18:01:57 -0800 +Subject: [PATCH 13/16] Trac Ticket #519 - Search with a complex filter + including range search is slow + +https://fedorahosted.org/389/ticket/519 + +Bug description: If a filter contains a range search, the +search retrieves one ID per one idl_fetch and merge it to +the idlist using idl_union, which is slow especially when +the range search result size is large. + +Fix description: When the idlist size is larger than nsslapd- +lookthroughlimit, the range search returns ALLID (default +value of nsslapd-lookthroughlimit is 5000). Then, the range +search filter is evaluated before returning to the client. +If the default value of nsslapd-lookthroughlimit can be used, +the search elapsed time is much shorter than generating a +complete idlist in index_range_read_ext. Since the nsslapd- +lookthroughlimit is shared among all the search operations, +larger value might be required for other cases. To have its +own control, this patch introduces a new config parameter +nsslapd-rangelookthroughlimit for the range search. + +Also, this patch replaced idl_union in index_range_read_ext +with idl_append_extend and sort the idlist at the end. It +improves the range search, but it is still slower than just +returning ALLID for the large range search. +(cherry picked from commit f026ef0447b18994e0e9b847698703436e874f84) +(cherry picked from commit 0a54aa676341b7f5f1056373a5067a69cbe54b89) +--- + ldap/servers/slapd/back-ldbm/back-ldbm.h | 5 +++- + ldap/servers/slapd/back-ldbm/idl.c | 7 +++++ + ldap/servers/slapd/back-ldbm/index.c | 39 +++++++++++++++++++------- + ldap/servers/slapd/back-ldbm/ldbm_config.c | 23 +++++++++++++++ + ldap/servers/slapd/back-ldbm/ldbm_config.h | 1 + + ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 1 + + ldap/servers/slapd/back-ldbm/start.c | 9 ++++++ + ldap/servers/slapd/back-ldbm/vlv.c | 8 +----- + 8 files changed, 75 insertions(+), 18 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h +index fb45a9f..aed57cf 100644 +--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h +@@ -210,7 +210,6 @@ typedef unsigned short u_int16_t; + #define DEFAULT_DBCACHE_SIZE 1000000 + #define DEFAULT_MODE 0600 + #define DEFAULT_ALLIDSTHRESHOLD 4000 +-#define DEFAULT_LOOKTHROUGHLIMIT 5000 + #define DEFAULT_IDL_TUNE 1 + #define DEFAULT_SEARCH_TUNE 0 + #define DEFAULT_IMPORT_INDEX_BUFFER_SIZE 0 +@@ -650,6 +649,8 @@ struct ldbminfo { + int li_pagedallidsthreshold; + int li_reslimit_pagedlookthrough_handle; + int li_reslimit_pagedallids_handle; /* allids aka idlistscan */ ++ int li_rangelookthroughlimit; ++ int li_reslimit_rangelookthrough_handle; + }; + + /* li_flags could store these bits defined in ../slapi-plugin.h +@@ -819,6 +820,8 @@ typedef struct _back_search_result_set + /* Name of attribute type used for binder-based look through limit */ + #define LDBM_LOOKTHROUGHLIMIT_AT "nsLookThroughLimit" + /* Name of attribute type used for binder-based look through limit */ ++#define LDBM_RANGELOOKTHROUGHLIMIT_AT "nsRangeSearchLookThroughLimit" ++/* Name of attribute type used for binder-based look through limit */ + #define LDBM_ALLIDSLIMIT_AT "nsIDListScanLimit" + /* Name of attribute type used for binder-based look through simple paged limit */ + #define LDBM_PAGEDLOOKTHROUGHLIMIT_AT "nsPagedLookThroughLimit" +diff --git a/ldap/servers/slapd/back-ldbm/idl.c b/ldap/servers/slapd/back-ldbm/idl.c +index 5d467bd..58736f8 100644 +--- a/ldap/servers/slapd/back-ldbm/idl.c ++++ b/ldap/servers/slapd/back-ldbm/idl.c +@@ -1620,3 +1620,10 @@ make_cont_key( DBT *contkey, DBT *key, ID id ) + sprintf( contkey->dptr, "%c%s%lu", CONT_PREFIX, (char *)key->dptr, (u_long)id ); + contkey->dsize = strlen( contkey->dptr ) + 1; + } ++ ++int ++idl_sort_cmp(const void *x, const void *y) ++{ ++ return *(ID *)x - *(ID *)y; ++} ++ +diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c +index a5c6ac5..5948717 100644 +--- a/ldap/servers/slapd/back-ldbm/index.c ++++ b/ldap/servers/slapd/back-ldbm/index.c +@@ -1236,6 +1236,7 @@ index_range_read_ext( + time_t curtime, stoptime, optime; + int timelimit = -1; + back_search_result_set *sr = NULL; ++ int isroot = 0; + + if (!pb) { + LDAPDebug(LDAP_DEBUG_ANY, "index_range_read: NULL pblock\n", +@@ -1270,11 +1271,11 @@ index_range_read_ext( + if (sr != NULL) { + /* the normal case */ + lookthrough_limit = sr->sr_lookthroughlimit; +- } else { +- int isroot = 0; +- slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot ); +- if (!isroot) { +- lookthrough_limit = li->li_lookthroughlimit; ++ } ++ slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot ); ++ if (!isroot) { ++ if (lookthrough_limit > li->li_rangelookthroughlimit) { ++ lookthrough_limit = li->li_rangelookthroughlimit; + } + } + +@@ -1478,7 +1479,7 @@ index_range_read_ext( + /* exit the loop when we either run off the end of the table, + * fail to read a key, or read a key that's out of range. + */ +- IDList *tmp, *tmp2; ++ IDList *tmp; + /* + char encbuf [BUFSIZ]; + LDAPDebug( LDAP_DEBUG_FILTER, " cur_key=%s(%li bytes)\n", +@@ -1549,10 +1550,22 @@ index_range_read_ext( + encoded(&cur_key, encbuf), (long)cur_key.dsize); + } + } else { +- tmp2 = idl_union( be, idl, tmp ); +- idl_free( idl ); +- idl_free( tmp ); +- idl = tmp2; ++ /* idl tmp only contains one id */ ++ /* append it at the end here; sort idlist at the end */ ++ if (ALLIDS(tmp)) { ++ idl_free(idl); ++ idl = tmp; ++ } else { ++ ID id; ++ for (id = idl_firstid(tmp); id != NOID; id = idl_nextid(tmp, id)) { ++ *err = idl_append_extend(&idl, id); ++ if (*err) { ++ ldbm_nasty("index_range_read - failed to generate idlist", ++ 1097, *err); ++ } ++ } ++ idl_free(tmp); ++ } + if (ALLIDS(idl)) { + LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read hit an allids value\n", + 0, 0, 0); +@@ -1601,6 +1614,12 @@ error: + + dblayer_release_index_file( be, ai, db ); + ++ /* sort idl */ ++ if (idl && !ALLIDS(idl)) { ++ qsort((void *)&idl->b_ids[0], idl->b_nids, ++ (size_t)sizeof(ID), idl_sort_cmp); ++ } ++ + LDAPDebug( LDAP_DEBUG_TRACE, "<= index_range_read(%s,%s) %lu candidates\n", + type, prefix, (u_long)IDL_NIDS(idl) ); + return( idl ); +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c +index d0664eb..232af54 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c +@@ -187,6 +187,28 @@ static int ldbm_config_pagedlookthroughlimit_set(void *arg, void *value, char *e + return retval; + } + ++static void *ldbm_config_rangelookthroughlimit_get(void *arg) ++{ ++ struct ldbminfo *li = (struct ldbminfo *) arg; ++ ++ return (void *) ((uintptr_t)(li->li_rangelookthroughlimit)); ++} ++ ++static int ldbm_config_rangelookthroughlimit_set(void *arg, void *value, char *errorbuf, int phase, int apply) ++{ ++ struct ldbminfo *li = (struct ldbminfo *) arg; ++ int retval = LDAP_SUCCESS; ++ int val = (int) ((uintptr_t)value); ++ ++ /* Do whatever we can to make sure the data is ok. */ ++ ++ if (apply) { ++ li->li_rangelookthroughlimit = val; ++ } ++ ++ return retval; ++} ++ + static void *ldbm_config_mode_get(void *arg) + { + struct ldbminfo *li = (struct ldbminfo *) arg; +@@ -1341,6 +1363,7 @@ static config_info ldbm_config[] = { + {CONFIG_ENTRYRDN_NOANCESTORID, CONFIG_TYPE_ONOFF, "off", &ldbm_config_entryrdn_noancestorid_get, &ldbm_config_entryrdn_noancestorid_set, 0 /* no show */}, + {CONFIG_PAGEDLOOKTHROUGHLIMIT, CONFIG_TYPE_INT, "0", &ldbm_config_pagedlookthroughlimit_get, &ldbm_config_pagedlookthroughlimit_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, + {CONFIG_PAGEDIDLISTSCANLIMIT, CONFIG_TYPE_INT, "0", &ldbm_config_pagedallidsthreshold_get, &ldbm_config_pagedallidsthreshold_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, ++ {CONFIG_RANGELOOKTHROUGHLIMIT, CONFIG_TYPE_INT, "5000", &ldbm_config_rangelookthroughlimit_get, &ldbm_config_rangelookthroughlimit_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, + {NULL, 0, NULL, NULL, NULL, 0} + }; + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.h b/ldap/servers/slapd/back-ldbm/ldbm_config.h +index 36b8f60..a5830e3 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_config.h ++++ b/ldap/servers/slapd/back-ldbm/ldbm_config.h +@@ -85,6 +85,7 @@ struct config_info { + + #define CONFIG_INSTANCE "nsslapd-instance" + #define CONFIG_LOOKTHROUGHLIMIT "nsslapd-lookthroughlimit" ++#define CONFIG_RANGELOOKTHROUGHLIMIT "nsslapd-rangelookthroughlimit" + #define CONFIG_PAGEDLOOKTHROUGHLIMIT "nsslapd-pagedlookthroughlimit" + #define CONFIG_IDLISTSCANLIMIT "nsslapd-idlistscanlimit" + #define CONFIG_PAGEDIDLISTSCANLIMIT "nsslapd-pagedidlistscanlimit" +diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +index be4120a..48b3164 100644 +--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +@@ -235,6 +235,7 @@ int idl_is_allids(IDList *idl); + int idl_append(IDList *idl, ID id); + int idl_append_extend(IDList **idl, ID id); + void idl_insert(IDList **idl, ID id); ++int idl_sort_cmp(const void *x, const void *y); + /* + * idl_delete - delete an id from an id list. + * returns 0 id deleted +diff --git a/ldap/servers/slapd/back-ldbm/start.c b/ldap/servers/slapd/back-ldbm/start.c +index 0f42bed..4276c3b 100644 +--- a/ldap/servers/slapd/back-ldbm/start.c ++++ b/ldap/servers/slapd/back-ldbm/start.c +@@ -116,6 +116,15 @@ ldbm_back_start( Slapi_PBlock *pb ) + return SLAPI_FAIL_GENERAL; + } + ++ /* lookthrough limit for the rangesearch */ ++ if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT, ++ LDBM_RANGELOOKTHROUGHLIMIT_AT, &li->li_reslimit_rangelookthrough_handle ) ++ != SLAPI_RESLIMIT_STATUS_SUCCESS ) { ++ LDAPDebug( LDAP_DEBUG_ANY, "start: Resource limit registration failed for rangelookthroughlimit\n", ++ 0, 0, 0 ); ++ return SLAPI_FAIL_GENERAL; ++ } ++ + /* If the db directory hasn't been set yet, we need to set it to + * the default. */ + if (NULL == li->li_directory || '\0' == li->li_directory[0]) { +diff --git a/ldap/servers/slapd/back-ldbm/vlv.c b/ldap/servers/slapd/back-ldbm/vlv.c +index 7172104..39d16bf 100644 +--- a/ldap/servers/slapd/back-ldbm/vlv.c ++++ b/ldap/servers/slapd/back-ldbm/vlv.c +@@ -1048,12 +1048,6 @@ vlv_build_candidate_list_byvalue( struct vlvIndex* p, DBC *dbc, PRUint32 length, + return si; + } + +-static int +-vlv_idl_sort_cmp(const void *x, const void *y) +-{ +- return *(ID *)x - *(ID *)y; +-} +- + /* build a candidate list (IDL) from a VLV index, given the starting index + * and the ending index (as an inclusive list). + * returns 0 on success, or an LDAP error code. +@@ -1111,7 +1105,7 @@ int vlv_build_idl(PRUint32 start, PRUint32 stop, DB *db, DBC *dbc, + if (dosort) + { + qsort((void *)&idl->b_ids[0], idl->b_nids, +- (size_t)sizeof(ID), vlv_idl_sort_cmp); ++ (size_t)sizeof(ID), idl_sort_cmp); + } + *candidates = idl; + +-- +1.7.11.7 + diff --git a/0014-Trac-Ticket-520-RedHat-Directory-Server-crashes-segf.patch b/0014-Trac-Ticket-520-RedHat-Directory-Server-crashes-segf.patch new file mode 100644 index 0000000..0356425 --- /dev/null +++ b/0014-Trac-Ticket-520-RedHat-Directory-Server-crashes-segf.patch @@ -0,0 +1,58 @@ +From c038959812a2e7d92285fc9d304e1dae99a8cfa4 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Wed, 14 Nov 2012 12:23:06 -0800 +Subject: [PATCH 14/16] Trac Ticket #520 - RedHat Directory Server crashes + (segfaults) when moving ldap entry + +https://fedorahosted.org/389/ticket/520 + +Fix description: The code to check if the new superior entry exists +or not was returning the "No such object" error only when the op +was requested by the directory manager. This patch is removing +the condition so that whoever the requester is, it returns the error. +(cherry picked from commit 40e68b18dae23a21654719a742419f172aa54806) +(cherry picked from commit d4dbb3d01a7f3f39c5370a10a02109d90c5140e0) +--- + ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +index c7d821a..69fc053 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +@@ -426,10 +426,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) + if ( newparententry == NULL ) + { + /* There may not be a new parent because we don't intend there to be one. */ +- if(slapi_sdn_get_ndn(dn_newsuperiordn)!=NULL) ++ if (slapi_sdn_get_ndn(dn_newsuperiordn)) + { +- /* If the new entry is to be a suffix, and we're root, then it's OK that the new parent doesn't exist */ +- if (!(slapi_be_issuffix(pb->pb_backend, &dn_newdn)) && isroot) ++ /* If the new entry is not to be a suffix, ++ * return an error no matter who requested this modrdn */ ++ if (!slapi_be_issuffix(pb->pb_backend, &dn_newdn)) + { + /* Here means that we didn't find the parent */ + int err = 0; +@@ -447,7 +448,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) + slapi_sdn_get_ndn(dn_newsuperiordn), 0 ); + slapi_sdn_done(&ancestorsdn); + goto error_return; +- } ++ } + } + } + else +@@ -465,7 +466,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) + if ( parententry == NULL ) + { + /* If the entry a suffix, and we're root, then it's OK that the parent doesn't exist */ +- if (!(slapi_be_issuffix(pb->pb_backend, sdn)) && isroot) ++ if (!(slapi_be_issuffix(pb->pb_backend, sdn)) && !isroot) + { + /* Here means that we didn't find the parent */ + ldap_result_matcheddn = "NULL"; +-- +1.7.11.7 + diff --git a/0015-Ticket-517-crash-in-DNA-if-no-dnaMagicRegen-is-speci.patch b/0015-Ticket-517-crash-in-DNA-if-no-dnaMagicRegen-is-speci.patch new file mode 100644 index 0000000..9e11088 --- /dev/null +++ b/0015-Ticket-517-crash-in-DNA-if-no-dnaMagicRegen-is-speci.patch @@ -0,0 +1,111 @@ +From fa889bc385ff09b752769b04acc91df84d44ae4c Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 14 Nov 2012 15:18:57 -0500 +Subject: [PATCH 15/16] Ticket 517 - crash in DNA if no dnaMagicRegen is + specified + +Bug Description: There are several places where we deference config_entry->generate + +Fix Description: Properly check for NULL, and allow the update of dnaType. + +https://fedorahosted.org/389/ticket/517 + +Reviewed by: richm(Thanks Rich) +(cherry picked from commit d97835969db3e957032c52ac317699354299c07c) +(cherry picked from commit 322c4ecc2363c4e7a7107ae2e8aa05aa3a55ddf3) +--- + ldap/servers/plugins/dna/dna.c | 49 +++++++++++++++++++----------------------- + 1 file changed, 22 insertions(+), 27 deletions(-) + +diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c +index 34d67ab..ef01735 100644 +--- a/ldap/servers/plugins/dna/dna.c ++++ b/ldap/servers/plugins/dna/dna.c +@@ -804,10 +804,9 @@ dna_parse_config_entry(Slapi_Entry * e, int apply) + value = slapi_entry_attr_get_charptr(e, DNA_GENERATE); + if (value) { + entry->generate = value; +- } +- +- slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM, ++ slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM, + "----------> %s [%s]\n", DNA_GENERATE, entry->generate); ++ } + + value = slapi_entry_attr_get_charptr(e, DNA_FILTER); + if (value) { +@@ -2809,8 +2808,7 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e) + + /* does the entry match the filter? */ + if (config_entry->slapi_filter) { +- ret = slapi_vattr_filter_test(pb, e, config_entry->slapi_filter, +- 0); ++ ret = slapi_vattr_filter_test(pb, e, config_entry->slapi_filter, 0); + if (LDAP_SUCCESS != ret) { + goto next; + } +@@ -2820,28 +2818,23 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e) + /* For a multi-type range, we only generate a value + * for types where the magic value is set. We do not + * generate a value for missing types. */ +- for (i = 0; config_entry->types && config_entry->types[i]; +- i++) { +- value = slapi_entry_attr_get_charptr(e, +- config_entry->types[i]); +- +- if (value && +- !slapi_UTF8CASECMP(config_entry->generate, value)) { +- slapi_ch_array_add(&types_to_generate, +- slapi_ch_strdup(config_entry->types[i])); ++ for (i = 0; config_entry->types && config_entry->types[i]; i++) { ++ value = slapi_entry_attr_get_charptr(e, config_entry->types[i]); ++ if (value){ ++ if(config_entry->generate == NULL || !slapi_UTF8CASECMP(config_entry->generate, value)){ ++ slapi_ch_array_add(&types_to_generate, slapi_ch_strdup(config_entry->types[i])); ++ } ++ slapi_ch_free_string(&value); + } +- slapi_ch_free_string(&value); + } + } else { + /* For a single type range, we generate the value if + * the magic value is set or if the type is missing. */ + value = slapi_entry_attr_get_charptr(e, config_entry->types[0]); + +- if ((value && +- !slapi_UTF8CASECMP(config_entry->generate, value)) || +- (0 == value)) { +- slapi_ch_array_add(&types_to_generate, +- slapi_ch_strdup(config_entry->types[0])); ++ if((config_entry->generate == NULL) || (0 == value) || ++ (value && !slapi_UTF8CASECMP(config_entry->generate, value))){ ++ slapi_ch_array_add(&types_to_generate, slapi_ch_strdup(config_entry->types[0])); + } + slapi_ch_free_string(&value); + } +@@ -3060,13 +3053,15 @@ _dna_pre_op_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Mods *smods) + + /* If we have a value, see if it's the magic value. */ + if (bv) { +- len = strlen(config_entry->generate); +- if (len == bv->bv_len) { +- if (!slapi_UTF8NCASECMP(bv->bv_val, +- config_entry->generate, +- len)) { +- slapi_ch_array_add(&types_to_generate, +- slapi_ch_strdup(type)); ++ if(config_entry->generate == NULL){ ++ /* we don't have a magic number set, so apply the update */ ++ slapi_ch_array_add(&types_to_generate, slapi_ch_strdup(type)); ++ } else { ++ len = strlen(config_entry->generate); ++ if (len == bv->bv_len) { ++ if (!slapi_UTF8NCASECMP(bv->bv_val, config_entry->generate,len)){ ++ slapi_ch_array_add(&types_to_generate, slapi_ch_strdup(type)); ++ } + } + } + } else if (!dna_is_multitype_range(config_entry)) { +-- +1.7.11.7 + diff --git a/0016-Ticket-495-internalModifiersname-not-updated-by-DNA-.patch b/0016-Ticket-495-internalModifiersname-not-updated-by-DNA-.patch new file mode 100644 index 0000000..72c0a7a --- /dev/null +++ b/0016-Ticket-495-internalModifiersname-not-updated-by-DNA-.patch @@ -0,0 +1,225 @@ +From 4cf64c10bc92fd7627f452cd6b991671015ba8fa Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 19 Oct 2012 10:22:21 -0400 +Subject: [PATCH 16/16] Ticket 495 - internalModifiersname not updated by DNA + plugin + +Bug Description: If you are using the "nsslapd-plugin-binddn-tracking", and the DNA plugin + modifiers the entry, the internalmodifiersname is not updated. + +Fix Description: This is because the DNA plugin directly modifies the entry, and does not + use the internal modify functions that would trigger the last mod attributes + to be updated. So we have to call the last mod update funtciont directly from + the dna plugin. + + There is also a slight change to the behavior now. The internalModifiersname & + internalCreatorsname will never be the bind dn, but instead it will be the plugin + that actually did the update. So if a entry was not touched by a DS plugin, then + the "database" plugin would be the internal modifier/creator: + + cn=ldbm database,cn=plugins,cn=config + + This would also allow us to detect if someone replaced the default backend. + +https://fedorahosted.org/389/ticket/495 + +Reviewed by: nhosoi(Thanks!) +(cherry picked from commit fb8c9f305398f713154bc3d8dddeb89d3c9d386a) +--- + ldap/servers/plugins/dna/dna.c | 4 +++ + ldap/servers/slapd/add.c | 56 ++++++++++++++++++++++++++++++++++---- + ldap/servers/slapd/opshared.c | 8 ++++-- + ldap/servers/slapd/proto-slap.h | 1 - + ldap/servers/slapd/slapi-private.h | 10 +++++++ + 5 files changed, 71 insertions(+), 8 deletions(-) + +diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c +index ef01735..66d4a05 100644 +--- a/ldap/servers/plugins/dna/dna.c ++++ b/ldap/servers/plugins/dna/dna.c +@@ -2846,6 +2846,8 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e) + /* no need to dup */ + DNA_NEEDS_UPDATE); + } ++ /* Update the internalModifiersname for this add op */ ++ add_internal_modifiersname(pb, e); + + /* Make sure we don't generate for this + * type again by keeping a list of types +@@ -3101,6 +3103,8 @@ _dna_pre_op_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Mods *smods) + /* no need to dup */ + DNA_NEEDS_UPDATE); + } ++ /* Update the internalModifersname for this mod op */ ++ modify_update_last_modified_attr(pb, smods); + + /* Make sure we don't generate for this + * type again by keeping a list of types +diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c +index 55deeee..3206d5b 100644 +--- a/ldap/servers/slapd/add.c ++++ b/ldap/servers/slapd/add.c +@@ -73,7 +73,7 @@ + /* Forward declarations */ + static int add_internal_pb (Slapi_PBlock *pb); + static void op_shared_add (Slapi_PBlock *pb); +-static int add_created_attrs(Operation *op, Slapi_Entry *e); ++static int add_created_attrs(Slapi_PBlock *pb, Slapi_Entry *e); + static int check_rdn_for_created_attrs(Slapi_Entry *e); + static void handle_fast_add(Slapi_PBlock *pb, Slapi_Entry *entry); + static int add_uniqueid (Slapi_Entry *e); +@@ -631,7 +631,7 @@ static void op_shared_add (Slapi_PBlock *pb) + /* can get lastmod only after backend is selected */ + slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod); + +- if (lastmod && add_created_attrs(operation, e) != 0) ++ if (lastmod && add_created_attrs(pb, e) != 0) + { + send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, + "cannot insert computed attributes", 0, NULL); +@@ -745,20 +745,25 @@ done: + } + + static int +-add_created_attrs(Operation *op, Slapi_Entry *e) ++add_created_attrs(Slapi_PBlock *pb, Slapi_Entry *e) + { + char buf[20]; + char *binddn = NULL; ++ char *plugin_dn = NULL; + struct berval bv; + struct berval *bvals[2]; + time_t curtime; + struct tm ltm; ++ Operation *op; ++ struct slapdplugin *plugin = NULL; ++ struct slapi_componentid *cid = NULL; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + LDAPDebug(LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0); + + bvals[0] = &bv; + bvals[1] = NULL; ++ slapi_pblock_get(pb, SLAPI_OPERATION, &op); + + if(slapdFrontendConfig->plugin_track){ + /* plugin bindDN tracking is enabled, grab the dn from thread local storage */ +@@ -766,8 +771,21 @@ add_created_attrs(Operation *op, Slapi_Entry *e) + bv.bv_val = ""; + bv.bv_len = strlen(bv.bv_val); + } else { +- bv.bv_val = (char*)slapi_sdn_get_dn(&op->o_sdn); +- bv.bv_len = strlen(bv.bv_val); ++ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid); ++ if (cid){ ++ plugin=(struct slapdplugin *) cid->sci_plugin; ++ } else { ++ slapi_pblock_get (pb, SLAPI_PLUGIN, &plugin); ++ } ++ if(plugin) ++ plugin_dn = plugin_get_dn (plugin); ++ if(plugin_dn){ ++ bv.bv_val = plugin_dn; ++ bv.bv_len = strlen(bv.bv_val); ++ } else { ++ bv.bv_val = (char*)slapi_sdn_get_dn(&op->o_sdn); ++ bv.bv_len = strlen(bv.bv_val); ++ } + } + slapi_entry_attr_replace(e, "internalCreatorsName", bvals); + slapi_entry_attr_replace(e, "internalModifiersName", bvals); +@@ -971,3 +989,31 @@ check_oc_subentry(Slapi_Entry *e, struct berval **vals, char *normtype) { + } + return subentry; + } ++ ++/* ++ * Used by plugins that modify entries on add operations, otherwise the internalModifiersname ++ * would be incorrect. ++ */ ++void ++add_internal_modifiersname(Slapi_PBlock *pb, Slapi_Entry *e) ++{ ++ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); ++ struct slapi_componentid *cid = NULL; ++ struct slapdplugin *plugin = NULL; ++ char *plugin_dn = NULL; ++ ++ if(slapdFrontendConfig->plugin_track){ ++ /* plugin bindDN tracking is enabled, grab the bind dn from thread local storage */ ++ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid); ++ if (cid){ ++ plugin=(struct slapdplugin *) cid->sci_plugin; ++ } else { ++ slapi_pblock_get (pb, SLAPI_PLUGIN, &plugin); ++ } ++ if(plugin) ++ plugin_dn = plugin_get_dn (plugin); ++ if(plugin_dn){ ++ slapi_entry_attr_set_charptr(e, "internalModifiersname", plugin_dn); ++ } ++ } ++} +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index 2701250..485763e 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -133,7 +133,8 @@ do_ps_service(Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chgtype, ber_int_t c + (ps_service_fn)(e, eprev, chgtype, chgnum); + } + +-void modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods) ++void ++modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods) + { + char buf[20]; + char *plugin_dn = NULL; +@@ -160,8 +161,11 @@ void modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods) + bv.bv_len = strlen(bv.bv_val); + } else { + slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid); +- if (cid) ++ if (cid){ + plugin=(struct slapdplugin *) cid->sci_plugin; ++ } else { ++ slapi_pblock_get (pb, SLAPI_PLUGIN, &plugin); ++ } + if(plugin) + plugin_dn = plugin_get_dn (plugin); + if(plugin_dn){ +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index 7e438b7..2289efa 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -1284,7 +1284,6 @@ void set_config_params (Slapi_PBlock *pb); + /* set parameters common for all internal operations */ + void set_common_params (Slapi_PBlock *pb); + void do_ps_service(Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chgtype, ber_int_t chgnum); +-void modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods); + + /* + * debugdump.cpp +diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h +index f995e30..f7b4d04 100644 +--- a/ldap/servers/slapd/slapi-private.h ++++ b/ldap/servers/slapd/slapi-private.h +@@ -1247,6 +1247,16 @@ int is_slapd_running(); + /* attrsyntax.c */ + int slapi_add_internal_attr_syntax( const char *name, const char *oid, const char *syntax, const char *mr_equality, unsigned long extraflags ); + ++/* pw.c */ ++void pw_exp_init ( void ); ++int pw_copy_entry_ext(Slapi_Entry *src_e, Slapi_Entry *dest_e); ++ ++/* op_shared.c */ ++void modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods); ++ ++/* add.c */ ++void add_internal_modifiersname(Slapi_PBlock *pb, Slapi_Entry *e); ++ + #ifdef __cplusplus + } + #endif +-- +1.7.11.7 + diff --git a/0017-Ticket-337-improve-CLEANRUV-functionality.patch b/0017-Ticket-337-improve-CLEANRUV-functionality.patch new file mode 100644 index 0000000..850afed --- /dev/null +++ b/0017-Ticket-337-improve-CLEANRUV-functionality.patch @@ -0,0 +1,2998 @@ +From b04b2271f48f427330344ca9c61d76e312e9eb8c Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 20 Nov 2012 16:14:42 -0500 +Subject: [PATCH 17/22] Ticket 337 - improve CLEANRUV functionality + +Bug Description: Without anonymous access allowed, then task could not + contact other servers and retrieve data(ruv, maxcsns, etc). + +Fix Description: Changed all communication to use extended operations, and improved + sychronization between the replicas. + +https://fedorahosted.org/389/ticket/337 + +Reviewed by: richm(Thanks Rich!) +(cherry picked from commit ecbd8b7513d05dab5876a88ca56b102c08a7a67c) +(cherry picked from commit 7a3014c0746134403f1fe9a25eac9581750aef0b) +--- + ldap/servers/plugins/replication/cl5_api.c | 21 +- + ldap/servers/plugins/replication/repl5.h | 29 +- + ldap/servers/plugins/replication/repl5_agmt.c | 99 -- + ldap/servers/plugins/replication/repl5_agmtlist.c | 11 +- + .../servers/plugins/replication/repl5_connection.c | 6 + + ldap/servers/plugins/replication/repl5_init.c | 69 +- + ldap/servers/plugins/replication/repl5_replica.c | 132 +-- + .../plugins/replication/repl5_replica_config.c | 1055 +++++++++++++------- + ldap/servers/plugins/replication/repl_extop.c | 266 ++++- + ldap/servers/plugins/replication/replutil.c | 47 +- + ldap/servers/slapd/back-ldbm/ldbm_modify.c | 7 +- + ldap/servers/slapd/back-ldbm/misc.c | 2 +- + ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 1 + + ldap/servers/slapd/entry.c | 10 +- + ldap/servers/slapd/slapi-private.h | 2 +- + 15 files changed, 1104 insertions(+), 653 deletions(-) + +diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c +index a347c57..6c94b3d 100644 +--- a/ldap/servers/plugins/replication/cl5_api.c ++++ b/ldap/servers/plugins/replication/cl5_api.c +@@ -1474,13 +1474,13 @@ int cl5WriteOperation(const char *replName, const char *replGen, + } + + /* Name: cl5CreateReplayIterator +- Description: creates an iterator that allows to retireve changes that should +- to be sent to the consumer identified by ruv. The iteration is peformed by ++ Description: creates an iterator that allows to retrieve changes that should ++ to be sent to the consumer identified by ruv. The iteration is performed by + repeated calls to cl5GetNextOperationToReplay. + Parameters: replica - replica whose data we wish to iterate; + ruv - consumer ruv; + iterator - iterator to be passed to cl5GetNextOperationToReplay call +- Return: CL5_SUCCESS, if function is successfull; ++ Return: CL5_SUCCESS, if function is successful; + CL5_MISSING_DATA, if data that should be in the changelog is missing + CL5_PURGED_DATA, if some data that consumer needs has been purged. + Note that the iterator can be non null if the supplier contains +@@ -1488,14 +1488,14 @@ int cl5WriteOperation(const char *replName, const char *replGen, + CL5_NOTFOUND if the consumer is up to data with respect to the supplier + CL5_BAD_DATA if invalid parameter is passed; + CL5_BAD_STATE if db has not been open; +- CL5_DB_ERROR if any other db error occured; ++ CL5_DB_ERROR if any other db error occurred; + CL5_MEMORY_ERROR if memory allocation fails. + Algorithm: Build a list of csns from consumer's and supplier's ruv. For each element + of the consumer's ruv put max csn into the csn list. For each element + of the supplier's ruv not in the consumer's ruv put min csn from the + supplier's ruv into the list. The list contains, for each known replica, + the starting point for changes to be sent to the consumer. +- Sort the list in accending order. ++ Sort the list in ascending order. + Build a hash which contains, for each known replica, whether the + supplier can bring the consumer up to data with respect to that replica. + The hash is used to decide whether a change can be sent to the consumer +@@ -1503,7 +1503,7 @@ int cl5WriteOperation(const char *replName, const char *replGen, + we can bring the consumer up to date. + Position the db cursor on the change entry that corresponds to this csn. + Hash entries are created for each replica traversed so far. sendChanges +- flag is set to FALSE for all repolicas except the last traversed. ++ flag is set to FALSE for all replicas except the last traversed. + + */ + int cl5CreateReplayIteratorEx (Private_Repl_Protocol *prp, const RUV *consumerRuv, +@@ -6543,7 +6543,9 @@ bail: + void + cl5CleanRUV(ReplicaId rid){ + CL5DBFile *file; +- Object *obj; ++ Object *obj = NULL; ++ ++ slapi_rwlock_wrlock (s_cl5Desc.stLock); + + obj = objset_first_obj(s_cl5Desc.dbFiles); + while (obj){ +@@ -6552,6 +6554,11 @@ cl5CleanRUV(ReplicaId rid){ + ruv_delete_replica(file->maxRUV, rid); + obj = objset_next_obj(s_cl5Desc.dbFiles, obj); + } ++ if(obj){ ++ object_release (obj); ++ } ++ ++ slapi_rwlock_unlock (s_cl5Desc.stLock); + } + + void trigger_cl_trimming(ReplicaId rid){ +diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h +index 61b51b0..bd582bc 100644 +--- a/ldap/servers/plugins/replication/repl5.h ++++ b/ldap/servers/plugins/replication/repl5.h +@@ -97,8 +97,14 @@ + /* cleanallruv extended ops */ + #define REPL_CLEANRUV_OID "2.16.840.1.113730.3.6.5" + #define REPL_ABORT_CLEANRUV_OID "2.16.840.1.113730.3.6.6" +-#define CLEANRUV_NOTIFIED 0 +-#define CLEANRUV_RELEASED 1 ++#define REPL_CLEANRUV_GET_MAXCSN_OID "2.16.840.1.113730.3.6.7" ++#define REPL_CLEANRUV_CHECK_STATUS_OID "2.16.840.1.113730.3.6.8" ++ ++#define CLEANRUV_ACCEPTED "accepted" ++#define CLEANRUV_REJECTED "rejected" ++#define CLEANRUV_FINISHED "finished" ++#define CLEANRUV_CLEANING "cleaning" ++#define CLEANRUV_NO_MAXCSN "no maxcsn" + + /* DS 5.0 replication protocol error codes */ + #define NSDS50_REPL_REPLICA_READY 0x00 /* Replica ready, go ahead */ +@@ -230,6 +236,8 @@ int multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb); + int multimaster_extop_EndNSDS50ReplicationRequest(Slapi_PBlock *pb); + int multimaster_extop_cleanruv(Slapi_PBlock *pb); + int multimaster_extop_abort_cleanruv(Slapi_PBlock *pb); ++int multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb); ++int multimaster_extop_cleanruv_check_status(Slapi_PBlock *pb); + int extop_noop(Slapi_PBlock *pb); + struct berval *NSDS50StartReplicationRequest_new(const char *protocol_oid, + const char *repl_root, char **extra_referrals, CSN *csn); +@@ -365,9 +373,6 @@ PRBool agmt_is_enabled(Repl_Agmt *ra); + int agmt_set_enabled_from_entry(Repl_Agmt *ra, Slapi_Entry *e, char *returntext); + char **agmt_get_attrs_to_strip(Repl_Agmt *ra); + int agmt_set_attrs_to_strip(Repl_Agmt *ra, Slapi_Entry *e); +-void agmt_set_cleanruv_notified_from_entry(Repl_Agmt *ra, Slapi_Entry *e); +-int agmt_set_cleanruv_data(Repl_Agmt *ra, ReplicaId rid, int op); +-int agmt_is_cleanruv_notified(Repl_Agmt *ra, ReplicaId rid); + int agmt_set_timeout(Repl_Agmt *ra, long timeout); + void agmt_update_done(Repl_Agmt *ra, int is_total); + +@@ -454,6 +459,7 @@ LDAP * conn_get_ldap(Repl_Connection *conn); + void conn_lock(Repl_Connection *conn); + void conn_unlock(Repl_Connection *conn); + void conn_delete_internal_ext(Repl_Connection *conn); ++const char* conn_get_bindmethod(Repl_Connection *conn); + + /* In repl5_protocol.c */ + typedef struct repl_protocol Repl_Protocol; +@@ -608,7 +614,7 @@ int replica_config_init(); + void replica_config_destroy (); + int get_replica_type(Replica *r); + int replica_execute_cleanruv_task_ext(Object *r, ReplicaId rid); +-void add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn); ++void add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn, char *forcing); + int is_cleaned_rid(ReplicaId rid); + int replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, + int *returncode, char *returntext, void *arg); +@@ -616,17 +622,15 @@ void replica_cleanallruv_thread_ext(void *arg); + void stop_ruv_cleaning(); + int task_aborted(); + void replica_abort_task_thread(void *arg); +-void delete_cleaned_rid(Replica *r, ReplicaId rid, CSN *maxcsn); ++void remove_cleaned_rid(ReplicaId rid); + int process_repl_agmts(Replica *replica, int *agmt_info, char *oid, Slapi_Task *task, struct berval *payload, int op); + int decode_cleanruv_payload(struct berval *extop_value, char **payload); +-struct berval *create_ruv_payload(char *value); +-void replica_add_cleanruv_data(Replica *r, char *val); +-void replica_remove_cleanruv_data(Replica *r, char *val); +-CSN *replica_get_cleanruv_maxcsn(Replica *r, ReplicaId rid); ++struct berval *create_cleanruv_payload(char *value); + void ruv_get_cleaned_rids(RUV *ruv, ReplicaId *rids); + void add_aborted_rid(ReplicaId rid, Replica *r, char *repl_root); + int is_task_aborted(ReplicaId rid); +-void delete_aborted_rid(Replica *replica, ReplicaId rid, char *repl_root); ++void delete_aborted_rid(Replica *replica, ReplicaId rid, char *repl_root, int skip); ++int is_pre_cleaned_rid(ReplicaId rid); + void set_cleaned_rid(ReplicaId rid); + void cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...); + +@@ -643,6 +647,7 @@ typedef struct _cleanruv_data + char *repl_root; + Slapi_DN *sdn; + char *certify; ++ char *force; + } cleanruv_data; + + /* replutil.c */ +diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c +index d25f54b..935fb37 100644 +--- a/ldap/servers/plugins/replication/repl5_agmt.c ++++ b/ldap/servers/plugins/replication/repl5_agmt.c +@@ -141,7 +141,6 @@ typedef struct repl5agmt { + char **attrs_to_strip; /* for fractional replication, if a "mod" is empty, strip out these attributes: + * modifiersname, modifytimestamp, internalModifiersname, internalModifyTimestamp, etc */ + int agreement_type; +- int cleanruv_notified[CLEANRIDSIZ + 1]; /* specifies if the replica has been notified of a CLEANALLRUV task */ + } repl5agmt; + + /* Forward declarations */ +@@ -252,7 +251,6 @@ agmt_new_from_entry(Slapi_Entry *e) + Repl_Agmt *ra; + Slapi_Attr *sattr; + char *tmpstr; +- char **clean_vals = NULL; + char **denied_attrs = NULL; + char *auto_initialize = NULL; + char *val_nsds5BeginReplicaRefresh = "start"; +@@ -431,20 +429,6 @@ agmt_new_from_entry(Slapi_Entry *e) + ra->last_init_start_time = 0UL; + ra->last_init_status[0] = '\0'; + +- /* cleanruv notification */ +- clean_vals = slapi_entry_attr_get_charray(e, type_nsds5ReplicaCleanRUVnotified); +- if(clean_vals){ +- int i; +- for (i = 0; i < CLEANRIDSIZ && clean_vals[i]; i++){ +- ra->cleanruv_notified[i] = atoi(clean_vals[i]); +- } +- if(i < CLEANRIDSIZ) +- ra->cleanruv_notified[i + 1] = 0; +- slapi_ch_array_free(clean_vals); +- } else { +- ra->cleanruv_notified[0] = 0; +- } +- + /* Fractional attributes */ + slapi_entry_attr_find(e, type_nsds5ReplicatedAttributeList, &sattr); + +@@ -2623,89 +2607,6 @@ agmt_set_attrs_to_strip(Repl_Agmt *ra, Slapi_Entry *e) + return -1; + } + +-int +-agmt_is_cleanruv_notified(Repl_Agmt *ra, ReplicaId rid){ +- int notified = 0; +- int i; +- +- PR_Lock(ra->lock); +- for(i = 0; i < CLEANRIDSIZ && ra->cleanruv_notified[i]; i++){ +- if(ra->cleanruv_notified[i] == rid){ +- notified = 1; +- break; +- } +- } +- PR_Unlock(ra->lock); +- +- return notified; +-} +- +-/* +- * This will trigger agmt_set_cleanruv_notified_from_entry() to be called, +- * which will update the in memory agmt. +- * +- * op can be: CLEANRUV_NOTIFIED or CLEANRUV_RELEASED +- */ +-int +-agmt_set_cleanruv_data(Repl_Agmt *ra, ReplicaId rid, int op){ +- Slapi_PBlock *pb; +- LDAPMod *mods[2]; +- LDAPMod mod; +- struct berval *vals[2]; +- struct berval val; +- char data[6]; +- int rc = 0; +- +- if(ra == NULL){ +- return -1; +- } +- +- if(op == CLEANRUV_NOTIFIED){ +- /* add the cleanruv data */ +- mod.mod_op = LDAP_MOD_ADD|LDAP_MOD_BVALUES; +- } else { +- /* remove the cleanruv data */ +- mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; +- } +- +- pb = slapi_pblock_new(); +- val.bv_len = PR_snprintf(data, sizeof(data), "%d", (int)rid); +- mod.mod_type = (char *)type_nsds5ReplicaCleanRUVnotified; +- mod.mod_bvalues = vals; +- vals [0] = &val; +- vals [1] = NULL; +- val.bv_val = data; +- mods[0] = &mod; +- mods[1] = NULL; +- +- slapi_modify_internal_set_pb_ext (pb, ra->dn, mods, NULL, NULL, +- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); +- slapi_modify_internal_pb (pb); +- slapi_pblock_destroy(pb); +- +- return rc; +-} +- +-void +-agmt_set_cleanruv_notified_from_entry(Repl_Agmt *ra, Slapi_Entry *e){ +- char **attr_vals = NULL; +- int i; +- +- PR_Lock(ra->lock); +- attr_vals = slapi_entry_attr_get_charray(e, type_nsds5ReplicaCleanRUVnotified); +- if(attr_vals){ +- for (i = 0; i < CLEANRIDSIZ && attr_vals[i]; i++){ +- ra->cleanruv_notified[i] = atoi(attr_vals[i]); +- } +- if( i < CLEANRIDSIZ ) +- ra->cleanruv_notified[i + 1] = 0; +- slapi_ch_array_free(attr_vals); +- } else { +- ra->cleanruv_notified[0] = 0; +- } +- PR_Unlock(ra->lock); +-} +- + /* this is called whenever an update (total/incremental) + is completed */ + void +diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c +index 537cfd8..70f71a8 100644 +--- a/ldap/servers/plugins/replication/repl5_agmtlist.c ++++ b/ldap/servers/plugins/replication/repl5_agmtlist.c +@@ -248,7 +248,12 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry + /* we don't allow delete attribute operations unless it was issued by + the replication plugin - handled above */ + if (mods[i]->mod_op & LDAP_MOD_DELETE) +- { ++ { ++ if(strcasecmp (mods[i]->mod_type, type_nsds5ReplicaCleanRUVnotified) == 0){ ++ /* allow the deletion of cleanallruv agmt attr */ ++ continue; ++ } ++ + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " + "deletion of %s attribute is not allowed\n", type_nsds5ReplicaInitialize); + *returncode = LDAP_UNWILLING_TO_PERFORM; +@@ -508,10 +513,6 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry + rc = SLAPI_DSE_CALLBACK_ERROR; + } + } +- else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaCleanRUVnotified)) +- { +- agmt_set_cleanruv_notified_from_entry(agmt, e); +- } + else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e)) + { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " +diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c +index 51a2bc5..5efd0e6 100644 +--- a/ldap/servers/plugins/replication/repl5_connection.c ++++ b/ldap/servers/plugins/replication/repl5_connection.c +@@ -1760,6 +1760,12 @@ bind_method_to_mech(int bindmethod) + return LDAP_SASL_SIMPLE; + } + ++const char* ++conn_get_bindmethod(Repl_Connection *conn) ++{ ++ return (bind_method_to_mech(conn->bindmethod)); ++} ++ + /* + * Check the result of an ldap BIND operation to see we it + * contains the expiration controls +diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c +index 7a80c6f..a0f02fe 100644 +--- a/ldap/servers/plugins/replication/repl5_init.c ++++ b/ldap/servers/plugins/replication/repl5_init.c +@@ -123,7 +123,7 @@ static char *cleanruv_oid_list[] = { + NULL + }; + static char *cleanruv_name_list[] = { +- NSDS_REPL_NAME_PREFIX " Cleanruv", ++ NSDS_REPL_NAME_PREFIX " CleanAllRUV", + NULL + }; + static char *cleanruv_abort_oid_list[] = { +@@ -131,9 +131,26 @@ static char *cleanruv_abort_oid_list[] = { + NULL + }; + static char *cleanruv_abort_name_list[] = { +- NSDS_REPL_NAME_PREFIX " Cleanruv Abort", ++ NSDS_REPL_NAME_PREFIX " CleanAllRUV Abort", + NULL + }; ++static char *cleanruv_maxcsn_oid_list[] = { ++ REPL_CLEANRUV_GET_MAXCSN_OID, ++ NULL ++}; ++static char *cleanruv_maxcsn_name_list[] = { ++ NSDS_REPL_NAME_PREFIX " CleanAllRUV Retrieve MaxCSN", ++ NULL ++}; ++static char *cleanruv_status_oid_list[] = { ++ REPL_CLEANRUV_CHECK_STATUS_OID, ++ NULL ++}; ++static char *cleanruv_status_name_list[] = { ++ NSDS_REPL_NAME_PREFIX " CleanAllRUV Check Status", ++ NULL ++}; ++ + + /* List of plugin identities for every plugin registered. Plugin identity + is passed by the server in the plugin init function and must be supplied +@@ -403,6 +420,52 @@ multimaster_end_extop_init( Slapi_PBlock *pb ) + return rc; + } + ++int ++multimaster_cleanruv_maxcsn_extop_init( Slapi_PBlock *pb ) ++{ ++ int rc= 0; /* OK */ ++ void *identity = NULL; ++ ++ /* get plugin identity and store it to pass to internal operations */ ++ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity); ++ PR_ASSERT (identity); ++ ++ if (slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 || ++ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterextopdesc ) != 0 || ++ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, (void *)cleanruv_maxcsn_oid_list ) != 0 || ++ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, (void *)cleanruv_maxcsn_name_list ) != 0 || ++ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_FN, (void *)multimaster_extop_cleanruv_get_maxcsn )) ++ { ++ slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_cleanruv_extop_init failed\n" ); ++ rc= -1; ++ } ++ ++ return rc; ++} ++ ++int ++multimaster_cleanruv_status_extop_init( Slapi_PBlock *pb ) ++{ ++ int rc= 0; /* OK */ ++ void *identity = NULL; ++ ++ /* get plugin identity and store it to pass to internal operations */ ++ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity); ++ PR_ASSERT (identity); ++ ++ if (slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 || ++ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterextopdesc ) != 0 || ++ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, (void *)cleanruv_status_oid_list ) != 0 || ++ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, (void *)cleanruv_status_name_list ) != 0 || ++ slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_FN, (void *)multimaster_extop_cleanruv_check_status )) ++ { ++ slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_cleanruv_extop_init failed\n" ); ++ rc= -1; ++ } ++ ++ return rc; ++} ++ + + int + multimaster_total_extop_init( Slapi_PBlock *pb ) +@@ -679,6 +742,8 @@ int replication_multimaster_plugin_init(Slapi_PBlock *pb) + rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_response_extop_init", multimaster_response_extop_init, "Multimaster replication extended response plugin", NULL, identity); + rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_extop_init", multimaster_cleanruv_extop_init, "Multimaster replication cleanruv extended operation plugin", NULL, identity); + rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_abort_extop_init", multimaster_cleanruv_abort_extop_init, "Multimaster replication cleanruv abort extended operation plugin", NULL, identity); ++ rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_maxcsn_extop_init", multimaster_cleanruv_maxcsn_extop_init, "Multimaster replication cleanruv maxcsn extended operation plugin", NULL, identity); ++ rc= slapi_register_plugin("extendedop", 1 /* Enabled */, "multimaster_cleanruv_status_extop_init", multimaster_cleanruv_status_extop_init, "Multimaster replication cleanruv status extended operation plugin", NULL, identity); + if (0 == rc) + { + multimaster_initialised = 1; +diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c +index 2b1d958..b3df831 100644 +--- a/ldap/servers/plugins/replication/repl5_replica.c ++++ b/ldap/servers/plugins/replication/repl5_replica.c +@@ -88,7 +88,6 @@ struct replica { + PRBool state_update_inprogress; /* replica state is being updated */ + PRLock *agmt_lock; /* protects agreement creation, start and stop */ + char *locking_purl; /* supplier who has exclusive access */ +- char *repl_cleanruv_data[CLEANRIDSIZ + 1]; + }; + + +@@ -310,7 +309,6 @@ replica_destroy(void **arg) + { + Replica *r; + void *repl_name; +- int i; + + if (arg == NULL) + return; +@@ -397,10 +395,6 @@ replica_destroy(void **arg) + csnplFree(&r->min_csn_pl);; + } + +- for(i = 0;r->repl_cleanruv_data[i] != NULL; i++){ +- slapi_ch_free_string(&r->repl_cleanruv_data[i]); +- } +- + slapi_ch_free((void **)arg); + } + +@@ -1502,7 +1496,7 @@ int replica_check_for_data_reload (Replica *r, void *arg) + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_check_for_data_reload: " + "Warning: for replica %s there were some differences between the changelog max RUV and the " + "database RUV. If there are obsolete elements in the database RUV, you " +- "should remove them using CLEANRUV task. If they are not obsolete, " ++ "should remove them using the CLEANALLRUV task. If they are not obsolete, " + "you should check their status to see why there are no changes from those " + "servers in the changelog.\n", + slapi_sdn_get_dn(r->repl_root)); +@@ -1819,12 +1813,13 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e) + PRThread *thread = NULL; + struct berval *payload = NULL; + CSN *maxcsn = NULL; +- char *csnpart; +- char *iter; ++ ReplicaId rid; + char csnstr[CSN_STRSIZE]; +- char *ridstr; + char *token = NULL; +- ReplicaId rid; ++ char *forcing; ++ char *csnpart; ++ char *ridstr; ++ char *iter; + int i; + + for(i = 0; i < CLEANRIDSIZ && clean_vals[i]; i++){ +@@ -1833,7 +1828,6 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e) + /* + * Set the cleanruv data, and add the cleaned rid + */ +- r->repl_cleanruv_data[i] = slapi_ch_strdup(clean_vals[i]); + token = ldap_utf8strtok_r(clean_vals[i], ":", &iter); + if(token){ + rid = atoi(token); +@@ -1851,15 +1845,18 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e) + maxcsn = csn_new(); + csn_init_by_string(maxcsn, csnpart); + csn_as_string(maxcsn, PR_FALSE, csnstr); +- add_cleaned_rid(rid, r, csnstr); ++ forcing = ldap_utf8strtok_r(iter, ":", &iter); ++ if(forcing == NULL){ ++ forcing = "no"; ++ } + + slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: cleanAllRUV task found, " + "resuming the cleaning of rid(%d)...\n", rid); + /* + * Create payload + */ +- ridstr = slapi_ch_smprintf("%d:%s:%s", rid, slapi_sdn_get_dn(replica_get_root(r)), csnstr); +- payload = create_ruv_payload(ridstr); ++ ridstr = slapi_ch_smprintf("%d:%s:%s:%s", rid, slapi_sdn_get_dn(replica_get_root(r)), csnstr, forcing); ++ payload = create_cleanruv_payload(ridstr); + slapi_ch_free_string(&ridstr); + + if(payload == NULL){ +@@ -1882,8 +1879,10 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e) + data->rid = rid; + data->task = NULL; + data->maxcsn = maxcsn; +- data->sdn = slapi_sdn_dup(r->repl_root); + data->payload = payload; ++ data->sdn = slapi_sdn_dup(r->repl_root); ++ data->force = slapi_ch_strdup(forcing); ++ data->repl_root = NULL; + + thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread_ext, + (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, +@@ -1895,11 +1894,11 @@ replica_check_for_tasks(Replica *r, Slapi_Entry *e) + csn_free(&maxcsn); + slapi_sdn_free(&data->sdn); + ber_bvfree(data->payload); ++ slapi_ch_free_string(&data->force); + slapi_ch_free((void **)&data); + } + } + } +- r->repl_cleanruv_data[i] = NULL; + + done: + slapi_ch_array_free(clean_vals); +@@ -1909,13 +1908,12 @@ done: + { + PRThread *thread = NULL; + struct berval *payload; +- CSN *maxcsn = NULL; +- char *iter; ++ ReplicaId rid; ++ char *certify = NULL; + char *ridstr = NULL; +- char *repl_root; + char *token = NULL; +- char *certify = NULL; +- ReplicaId rid; ++ char *repl_root; ++ char *iter; + int i; + + for(i = 0; clean_vals[i]; i++){ +@@ -1926,21 +1924,27 @@ done: + rid = atoi(token); + if(rid <= 0 || rid >= READ_ONLY_REPLICA_ID){ + slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: invalid replica id(%d) " +- "aborting task.\n", rid); ++ "aborting abort task.\n", rid); + goto done2; + } + } else { + slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: unable to parse cleanallruv " +- "data (%s), aborting task.\n",clean_vals[i]); ++ "data (%s), aborting abort task.\n",clean_vals[i]); + goto done2; + } + + repl_root = ldap_utf8strtok_r(iter, ":", &iter); + certify = ldap_utf8strtok_r(iter, ":", &iter); ++ ++ if(!is_cleaned_rid(rid)){ ++ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: replica id(%d) is not " ++ "being cleaned, nothing to abort. Aborting abort task.\n", rid); ++ delete_aborted_rid(r, rid, repl_root, 0); ++ goto done2; ++ } ++ ++ add_aborted_rid(rid, r, repl_root); + stop_ruv_cleaning(); +- maxcsn = replica_get_cleanruv_maxcsn(r, rid); +- delete_cleaned_rid(r, rid, maxcsn); +- csn_free(&maxcsn); + + slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: abort task found, " + "resuming abort of rid(%d).\n", rid); +@@ -1951,8 +1955,8 @@ done: + if (data == NULL) { + slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to allocate cleanruv_data.\n"); + } else { +- ridstr = slapi_ch_smprintf("%d:%s", rid, repl_root); +- payload = create_ruv_payload(ridstr); ++ ridstr = slapi_ch_smprintf("%d:%s:%s", rid, repl_root, certify); ++ payload = create_cleanruv_payload(ridstr); + slapi_ch_free_string(&ridstr); + + if(payload == NULL){ +@@ -2583,7 +2587,7 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods + must use the CLEANRUV task instead */ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "replica_ruv_smods_for_op: attempted to directly modify the tombstone RUV " +- "entry [%s] - use the CLEANRUV task instead\n", ++ "entry [%s] - use the CLEANALLRUV task instead\n", + slapi_entry_get_dn_const(target_entry)); + return (-1); + } +@@ -3430,7 +3434,7 @@ replica_replace_ruv_tombstone(Replica *r) + + if (rc != LDAP_SUCCESS) + { +- if ((rc != LDAP_NO_SUCH_OBJECT) || !replica_is_state_flag_set(r, REPLICA_IN_USE)) ++ if ((rc != LDAP_NO_SUCH_OBJECT && rc != LDAP_TYPE_OR_VALUE_EXISTS) || !replica_is_state_flag_set(r, REPLICA_IN_USE)) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_replace_ruv_tombstone: " + "failed to update replication update vector for replica %s: LDAP " +@@ -3794,69 +3798,3 @@ replica_get_attr ( Slapi_PBlock *pb, const char* type, void *value ) + + return rc; + } +- +-void +-replica_add_cleanruv_data(Replica *r, char *val) +-{ +- int i; +- +- PR_Lock(r->repl_lock); +- +- for (i = 0; i < CLEANRIDSIZ && r->repl_cleanruv_data[i] != NULL; i++); /* goto the end of the list */ +- if( i < CLEANRIDSIZ){ +- r->repl_cleanruv_data[i] = slapi_ch_strdup(val); /* append to list */ +- r->repl_cleanruv_data[i + 1] = 0; +- } +- +- PR_Unlock(r->repl_lock); +-} +- +-void +-replica_remove_cleanruv_data(Replica *r, char *val) +-{ +- int i; +- +- PR_Lock(r->repl_lock); +- +- for(i = 0; i < CLEANRIDSIZ && r->repl_cleanruv_data[i] && strcmp(r->repl_cleanruv_data[i], val) != 0; i++); +- if( i < CLEANRIDSIZ ){ +- slapi_ch_free_string(&r->repl_cleanruv_data[i]); +- for(; i < CLEANRIDSIZ; i++){ +- /* rewrite entire array */ +- r->repl_cleanruv_data[i] = r->repl_cleanruv_data[i + 1]; +- } +- } +- +- PR_Unlock(r->repl_lock); +-} +- +-CSN * +-replica_get_cleanruv_maxcsn(Replica *r, ReplicaId rid) +-{ +- CSN *newcsn; +- char *csnstr; +- char *token; +- char *iter; +- int repl_rid = 0; +- int i; +- +- PR_Lock(r->repl_lock); +- +- for(i = 0; i < CLEANRIDSIZ && r->repl_cleanruv_data[i]; i++){ +- token = ldap_utf8strtok_r(r->repl_cleanruv_data[i], ":", &iter); +- if(token){ +- repl_rid = atoi(token); +- } +- csnstr = ldap_utf8strtok_r(iter, ":", &iter); +- if(repl_rid == rid){ +- newcsn = csn_new(); +- csn_init_by_string(newcsn, csnstr); +- PR_Unlock(r->repl_lock); +- return newcsn; +- } +- } +- +- PR_Unlock(r->repl_lock); +- +- return NULL; +-} +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index c5ca965..0fd785b 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -64,6 +64,7 @@ + + int slapi_log_urp = SLAPI_LOG_REPL; + static ReplicaId cleaned_rids[CLEANRIDSIZ + 1] = {0}; ++static ReplicaId pre_cleaned_rids[CLEANRIDSIZ + 1] = {0}; + static ReplicaId aborted_rids[CLEANRIDSIZ + 1] = {0}; + static Slapi_RWLock *rid_lock = NULL; + static Slapi_RWLock *abort_rid_lock = NULL; +@@ -84,20 +85,27 @@ static int replica_execute_task (Object *r, const char *task_name, char *returnt + static int replica_execute_cl2ldif_task (Object *r, char *returntext); + static int replica_execute_ldif2cl_task (Object *r, char *returntext); + static int replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext); +-static int replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, char *returntext); ++static int replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, const char *force_cleaning, char *returntext); + static void replica_cleanallruv_thread(void *arg); +-static void replica_send_cleanruv_task(Repl_Agmt *agmt, ReplicaId rid, Slapi_Task *task); ++static void replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data); + static int check_agmts_are_alive(Replica *replica, ReplicaId rid, Slapi_Task *task); +-static int check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_Task *task); +-static int replica_cleanallruv_send_extop(Repl_Agmt *ra, ReplicaId rid, Slapi_Task *task, struct berval *payload, int check_result); ++static int check_agmts_are_caught_up(cleanruv_data *data, char *maxcsn); ++static int replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *data, int check_result); + static int replica_cleanallruv_send_abort_extop(Repl_Agmt *ra, Slapi_Task *task, struct berval *payload); +-static int replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *rid_text, char *maxcsn, Slapi_Task *task); ++static int replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *basedn, char *rid_text, char *maxcsn, Slapi_Task *task); + static int replica_cleanallruv_replica_alive(Repl_Agmt *agmt); +-static int replica_cleanallruv_check_ruv(Repl_Agmt *ra, char *rid_text, Slapi_Task *task); ++static int replica_cleanallruv_check_ruv(char *repl_root, Repl_Agmt *ra, char *rid_text, Slapi_Task *task); + static int get_cleanruv_task_count(); + static int get_abort_cleanruv_task_count(); + static int replica_cleanup_task (Object *r, const char *task_name, char *returntext, int apply_mods); + static int replica_task_done(Replica *replica); ++static void delete_cleaned_rid_config(cleanruv_data *data); ++static int replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task); ++static void check_replicas_are_done_cleaning(cleanruv_data *data); ++static void check_replicas_are_done_aborting(cleanruv_data *data ); ++static CSN* replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn); ++static int replica_cleanallruv_get_replica_maxcsn(Repl_Agmt *agmt, char *rid_text, char *basedn, CSN **csn); ++static void preset_cleaned_rid(ReplicaId rid); + static multimaster_mtnode_extension * _replica_config_get_mtnode_ext (const Slapi_Entry *e); + + /* +@@ -385,6 +393,12 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* + if (apply_mods) + replica_set_legacy_consumer (r, PR_FALSE); + } ++ else if (strcasecmp (config_attr, type_replicaCleanRUV) == 0 || ++ strcasecmp (config_attr, type_replicaAbortCleanRUV) == 0) ++ { ++ /* only allow the deletion of the cleanAllRUV config attributes */ ++ continue; ++ } + else + { + *returncode = LDAP_UNWILLING_TO_PERFORM; +@@ -891,7 +905,7 @@ static int replica_execute_task (Object *r, const char *task_name, char *returnt + if (apply_mods) + { + Slapi_Task *empty_task = NULL; +- return replica_execute_cleanall_ruv_task(r, (ReplicaId)temprid, empty_task, returntext); ++ return replica_execute_cleanall_ruv_task(r, (ReplicaId)temprid, empty_task, returntext, "no"); + } + else + return LDAP_SUCCESS; +@@ -1225,35 +1239,52 @@ replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, + Slapi_Task *task = NULL; + const Slapi_DN *task_dn; + Slapi_DN *dn = NULL; ++ ReplicaId rid; + Object *r; ++ const char *force_cleaning; + const char *base_dn; + const char *rid_str; +- ReplicaId rid; + int rc = SLAPI_DSE_CALLBACK_OK; + + /* allocate new task now */ + task = slapi_new_task(slapi_entry_get_ndn(e)); ++ task_dn = slapi_entry_get_sdn(e); + if(task == NULL){ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Failed to create new task\n"); + rc = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } +- + /* + * Get our task settings + */ + if ((base_dn = fetch_attr(e, "replica-base-dn", 0)) == NULL){ ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Missing replica-base-dn attribute"); ++ cleanruv_log(task, CLEANALLRUV_ID, "%s", returntext); + *returncode = LDAP_OBJECT_CLASS_VIOLATION; + rc = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } + if ((rid_str = fetch_attr(e, "replica-id", 0)) == NULL){ ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Missing replica-id attribute"); ++ cleanruv_log(task, CLEANALLRUV_ID, "%s", returntext); + *returncode = LDAP_OBJECT_CLASS_VIOLATION; + rc = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } + +- task_dn = slapi_entry_get_sdn(e); ++ if ((force_cleaning = fetch_attr(e, "replica-force-cleaning", 0)) != NULL){ ++ if(strcasecmp(force_cleaning,"yes") != 0 && strcasecmp(force_cleaning,"no") != 0){ ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid value for replica-force-cleaning " ++ "(%s). Value must be \"yes\" or \"no\" for task - (%s)", ++ force_cleaning, slapi_sdn_get_dn(task_dn)); ++ cleanruv_log(task, CLEANALLRUV_ID, "%s", returntext); ++ *returncode = LDAP_OPERATIONS_ERROR; ++ rc = SLAPI_DSE_CALLBACK_ERROR; ++ goto out; ++ } ++ } else { ++ force_cleaning = "no"; ++ } + /* + * Check the rid + */ +@@ -1266,6 +1297,14 @@ replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, + rc = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } ++ if(is_cleaned_rid(rid)){ ++ /* we are already cleaning this rid */ ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Replica id (%d) is already being cleaned", rid); ++ cleanruv_log(task, CLEANALLRUV_ID, "%s", returntext); ++ *returncode = LDAP_UNWILLING_TO_PERFORM; ++ rc = SLAPI_DSE_CALLBACK_ERROR; ++ goto out; ++ } + /* + * Get the replica object + */ +@@ -1279,7 +1318,7 @@ replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, + } + + /* clean the RUV's */ +- rc = replica_execute_cleanall_ruv_task (r, rid, task, returntext); ++ rc = replica_execute_cleanall_ruv_task (r, rid, task, force_cleaning, returntext); + + out: + if(rc){ +@@ -1302,31 +1341,36 @@ out: + * + */ + static int +-replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, char *returntext) ++replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, const char* force_cleaning, char *returntext) + { +- PRThread *thread = NULL; ++ struct berval *payload = NULL; + Slapi_Task *pre_task = NULL; /* this is supposed to be null for logging */ +- Replica *replica; +- Object *ruv_obj; + cleanruv_data *data = NULL; ++ PRThread *thread = NULL; + CSN *maxcsn = NULL; +- const RUV *ruv; +- struct berval *payload = NULL; +- char *ridstr = NULL; ++ Replica *replica; + char csnstr[CSN_STRSIZE]; ++ char *ridstr = NULL; ++ char *basedn = NULL; + int rc = 0; + ++ cleanruv_log(pre_task, CLEANALLRUV_ID,"Initiating CleanAllRUV Task..."); ++ + if(get_cleanruv_task_count() >= CLEANRIDSIZ){ + /* we are already running the maximum number of tasks */ + cleanruv_log(pre_task, CLEANALLRUV_ID, + "Exceeded maximum number of active CLEANALLRUV tasks(%d)",CLEANRIDSIZ); + return LDAP_UNWILLING_TO_PERFORM; + } +- + /* + * Grab the replica + */ +- replica = (Replica*)object_get_data (r); ++ if(r){ ++ replica = (Replica*)object_get_data (r); ++ } else { ++ cleanruv_log(pre_task, CLEANALLRUV_ID, "Replica object is NULL, aborting task"); ++ return -1; ++ } + /* + * Check if this is a consumer + */ +@@ -1342,32 +1386,25 @@ replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, c + /* + * Grab the max csn of the deleted replica + */ +- ruv_obj = replica_get_ruv(replica); +- ruv = object_get_data (ruv_obj); +- if(ruv_get_rid_max_csn(ruv, &maxcsn, rid) == RUV_BAD_DATA){ +- /* no maxcsn, can not proceed */ +- cleanruv_log(pre_task, CLEANALLRUV_ID, "Could not find maxcsn for rid (%d)", rid); +- rc = -1; +- object_release(ruv_obj); +- goto fail; +- } else { +- object_release(ruv_obj); +- if(maxcsn == NULL || csn_get_replicaid(maxcsn) == 0){ +- /* +- * This is for consistency with extop csn creation, where +- * we want the csn string to be "0000000000000000000" not "" +- */ +- csn_free(&maxcsn); +- maxcsn = csn_new(); +- csn_init_by_string(maxcsn, ""); +- } +- csn_as_string(maxcsn, PR_FALSE, csnstr); ++ cleanruv_log(pre_task, CLEANALLRUV_ID, "Retrieving maxcsn..."); ++ basedn = (char *)slapi_sdn_get_dn(replica_get_root(replica)); ++ maxcsn = replica_cleanallruv_find_maxcsn(replica, rid, basedn); ++ if(maxcsn == NULL || csn_get_replicaid(maxcsn) == 0){ ++ /* ++ * This is for consistency with extop csn creation, where ++ * we want the csn string to be "0000000000000000000" not "" ++ */ ++ csn_free(&maxcsn); ++ maxcsn = csn_new(); ++ csn_init_by_string(maxcsn, ""); + } ++ csn_as_string(maxcsn, PR_FALSE, csnstr); ++ cleanruv_log(pre_task, CLEANALLRUV_ID, "Found maxcsn (%s)",csnstr); + /* + * Create payload + */ +- ridstr = slapi_ch_smprintf("%d:%s:%s", rid, slapi_sdn_get_dn(replica_get_root(replica)), csnstr); +- payload = create_ruv_payload(ridstr); ++ ridstr = slapi_ch_smprintf("%d:%s:%s:%s", rid, basedn, csnstr, force_cleaning); ++ payload = create_cleanruv_payload(ridstr); + slapi_ch_free_string(&ridstr); + + if(payload == NULL){ +@@ -1389,15 +1426,19 @@ replica_execute_cleanall_ruv_task (Object *r, ReplicaId rid, Slapi_Task *task, c + data->replica = replica; + data->rid = rid; + data->task = task; +- data->maxcsn = maxcsn; + data->payload = payload; + data->sdn = NULL; ++ data->maxcsn = maxcsn; ++ data->repl_root = slapi_ch_strdup(basedn); ++ data->force = slapi_ch_strdup(force_cleaning); + + thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread, + (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE); + if (thread == NULL) { + rc = -1; ++ slapi_ch_free_string(&data->force); ++ slapi_ch_free_string(&data->repl_root); + goto fail; + } else { + goto done; +@@ -1441,11 +1482,11 @@ replica_cleanallruv_thread_ext(void *arg) + static void + replica_cleanallruv_thread(void *arg) + { +- Object *ruv_obj = NULL; ++ cleanruv_data *data = arg; + Object *agmt_obj = NULL; ++ Object *ruv_obj = NULL; + Repl_Agmt *agmt = NULL; + RUV *ruv = NULL; +- cleanruv_data *data = arg; + char csnstr[CSN_STRSIZE]; + char *returntext = NULL; + char *rid_text = NULL; +@@ -1466,7 +1507,7 @@ replica_cleanallruv_thread(void *arg) + * the backends might not be online yet. + */ + PR_Lock( notify_lock ); +- PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(5) ); ++ PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(10) ); + PR_Unlock( notify_lock ); + data->repl_obj = replica_get_replica_from_dn(data->sdn); + if(data->repl_obj == NULL){ +@@ -1488,17 +1529,25 @@ replica_cleanallruv_thread(void *arg) + aborted = 1; + goto done; + } ++ if(data->repl_root == NULL){ ++ /* we must have resumed from start up, fill in the repl root */ ++ data->repl_root = slapi_ch_strdup(slapi_sdn_get_dn(replica_get_root(data->replica))); ++ } + if(data->task){ + slapi_task_begin(data->task, 1); + } +- rid_text = slapi_ch_smprintf("{replica %d ldap", data->rid); ++ /* ++ * Presetting the rid prevents duplicate thread creation, but allows the db and changelog to still ++ * process updates from the rid. set_cleaned_rid() blocks updates, so we don't want to do that... yet. ++ */ ++ preset_cleaned_rid(data->rid); ++ rid_text = slapi_ch_smprintf("%d", data->rid); + csn_as_string(data->maxcsn, PR_FALSE, csnstr); +- + /* + * Add the cleanallruv task to the repl config - so we can handle restarts + */ ++ add_cleaned_rid(data->rid, data->replica, csnstr, data->force); /* marks config that we started cleaning a rid */ + cleanruv_log(data->task, CLEANALLRUV_ID, "Cleaning rid (%d)...", data->rid); +- add_cleaned_rid(data->rid, data->replica, csnstr); /* marks config that we started cleaning a rid */ + /* + * First, wait for the maxcsn to be covered + */ +@@ -1506,7 +1555,7 @@ replica_cleanallruv_thread(void *arg) + ruv_obj = replica_get_ruv(data->replica); + ruv = object_get_data (ruv_obj); + while(data->maxcsn && !is_task_aborted(data->rid) && !is_cleaned_rid(data->rid) && !slapi_is_shutting_down()){ +- if(csn_get_replicaid(data->maxcsn) == 0 || ruv_covers_csn_cleanallruv(ruv,data->maxcsn)){ ++ if(csn_get_replicaid(data->maxcsn) == 0 || ruv_covers_csn_cleanallruv(ruv,data->maxcsn) || strcasecmp(data->force,"yes") == 0){ + /* We are caught up, now we can clean the ruv's */ + break; + } +@@ -1517,6 +1566,8 @@ replica_cleanallruv_thread(void *arg) + object_release(ruv_obj); + /* + * Next, make sure all the replicas are up and running before sending off the clean ruv tasks ++ * ++ * Even if we are forcing the cleaning, the replicas still need to be up + */ + cleanruv_log(data->task, CLEANALLRUV_ID,"Waiting for all the replicas to be online..."); + if(check_agmts_are_alive(data->replica, data->rid, data->task)){ +@@ -1528,7 +1579,7 @@ replica_cleanallruv_thread(void *arg) + * Make sure all the replicas have seen the max csn + */ + cleanruv_log(data->task, CLEANALLRUV_ID,"Waiting for all the replicas to receive all the deleted replica updates..."); +- if(check_agmts_are_caught_up(data->replica, data->rid, csnstr, data->task)){ ++ if(strcasecmp(data->force,"no") == 0 && check_agmts_are_caught_up(data, csnstr)){ + /* error, aborted or shutdown */ + aborted = 1; + goto done; +@@ -1555,10 +1606,11 @@ replica_cleanallruv_thread(void *arg) + agmt_not_notified = 0; + continue; + } +- if(replica_cleanallruv_send_extop(agmt, data->rid, data->task, data->payload, 1) == 0){ ++ if(replica_cleanallruv_send_extop(agmt, data, 1) == 0){ + agmt_not_notified = 0; + } else { + agmt_not_notified = 1; ++ cleanruv_log(data->task, CLEANALLRUV_ID, "Failed to send task to replica (%s)",agmt_get_long_name(agmt)); + break; + } + agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj); +@@ -1609,10 +1661,11 @@ replica_cleanallruv_thread(void *arg) + found_dirty_rid = 0; + continue; + } +- if(replica_cleanallruv_check_ruv(agmt, rid_text, data->task) == 0){ ++ if(replica_cleanallruv_check_ruv(data->repl_root, agmt, rid_text, data->task) == 0){ + found_dirty_rid = 0; + } else { + found_dirty_rid = 1; ++ cleanruv_log(data->task, CLEANALLRUV_ID,"Replica is not cleaned yet (%s)",agmt_get_long_name(agmt)); + break; + } + agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj); +@@ -1623,7 +1676,7 @@ replica_cleanallruv_thread(void *arg) + goto done; + } + if(found_dirty_rid == 0){ +- break; ++ break; + } + /* + * need to sleep between passes +@@ -1647,9 +1700,11 @@ done: + */ + if(!aborted){ + trigger_cl_trimming(data->rid); +- delete_cleaned_rid(data->replica, data->rid, data->maxcsn); ++ delete_cleaned_rid_config(data); ++ /* make sure all the replicas have been "pre_cleaned" before finishing */ ++ check_replicas_are_done_cleaning(data); + cleanruv_log(data->task, CLEANALLRUV_ID, "Successfully cleaned rid(%d).", data->rid); +- slapi_task_finish(data->task, rc); ++ remove_cleaned_rid(data->rid); + } else { + /* + * Shutdown or abort +@@ -1658,29 +1713,189 @@ done: + cleanruv_log(data->task, CLEANALLRUV_ID,"Server shutting down. Process will resume at server startup"); + } else { + cleanruv_log(data->task, CLEANALLRUV_ID,"Task aborted for rid(%d).",data->rid); +- } +- if(data->task){ +- slapi_task_finish(data->task, rc); ++ delete_cleaned_rid_config(data); ++ remove_cleaned_rid(data->rid); + } + } +- ++ if(data->task){ ++ slapi_task_finish(data->task, rc); ++ } + if(data->payload){ + ber_bvfree(data->payload); + } + if(data->repl_obj && free_obj){ + object_release(data->repl_obj); + } ++ csn_free(&data->maxcsn); + slapi_sdn_free(&data->sdn); ++ slapi_ch_free_string(&data->repl_root); ++ slapi_ch_free_string(&data->force); + slapi_ch_free_string(&rid_text); +- csn_free(&data->maxcsn); + slapi_ch_free((void **)&data); + } + + /* ++ * Loop over the agmts, and check if they are in the last phase of cleaning, meaning they have ++ * released cleanallruv data from the config ++ */ ++static void ++check_replicas_are_done_cleaning(cleanruv_data *data ) ++{ ++ Object *agmt_obj; ++ Repl_Agmt *agmt; ++ char csnstr[CSN_STRSIZE]; ++ char *filter = NULL; ++ int not_all_cleaned = 1; ++ int interval = 10; ++ ++ cleanruv_log(data->task, CLEANALLRUV_ID, "Waiting for all the replicas to finish cleaning..."); ++ ++ csn_as_string(data->maxcsn, PR_FALSE, csnstr); ++ filter = PR_smprintf("(%s=%d:%s:%s)", type_replicaCleanRUV,(int)data->rid, csnstr, data->force); ++ while(not_all_cleaned && !is_task_aborted(data->rid) && !slapi_is_shutting_down()){ ++ agmt_obj = agmtlist_get_first_agreement_for_replica (data->replica); ++ if(agmt_obj == NULL){ ++ not_all_cleaned = 0; ++ break; ++ } ++ while (agmt_obj && !slapi_is_shutting_down()){ ++ agmt = (Repl_Agmt*)object_get_data (agmt_obj); ++ if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){ ++ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj); ++ not_all_cleaned = 0; ++ continue; ++ } ++ if(replica_cleanallruv_is_finished(agmt, filter, data->task) == 0){ ++ not_all_cleaned = 0; ++ } else { ++ not_all_cleaned = 1; ++ break; ++ } ++ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj); ++ } ++ if(not_all_cleaned == 0 || is_task_aborted(data->rid) ){ ++ break; ++ } ++ cleanruv_log(data->task, CLEANALLRUV_ID, "Not all replicas finished cleaning, retrying in %d seconds",interval); ++ PR_Lock( notify_lock ); ++ PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) ); ++ PR_Unlock( notify_lock ); ++ if(interval < 14400){ /* 4 hour max */ ++ interval = interval * 2; ++ } else { ++ interval = 14400; ++ } ++ } ++ slapi_ch_free_string(&filter); ++} ++ ++/* ++ * Search this replica for the nsds5ReplicaCleanruv attribute, we don't return ++ * an entry, we know it has finished cleaning. ++ */ ++static int ++replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task) ++{ ++ Repl_Connection *conn = NULL; ++ ConnResult crc = 0; ++ struct berval *payload = NULL; ++ int msgid = 0; ++ int rc = -1; ++ ++ if((conn = conn_new(agmt)) == NULL){ ++ return -1; ++ } ++ if(conn_connect(conn) == CONN_OPERATION_SUCCESS){ ++ payload = create_cleanruv_payload(filter); ++ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_CHECK_STATUS_OID, payload, NULL, &msgid); ++ if(crc == CONN_OPERATION_SUCCESS){ ++ struct berval *retsdata = NULL; ++ char *retoid = NULL; ++ ++ crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1); ++ if (CONN_OPERATION_SUCCESS == crc ){ ++ char *response = NULL; ++ ++ decode_cleanruv_payload(retsdata, &response); ++ if(response && strcmp(response,CLEANRUV_FINISHED) == 0){ ++ /* finished cleaning */ ++ rc = 0; ++ } ++ if (NULL != retsdata) ++ ber_bvfree(retsdata); ++ slapi_ch_free_string(&response); ++ slapi_ch_free_string(&retoid); ++ } ++ } ++ } else { ++ rc = -1; ++ } ++ conn_delete_internal_ext(conn); ++ if(payload) ++ ber_bvfree(payload); ++ ++ return rc; ++} ++ ++/* ++ * Loop over the agmts, and check if they are in the last phase of aborting, meaning they have ++ * released the abort cleanallruv data from the config ++ */ ++static void ++check_replicas_are_done_aborting(cleanruv_data *data ) ++{ ++ Object *agmt_obj; ++ Repl_Agmt *agmt; ++ char *filter = NULL; ++ int not_all_aborted = 1; ++ int interval = 10; ++ ++ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID,"Waiting for all the replicas to finish aborting..."); ++ ++ filter = PR_smprintf("(%s=%d:%s)", type_replicaAbortCleanRUV, data->rid, data->repl_root); ++ ++ while(not_all_aborted && !slapi_is_shutting_down()){ ++ agmt_obj = agmtlist_get_first_agreement_for_replica (data->replica); ++ if(agmt_obj == NULL){ ++ not_all_aborted = 0; ++ break; ++ } ++ while (agmt_obj && !slapi_is_shutting_down()){ ++ agmt = (Repl_Agmt*)object_get_data (agmt_obj); ++ if(get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){ ++ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj); ++ not_all_aborted = 0; ++ continue; ++ } ++ if(replica_cleanallruv_is_finished(agmt, filter, data->task) == 0){ ++ not_all_aborted = 0; ++ } else { ++ not_all_aborted = 1; ++ break; ++ } ++ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj); ++ } ++ if(not_all_aborted == 0){ ++ break; ++ } ++ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Not all replicas finished aborting, retrying in %d seconds",interval); ++ PR_Lock( notify_lock ); ++ PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) ); ++ PR_Unlock( notify_lock ); ++ if(interval < 14400){ /* 4 hour max */ ++ interval = interval * 2; ++ } else { ++ interval = 14400; ++ } ++ } ++ slapi_ch_free_string(&filter); ++} ++ ++/* + * Waits for all the repl agmts to be have have the maxcsn. Returns error only on abort or shutdown + */ + static int +-check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_Task *task) ++check_agmts_are_caught_up(cleanruv_data *data, char *maxcsn) + { + Object *agmt_obj; + Repl_Agmt *agmt; +@@ -1688,10 +1903,10 @@ check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_T + int not_all_caughtup = 1; + int interval = 10; + +- rid_text = slapi_ch_smprintf("{replica %d ldap", rid); ++ rid_text = slapi_ch_smprintf("%d", data->rid); + +- while(not_all_caughtup && !is_task_aborted(rid) && !slapi_is_shutting_down()){ +- agmt_obj = agmtlist_get_first_agreement_for_replica (replica); ++ while(not_all_caughtup && !is_task_aborted(data->rid) && !slapi_is_shutting_down()){ ++ agmt_obj = agmtlist_get_first_agreement_for_replica (data->replica); + if(agmt_obj == NULL){ + not_all_caughtup = 0; + break; +@@ -1699,23 +1914,24 @@ check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_T + while (agmt_obj){ + agmt = (Repl_Agmt*)object_get_data (agmt_obj); + if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){ +- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); ++ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj); + not_all_caughtup = 0; + continue; + } +- if(replica_cleanallruv_check_maxcsn(agmt, rid_text, maxcsn, task) == 0){ ++ if(replica_cleanallruv_check_maxcsn(agmt, data->repl_root, rid_text, maxcsn, data->task) == 0){ + not_all_caughtup = 0; + } else { + not_all_caughtup = 1; ++ cleanruv_log(data->task, CLEANALLRUV_ID, "Replica not caught up (%s)",agmt_get_long_name(agmt)); + break; + } +- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); +- } /* agmt while */ ++ agmt_obj = agmtlist_get_next_agreement_for_replica (data->replica, agmt_obj); ++ } + +- if(not_all_caughtup == 0 || is_task_aborted(rid) ){ ++ if(not_all_caughtup == 0 || is_task_aborted(data->rid) ){ + break; + } +- cleanruv_log(task, CLEANALLRUV_ID, "Not all replicas caught up, retrying in %d seconds",interval); ++ cleanruv_log(data->task, CLEANALLRUV_ID, "Not all replicas caught up, retrying in %d seconds",interval); + PR_Lock( notify_lock ); + PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) ); + PR_Unlock( notify_lock ); +@@ -1728,7 +1944,7 @@ check_agmts_are_caught_up(Replica *replica, ReplicaId rid, char *maxcsn, Slapi_T + } + slapi_ch_free_string(&rid_text); + +- if(is_task_aborted(rid)){ ++ if(is_task_aborted(data->rid)){ + return -1; + } + +@@ -1763,6 +1979,7 @@ check_agmts_are_alive(Replica *replica, ReplicaId rid, Slapi_Task *task) + not_all_alive = 0; + } else { + not_all_alive = 1; ++ cleanruv_log(task, CLEANALLRUV_ID, "Replica not online (%s)",agmt_get_long_name(agmt)); + break; + } + agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); +@@ -1793,7 +2010,7 @@ check_agmts_are_alive(Replica *replica, ReplicaId rid, Slapi_Task *task) + * Create the CLEANALLRUV extended op payload + */ + struct berval * +-create_ruv_payload(char *value) ++create_cleanruv_payload(char *value) + { + struct berval *req_data = NULL; + BerElement *tmp_bere = NULL; +@@ -1801,10 +2018,7 @@ create_ruv_payload(char *value) + if ((tmp_bere = der_alloc()) == NULL){ + goto error; + } +- if (ber_printf(tmp_bere, "{s", value) == -1){ +- goto error; +- } +- if (ber_printf(tmp_bere, "}") == -1){ ++ if (ber_printf(tmp_bere, "{s}", value) == -1){ + goto error; + } + if (ber_flatten(tmp_bere, &req_data) == -1){ +@@ -1832,7 +2046,7 @@ done: + * the CLEANALLRUV task. + */ + static void +-replica_send_cleanruv_task(Repl_Agmt *agmt, ReplicaId rid, Slapi_Task *task) ++replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data) + { + Repl_Connection *conn; + ConnResult crc = 0; +@@ -1859,7 +2073,7 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, ReplicaId rid, Slapi_Task *task) + conn_delete_internal_ext(conn); + return; + } +- val.bv_len = PR_snprintf(data, sizeof(data), "CLEANRUV%d", rid); ++ val.bv_len = PR_snprintf(data, sizeof(data), "CLEANRUV%d", clean_data->rid); + sdn = agmt_get_replarea(agmt); + mod.mod_op = LDAP_MOD_ADD|LDAP_MOD_BVALUES; + mod.mod_type = "nsds5task"; +@@ -1876,7 +2090,7 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, ReplicaId rid, Slapi_Task *task) + rc = ldap_modify_ext_s( ld, repl_dn, mods, NULL, NULL); + + if(rc != LDAP_SUCCESS){ +- cleanruv_log(task, CLEANALLRUV_ID, "Failed to add CLEANRUV task replica " ++ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task replica " + "(%s). You will need to manually run the CLEANRUV task on this replica (%s) error (%d)", + agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc); + } +@@ -1906,6 +2120,23 @@ is_cleaned_rid(ReplicaId rid) + } + + int ++is_pre_cleaned_rid(ReplicaId rid) ++{ ++ int i; ++ ++ slapi_rwlock_rdlock(rid_lock); ++ for(i = 0; i < CLEANRIDSIZ && pre_cleaned_rids[i] != 0; i++){ ++ if(rid == pre_cleaned_rids[i]){ ++ slapi_rwlock_unlock(rid_lock); ++ return 1; ++ } ++ } ++ slapi_rwlock_unlock(rid_lock); ++ ++ return 0; ++} ++ ++int + is_task_aborted(ReplicaId rid) + { + int i; +@@ -1924,6 +2155,22 @@ is_task_aborted(ReplicaId rid) + return 0; + } + ++static void ++preset_cleaned_rid(ReplicaId rid) ++{ ++ int i; ++ ++ slapi_rwlock_wrlock(rid_lock); ++ for(i = 0; i < CLEANRIDSIZ; i++){ ++ if(pre_cleaned_rids[i] == 0){ ++ pre_cleaned_rids[i] = rid; ++ pre_cleaned_rids[i + 1] = 0; ++ break; ++ } ++ } ++ slapi_rwlock_unlock(rid_lock); ++} ++ + /* + * Just add the rid to the in memory, as we don't want it to survive after a restart, + * This prevent the changelog from sending updates from this rid, and the local ruv +@@ -1948,7 +2195,7 @@ set_cleaned_rid(ReplicaId rid) + * Add the rid and maxcsn to the repl config (so we can resume after a server restart) + */ + void +-add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn) ++add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn, char *forcing) + { + Slapi_PBlock *pb; + struct berval *vals[2]; +@@ -1965,7 +2212,7 @@ add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn) + /* + * Write the rid & maxcsn to the config entry + */ +- val.bv_len = PR_snprintf(data, sizeof(data),"%d:%s", rid, maxcsn); ++ val.bv_len = PR_snprintf(data, sizeof(data),"%d:%s:%s", rid, maxcsn, forcing); + dn = replica_get_dn(r); + pb = slapi_pblock_new(); + mod.mod_op = LDAP_MOD_ADD|LDAP_MOD_BVALUES; +@@ -1977,13 +2224,11 @@ add_cleaned_rid(ReplicaId rid, Replica *r, char *maxcsn) + mods[0] = &mod; + mods[1] = NULL; + +- replica_add_cleanruv_data(r, val.bv_val); +- + slapi_modify_internal_set_pb (pb, dn, mods, NULL, NULL, + repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); + slapi_modify_internal_pb (pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); +- if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS){ ++ if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS && rc != LDAP_NO_SUCH_OBJECT){ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to update replica " + "config (%d), rid (%d)\n", rc, rid); + } +@@ -2036,7 +2281,7 @@ add_aborted_rid(ReplicaId rid, Replica *r, char *repl_root) + repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); + slapi_modify_internal_pb (pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); +- if (rc != LDAP_SUCCESS){ ++ if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS && rc != LDAP_NO_SUCH_OBJECT){ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to update " + "replica config (%d), rid (%d)\n", rc, rid); + } +@@ -2047,7 +2292,7 @@ add_aborted_rid(ReplicaId rid, Replica *r, char *repl_root) + } + + void +-delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root){ ++delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){ + Slapi_PBlock *pb; + LDAPMod *mods[2]; + LDAPMod mod; +@@ -2061,117 +2306,126 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root){ + if(r == NULL) + return; + +- /* +- * Remove this rid, and optimize the array +- */ +- slapi_rwlock_wrlock(abort_rid_lock); +- for(i = 0; i < CLEANRIDSIZ && aborted_rids[i] != rid; i++); /* found rid, stop */ +- for(; i < CLEANRIDSIZ; i++){ +- /* rewrite entire array */ +- aborted_rids[i] = aborted_rids[i + 1]; ++ if(skip){ ++ /* skip the deleting of the config, and just remove the in memory rid */ ++ slapi_rwlock_wrlock(abort_rid_lock); ++ for(i = 0; i < CLEANRIDSIZ && aborted_rids[i] != rid; i++); /* found rid, stop */ ++ for(; i < CLEANRIDSIZ; i++){ ++ /* rewrite entire array */ ++ aborted_rids[i] = aborted_rids[i + 1]; ++ } ++ slapi_rwlock_unlock(abort_rid_lock); ++ } else { ++ /* only remove the config, leave the in-memory rid */ ++ dn = replica_get_dn(r); ++ pb = slapi_pblock_new(); ++ data = PR_smprintf("%d:%s", (int)rid, repl_root); ++ ++ mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; ++ mod.mod_type = (char *)type_replicaAbortCleanRUV; ++ mod.mod_bvalues = vals; ++ vals [0] = &val; ++ vals [1] = NULL; ++ val.bv_val = data; ++ val.bv_len = strlen (data); ++ mods[0] = &mod; ++ mods[1] = NULL; ++ ++ slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); ++ slapi_modify_internal_pb (pb); ++ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); ++ if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to remove replica " ++ "config (%d), rid (%d)\n", rc, rid); ++ } ++ slapi_pblock_destroy (pb); ++ slapi_ch_free_string(&dn); ++ slapi_ch_free_string(&data); + } +- slapi_rwlock_unlock(abort_rid_lock); ++} ++ ++/* ++ * Just remove the dse.ldif config, but we need to keep the cleaned rids in memory until we know we are done ++ */ ++static void ++delete_cleaned_rid_config(cleanruv_data *clean_data) ++{ ++ Slapi_PBlock *pb; ++ LDAPMod *mods[2]; ++ LDAPMod mod; ++ struct berval *vals[2]; ++ struct berval val; ++ char data[CSN_STRSIZE + 15]; ++ char csnstr[CSN_STRSIZE]; ++ char *dn; ++ int rc; ++ + /* + * Prepare the mods for the config entry + */ +- dn = replica_get_dn(r); ++ csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr); ++ val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", (int)clean_data->rid, csnstr, clean_data->force); ++ dn = replica_get_dn(clean_data->replica); + pb = slapi_pblock_new(); +- data = PR_smprintf("%d:%s", (int)rid, repl_root); +- + mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; + mod.mod_type = (char *)type_replicaAbortCleanRUV; ++ mod.mod_type = (char *)type_replicaCleanRUV; + mod.mod_bvalues = vals; + vals [0] = &val; + vals [1] = NULL; + val.bv_val = data; +- val.bv_len = strlen (data); ++ + mods[0] = &mod; + mods[1] = NULL; +- + slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); + slapi_modify_internal_pb (pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); + if (rc != LDAP_SUCCESS){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to remove replica " +- "config (%d), rid (%d)\n", rc, rid); +- } +- slapi_pblock_destroy (pb); +- slapi_ch_free_string(&dn); +- slapi_ch_free_string(&data); +-} ++ /* ++ * When aborting a task, we don't know if the "force" option was used. ++ * So we assume it is set to "no", but if this op fails, we'll try "yes" ++ */ ++ slapi_pblock_destroy (pb); ++ pb = slapi_pblock_new(); ++ memset(data,'0',sizeof(data)); ++ val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:yes", (int)clean_data->rid, csnstr); ++ slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); ++ slapi_modify_internal_pb (pb); ++ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); ++ if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config " ++ "(%d), rid (%d)\n", rc, clean_data->rid); ++ } ++ } ++ slapi_pblock_destroy (pb); ++ slapi_ch_free_string(&dn); ++ } + + /* + * Remove the rid from our list, and the config + */ + void +-delete_cleaned_rid(Replica *r, ReplicaId rid, CSN *maxcsn) ++remove_cleaned_rid(ReplicaId rid) + { +- Slapi_PBlock *pb; +- Object *agmt_obj; +- Repl_Agmt *agmt; +- LDAPMod *mods[2]; +- LDAPMod mod; +- struct berval *vals[2]; +- struct berval val; +- char *dn; +- char data[CSN_STRSIZE + 10]; +- char csnstr[CSN_STRSIZE]; +- int rc; + int i; +- +- if(r == NULL || maxcsn == NULL) +- return; +- + /* + * Remove this rid, and optimize the array + */ + slapi_rwlock_wrlock(rid_lock); ++ + for(i = 0; i < CLEANRIDSIZ && cleaned_rids[i] != rid; i++); /* found rid, stop */ + for(; i < CLEANRIDSIZ; i++){ + /* rewrite entire array */ + cleaned_rids[i] = cleaned_rids[i + 1]; + } +- slapi_rwlock_unlock(rid_lock); +- /* +- * Prepare the mods for the config entry +- */ +- csn_as_string(maxcsn, PR_FALSE, csnstr); +- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s", (int)rid, csnstr); +- dn = replica_get_dn(r); +- pb = slapi_pblock_new(); +- mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; +- mod.mod_type = (char *)type_replicaCleanRUV; +- mod.mod_bvalues = vals; +- vals [0] = &val; +- vals [1] = NULL; +- val.bv_val = data; +- mods[0] = &mod; +- mods[1] = NULL; +- +- replica_remove_cleanruv_data(r, data); +- +- slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); +- slapi_modify_internal_pb (pb); +- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); +- if (rc != LDAP_SUCCESS){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config " +- "(%d), rid (%d)\n", rc, rid); +- } +- slapi_pblock_destroy (pb); +- slapi_ch_free_string(&dn); +- /* +- * Now release the cleaned rid from the repl agmts +- */ +- agmt_obj = agmtlist_get_first_agreement_for_replica (r); +- while (agmt_obj){ +- agmt = (Repl_Agmt*)object_get_data (agmt_obj); +- if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){ +- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj); +- continue; +- } +- agmt_set_cleanruv_data(agmt, rid, CLEANRUV_RELEASED); +- agmt_obj = agmtlist_get_next_agreement_for_replica (r, agmt_obj); ++ /* now do the preset cleaned rids */ ++ for(i = 0; i < CLEANRIDSIZ && pre_cleaned_rids[i] != rid; i++); /* found rid, stop */ ++ for(; i < CLEANRIDSIZ; i++){ ++ /* rewrite entire array */ ++ pre_cleaned_rids[i] = pre_cleaned_rids[i + 1]; + } ++ ++ slapi_rwlock_unlock(rid_lock); + } + + /* +@@ -2181,18 +2435,17 @@ int + replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, + int *returncode, char *returntext, void *arg) + { +- PRThread *thread = NULL; + struct berval *payload = NULL; +- Slapi_Task *task = NULL; +- Replica *replica; +- ReplicaId rid; + cleanruv_data *data = NULL; ++ PRThread *thread = NULL; ++ Slapi_Task *task = NULL; + Slapi_DN *sdn = NULL; ++ Replica *replica; ++ ReplicaId rid;; + Object *r; +- CSN *maxcsn = NULL; ++ const char *certify_all; + const char *base_dn; + const char *rid_str; +- const char *certify_all; + char *ridstr = NULL; + int rc = SLAPI_DSE_CALLBACK_OK; + +@@ -2216,13 +2469,6 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter + rc = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } +- if ((base_dn = fetch_attr(e, "replica-base-dn", 0)) == NULL){ +- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Missing required attr \"replica-base-dn\""); +- cleanruv_log(task, ABORT_CLEANALLRUV_ID, "%s", returntext); +- *returncode = LDAP_OBJECT_CLASS_VIOLATION; +- rc = SLAPI_DSE_CALLBACK_ERROR; +- goto out; +- } + certify_all = fetch_attr(e, "replica-certify-all", 0); + /* + * Check the rid +@@ -2236,6 +2482,29 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter + rc = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } ++ if ((base_dn = fetch_attr(e, "replica-base-dn", 0)) == NULL){ ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Missing required attr \"replica-base-dn\""); ++ cleanruv_log(task, ABORT_CLEANALLRUV_ID, "%s", returntext); ++ *returncode = LDAP_OBJECT_CLASS_VIOLATION; ++ rc = SLAPI_DSE_CALLBACK_ERROR; ++ goto out; ++ } ++ if(!is_cleaned_rid(rid) && !is_pre_cleaned_rid(rid)){ ++ /* we are not cleaning this rid */ ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Replica id (%d) is not being cleaned, nothing to abort.", rid); ++ cleanruv_log(task, ABORT_CLEANALLRUV_ID, "%s", returntext); ++ *returncode = LDAP_UNWILLING_TO_PERFORM; ++ rc = SLAPI_DSE_CALLBACK_ERROR; ++ goto out; ++ } ++ if(is_task_aborted(rid)){ ++ /* we are already aborting this rid */ ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Replica id (%d) is already being aborted", rid); ++ cleanruv_log(task, ABORT_CLEANALLRUV_ID, "%s", returntext); ++ *returncode = LDAP_UNWILLING_TO_PERFORM; ++ rc = SLAPI_DSE_CALLBACK_ERROR; ++ goto out; ++ } + /* + * Get the replica object + */ +@@ -2248,7 +2517,7 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter + goto out; + } + /* +- * Check verify value ++ * Check certify value + */ + if(certify_all){ + if(strcasecmp(certify_all,"yes") && strcasecmp(certify_all,"no")){ +@@ -2260,13 +2529,13 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter + goto out; + } + } else { +- certify_all = "no"; ++ certify_all = "yes"; + } + /* + * Create payload + */ + ridstr = slapi_ch_smprintf("%d:%s:%s", rid, base_dn, certify_all); +- payload = create_ruv_payload(ridstr); ++ payload = create_cleanruv_payload(ridstr); + + if(payload == NULL){ + cleanruv_log(task, ABORT_CLEANALLRUV_ID, "Failed to create extended op payload, aborting task"); +@@ -2278,8 +2547,6 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter + * Stop the cleaning, and delete the rid + */ + replica = (Replica*)object_get_data (r); +- maxcsn = replica_get_cleanruv_maxcsn(replica, rid); +- delete_cleaned_rid(replica, rid, maxcsn); + add_aborted_rid(rid, replica, (char *)base_dn); + stop_ruv_cleaning(); + /* +@@ -2308,11 +2575,11 @@ replica_cleanall_ruv_abort(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter + object_release(r); + cleanruv_log(task, ABORT_CLEANALLRUV_ID,"Unable to create abort thread. Aborting task."); + *returncode = LDAP_OPERATIONS_ERROR; ++ slapi_ch_free_string(&data->certify); + rc = SLAPI_DSE_CALLBACK_ERROR; + } + + out: +- csn_free(&maxcsn); + slapi_ch_free_string(&ridstr); + slapi_sdn_free(&sdn); + +@@ -2337,6 +2604,8 @@ replica_abort_task_thread(void *arg) + int interval = 10; + int release_it = 0; + ++ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Aborting task for rid(%d)...",data->rid); ++ + /* + * Need to build the replica from the dn + */ +@@ -2414,8 +2683,12 @@ done: + /* + * Clean up the config + */ +- delete_aborted_rid(data->replica, data->rid, data->repl_root); +- cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted cleanAllRUV task for rid(%d)", data->rid); ++ delete_aborted_rid(data->replica, data->rid, data->repl_root, 1); /* delete just the config, leave rid in memory */ ++ if(strcasecmp(data->certify, "yes") == 0){ ++ check_replicas_are_done_aborting(data); ++ } ++ delete_aborted_rid(data->replica, data->rid, data->repl_root, 0); /* remove the in-memory aborted rid */ ++ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid); + } + if(data->task){ + slapi_task_finish(data->task, agmt_not_notified); +@@ -2437,10 +2710,10 @@ replica_cleanallruv_send_abort_extop(Repl_Agmt *ra, Slapi_Task *task, struct ber + Repl_Connection *conn = NULL; + ConnResult crc = 0; + int msgid = 0; +- int rc = 0; ++ int rc = -1; + + if((conn = conn_new(ra)) == NULL){ +- return -1; ++ return rc; + } + if(conn_connect(conn) == CONN_OPERATION_SUCCESS){ + crc = conn_send_extended_operation(conn, REPL_ABORT_CLEANRUV_OID, payload, NULL, &msgid); +@@ -2462,186 +2735,262 @@ replica_cleanallruv_send_abort_extop(Repl_Agmt *ra, Slapi_Task *task, struct ber + + + static int +-replica_cleanallruv_send_extop(Repl_Agmt *ra, ReplicaId rid, Slapi_Task *task, struct berval *payload, int check_result) ++replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int check_result) + { + Repl_Connection *conn = NULL; + ConnResult crc = 0; + int msgid = 0; +- int rc = 0; ++ int rc = -1; + + if((conn = conn_new(ra)) == NULL){ +- return -1; ++ return rc; + } + if(conn_connect(conn) == CONN_OPERATION_SUCCESS){ +- crc = conn_send_extended_operation(conn, REPL_CLEANRUV_OID, payload, NULL, &msgid); ++ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_OID, clean_data->payload, NULL, &msgid); + if(crc == CONN_OPERATION_SUCCESS && check_result){ + struct berval *retsdata = NULL; + char *retoid = NULL; + + crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1); + if (CONN_OPERATION_SUCCESS == crc ){ +- struct berval **ruv_bervals = NULL; +- struct berval *data = NULL; +- char *data_guid = NULL; +- +- decode_repl_ext_response(retsdata, &rc, &ruv_bervals, &data_guid, &data); +- /* just free everything, we only wanted "rc" */ +- slapi_ch_free_string(&data_guid); +- if(data) +- ber_bvfree(data); +- if (ruv_bervals) +- ber_bvecfree(ruv_bervals); +- +- if(rc == 0 ){ /* rc == 1 is success */ +- cleanruv_log(task, CLEANALLRUV_ID,"Replica %s does not support the CLEANALLRUV task. Sending replica CLEANRUV task...", ++ char *response = NULL; ++ ++ decode_cleanruv_payload(retsdata, &response); ++ if(response && strcmp(response,CLEANRUV_ACCEPTED) == 0){ ++ /* extop was accepted */ ++ rc = 0; ++ } else { ++ cleanruv_log(clean_data->task, CLEANALLRUV_ID,"Replica %s does not support the CLEANALLRUV task. Sending replica CLEANRUV task...", + slapi_sdn_get_dn(agmt_get_dn_byref(ra))); + /* + * Ok, this replica doesn't know about CLEANALLRUV, so just manually + * add the CLEANRUV task to the replica. + */ +- replica_send_cleanruv_task(ra, rid, task); +- } else { +- /* extop was accepted */ +- rc = 0; ++ replica_send_cleanruv_task(ra, clean_data); + } +- if (NULL != retoid) +- ldap_memfree(retoid); + if (NULL != retsdata) + ber_bvfree(retsdata); ++ slapi_ch_free_string(&retoid); ++ slapi_ch_free_string(&response); + } +- agmt_set_cleanruv_data(ra, rid, CLEANRUV_NOTIFIED); + } else { + /* + * success or failure, just return the error code + */ + rc = crc; + } +- } else { +- rc =-1; + } + conn_delete_internal_ext(conn); + + return rc; + } + ++static CSN* ++replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn) ++{ ++ Object *agmt_obj; ++ Repl_Agmt *agmt; ++ char *rid_text; ++ CSN *maxcsn = NULL, *topcsn = NULL; ++ int done = 1, found = 0; ++ int interval = 10; ++ ++ rid_text = slapi_ch_smprintf("%d", rid); ++ ++ while(done && !is_task_aborted(rid) && !slapi_is_shutting_down()){ ++ agmt_obj = agmtlist_get_first_agreement_for_replica (replica); ++ if(agmt_obj == NULL){ ++ break; ++ } ++ while (agmt_obj && !slapi_is_shutting_down()){ ++ agmt = (Repl_Agmt*)object_get_data (agmt_obj); ++ if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){ ++ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); ++ done = 0; ++ continue; ++ } ++ if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){ ++ if(maxcsn == NULL){ ++ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); ++ continue; ++ } ++ found = 1; ++ if(topcsn == NULL){ ++ topcsn = maxcsn; ++ } else { ++ if(csn_compare(topcsn, maxcsn) < 0){ ++ csn_free(&topcsn); ++ topcsn = maxcsn; ++ } else { ++ csn_free(&maxcsn); ++ } ++ } ++ done = 0; ++ } else { ++ done = 1; ++ break; ++ } ++ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); ++ } /* agmt while */ ++ if(done == 0 || is_task_aborted(rid) ){ ++ break; ++ } ++ if(!found){ ++ /* we could not find any maxcsn's - already cleaned? */ ++ return NULL; ++ } ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: Not all replicas online, retrying in %d seconds\n",interval); ++ PR_Lock( notify_lock ); ++ PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) ); ++ PR_Unlock( notify_lock ); ++ ++ if(interval < 14400){ /* 4 hour max */ ++ interval = interval * 2; ++ } else { ++ interval = 14400; ++ } ++ } ++ slapi_ch_free_string(&rid_text); ++ ++ if(is_task_aborted(rid)){ ++ return NULL; ++ } ++ ++ return topcsn; ++} ++ + static int +-replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *rid_text, char *maxcsn, Slapi_Task *task) ++replica_cleanallruv_get_replica_maxcsn(Repl_Agmt *agmt, char *rid_text, char *basedn, CSN **csn) + { + Repl_Connection *conn = NULL; +- LDAP *ld; +- Slapi_DN *sdn; +- struct berval **vals; +- LDAPMessage *result = NULL, *entry = NULL; +- BerElement *ber; +- char *attrs[2]; +- char *attr = NULL; +- char *iter = NULL; +- char *ruv_part = NULL; +- int found_rid = 0; +- int part_count = 0; +- int rc = 0, i; ++ ConnResult crc = -1; ++ struct berval *payload = NULL; ++ CSN *maxcsn = NULL; ++ char *data = NULL; ++ int msgid = 0; + + if((conn = conn_new(agmt)) == NULL){ + return -1; + } + ++ data = slapi_ch_smprintf("%s:%s",rid_text, basedn); ++ payload = create_cleanruv_payload(data); ++ + if(conn_connect(conn) == CONN_OPERATION_SUCCESS){ +- attrs[0] = "nsds50ruv"; +- attrs[1] = NULL; +- ld = conn_get_ldap(conn); +- if(ld == NULL){ +- conn_delete_internal_ext(conn); +- return -1; +- } +- sdn = agmt_get_replarea(agmt); +- rc = ldap_search_ext_s(ld, slapi_sdn_get_dn(sdn), LDAP_SCOPE_SUBTREE, +- "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))", +- attrs, 0, NULL, NULL, NULL, 0, &result); +- slapi_sdn_free(&sdn); +- if(rc != LDAP_SUCCESS){ +- cleanruv_log(task, CLEANALLRUV_ID,"Failed to contact " +- "agmt (%s) error (%d), will retry later.", agmt_get_long_name(agmt), rc); +- conn_delete_internal_ext(conn); +- return -1; +- } +- entry = ldap_first_entry( ld, result ); +- if ( entry != NULL ) { +- for ( attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL; attr = ldap_next_attribute( ld, entry, ber ) ){ +- /* make sure the attribute is nsds50ruv */ +- if(strcasecmp(attr,"nsds50ruv") != 0){ +- ldap_memfree( attr ); +- continue; ++ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_GET_MAXCSN_OID, payload, NULL, &msgid); ++ if(crc == CONN_OPERATION_SUCCESS){ ++ struct berval *retsdata = NULL; ++ char *retoid = NULL; ++ ++ crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1); ++ if (CONN_OPERATION_SUCCESS == crc ){ ++ char *remote_maxcsn = NULL; ++ ++ decode_cleanruv_payload(retsdata, &remote_maxcsn); ++ if(remote_maxcsn && strcmp(remote_maxcsn, CLEANRUV_NO_MAXCSN)){ ++ maxcsn = csn_new(); ++ csn_init_by_string(maxcsn, remote_maxcsn); ++ *csn = maxcsn; ++ } else { ++ /* no csn */ ++ *csn = NULL; + } +- found_rid = 0; +- if ((vals = ldap_get_values_len( ld, entry, attr)) != NULL ) { +- for ( i = 0; vals[i] && vals[i]->bv_val; i++ ) { +- /* look for this replica */ +- if(strstr(vals[i]->bv_val, rid_text)){ +- found_rid = 1; +- /* get the max csn compare it to our known max csn */ +- ruv_part = ldap_utf8strtok_r(vals[i]->bv_val, " ", &iter); +- for(part_count = 1; ruv_part && part_count < 5; part_count++){ +- ruv_part = ldap_utf8strtok_r(iter, " ", &iter); +- } +- if(part_count == 5 && ruv_part){ +- /* we have the maxcsn */ +- if(strcmp(ruv_part, maxcsn)){ +- /* we are not caught up yet, free, and return */ +- ldap_value_free_len(vals); +- ldap_memfree( attr ); +- ldap_msgfree( result ); +- if(ber){ +- ber_free( ber, 0 ); +- } +- conn_delete_internal_ext(conn); +- return -1; +- } else { +- /* ok this replica has all the updates from the deleted replica */ +- rc = 0; +- } +- } else { +- /* there is no maxcsn for this rid - treat it as caught up */ +- rc = 0; +- } +- } +- } +- if(!found_rid){ +- /* must have been cleaned already */ ++ slapi_ch_free_string(&retoid); ++ slapi_ch_free_string(&remote_maxcsn); ++ if (NULL != retsdata) ++ ber_bvfree(retsdata); ++ } ++ } ++ } ++ conn_delete_internal_ext(conn); ++ slapi_ch_free_string(&data); ++ if(payload) ++ ber_bvfree(payload); ++ ++ return (int)crc; ++} ++ ++static int ++replica_cleanallruv_check_maxcsn(Repl_Agmt *agmt, char *basedn, char *rid_text, char *maxcsn, Slapi_Task *task) ++{ ++ Repl_Connection *conn = NULL; ++ ConnResult crc = 0; ++ struct berval *payload = NULL; ++ char *data = NULL; ++ int msgid = 0; ++ int rc = -1; ++ ++ if((conn = conn_new(agmt)) == NULL){ ++ return -1; ++ } ++ ++ data = slapi_ch_smprintf("%s:%s",rid_text, basedn); ++ payload = create_cleanruv_payload(data); ++ ++ if(conn_connect(conn) == CONN_OPERATION_SUCCESS){ ++ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_GET_MAXCSN_OID, payload, NULL, &msgid); ++ if(crc == CONN_OPERATION_SUCCESS){ ++ struct berval *retsdata = NULL; ++ char *retoid = NULL; ++ ++ crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1); ++ if (CONN_OPERATION_SUCCESS == crc ){ ++ char *remote_maxcsn = NULL; ++ ++ decode_cleanruv_payload(retsdata, &remote_maxcsn); ++ if(remote_maxcsn && strcmp(remote_maxcsn, CLEANRUV_NO_MAXCSN)){ ++ CSN *max, *repl_max; ++ ++ max = csn_new(); ++ repl_max = csn_new(); ++ csn_init_by_string(max, maxcsn); ++ csn_init_by_string(repl_max, remote_maxcsn); ++ if(csn_compare (repl_max, max) < 0){ ++ /* we are not caught up yet, free, and return */ ++ cleanruv_log(task, CLEANALLRUV_ID,"Replica maxcsn (%s) is not caught up with deleted replica's maxcsn(%s)", ++ remote_maxcsn, maxcsn); ++ rc = -1; ++ } else { ++ /* ok this replica is caught up */ + rc = 0; + } +- ldap_value_free_len(vals); ++ csn_free(&max); ++ csn_free(&repl_max); ++ } else { ++ /* no remote_maxcsn - return success */ ++ rc = 0; + } +- ldap_memfree( attr ); +- } +- if ( ber != NULL ) { +- ber_free( ber, 0 ); +- } +- } +- if(result) +- ldap_msgfree( result ); +- } else { +- rc = -1; ++ slapi_ch_free_string(&retoid); ++ slapi_ch_free_string(&remote_maxcsn); ++ if (NULL != retsdata) ++ ber_bvfree(retsdata); ++ } ++ } + } + conn_delete_internal_ext(conn); ++ slapi_ch_free_string(&data); ++ if(payload) ++ ber_bvfree(payload); + +- return rc; ++ return rc; + } + ++ + static int + replica_cleanallruv_replica_alive(Repl_Agmt *agmt) + { + Repl_Connection *conn = NULL; + LDAP *ld = NULL; + LDAPMessage *result = NULL; +- int rc = 0; ++ int rc = -1; + + if((conn = conn_new(agmt)) == NULL){ +- return -1; ++ return rc; + } + if(conn_connect(conn) == CONN_OPERATION_SUCCESS){ + ld = conn_get_ldap(conn); + if(ld == NULL){ +- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanAllRUV_task: failed to get LDAP " ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "CleanAllRUV_task: failed to get LDAP " + "handle from the replication agmt (%s). Moving on to the next agmt.\n",agmt_get_long_name(agmt)); + conn_delete_internal_ext(conn); + return -1; +@@ -2655,8 +3004,6 @@ replica_cleanallruv_replica_alive(Repl_Agmt *agmt) + } + if(result) + ldap_msgfree( result ); +- } else { +- rc = -1; + } + conn_delete_internal_ext(conn); + +@@ -2664,83 +3011,51 @@ replica_cleanallruv_replica_alive(Repl_Agmt *agmt) + } + + static int +-replica_cleanallruv_check_ruv(Repl_Agmt *ra, char *rid_text, Slapi_Task *task) ++replica_cleanallruv_check_ruv(char *repl_root, Repl_Agmt *agmt, char *rid_text, Slapi_Task *task) + { + Repl_Connection *conn = NULL; +- BerElement *ber = NULL; +- struct berval **vals = NULL; +- LDAPMessage *result = NULL, *entry = NULL; +- LDAP *ld = NULL; +- Slapi_DN *sdn; +- char *attrs[2]; +- char *attr = NULL; +- int rc = 0, i; ++ ConnResult crc = 0; ++ struct berval *payload = NULL; ++ char *data = NULL; ++ int msgid = 0; ++ int rc = -1; + +- if((conn = conn_new(ra)) == NULL){ +- return -1; ++ if((conn = conn_new(agmt)) == NULL){ ++ return rc; + } ++ ++ data = slapi_ch_smprintf("%s:%s",rid_text, repl_root); ++ payload = create_cleanruv_payload(data); ++ + if(conn_connect(conn) == CONN_OPERATION_SUCCESS){ +- attrs[0] = "nsds50ruv"; +- attrs[1] = NULL; +- ld = conn_get_ldap(conn); +- if(ld == NULL){ +- cleanruv_log(task, CLEANALLRUV_ID,"Failed to get LDAP handle from " +- "the replication agmt (%s). Moving on to the next agmt.",agmt_get_long_name(ra)); +- rc = -1; +- goto done; +- } ++ crc = conn_send_extended_operation(conn, REPL_CLEANRUV_GET_MAXCSN_OID, payload, NULL, &msgid); ++ if(crc == CONN_OPERATION_SUCCESS){ ++ struct berval *retsdata = NULL; ++ char *retoid = NULL; + +- sdn = agmt_get_replarea(ra); +- rc = ldap_search_ext_s(ld, slapi_sdn_get_dn(sdn), LDAP_SCOPE_SUBTREE, +- "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))", +- attrs, 0, NULL, NULL, NULL, 0, &result); +- slapi_sdn_free(&sdn); +- if(rc != LDAP_SUCCESS){ +- cleanruv_log(task, CLEANALLRUV_ID,"Failed to contact " +- "agmt (%s) error (%d), will retry later.", agmt_get_long_name(ra), rc); +- rc = -1; +- goto done; +- } +- entry = ldap_first_entry( ld, result ); +- if ( entry != NULL ) { +- for ( attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL; attr = ldap_next_attribute( ld, entry, ber ) ){ +- /* make sure the attribute is nsds50ruv */ +- if(strcasecmp(attr,"nsds50ruv") != 0){ +- ldap_memfree( attr ); +- continue; +- } +- if ((vals = ldap_get_values_len( ld, entry, attr)) != NULL ) { +- for ( i = 0; vals[i] && vals[i]->bv_val; i++ ) { +- /* look for this replica */ +- if(strstr(vals[i]->bv_val, rid_text)){ +- /* rid has not been cleaned yet, free and return */ +- rc = -1; +- ldap_value_free_len(vals); +- ldap_memfree( attr ); +- if ( ber != NULL ) { +- ber_free( ber, 0 ); +- ber = NULL; +- } +- goto done; +- } else { +- rc = 0; +- } +- } +- ldap_value_free_len(vals); ++ crc = conn_read_result_ex(conn, &retoid, &retsdata, NULL, msgid, NULL, 1); ++ if (CONN_OPERATION_SUCCESS == crc ){ ++ char *remote_maxcsn = NULL; ++ ++ decode_cleanruv_payload(retsdata, &remote_maxcsn); ++ if(remote_maxcsn && strcmp(remote_maxcsn, CLEANRUV_NO_MAXCSN)){ ++ /* remote replica still has dirty RUV element */ ++ rc = -1; ++ } else { ++ /* no maxcsn = we're clean */ ++ rc = 0; + } +- ldap_memfree( attr ); +- } /* for loop */ +- if ( ber != NULL ) { +- ber_free( ber, 0 ); ++ slapi_ch_free_string(&retoid); ++ slapi_ch_free_string(&remote_maxcsn); ++ if (NULL != retsdata) ++ ber_bvfree(retsdata); + } + } +-done: +- if(result) +- ldap_msgfree( result ); +- } else { +- return -1; + } + conn_delete_internal_ext(conn); ++ slapi_ch_free_string(&data); ++ if(payload) ++ ber_bvfree(payload); + + return rc; + } +diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c +index 3a6f422..e842c62 100644 +--- a/ldap/servers/plugins/replication/repl_extop.c ++++ b/ldap/servers/plugins/replication/repl_extop.c +@@ -1451,7 +1451,6 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + cleanruv_data *data; + Replica *r; + ReplicaId rid; +- CSN *maxcsn = NULL; + struct berval *extop_payload = NULL; + char *extop_oid; + char *repl_root; +@@ -1463,7 +1462,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload); + +- if (NULL == extop_oid || strcmp(extop_oid, REPL_CLEANRUV_OID) != 0 || ++ if (NULL == extop_oid || strcmp(extop_oid, REPL_ABORT_CLEANRUV_OID) != 0 || + NULL == extop_payload || NULL == extop_payload->bv_val){ + /* something is wrong, error out */ + return LDAP_OPERATIONS_ERROR; +@@ -1472,24 +1471,24 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + * Decode the payload, and grab our settings + */ + if(decode_cleanruv_payload(extop_payload, &payload)){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: failed to decode payload. Aborting ext op\n"); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to decode payload. Aborting ext op\n"); + return LDAP_OPERATIONS_ERROR; + } + rid = atoi(ldap_utf8strtok_r(payload, ":", &iter)); + repl_root = ldap_utf8strtok_r(iter, ":", &iter); + certify_all = ldap_utf8strtok_r(iter, ":", &iter); + +- if(!is_cleaned_rid(rid) || is_task_aborted(rid)){ ++ if(!is_cleaned_rid(rid) || !is_pre_cleaned_rid(rid) || is_task_aborted(rid)){ + /* This replica has already been aborted, or was never cleaned, or already finished cleaning */ + goto out; + } else { +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: aborting cleanallruv task for rid(%d)\n", rid); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: aborting cleanallruv task for rid(%d)\n", rid); + } + /* + * Get the node, so we can get the replica and its agreements + */ + if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: failed to get replication node " ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: failed to get replication node " + "from (%s), aborting operation\n", repl_root); + rc = LDAP_OPERATIONS_ERROR; + goto out; +@@ -1498,14 +1497,14 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + object_acquire (mtnode_ext->replica); + release_it = 1; + } else { +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: replica is missing from (%s), " ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: replica is missing from (%s), " + "aborting operation\n",repl_root); + rc = LDAP_OPERATIONS_ERROR; + goto out; + } + r = (Replica*)object_get_data (mtnode_ext->replica); + if(r == NULL){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort cleanAllRUV task: replica is NULL, aborting task\n"); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Abort CleanAllRUV Task: replica is NULL, aborting task\n"); + rc = LDAP_OPERATIONS_ERROR; + goto out; + } +@@ -1514,7 +1513,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + */ + data = (cleanruv_data*)slapi_ch_calloc(1, sizeof(cleanruv_data)); + if (data == NULL) { +- slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort cleanAllRUV task: failed to allocate " ++ slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort CleanAllRUV Task: failed to allocate " + "abort_cleanruv_data. Aborting task.\n"); + rc = LDAP_OPERATIONS_ERROR; + goto out; +@@ -1528,11 +1527,8 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + data->repl_root = slapi_ch_strdup(repl_root); + data->certify = slapi_ch_strdup(certify_all); + /* +- * Stop the cleaning, and delete the rid ++ * Set the aborted rid and stop the cleaning + */ +- maxcsn = replica_get_cleanruv_maxcsn(r, rid); +- delete_cleaned_rid(r, rid, maxcsn); +- csn_free(&maxcsn); + add_aborted_rid(rid, r, repl_root); + stop_ruv_cleaning(); + /* +@@ -1542,7 +1538,7 @@ multimaster_extop_abort_cleanruv(Slapi_PBlock *pb) + (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE); + if (thread == NULL) { +- slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort cleanAllRUV task: unable to create abort " ++ slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "Abort CleanAllRUV Task: unable to create abort " + "thread. Aborting task.\n"); + release_it = 1; /* have to release mtnode_ext->replica now */ + slapi_ch_free_string(&data->repl_root); +@@ -1583,10 +1579,11 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + struct berval *extop_payload; + struct berval *resp_bval = NULL; + BerElement *resp_bere = NULL; +- char *extop_oid; +- char *repl_root; + char *payload = NULL; + char *csnstr = NULL; ++ char *force = NULL; ++ char *extop_oid; ++ char *repl_root; + char *iter; + int release_it = 0; + int rid = 0; +@@ -1604,28 +1601,31 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + * Decode the payload + */ + if(decode_cleanruv_payload(extop_payload, &payload)){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to decode payload. Aborting ext op\n"); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to decode payload. Aborting ext op\n"); + goto free_and_return; + } + rid = atoi(ldap_utf8strtok_r(payload, ":", &iter)); + repl_root = ldap_utf8strtok_r(iter, ":", &iter); + csnstr = ldap_utf8strtok_r(iter, ":", &iter); ++ force = ldap_utf8strtok_r(iter, ":", &iter); ++ if(force == NULL){ ++ force = "no"; ++ } + maxcsn = csn_new(); + csn_init_by_string(maxcsn, csnstr); + /* + * If we already cleaned this server, just return success + */ +- if(is_cleaned_rid(rid)){ ++ if(is_cleaned_rid(rid) || is_pre_cleaned_rid(rid) || is_task_aborted(rid)){ + csn_free(&maxcsn); + rc = LDAP_SUCCESS; + goto free_and_return; + } +- + /* + * Get the node, so we can get the replica and its agreements + */ + if((mtnode_ext = replica_config_get_mtnode_by_dn(repl_root)) == NULL){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to get replication node " ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to get replication node " + "from (%s), aborting operation\n", repl_root); + goto free_and_return; + } +@@ -1634,14 +1634,14 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + object_acquire (mtnode_ext->replica); + release_it = 1; + } else { +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: replica is missing from (%s), " ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica is missing from (%s), " + "aborting operation\n",repl_root); + goto free_and_return; + } + + r = (Replica*)object_get_data (mtnode_ext->replica); + if(r == NULL){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: replica is NULL, aborting task\n"); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica is NULL, aborting task\n"); + goto free_and_return; + } + +@@ -1651,10 +1651,10 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + * + * This will also release mtnode_ext->replica + */ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: launching cleanAllRUV thread...\n"); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: launching cleanAllRUV thread...\n"); + data = (cleanruv_data*)slapi_ch_calloc(1, sizeof(cleanruv_data)); + if (data == NULL) { +- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: failed to allocate " ++ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to allocate " + "cleanruv_Data\n"); + goto free_and_return; + } +@@ -1664,15 +1664,19 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + data->task = NULL; + data->maxcsn = maxcsn; + data->payload = slapi_ch_bvdup(extop_payload); ++ data->force = slapi_ch_strdup(force); ++ data->repl_root = slapi_ch_strdup(repl_root); + + thread = PR_CreateThread(PR_USER_THREAD, replica_cleanallruv_thread_ext, + (void *)data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE); + if (thread == NULL) { +- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: unable to create cleanAllRUV " ++ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: unable to create cleanAllRUV " + "monitoring thread. Aborting task.\n"); + ber_bvfree(data->payload); + data->payload = NULL; ++ slapi_ch_free_string(&data->force); ++ slapi_ch_free_string(&data->repl_root); + slapi_ch_free((void **)&data); + } else { + release_it = 0; /* thread will release data->repl_obj == mtnode_ext->replica */ +@@ -1694,18 +1698,18 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + /* we've already been cleaned */ + break; + } +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: checking if we're caught up...\n"); +- if(ruv_covers_csn_cleanallruv(ruv,maxcsn) || csn_get_replicaid(maxcsn) == 0){ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: checking if we're caught up...\n"); ++ if(ruv_covers_csn_cleanallruv(ruv,maxcsn) || csn_get_replicaid(maxcsn) == 0|| strcmp(force,"yes") == 0){ + /* We are caught up */ + break; + } else { + char csnstr[CSN_STRSIZE]; + csn_as_string(maxcsn, PR_FALSE, csnstr); +- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: not ruv caught up maxcsn(%s)\n", csnstr); ++ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: not ruv caught up maxcsn(%s)\n", csnstr); + } + DS_Sleep(PR_SecondsToInterval(5)); + } +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: we're caught up...\n"); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: we're caught up...\n"); + /* + * Set cleaned rid in memory only - does not survive a server restart + */ +@@ -1721,8 +1725,8 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb) + * This read-only replica has no easy way to tell when it's safe to release the rid. + * So we won't release it, not until a server restart. + */ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: You must restart the server if you want to reuse rid(%d).\n", rid); +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cleanAllRUV_task: Successfully cleaned rid(%d).\n", rid); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: You must restart the server if you want to reuse rid(%d).\n", rid); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: Successfully cleaned rid(%d).\n", rid); + rc = LDAP_SUCCESS; + } + +@@ -1737,10 +1741,120 @@ free_and_return: + * Craft a message so we know this replica supports the task + */ + if ((resp_bere = der_alloc())){ ++ ber_printf(resp_bere, "{s}", CLEANRUV_ACCEPTED); ++ ber_flatten(resp_bere, &resp_bval); ++ slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, resp_bval); ++ slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); ++ /* resp_bere */ ++ if (NULL != resp_bere) ++ { ++ ber_free(resp_bere, 1); ++ } ++ /* resp_bval */ ++ if (NULL != resp_bval) ++ { ++ ber_bvfree(resp_bval); ++ } ++ /* tell extendop code that we have already sent the result */ ++ rc = SLAPI_PLUGIN_EXTENDED_SENT_RESULT; ++ } else { ++ rc = LDAP_OPERATIONS_ERROR; ++ } + +- ber_int_t response = 1; ++ return rc; ++} ++ ++/* ++ * Get the max csn for the designated repl area ++ */ ++int ++multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb) ++{ ++ Slapi_PBlock *search_pb = NULL; ++ Slapi_Entry **entries = NULL; ++ struct berval *resp_bval = NULL; ++ struct berval *extop_payload; ++ BerElement *resp_bere = NULL; ++ char **ruv_elements = NULL; ++ char *extop_oid = NULL; ++ char *ruv_part = NULL; ++ char *base_dn = NULL; ++ char *payload = NULL; ++ char *maxcsn = NULL; ++ char *filter = NULL; ++ char *ridstr = NULL; ++ char *iter = NULL; ++ char *attrs[2]; ++ int part_count = 0; ++ int rid = 0; ++ int res = 0; ++ int rc = LDAP_OPERATIONS_ERROR; ++ int i = 0; ++ ++ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); ++ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload); + +- ber_printf(resp_bere, "{e}", response); ++ if (NULL == extop_oid || strcmp(extop_oid, REPL_CLEANRUV_GET_MAXCSN_OID) != 0 || ++ NULL == extop_payload || NULL == extop_payload->bv_val){ ++ /* something is wrong, error out */ ++ goto free_and_return; ++ } ++ /* ++ * Decode the payload ++ */ ++ if(decode_cleanruv_payload(extop_payload, &payload)){ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Get MaxCSN Task: failed to decode payload. Aborting ext op\n"); ++ goto free_and_return; ++ } ++ rid = atoi(ldap_utf8strtok_r(payload, ":", &iter)); ++ base_dn = ldap_utf8strtok_r(iter, ":", &iter); ++ /* ++ * Get the maxruv from the database tombstone entry ++ */ ++ filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))"; ++ attrs[0] = "nsds50ruv"; ++ attrs[1] = NULL; ++ ridstr = slapi_ch_smprintf("{replica %d ldap", rid); ++ ++ search_pb = slapi_pblock_new(); ++ slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0); ++ slapi_search_internal_pb (search_pb); ++ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res); ++ ++ if ( LDAP_SUCCESS == res ) { ++ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); ++ if (NULL == entries || entries[0] == NULL) { ++ /* Hmmm, no tombstpne! Error out */ ++ } else { ++ /* find the right ruv element, and find the maxcsn */ ++ ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]); ++ for(i = 0; ruv_elements && ruv_elements[i] ; i++){ ++ if(strstr(ruv_elements[i], ridstr)){ ++ /* get the max csn */ ++ ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter); ++ for(part_count = 1; ruv_part && part_count < 5; part_count++){ ++ ruv_part = ldap_utf8strtok_r(iter, " ", &iter); ++ } ++ if(part_count == 5 && ruv_part){/* we have the maxcsn */ ++ maxcsn = slapi_ch_strdup(ruv_part); ++ break; ++ } ++ } ++ } ++ slapi_ch_array_free(ruv_elements); ++ } ++ } else { ++ /* internal search failed */ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Get MaxCSN Task: internal search failed (%d)\n", res); ++ } ++ if(maxcsn == NULL){ ++ maxcsn = slapi_ch_strdup(CLEANRUV_NO_MAXCSN); ++ } ++ /* ++ * Send the extended op response ++ */ ++ if ((resp_bere = der_alloc())){ ++ ber_printf(resp_bere, "{s}", maxcsn); + ber_flatten(resp_bere, &resp_bval); + slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, resp_bval); + slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); +@@ -1760,10 +1874,96 @@ free_and_return: + rc = LDAP_OPERATIONS_ERROR; + } + ++free_and_return: ++ slapi_free_search_results_internal(search_pb); ++ slapi_pblock_destroy(search_pb); ++ slapi_ch_free_string(&payload); ++ slapi_ch_free_string(&maxcsn); ++ slapi_ch_free_string(&ridstr); ++ + return rc; + } + + /* ++ * Search cn=config for the cleanallruv attributes (clean & abort) ++ */ ++int ++multimaster_extop_cleanruv_check_status(Slapi_PBlock *pb) ++{ ++ Slapi_PBlock *search_pb = NULL; ++ Slapi_Entry **entries = NULL; ++ struct berval *resp_bval = NULL; ++ struct berval *extop_payload; ++ BerElement *resp_bere = NULL; ++ char *response = NULL; ++ char *filter = NULL; ++ char *extop_oid; ++ int res = 0; ++ int rc = LDAP_OPERATIONS_ERROR; ++ ++ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); ++ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload); ++ ++ if (NULL == extop_oid || strcmp(extop_oid, REPL_CLEANRUV_CHECK_STATUS_OID) != 0 || ++ NULL == extop_payload || NULL == extop_payload->bv_val){ ++ /* something is wrong, error out */ ++ goto free_and_return; ++ } ++ /* ++ * Decode the payload - which should just be a filter ++ */ ++ if(decode_cleanruv_payload(extop_payload, &filter)){ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Check Status Task: failed to decode payload. Aborting ext op\n"); ++ goto free_and_return; ++ } ++ ++ search_pb = slapi_pblock_new(); ++ slapi_search_internal_set_pb(search_pb, "cn=config", LDAP_SCOPE_SUBTREE, ++ filter, NULL, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0); ++ slapi_search_internal_pb (search_pb); ++ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res); ++ if ( LDAP_SUCCESS == res ) { ++ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); ++ if (NULL == entries || entries[0] == NULL) { ++ /* cleaning task has finished, send repsonse */ ++ response = CLEANRUV_FINISHED; ++ } else { ++ response = CLEANRUV_CLEANING; ++ } ++ /* ++ * Send the extended op response ++ */ ++ if ((resp_bere = der_alloc())){ ++ ber_printf(resp_bere, "{s}", response); ++ ber_flatten(resp_bere, &resp_bval); ++ slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, resp_bval); ++ slapi_send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL); ++ /* resp_bere */ ++ if (NULL != resp_bere) ++ { ++ ber_free(resp_bere, 1); ++ } ++ /* resp_bval */ ++ if (NULL != resp_bval) ++ { ++ ber_bvfree(resp_bval); ++ } ++ /* tell extendop code that we have already sent the result */ ++ rc = SLAPI_PLUGIN_EXTENDED_SENT_RESULT; ++ } ++ } ++ ++free_and_return: ++ ++ slapi_free_search_results_internal(search_pb); ++ slapi_pblock_destroy(search_pb); ++ slapi_ch_free_string(&filter); ++ ++ return rc; ++} ++ ++ ++/* + * This plugin entry point is a noop entry + * point. It's used when registering extops that + * are only used as responses. We'll never receive +diff --git a/ldap/servers/plugins/replication/replutil.c b/ldap/servers/plugins/replication/replutil.c +index 5e8019c..d007f6c 100644 +--- a/ldap/servers/plugins/replication/replutil.c ++++ b/ldap/servers/plugins/replication/replutil.c +@@ -765,33 +765,32 @@ repl_set_mtn_state_and_referrals( + ldap_free_urldesc(lud); + } + +- if (!referrals_to_set) { /* deleting referrals */ +- /* Set state before */ +- if (!chain_on_update) { +- slapi_mtn_set_state(repl_root_sdn, (char *)mtn_state); ++ if (!referrals_to_set) { /* deleting referrals */ ++ /* Set state before */ ++ if (!chain_on_update) { ++ slapi_mtn_set_state(repl_root_sdn, (char *)mtn_state); ++ } ++ /* We should delete referral only if we want to set the ++ replica database in backend state mode */ ++ /* if chain on update mode, go ahead and set the referrals anyway */ ++ if (strcasecmp(mtn_state, STATE_BACKEND) == 0 || chain_on_update) { ++ rc = slapi_mtn_set_referral(repl_root_sdn, referrals_to_set); ++ if (rc == LDAP_NO_SUCH_ATTRIBUTE) { ++ /* we will get no such attribute (16) if we try to set the referrals to NULL if ++ there are no referrals - not an error */ ++ rc = LDAP_SUCCESS; + } +- /* We should delete referral only if we want to set the +- replica database in backend state mode */ +- /* if chain on update mode, go ahead and set the referrals anyway */ +- if (strcasecmp(mtn_state, STATE_BACKEND) == 0 || chain_on_update) { +- rc = slapi_mtn_set_referral(repl_root_sdn, referrals_to_set); +- if (rc == LDAP_NO_SUCH_ATTRIBUTE) { +- /* we will get no such attribute (16) if we try to set the referrals to NULL if +- there are no referrals - not an error */ +- rc = LDAP_SUCCESS; +- } +- } +- } else { /* Replacing */ +- rc = slapi_mtn_set_referral(repl_root_sdn, referrals_to_set); +- if (rc == LDAP_SUCCESS && !chain_on_update){ +- slapi_mtn_set_state(repl_root_sdn, (char *)mtn_state); +- } +- } ++ } ++ } else { /* Replacing */ ++ rc = slapi_mtn_set_referral(repl_root_sdn, referrals_to_set); ++ if (rc == LDAP_SUCCESS && !chain_on_update){ ++ slapi_mtn_set_state(repl_root_sdn, (char *)mtn_state); ++ } ++ } + +- if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) { ++ if (rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS) { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "repl_set_mtn_referrals: could " +- "not set referrals for replica %s: %d\n", +- slapi_sdn_get_dn(repl_root_sdn), rc); ++ "not set referrals for replica %s: %d\n", slapi_sdn_get_dn(repl_root_sdn), rc); + } + + charray_free(referrals_to_set); +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +index 6d2e6f6..5c9585f 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +@@ -71,6 +71,11 @@ void modify_init(modify_context *mc,struct backentry *old_entry) + + int modify_apply_mods(modify_context *mc, Slapi_Mods *smods) + { ++ return modify_apply_mods_ignore_error(mc, smods, -1); ++} ++ ++int modify_apply_mods_ignore_error(modify_context *mc, Slapi_Mods *smods, int error) ++{ + int ret = 0; + /* Make a copy of the entry */ + PR_ASSERT(mc->old_entry != NULL); +@@ -78,7 +83,7 @@ int modify_apply_mods(modify_context *mc, Slapi_Mods *smods) + mc->new_entry = backentry_dup(mc->old_entry); + PR_ASSERT(smods!=NULL); + if ( mods_have_effect (mc->new_entry->ep_entry, smods) ) { +- ret = entry_apply_mods( mc->new_entry->ep_entry, slapi_mods_get_ldapmods_byref(smods)); ++ ret = entry_apply_mods_ignore_error( mc->new_entry->ep_entry, slapi_mods_get_ldapmods_byref(smods), error); + } + mc->smods= smods; + return ret; +diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c +index a56069b..fd62df9 100644 +--- a/ldap/servers/slapd/back-ldbm/misc.c ++++ b/ldap/servers/slapd/back-ldbm/misc.c +@@ -444,7 +444,7 @@ ldbm_txn_ruv_modify_context( Slapi_PBlock *pb, modify_context *mc ) + + modify_init( mc, bentry ); + +- if (modify_apply_mods( mc, smods )) { ++ if (modify_apply_mods_ignore_error( mc, smods, LDAP_TYPE_OR_VALUE_EXISTS )) { + LDAPDebug( LDAP_DEBUG_ANY, "Error: ldbm_txn_ruv_modify_context failed to apply updates to RUV entry\n", + 0, 0, 0 ); + rc = -1; +diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +index 48b3164..a7fb06d 100644 +--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +@@ -347,6 +347,7 @@ void modify_init(modify_context *mc,struct backentry *old_entry); + int modify_apply_mods(modify_context *mc, Slapi_Mods *smods); + int modify_term(modify_context *mc,backend *be); + int modify_switch_entries(modify_context *mc,backend *be); ++int modify_apply_mods_ignore_error(modify_context *mc, Slapi_Mods *smods, int error); + + /* + * add.c +diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c +index 6339a6f..58a9d51 100644 +--- a/ldap/servers/slapd/entry.c ++++ b/ldap/servers/slapd/entry.c +@@ -3259,6 +3259,12 @@ int slapi_entry_apply_mod( Slapi_Entry *e, LDAPMod *mod ) + int + entry_apply_mods( Slapi_Entry *e, LDAPMod **mods ) + { ++ return entry_apply_mods_ignore_error(e, mods, -1); ++} ++ ++int ++entry_apply_mods_ignore_error( Slapi_Entry *e, LDAPMod **mods, int ignore_error ) ++{ + int err; + LDAPMod **mp = NULL; + +@@ -3268,7 +3274,9 @@ entry_apply_mods( Slapi_Entry *e, LDAPMod **mods ) + for ( mp = mods; mp && *mp; mp++ ) + { + err = entry_apply_mod( e, *mp ); +- if ( err != LDAP_SUCCESS ) { ++ if(err == ignore_error){ ++ (*mp)->mod_op = LDAP_MOD_IGNORE; ++ } else if ( err != LDAP_SUCCESS ) { + break; + } + } +diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h +index f7b4d04..ddeac62 100644 +--- a/ldap/servers/slapd/slapi-private.h ++++ b/ldap/servers/slapd/slapi-private.h +@@ -331,7 +331,7 @@ int entry_next_deleted_attribute( const Slapi_Entry *e, Slapi_Attr **a); + /* entry.c */ + int entry_apply_mods( Slapi_Entry *e, LDAPMod **mods ); + int is_type_protected(const char *type); +- ++int entry_apply_mods_ignore_error( Slapi_Entry *e, LDAPMod **mods, int ignore_error ); + int slapi_entries_diff(Slapi_Entry **old_entries, Slapi_Entry **new_entries, int testall, const char *logging_prestr, const int force_update, void *plg_id); + + /* entrywsi.c */ +-- +1.7.11.7 + diff --git a/0018-Ticket-526-Coverity-Fixes.patch b/0018-Ticket-526-Coverity-Fixes.patch new file mode 100644 index 0000000..4a959a7 --- /dev/null +++ b/0018-Ticket-526-Coverity-Fixes.patch @@ -0,0 +1,74 @@ +From 0ddb8ba7b42403f679b2269087fd39aa322cb1ec Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 26 Nov 2012 11:04:36 -0500 +Subject: [PATCH 18/22] Ticket 526 - Coverity Fixes + +12626 +13030 +13114 +13115 +13116 + +Reviewed by: richm (Thanks Rich!) +(cherry picked from commit 4850b2720a6d2a1cf65b2cbfa296e37f04f85c5d) +(cherry picked from commit 7d22bc2eca8d71ac212879fb28d39c8a31a7be58) +--- + ldap/servers/plugins/replication/cl5_api.c | 3 --- + ldap/servers/plugins/replication/repl5_replica_config.c | 6 ++++-- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c +index 6c94b3d..175eb80 100644 +--- a/ldap/servers/plugins/replication/cl5_api.c ++++ b/ldap/servers/plugins/replication/cl5_api.c +@@ -6554,9 +6554,6 @@ cl5CleanRUV(ReplicaId rid){ + ruv_delete_replica(file->maxRUV, rid); + obj = objset_next_obj(s_cl5Desc.dbFiles, obj); + } +- if(obj){ +- object_release (obj); +- } + + slapi_rwlock_unlock (s_cl5Desc.stLock); + } +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 0fd785b..e234c15 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -1743,7 +1743,7 @@ check_replicas_are_done_cleaning(cleanruv_data *data ) + { + Object *agmt_obj; + Repl_Agmt *agmt; +- char csnstr[CSN_STRSIZE]; ++ char *csnstr = NULL; + char *filter = NULL; + int not_all_cleaned = 1; + int interval = 10; +@@ -1786,6 +1786,7 @@ check_replicas_are_done_cleaning(cleanruv_data *data ) + interval = 14400; + } + } ++ slapi_ch_free_string(&csnstr); + slapi_ch_free_string(&filter); + } + +@@ -2356,7 +2357,7 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + struct berval *vals[2]; + struct berval val; + char data[CSN_STRSIZE + 15]; +- char csnstr[CSN_STRSIZE]; ++ char *csnstr = NULL; + char *dn; + int rc; + +@@ -2399,6 +2400,7 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + } + slapi_pblock_destroy (pb); + slapi_ch_free_string(&dn); ++ slapi_ch_free_string(&csnstr); + } + + /* +-- +1.7.11.7 + diff --git a/0019-Ticket-20-Allow-automember-to-work-on-entries-that-h.patch b/0019-Ticket-20-Allow-automember-to-work-on-entries-that-h.patch new file mode 100644 index 0000000..3d7f1fc --- /dev/null +++ b/0019-Ticket-20-Allow-automember-to-work-on-entries-that-h.patch @@ -0,0 +1,236 @@ +From db6a42a3ea5f6773e0e4e350211f7fc5b2b342d2 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 27 Nov 2012 10:24:02 -0500 +Subject: [PATCH 19/22] Ticket 20 - Allow automember to work on entries that + have already been added + +Bug Description: If the server can not open a ldif for reading(mapping task), an + incorrect error and file name is returned. + +Fix Description: Report the correct file name, and correctly grab the OS error/string. + Also made slapd_pr_strerr() and slapd_system_strerr() public, so I + refactored the function names to be "slapi_" - so a lot of files are + touched but the main change for this ticket is still in automember.c + +https://fedorahosted.org/389/ticket/20 + +Reviewed by: richm(Thanks) +(cherry picked from commit bf2bfaab8e61f335442e4341ff33521a822bd830) +--- + ldap/servers/plugins/automember/automember.c | 44 +++++++++------- + ldap/servers/slapd/errormap.c | 10 ++++ + ldap/servers/slapd/slapi-plugin.h | 75 ++++++++++++++++++++++++++++ + 3 files changed, 111 insertions(+), 18 deletions(-) + +diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c +index a11909f..424b507 100644 +--- a/ldap/servers/plugins/automember/automember.c ++++ b/ldap/servers/plugins/automember/automember.c +@@ -2333,6 +2333,7 @@ void automember_export_task_thread(void *arg){ + task_data *td = NULL; + PRFileDesc *ldif_fd; + int i = 0; ++ int rc = 0; + + td = (task_data *)slapi_task_get_data(task); + slapi_task_begin(task, 1); +@@ -2341,13 +2342,14 @@ void automember_export_task_thread(void *arg){ + + /* make sure we can open the ldif file */ + if (( ldif_fd = PR_Open( td->ldif_out, PR_CREATE_FILE | PR_WRONLY, DEFAULT_FILE_MODE )) == NULL ){ +- slapi_task_log_notice(task, "Automember export task could not open ldif file \"%s\" for writing %d\n", +- td->ldif_out, PR_GetError() ); +- slapi_task_log_status(task, "Automember export task could not open ldif file \"%s\" for writing %d\n", +- td->ldif_out, PR_GetError() ); ++ rc = PR_GetOSError(); ++ slapi_task_log_notice(task, "Automember export task could not open ldif file \"%s\" for writing, error %d (%s)\n", ++ td->ldif_out, rc, slapi_system_strerror(rc)); ++ slapi_task_log_status(task, "Automember export task could not open ldif file \"%s\" for writing, error %d (%s)\n", ++ td->ldif_out, rc, slapi_system_strerror(rc) ); + slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM, +- "Could not open ldif file \"%s\" for writing %d\n", +- td->ldif_out, PR_GetError() ); ++ "Could not open ldif file \"%s\" for writing, error %d (%s)\n", ++ td->ldif_out, rc, slapi_system_strerror(rc) ); + result = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } +@@ -2516,6 +2518,7 @@ void automember_map_task_thread(void *arg){ + task_data *td = NULL; + PRFileDesc *ldif_fd_out = NULL; + char *entrystr = NULL; ++ char *errstr = NULL; + #if defined(USE_OPENLDAP) + int buflen = 0; + LDIFFP *ldif_fd_in = NULL; +@@ -2534,29 +2537,34 @@ void automember_map_task_thread(void *arg){ + + /* make sure we can open the ldif files */ + if(( ldif_fd_out = PR_Open( td->ldif_out, PR_CREATE_FILE | PR_WRONLY, DEFAULT_FILE_MODE )) == NULL ){ +- slapi_task_log_notice(task, "The ldif file %s could not be accessed, error %d. Aborting task.\n", +- td->ldif_out, rc); +- slapi_task_log_status(task, "The ldif file %s could not be accessed, error %d. Aborting task.\n", +- td->ldif_out, rc); ++ rc = PR_GetOSError(); ++ slapi_task_log_notice(task, "The ldif file %s could not be accessed, error %d (%s). Aborting task.\n", ++ td->ldif_out, rc, slapi_system_strerror(rc)); ++ slapi_task_log_status(task, "The ldif file %s could not be accessed, error %d (%s). Aborting task.\n", ++ td->ldif_out, rc, slapi_system_strerror(rc)); + slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM, +- "Could not open ldif file \"%s\" for writing %d\n", +- td->ldif_out, PR_GetError() ); ++ "Could not open ldif file \"%s\" for writing, error %d (%s)\n", ++ td->ldif_out, rc, slapi_system_strerror(rc) ); + result = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } + + #if defined(USE_OPENLDAP) + if(( ldif_fd_in = ldif_open(td->ldif_in, "r")) == NULL ){ ++ rc = errno; ++ errstr = strerror(rc); + #else + if(( ldif_fd_in = PR_Open( td->ldif_in, PR_RDONLY, DEFAULT_FILE_MODE )) == NULL ){ ++ rc = PR_GetOSError(); ++ errstr = slapi_system_strerror(rc); + #endif +- slapi_task_log_notice(task, "The ldif file %s could not be accessed, error %d. Aborting task.\n", +- td->ldif_in, rc); +- slapi_task_log_status(task, "The ldif file %s could not be accessed, error %d. Aborting task.\n", +- td->ldif_in, rc); ++ slapi_task_log_notice(task, "The ldif file %s could not be accessed, error %d (%s). Aborting task.\n", ++ td->ldif_in, rc, errstr); ++ slapi_task_log_status(task, "The ldif file %s could not be accessed, error %d (%s). Aborting task.\n", ++ td->ldif_in, rc, errstr); + slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM, +- "Could not open ldif file \"%s\" for reading %d\n", +- td->ldif_out, PR_GetError() ); ++ "Could not open ldif file \"%s\" for reading, error %d (%s)\n", ++ td->ldif_in, rc, errstr ); + result = SLAPI_DSE_CALLBACK_ERROR; + goto out; + } +diff --git a/ldap/servers/slapd/errormap.c b/ldap/servers/slapd/errormap.c +index d05e495..c585d25 100644 +--- a/ldap/servers/slapd/errormap.c ++++ b/ldap/servers/slapd/errormap.c +@@ -73,6 +73,11 @@ slapd_pr_strerror( const int prerrno ) + return( s ); + } + ++char * ++slapi_pr_strerror( const int prerrno ) ++{ ++ return slapd_pr_strerror(prerrno); ++} + + /* + * return the string equivalent of a system error +@@ -92,6 +97,11 @@ slapd_system_strerror( const int syserrno ) + return( s ); + } + ++const char * ++slapi_system_strerror( const int syserrno ) ++{ ++ return slapd_system_strerror(syserrno); ++} + + /* + * return the string equivalent of an NSPR error. If "prerrno" is not +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h +index 4316833..4962b2a 100644 +--- a/ldap/servers/slapd/slapi-plugin.h ++++ b/ldap/servers/slapd/slapi-plugin.h +@@ -65,6 +65,7 @@ extern "C" { + #include "prtypes.h" + #include "ldap.h" + #include "prprf.h" ++#include "nspr.h" + NSPR_API(PRUint32) PR_snprintf(char *out, PRUint32 outlen, const char *fmt, ...) + #ifdef __GNUC__ + __attribute__ ((format (printf, 3, 4))); +@@ -7156,6 +7157,80 @@ uint64_t slapi_str_to_u64(const char *s); + + void slapi_set_plugin_open_rootdn_bind(Slapi_PBlock *pb); + ++/* ++ * Public entry extension getter/setter functions ++ * ++ * Currently, only slapi_pw_get/set_entry_ext is implemented. ++ * The functions are in pw.c. Detailed usage of the factory ++ * is found in the comments at the top of factory.c. ++ * ++ * When you plan to add other entry extension code AND ++ * the type-value pair is managed via ordinary mod, ++ * setter, getter and copy function having the same API ++ * are supposed to be implemented, then add the set to ++ * attrs_in_extension list in entry.c. The set is called ++ * in slapi_entry_apply_mod_extension. ++ * ++ * Note: setter and getter are public, but copy function ++ * is not. (for the copy function, see pw_copy_entry_ext in pw.c) ++ */ ++/* operation used in the entry extension setter */ ++#define SLAPI_EXT_SET_ADD 0 ++#define SLAPI_EXT_SET_REPLACE 1 ++ ++/** ++ * Get entry extension ++ * ++ * \param entry is the entry to retrieve the extension from ++ * \param vals is the array of (Slapi_Value *), which directly refers the extension. Caller must duplicate it to use it for other than referring. ++ * ++ * \return LDAP_SUCCESS if successful. ++ * \return non-zero otherwise. ++ */ ++int slapi_pw_get_entry_ext(Slapi_Entry *entry, Slapi_Value ***vals); ++ ++/** ++ * Set entry extension ++ * ++ * \param entry is the entry to set the extension to ++ * \param vals is the array of (Slapi_Value *), which is consumed in slapi_pw_set_ext if the call is successful. ++ * \param flags: SLAPI_EXT_SET_ADD -- add vals to the existing extension if any. ++ * SLAPI_EXT_SET_REPLACE -- replace vals with the existing extension if any. ++ * No difference if there is no extension in the entry. ++ * ++ * \return LDAP_SUCCESS if successful. ++ * \return non-zero otherwise. ++ */ ++int slapi_pw_set_entry_ext(Slapi_Entry *entry, Slapi_Value **vals, int flags); ++ ++/** ++ * Get stashed clear password. ++ * If multiple of them are in the extension, the first one is returned. ++ * ++ * \param entry is the entry to retrieve the extension from ++ * ++ * \return a pointer to the clear password string. Caller is responsible to free the string. ++ */ ++char *slapi_get_first_clear_text_pw(Slapi_Entry *entry); ++ ++/** ++ * Return the string equivalent of an NSPR error ++ * * ++ * \param a NSPR error code ++ * ++ * \return a pointer to the error code string. ++ */ ++char *slapi_pr_strerror( const PRErrorCode prerrno ); ++ ++/** ++ * Return the string equivalent of an OS error ++ * ++ * \param a OS error code ++ * ++ * \return a pointer to the system error code string. ++ */ ++const char *slapi_system_strerror( const int syserrno ); ++ + #ifdef __cplusplus + } + #endif +-- +1.7.11.7 + diff --git a/0020-Ticket-216-disable-replication-agreements.patch b/0020-Ticket-216-disable-replication-agreements.patch new file mode 100644 index 0000000..e4cbccf --- /dev/null +++ b/0020-Ticket-216-disable-replication-agreements.patch @@ -0,0 +1,35 @@ +From 7617746008bd2ebff36a6633ac7a175512db5979 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 29 Nov 2012 10:49:33 -0500 +Subject: [PATCH 20/22] Ticket 216 - disable replication agreements + +Bug Description: Objectclass violation when trying to add "nsds5ReplicaEnabled" + to a winSync agmt. + +Fix Description: Add this attribute to the "MAY" list for objectclass: nsDSWindowsReplicationAgreement + +https://fedorahosted.org/389/ticket/216 + +Reviewed by: richm(Thanks) +(cherry picked from commit b3a2f4010d4eae7bd62a0c09576b1a643eca3901) +(cherry picked from commit 77f126b85db760f0ad8e56575a8bac135b15fe49) +--- + ldap/schema/02common.ldif | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif +index c6cc6b8..ffec7ce 100644 +--- a/ldap/schema/02common.ldif ++++ b/ldap/schema/02common.ldif +@@ -180,7 +180,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.99 NAME 'cosSuperDefinition' DESC 'Netsca + objectClasses: ( 2.16.840.1.113730.3.2.100 NAME 'cosClassicDefinition' DESC 'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosTemplateDn $ cosspecifier ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.101 NAME 'cosPointerDefinition' DESC 'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosTemplateDn ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.102 NAME 'cosIndirectDefinition' DESC 'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosIndirectSpecifier ) X-ORIGIN 'Netscape Directory Server' ) +-objectClasses: ( 2.16.840.1.113730.3.2.503 NAME 'nsDSWindowsReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime $ nsds7WindowsReplicaSubtree $ nsds7DirectoryReplicaSubtree $ nsds7NewWinUserSyncEnabled $ nsds7NewWinGroupSyncEnabled $ nsds7WindowsDomain $ nsds7DirsyncCookie $ winSyncInterval $ oneWaySync $ winSyncMoveAction) X-ORIGIN 'Netscape Directory Server' ) ++objectClasses: ( 2.16.840.1.113730.3.2.503 NAME 'nsDSWindowsReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime $ nsds7WindowsReplicaSubtree $ nsds7DirectoryReplicaSubtree $ nsds7NewWinUserSyncEnabled $ nsds7NewWinGroupSyncEnabled $ nsds7WindowsDomain $ nsds7DirsyncCookie $ winSyncInterval $ oneWaySync $ winSyncMoveAction $ nsds5ReplicaEnabled ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.128 NAME 'costemplate' DESC 'Netscape defined objectclass' SUP top MAY ( cn $ cospriority ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.304 NAME 'nsView' DESC 'Netscape defined objectclass' SUP top AUXILIARY MAY ( nsViewFilter $ description ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.316 NAME 'nsAttributeEncryption' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsEncryptionAlgorithm ) X-ORIGIN 'Netscape Directory Server' ) +-- +1.7.11.7 + diff --git a/0021-Ticket-526-Coverity-Issues-for-1.2.11.patch b/0021-Ticket-526-Coverity-Issues-for-1.2.11.patch new file mode 100644 index 0000000..850b712 --- /dev/null +++ b/0021-Ticket-526-Coverity-Issues-for-1.2.11.patch @@ -0,0 +1,59 @@ +From 9ed455ca83f5a5c706d5ebab09fa4700e7da6c52 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 6 Dec 2012 11:41:29 -0500 +Subject: [PATCH 21/22] Ticket 526 - Coverity Issues for 1.2.11 + +Reviewed by: richm(Thanks!) +(cherry picked from commit 39b0938b43a5dbfdc566b343e504585bad7de859) +--- + ldap/servers/plugins/memberof/memberof.c | 7 +++++++ + ldap/servers/slapd/back-ldbm/dblayer.c | 2 ++ + lib/libaccess/acltools.cpp | 1 + + 3 files changed, 10 insertions(+) + +diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c +index 598f4d9..a3f875d 100644 +--- a/ldap/servers/plugins/memberof/memberof.c ++++ b/ldap/servers/plugins/memberof/memberof.c +@@ -1105,6 +1105,13 @@ memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config, + const char *op_this = slapi_sdn_get_ndn(op_this_sdn); + Slapi_Value *to_dn_val = slapi_value_new_string(op_to); + Slapi_Value *this_dn_val = slapi_value_new_string(op_this); ++ ++ if(this_dn_val == NULL || to_dn_val == NULL){ ++ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, ++ "memberof_modop_one_replace_r: failed to get DN values (NULL)\n"); ++ goto bail; ++ } ++ + /* op_this and op_to are both case-normalized */ + slapi_value_set_flags(this_dn_val, SLAPI_ATTR_FLAG_NORMALIZED_CIS); + slapi_value_set_flags(to_dn_val, SLAPI_ATTR_FLAG_NORMALIZED_CIS); +diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c +index 5452d6b..2fd2110 100644 +--- a/ldap/servers/slapd/back-ldbm/dblayer.c ++++ b/ldap/servers/slapd/back-ldbm/dblayer.c +@@ -1910,6 +1910,8 @@ dblayer_get_id2entry_size(ldbm_instance *inst) + ID2ENTRY LDBM_FILENAME_SUFFIX); + rc = PR_GetFileInfo(id2entry_file, &info); + slapi_ch_free_string(&id2entry_file); ++ if (inst_dirp != inst_dir) ++ slapi_ch_free_string(&inst_dirp); + if (rc) { + return 0; + } +diff --git a/lib/libaccess/acltools.cpp b/lib/libaccess/acltools.cpp +index 69d0c2e..df08658 100644 +--- a/lib/libaccess/acltools.cpp ++++ b/lib/libaccess/acltools.cpp +@@ -1415,6 +1415,7 @@ char *errmsg; + eid = ACLERR1500; + errmsg = system_errmsg(); + nserrGenerate(errp, rv, eid, ACL_Program, 2, "buffer", errmsg); ++ PERM_FREE(errmsg); + } + + } +-- +1.7.11.7 + diff --git a/0022-Ticket-527-ns-slapd-segfaults-if-it-cannot-rename-th.patch b/0022-Ticket-527-ns-slapd-segfaults-if-it-cannot-rename-th.patch new file mode 100644 index 0000000..d8d2f77 --- /dev/null +++ b/0022-Ticket-527-ns-slapd-segfaults-if-it-cannot-rename-th.patch @@ -0,0 +1,128 @@ +From 00e77c9c16be9f9cc10e6d5833e5e5ceb2ec61ad Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 6 Dec 2012 14:52:40 -0500 +Subject: [PATCH 22/22] Ticket 527 - ns-slapd segfaults if it cannot rename + the logs + +Bug Description: If we can not rename a log file, triggered by log rotation, + we try and log a message stating this error, but trying to + log this new message triggers log rotation again. This leads + to an infinite loop and a stack overflow. + +Fix Description: Created a new logging function that does not do a rotation check. + We use this new function for all emergency error logging. + +https://fedorahosted.org/389/ticket/527 + +Reviewed by: richm(Thanks!) +(cherry picked from commit 4e9aab8a172c8636ea78a9d1230c78c76268efd7) +(cherry picked from commit 85261ef0161df156ea3991a77046aabda6c34cf4) +--- + ldap/servers/slapd/log.c | 63 ++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 53 insertions(+), 10 deletions(-) + +diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c +index e622485..e65b247 100644 +--- a/ldap/servers/slapd/log.c ++++ b/ldap/servers/slapd/log.c +@@ -138,6 +138,7 @@ static void log_append_buffer2(time_t tnl, LogBufferInfo *lbi, char *msg1, size_ + static void log_flush_buffer(LogBufferInfo *lbi, int type, int sync_now); + static void log_write_title(LOGFD fp); + static void log__error_emergency(const char *errstr, int reopen, int locked); ++static void vslapd_log_emergency_error(LOGFD fp, const char *msg, int locked); + + static int + slapd_log_error_proc_internal( +@@ -1834,6 +1835,57 @@ slapd_log_error_proc_internal( + return( rc ); + } + ++/* ++ * Directly write the already formatted message to the error log ++ */ ++static void ++vslapd_log_emergency_error(LOGFD fp, const char *msg, int locked) ++{ ++ time_t tnl; ++ long tz; ++ struct tm *tmsp, tms; ++ char tbuf[ TBUFSIZE ]; ++ char buffer[SLAPI_LOG_BUFSIZ]; ++ char sign; ++ int size; ++ ++ tnl = current_time(); ++#ifdef _WIN32 ++ { ++ struct tm *pt = localtime( &tnl ); ++ tmsp = &tms; ++ memcpy(&tms, pt, sizeof(struct tm) ); ++ } ++#else ++ (void)localtime_r( &tnl, &tms ); ++ tmsp = &tms; ++#endif ++#ifdef BSD_TIME ++ tz = tmsp->tm_gmtoff; ++#else /* BSD_TIME */ ++ tz = - timezone; ++ if ( tmsp->tm_isdst ) { ++ tz += 3600; ++ } ++#endif /* BSD_TIME */ ++ sign = ( tz >= 0 ? '+' : '-' ); ++ if ( tz < 0 ) { ++ tz = -tz; ++ } ++ (void)strftime( tbuf, (size_t)TBUFSIZE, "%d/%b/%Y:%H:%M:%S", tmsp); ++ sprintf( buffer, "[%s %c%02d%02d] - %s", tbuf, sign, (int)( tz / 3600 ), (int)( tz % 3600 ), msg); ++ size = strlen(buffer); ++ ++ if(!locked) ++ LOG_ERROR_LOCK_WRITE(); ++ ++ slapi_write_buffer((fp), (buffer), (size)); ++ PR_Sync(fp); ++ ++ if(!locked) ++ LOG_ERROR_UNLOCK_WRITE(); ++} ++ + static int + vslapd_log_error( + LOGFD fp, +@@ -3102,9 +3154,6 @@ char rootpath[4]; + PR_snprintf(buffer, sizeof(buffer), + "log__enough_freespace: Unable to get the free space (errno:%d)\n", + errno); +- /* This function could be called in the ERROR WRITE LOCK, +- * which causes the self deadlock if you call LDAPDebug for logging. +- * Thus, instead of LDAPDebug, call log__error_emergency with locked == 1. */ + log__error_emergency(buffer, 0, 1); + return 1; + } else { +@@ -3351,9 +3400,6 @@ delete_logfile: + PR_snprintf (buffer, sizeof(buffer), "%s.%s", loginfo.log_error_file, tbuf); + if (PR_Delete(buffer) != PR_SUCCESS) { + PRErrorCode prerr = PR_GetError(); +- /* This function could be called in the ERROR WRITE LOCK, +- * which causes the self deadlock if you call LDAPDebug for logging. +- * Thus, instead of LDAPDebug, call log__error_emergency with locked == 1. */ + PR_snprintf(buffer, sizeof(buffer), + "LOGINFO:Unable to remove file:%s.%s error %d (%s)\n", + loginfo.log_error_file, tbuf, prerr, slapd_pr_strerror(prerr)); +@@ -3713,10 +3759,7 @@ log__error_emergency(const char *errstr, int reopen, int locked) + PRErrorCode prerr = PR_GetError(); + syslog(LOG_ERR, "Failed to reopen errors log file, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", prerr, slapd_pr_strerror(prerr)); + } else { +- /* LDAPDebug locks ERROR_LOCK_WRITE internally */ +- if (locked) LOG_ERROR_UNLOCK_WRITE(); +- LDAPDebug(LDAP_DEBUG_ANY, "%s\n", errstr, 0, 0); +- if (locked) LOG_ERROR_LOCK_WRITE( ); ++ vslapd_log_emergency_error(loginfo.log_error_fdes, errstr, locked); + } + return; + } +-- +1.7.11.7 + diff --git a/0023-Ticket-541-RootDN-Access-Control-plugin-is-missing-a.patch b/0023-Ticket-541-RootDN-Access-Control-plugin-is-missing-a.patch new file mode 100644 index 0000000..90bf4df --- /dev/null +++ b/0023-Ticket-541-RootDN-Access-Control-plugin-is-missing-a.patch @@ -0,0 +1,67 @@ +From 7fd5f3859be9c0c266201dd76853f82cb74ffe9e Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 18 Dec 2012 15:58:32 -0500 +Subject: [PATCH 23/24] Ticket 541 - RootDN Access Control plugin is missing after upgrade + +Created the upgrade ldif: 50rootdnaccesscontrolplugin.ldif + +https://fedorahosted.org/389/ticket/541 + +Reviewed by: richm(Thanks) +(cherry picked from commit 9a7fa90eed49f47aa0bc64c496815fececb437f2) +--- + Makefile.am | 1 + + Makefile.in | 1 + + .../src/scripts/50rootdnaccesscontrolplugin.ldif | 16 ++++++++++++++++ + 3 files changed, 18 insertions(+), 0 deletions(-) + create mode 100644 ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif + +diff --git a/Makefile.am b/Makefile.am +index 507a2d6..9ad2c3a 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -489,6 +489,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \ + ldap/admin/src/scripts/50faxsyntaxplugin.ldif \ + ldap/admin/src/scripts/50fixNsState.pl \ + ldap/admin/src/scripts/50telexnumbersyntaxplugin.ldif \ ++ ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif \ + ldap/admin/src/scripts/50guidesyntaxplugin.ldif \ + ldap/ldif/50replication-plugins.ldif \ + ldap/admin/src/scripts/50linkedattrsplugin.ldif \ +diff --git a/Makefile.in b/Makefile.in +index f105932..f731cfb 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -1715,6 +1715,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \ + ldap/admin/src/scripts/50faxsyntaxplugin.ldif \ + ldap/admin/src/scripts/50fixNsState.pl \ + ldap/admin/src/scripts/50telexnumbersyntaxplugin.ldif \ ++ ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif \ + ldap/admin/src/scripts/50guidesyntaxplugin.ldif \ + ldap/ldif/50replication-plugins.ldif \ + ldap/admin/src/scripts/50linkedattrsplugin.ldif \ +diff --git a/ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif b/ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif +new file mode 100644 +index 0000000..1b5e8b0 +--- /dev/null ++++ b/ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif +@@ -0,0 +1,16 @@ ++dn: cn=RootDN Access Control,cn=plugins,cn=config ++objectclass: top ++objectclass: nsSlapdPlugin ++objectclass: extensibleObject ++cn: RootDN Access Control ++nsslapd-pluginpath: librootdn-access-plugin.so ++nsslapd-plugininitfunc: rootdn_init ++nsslapd-plugintype: internalpreoperation ++nsslapd-pluginenabled: on ++nsslapd-plugin-depends-on-type: database ++# these will be replaced when the server loads the plugin ++nsslapd-pluginId: ID ++nsslapd-pluginVersion: PACKAGE_VERSION ++nsslapd-pluginVendor: VENDOR ++nsslapd-pluginDescription: DESC ++ +-- +1.7.1 + diff --git a/0024-Ticket-541-need-to-set-plugin-as-off-in-ldif-templat.patch b/0024-Ticket-541-need-to-set-plugin-as-off-in-ldif-templat.patch new file mode 100644 index 0000000..0de339a --- /dev/null +++ b/0024-Ticket-541-need-to-set-plugin-as-off-in-ldif-templat.patch @@ -0,0 +1,28 @@ +From 9484b6ca1be77a69b7675b96c1cf645cffcbbf2e Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 18 Dec 2012 16:04:01 -0500 +Subject: [PATCH 24/24] Ticket 541 - need to set plugin as off in ldif template + +Reviewed by: richm(Thanks) +(cherry picked from commit 1f7195980fa7073f88ba04fce74b62b07e43e143) +(cherry picked from commit d324d6782f74b7e28f7a457428fe43c77b39944c) +--- + .../src/scripts/50rootdnaccesscontrolplugin.ldif | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif b/ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif +index 1b5e8b0..74e23f4 100644 +--- a/ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif ++++ b/ldap/admin/src/scripts/50rootdnaccesscontrolplugin.ldif +@@ -6,7 +6,7 @@ cn: RootDN Access Control + nsslapd-pluginpath: librootdn-access-plugin.so + nsslapd-plugininitfunc: rootdn_init + nsslapd-plugintype: internalpreoperation +-nsslapd-pluginenabled: on ++nsslapd-pluginenabled: off + nsslapd-plugin-depends-on-type: database + # these will be replaced when the server loads the plugin + nsslapd-pluginId: ID +-- +1.7.1 + diff --git a/0025-Ticket-549-DNA-plugin-no-longer-reports-additional-i.patch b/0025-Ticket-549-DNA-plugin-no-longer-reports-additional-i.patch new file mode 100644 index 0000000..482358f --- /dev/null +++ b/0025-Ticket-549-DNA-plugin-no-longer-reports-additional-i.patch @@ -0,0 +1,120 @@ +From e7c1daf76b8c443b848ea988c3772f2be41eed0c Mon Sep 17 00:00:00 2001 +From: Nathan Kinder +Date: Fri, 4 Jan 2013 11:41:48 -0800 +Subject: [PATCH] Ticket 549 - DNA plugin no longer reports additional info + when range is depleted + +When the DNA plug-in was modified to allocate range values at the +bepreop phase, it stopped returning detailed error strings to the +client when the range was depleted. + +This patch allows our bepreop functions to fill in the error string +that the caller can return to the client. +(cherry picked from commit 3b177a768a48857f9dcb891a7dd3c8f8d9a220a4) +--- + ldap/servers/plugins/dna/dna.c | 32 ++++++++++++++++++++++++++++---- + 1 file changed, 28 insertions(+), 4 deletions(-) + +diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c +index 66d4a05..36dd936 100644 +--- a/ldap/servers/plugins/dna/dna.c ++++ b/ldap/servers/plugins/dna/dna.c +@@ -2759,7 +2759,7 @@ dna_create_valcheck_filter(struct configEntry *config_entry, PRUint64 value, cha + /* This function is called at BEPREOP timing to add uid/gidNumber + * if modtype is missing */ + static int +-_dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e) ++_dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e, char **errstr) + { + int ret = 0; + PRCList *list = NULL; +@@ -2886,6 +2886,10 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e) + if (LDAP_SUCCESS != ret) { + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_pre_op: no more values available!!\n"); ++ /* Set an error string to be returned to the client. */ ++ *errstr = slapi_ch_smprintf("Allocation of a new value for range" ++ " %s failed! Unable to proceed.", ++ config_entry->dn); + slapi_unlock_mutex(config_entry->lock); + break; + } +@@ -2895,6 +2899,10 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e) + if (LDAP_SUCCESS != ret){ + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_pre_op: failed to allocate a new ID\n"); ++ /* Set an error string to be returned to the client. */ ++ *errstr = slapi_ch_smprintf("Allocation of a new value for range" ++ " %s failed! Unable to proceed.", ++ config_entry->dn); + slapi_unlock_mutex(config_entry->lock); + break; + } +@@ -2902,6 +2910,10 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e) + /* dna_first_free_value() failed for some unknown reason */ + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_pre_op: failed to allocate a new ID!!\n"); ++ /* Set an error string to be returned to the client. */ ++ *errstr = slapi_ch_smprintf("Allocation of a new value for range" ++ " %s failed! Unable to proceed.", ++ config_entry->dn); + slapi_unlock_mutex(config_entry->lock); + break; + } +@@ -2943,7 +2955,7 @@ bail: + /* This function is called at BEPREOP timing to add uid/gidNumber + * if modtype is missing */ + static int +-_dna_pre_op_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Mods *smods) ++_dna_pre_op_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Mods *smods, char **errstr) + { + int ret = 0; + PRCList *list = NULL; +@@ -3144,6 +3156,10 @@ _dna_pre_op_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Mods *smods) + if (LDAP_SUCCESS != ret) { + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_pre_op: no more values available!!\n"); ++ /* Set an error string to be returned to the client. */ ++ *errstr = slapi_ch_smprintf("Allocation of a new value for range" ++ " %s failed! Unable to proceed.", ++ config_entry->dn); + slapi_unlock_mutex(config_entry->lock); + break; + } +@@ -3153,6 +3169,10 @@ _dna_pre_op_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Mods *smods) + if (LDAP_SUCCESS != ret){ + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_pre_op: failed to allocate a new ID\n"); ++ /* Set an error string to be returned to the client. */ ++ *errstr = slapi_ch_smprintf("Allocation of a new value for range" ++ " %s failed! Unable to proceed.", ++ config_entry->dn); + slapi_unlock_mutex(config_entry->lock); + break; + } +@@ -3160,6 +3180,10 @@ _dna_pre_op_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Mods *smods) + /* dna_first_free_value() failed for some unknown reason */ + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_pre_op: failed to allocate a new ID!!\n"); ++ /* Set an error string to be returned to the client. */ ++ *errstr = slapi_ch_smprintf("Allocation of a new value for range" ++ " %s failed! Unable to proceed.", ++ config_entry->dn); + slapi_unlock_mutex(config_entry->lock); + break; + } +@@ -3287,9 +3311,9 @@ dna_pre_op(Slapi_PBlock * pb, int modtype) + } + } else { + if (LDAP_CHANGETYPE_ADD == modtype) { +- ret = _dna_pre_op_add(pb, test_e); ++ ret = _dna_pre_op_add(pb, test_e, &errstr); + } else { +- if((ret = _dna_pre_op_modify(pb, test_e, smods))){ ++ if((ret = _dna_pre_op_modify(pb, test_e, smods, &errstr))){ + slapi_mods_free(&smods); + } + } +-- +1.7.11.7 + diff --git a/0026-Ticket-495-1.2.11-plugin-dn-is-missing-from-pblock.patch b/0026-Ticket-495-1.2.11-plugin-dn-is-missing-from-pblock.patch new file mode 100644 index 0000000..17d1cbf --- /dev/null +++ b/0026-Ticket-495-1.2.11-plugin-dn-is-missing-from-pblock.patch @@ -0,0 +1,38 @@ +From ac613f043328a027c13bdc24965062734d56002c Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 7 Jan 2013 14:55:29 -0500 +Subject: [PATCH] Ticket 495 - 1.2.11 - plugin dn is missing from pblock + +Bug Description: on 1.2.11 when setting the backend in the pblock we do not + set the plugin dn if its missing. This causes inconsistencies + with internalModifiersname and internalcreatorsname. + +Fix description: Set the plugin dn of the plugin if it is missing when setting the + backend in the pblock. + +https://fedorahosted.org/389/ticket/495 + +Reviewed by: ? +(cherry picked from commit d47fd4bc965e597c8d27368aa546d4012ce2546e) +--- + ldap/servers/slapd/pblock.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c +index 33559a7..1d1db1e 100644 +--- a/ldap/servers/slapd/pblock.c ++++ b/ldap/servers/slapd/pblock.c +@@ -1966,6 +1966,10 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value ) + switch ( arg ) { + case SLAPI_BACKEND: + pblock->pb_backend = (Slapi_Backend *) value; ++ if (pblock->pb_backend && (NULL == pblock->pb_plugin)) { ++ /* newly allocated pblock may not have backend plugin set. */ ++ pblock->pb_plugin = (struct slapdplugin *)pblock->pb_backend->be_database; ++ } + break; + case SLAPI_BACKEND_COUNT: + pblock->pb_backend_count = *((int *) value); +-- +1.7.11.7 + diff --git a/0027-Ticket-556-Don-t-overwrite-certmap.conf-during-upgra.patch b/0027-Ticket-556-Don-t-overwrite-certmap.conf-during-upgra.patch new file mode 100644 index 0000000..d524a6b --- /dev/null +++ b/0027-Ticket-556-Don-t-overwrite-certmap.conf-during-upgra.patch @@ -0,0 +1,44 @@ +From cfbe748bcf3d2e2a2903737ff3834bad05c96998 Mon Sep 17 00:00:00 2001 +From: Nathan Kinder +Date: Wed, 16 Jan 2013 14:20:14 -0800 +Subject: [PATCH] Ticket 556 - Don't overwrite certmap.conf during upgrade + +The certmap.conf config files were being overwritten with the +default template during upgrade. We need to skip writing the +certmap.conf files if they already exist so config changes are +not lost. +(cherry picked from commit e63ad6840e4a9a62f3ffae27eaba1091653a1c50) +--- + ldap/admin/src/scripts/DSCreate.pm.in | 16 ++++++++++------ + 1 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/ldap/admin/src/scripts/DSCreate.pm.in b/ldap/admin/src/scripts/DSCreate.pm.in +index 1d5e71a..0acd74f 100644 +--- a/ldap/admin/src/scripts/DSCreate.pm.in ++++ b/ldap/admin/src/scripts/DSCreate.pm.in +@@ -482,12 +482,16 @@ sub makeOtherConfigFiles { + my $src = "$inf->{General}->{prefix}@configdir@/certmap.conf"; + my $dest = "$inf->{slapd}->{config_dir}/certmap.conf"; + $! = 0; # clear errno +- copy($src, $dest); +- if ($!) { +- return ('error_copying_file', $src, $dest, $!); +- } +- if (@errs = changeOwnerMode($inf, 4, $dest)) { +- return @errs; ++ ++ #in skip mode, skip files that already exist ++ unless ($skip and -f $dest) { ++ copy($src, $dest); ++ if ($!) { ++ return ('error_copying_file', $src, $dest, $!); ++ } ++ if (@errs = changeOwnerMode($inf, 4, $dest)) { ++ return @errs; ++ } + } + + $src = "$inf->{General}->{prefix}@configdir@/slapd-collations.conf"; +-- +1.7.7.6 + diff --git a/0028-Ticket-572-PamConfig-schema-not-updated-during-upgra.patch b/0028-Ticket-572-PamConfig-schema-not-updated-during-upgra.patch new file mode 100644 index 0000000..4c87116 --- /dev/null +++ b/0028-Ticket-572-PamConfig-schema-not-updated-during-upgra.patch @@ -0,0 +1,34 @@ +From 75f4e59756e501eea33b611fa39c86ffec47e14b Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 5 Feb 2013 10:52:03 -0800 +Subject: [PATCH 28/33] Ticket #572 - PamConfig schema not updated during + upgrade + +Bug description: PAM passthrough schema was not upgraded in the +upgrade from 389-ds-base-1.2.10.2 to 389-ds-base-1.2.11.15. + +Fix description: This patch adds 60pam-plugin.ldif to the upgrade +schema file list. + +Reviewed by Nathan (Thank you!!) +(cherry picked from commit ac6b2c94bb32fc47870a56e8f7fc109ea81a3f47) +--- + ldap/admin/src/scripts/60upgradeschemafiles.pl | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/ldap/admin/src/scripts/60upgradeschemafiles.pl b/ldap/admin/src/scripts/60upgradeschemafiles.pl +index c308716..1208f4d 100644 +--- a/ldap/admin/src/scripts/60upgradeschemafiles.pl ++++ b/ldap/admin/src/scripts/60upgradeschemafiles.pl +@@ -11,7 +11,7 @@ sub runinst { + + # these schema files are obsolete, or we want to replace + # them with newer versions +- my @toremove = qw(00core.ldif 01core389.ldif 01common.ldif 02common.ldif 05rfc2247.ldif 05rfc4523.ldif 05rfc4524.ldif 06inetorgperson.ldif 10presence.ldif 28pilot.ldif 30ns-common.ldif 50ns-directory.ldif 60mozilla.ldif 60sudo.ldif); ++ my @toremove = qw(00core.ldif 01core389.ldif 01common.ldif 02common.ldif 05rfc2247.ldif 05rfc4523.ldif 05rfc4524.ldif 06inetorgperson.ldif 10presence.ldif 28pilot.ldif 30ns-common.ldif 50ns-directory.ldif 60mozilla.ldif 60pam-plugin.ldif 60sudo.ldif); + + # these hashes will be used to check for obsolete schema + # in 99user.ldif +-- +1.7.7.6 + diff --git a/0029-Bug-906005-Valgrind-reports-memleak-in-modify_update.patch b/0029-Bug-906005-Valgrind-reports-memleak-in-modify_update.patch new file mode 100644 index 0000000..5ad6c2e --- /dev/null +++ b/0029-Bug-906005-Valgrind-reports-memleak-in-modify_update.patch @@ -0,0 +1,50 @@ +From 7c1c79afd0147a03c7841fe6704421f4f52fee74 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 5 Feb 2013 13:53:11 -0800 +Subject: [PATCH 29/33] Bug 906005 - Valgrind reports memleak in + modify_update_last_modified_attr + +Fix description: plugin_get_dn returns plugin_dn, which is supposed +to be freed by the caller. This patch adds the free function to +modify_update_last_modified_attr, add_created_attrs and +add_internal_modifiersname. +--- + ldap/servers/slapd/add.c | 2 ++ + ldap/servers/slapd/opshared.c | 1 + + 2 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c +index 3206d5b..44a9aa2 100644 +--- a/ldap/servers/slapd/add.c ++++ b/ldap/servers/slapd/add.c +@@ -789,6 +789,7 @@ add_created_attrs(Slapi_PBlock *pb, Slapi_Entry *e) + } + slapi_entry_attr_replace(e, "internalCreatorsName", bvals); + slapi_entry_attr_replace(e, "internalModifiersName", bvals); ++ slapi_ch_free_string(&plugin_dn); + + /* Grab the thread data(binddn) */ + slapi_td_get_dn(&binddn); +@@ -1014,6 +1015,7 @@ add_internal_modifiersname(Slapi_PBlock *pb, Slapi_Entry *e) + plugin_dn = plugin_get_dn (plugin); + if(plugin_dn){ + slapi_entry_attr_set_charptr(e, "internalModifiersname", plugin_dn); ++ slapi_ch_free_string(&plugin_dn); + } + } + } +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index 485763e..fabe8a4 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -178,6 +178,7 @@ modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods) + } + slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, + "internalModifiersName", bvals); ++ slapi_ch_free_string(&plugin_dn); + + /* Grab the thread data(binddn) */ + slapi_td_get_dn(&binddn); +-- +1.7.7.6 + diff --git a/0030-Ticket-570-DS-returns-error-20-when-replacing-values.patch b/0030-Ticket-570-DS-returns-error-20-when-replacing-values.patch new file mode 100644 index 0000000..852bc66 --- /dev/null +++ b/0030-Ticket-570-DS-returns-error-20-when-replacing-values.patch @@ -0,0 +1,165 @@ +From 9b723851da58c9dc651de9b81b8beed58bff803e Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 5 Feb 2013 14:56:12 -0800 +Subject: [PATCH 30/33] Ticket 570 - DS returns error 20 when replacing values + of a multi-valued attribute (only when replication + is enabled) + +Bug Description: When replacing an attr value "SOME_VALUE" with "some_value", and replication + is enabled, an error 20(type or value exists) is incorrectly returned. + +Fix Description: For replace operations we were doing a bit-by-bit comparison. Ignoring the syntax + of the attribute. The fix was to remove this bit-by-bit check that is no longer + necessary with the current code base. + +https://fedorahosted.org/389/ticket/570 + +Reviewed by: ? +(cherry picked and fixed conflicts from commit 1c3bf98303c04323542251f1c564c8bdc4e8cc67) +--- + ldap/servers/slapd/attr.c | 95 ++++++++++++++--------------------------- + ldap/servers/slapd/entrywsi.c | 2 +- + ldap/servers/slapd/slap.h | 1 - + 3 files changed, 33 insertions(+), 65 deletions(-) + +diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c +index 2dc2a80..87dfe1e 100644 +--- a/ldap/servers/slapd/attr.c ++++ b/ldap/servers/slapd/attr.c +@@ -534,76 +534,45 @@ slapi_attr_flag_is_set( const Slapi_Attr *a, unsigned long flag ) + int + slapi_attr_value_cmp( const Slapi_Attr *a, const struct berval *v1, const struct berval *v2 ) + { +- int retVal; ++ Slapi_Attr a2 = *a; ++ struct ava ava; ++ Slapi_Value *cvals[2]; ++ Slapi_Value tmpcval; + +- if ( a->a_flags & SLAPI_ATTR_FLAG_CMP_BITBYBIT ) +- { +- int cmplen = ( v1->bv_len <= v2->bv_len ? v1->bv_len : v2->bv_len ); +- retVal = memcmp(v1->bv_val, v2->bv_val, cmplen); +- if ( retVal == 0 && v1->bv_len < v2->bv_len ) +- { +- retVal = -1; +- } +- else if ( retVal == 0 && v1->bv_len > v2->bv_len ) +- { +- retVal = 1; +- } +- } +- else +- { +- Slapi_Attr a2; +- struct ava ava; +- Slapi_Value *cvals[2]; +- Slapi_Value tmpcval; +- +- a2 = *a; +- cvals[0] = &tmpcval; +- cvals[0]->v_csnset = NULL; +- cvals[0]->bv = *v1; +- cvals[0]->v_flags = 0; +- cvals[1] = NULL; +- a2.a_present_values.va = cvals; /* JCM - PUKE */ +- ava.ava_type = a->a_type; +- ava.ava_value = *v2; +- ava.ava_private = NULL; +- retVal = plugin_call_syntax_filter_ava(&a2, LDAP_FILTER_EQUALITY, &ava); +- } +- return retVal; ++ cvals[0] = &tmpcval; ++ cvals[0]->v_csnset = NULL; ++ cvals[0]->bv = *v1; ++ cvals[0]->v_flags = 0; ++ cvals[1] = NULL; ++ a2.a_present_values.va = cvals; /* JCM - PUKE */ ++ ava.ava_type = a->a_type; ++ ava.ava_value = *v2; ++ ava.ava_private = NULL; ++ ++ return( plugin_call_syntax_filter_ava(&a2, LDAP_FILTER_EQUALITY, &ava)); + } + + int + slapi_attr_value_cmp_ext(const Slapi_Attr *a, Slapi_Value *v1, Slapi_Value *v2) + { +- int retVal; +- const struct berval *bv2 = slapi_value_get_berval(v2); ++ struct ava ava; ++ Slapi_Attr a2 = *a; ++ Slapi_Value *cvals[2]; ++ unsigned long v2_flags = v2->v_flags; ++ const struct berval *bv2 = slapi_value_get_berval(v2); ++ ++ cvals[0] = v1; ++ cvals[1] = NULL; ++ a2.a_present_values.va = cvals; ++ ava.ava_type = a->a_type; ++ ava.ava_value = *bv2; ++ if (v2_flags) { ++ ava.ava_private = &v2_flags; ++ } else { ++ ava.ava_private = NULL; ++ } + +- if ( a->a_flags & SLAPI_ATTR_FLAG_CMP_BITBYBIT ) +- { +- const struct berval *bv1 = slapi_value_get_berval(v1); +- return slapi_attr_value_cmp(a, bv1, bv2); +- } +- else +- { +- Slapi_Attr a2; +- struct ava ava; +- Slapi_Value *cvals[2]; +- unsigned long v2_flags = v2->v_flags; +- +- a2 = *a; +- cvals[0] = v1; +- cvals[1] = NULL; +- a2.a_present_values.va = cvals; /* JCM - PUKE */ +- +- ava.ava_type = a->a_type; +- ava.ava_value = *bv2; +- if (v2_flags) { +- ava.ava_private = &v2_flags; +- } else { +- ava.ava_private = NULL; +- } +- retVal = plugin_call_syntax_filter_ava(&a2, LDAP_FILTER_EQUALITY, &ava); +- } +- return retVal; ++ return (plugin_call_syntax_filter_ava(&a2, LDAP_FILTER_EQUALITY, &ava)); + } + + /* +diff --git a/ldap/servers/slapd/entrywsi.c b/ldap/servers/slapd/entrywsi.c +index 0419864..971e9e3 100644 +--- a/ldap/servers/slapd/entrywsi.c ++++ b/ldap/servers/slapd/entrywsi.c +@@ -709,7 +709,7 @@ entry_replace_present_values_wsi(Slapi_Entry *e, const char *type, struct berval + * slapi_entry_add_values() returns LDAP_SUCCESS and so the + * attribute remains deleted (which is the correct outcome). + */ +- return( entry_add_present_values_wsi( e, type, vals, csn, urp, SLAPI_ATTR_FLAG_CMP_BITBYBIT )); ++ return( entry_add_present_values_wsi( e, type, vals, csn, urp, 0)); + } + + /* +diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h +index e3cbc72..eea025a 100644 +--- a/ldap/servers/slapd/slap.h ++++ b/ldap/servers/slapd/slap.h +@@ -510,7 +510,6 @@ typedef struct asyntaxinfo { + if any */ + #define SLAPI_ATTR_FLAG_NOLOCKING 0x0020 /* the init code doesn't lock the + tables */ +-#define SLAPI_ATTR_FLAG_CMP_BITBYBIT 0x4000 /* do memcmp, not syntax cmp */ + #define SLAPI_ATTR_FLAG_KEEP 0x8000 /* keep when replacing all */ + + /* This is the type of the function passed into attr_syntax_enumerate_attrs */ +-- +1.7.7.6 + diff --git a/0031-Ticket-367-Invalid-chaining-config-triggers-a-disk-f.patch b/0031-Ticket-367-Invalid-chaining-config-triggers-a-disk-f.patch new file mode 100644 index 0000000..5ce0104 --- /dev/null +++ b/0031-Ticket-367-Invalid-chaining-config-triggers-a-disk-f.patch @@ -0,0 +1,301 @@ +From ecf7b877c158e79739845bcc6616821fc6e44535 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 11 May 2012 13:00:50 -0400 +Subject: [PATCH 31/33] Ticket 367 - Invalid chaining config triggers a disk + full error and shutdown + +Bug Description: If you use the root DN for the chaining bind DN a error -2 (LDAP_LOCAL_ERROR) + is returned from the callback. This is the same error code for SLAPI_FAIL_DISKFULL. + Once the error -2 is retuned, the server thinks we are out of disk space and the + instance is shutdown. + +Fix Description: Return -1, instead of -2(LDAP_LOCAL_ERROR) + +https://fedorahosted.org/389/ticket/367 + +Note: also did a little code cleanup with indentation + +Reviewed by: +(cherry picked from commit dc379838f8e4cfd2c736e8c2fb8366fb3b4f73d4) +--- + ldap/servers/plugins/chainingdb/cb_instance.c | 192 ++++++++++++------------- + 1 files changed, 92 insertions(+), 100 deletions(-) + +diff --git a/ldap/servers/plugins/chainingdb/cb_instance.c b/ldap/servers/plugins/chainingdb/cb_instance.c +index 9a33916..8fb694a 100644 +--- a/ldap/servers/plugins/chainingdb/cb_instance.c ++++ b/ldap/servers/plugins/chainingdb/cb_instance.c +@@ -511,15 +511,15 @@ int cb_instance_modify_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor + */ + + int +-cb_parse_instance_config_entry(cb_backend * cb, Slapi_Entry * e) { +- +- int rc =LDAP_SUCCESS; +- Slapi_Attr *attr = NULL; +- Slapi_Value *sval; +- const struct berval *attrValue; +- cb_backend_instance *inst=NULL; +- char *instname; +- char retmsg[CB_BUFSIZE]; ++cb_parse_instance_config_entry(cb_backend * cb, Slapi_Entry * e) ++{ ++ cb_backend_instance *inst = NULL; ++ Slapi_Attr *attr = NULL; ++ Slapi_Value *sval; ++ const struct berval *attrValue; ++ char *instname; ++ char retmsg[CB_BUFSIZE]; ++ int rc = LDAP_SUCCESS; + + CB_ASSERT(e!=NULL); + +@@ -529,17 +529,17 @@ cb_parse_instance_config_entry(cb_backend * cb, Slapi_Entry * e) { + */ + + if ( 0 == slapi_entry_attr_find( e, CB_CONFIG_INSTNAME, &attr )) { +- slapi_attr_first_value(attr, &sval); +- attrValue = slapi_value_get_berval(sval); +- instname=attrValue->bv_val; ++ slapi_attr_first_value(attr, &sval); ++ attrValue = slapi_value_get_berval(sval); ++ instname = attrValue->bv_val; + } else { + slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, + "Malformed backend instance (<%s> missing)>\n", CB_CONFIG_INSTNAME); +- return LDAP_LOCAL_ERROR; ++ return -1; + } + +- /* Allocate a new backend internal data structure */ +- inst = cb_instance_alloc(cb,instname,slapi_entry_get_dn(e)); ++ /* Allocate a new backend internal data structure */ ++ inst = cb_instance_alloc(cb,instname,slapi_entry_get_dn(e)); + + /* Emulate a add config entry to configure */ + /* this backend instance. */ +@@ -556,99 +556,96 @@ cb_parse_instance_config_entry(cb_backend * cb, Slapi_Entry * e) { + */ + + static int +-cb_instance_config_initialize(cb_backend_instance * inst, Slapi_Entry * e , int phase, int apply) { +- +- int rc =LDAP_SUCCESS; +- Slapi_Attr *attr = NULL; +- Slapi_Value *sval; +- struct berval * bval; +- int using_def_connlifetime,i; +- char err_buf[SLAPI_DSE_RETURNTEXT_SIZE]; +- int urlfound=0; +- char *rootdn; ++cb_instance_config_initialize(cb_backend_instance * inst, Slapi_Entry * e , int phase, int apply) ++{ ++ Slapi_Attr *attr = NULL; ++ Slapi_Value *sval; ++ Slapi_DN *suffix; ++ struct berval *bval; ++ char err_buf[SLAPI_DSE_RETURNTEXT_SIZE]; ++ char *attr_name = NULL; ++ char *rootdn; ++ int using_def_connlifetime, i; ++ int urlfound = 0; ++ int rc = LDAP_SUCCESS; + + using_def_connlifetime=1; + +- for (slapi_entry_first_attr(e, &attr); attr; slapi_entry_next_attr(e, attr, &attr)) { +- char * attr_name=NULL; +- slapi_attr_get_type(attr, &attr_name); ++ for (slapi_entry_first_attr(e, &attr); attr; slapi_entry_next_attr(e, attr, &attr)) { ++ attr_name = NULL; ++ slapi_attr_get_type(attr, &attr_name); + + if ( !strcasecmp ( attr_name, CB_CONFIG_SUFFIX )) { + if (apply && ( inst->inst_be != NULL )) { +- Slapi_DN *suffix; + suffix = slapi_sdn_new(); +- i = slapi_attr_first_value(attr, &sval); +- while (i != -1 ) { +- bval = (struct berval *) slapi_value_get_berval(sval); +- slapi_sdn_set_dn_byref(suffix, bval->bv_val); +- +- if (!slapi_be_issuffix(inst->inst_be, suffix)) { +- slapi_be_addsuffix(inst->inst_be, suffix); +- } +- i = slapi_attr_next_value(attr, i, &sval); +- } ++ i = slapi_attr_first_value(attr, &sval); ++ while (i != -1 ) { ++ bval = (struct berval *) slapi_value_get_berval(sval); ++ slapi_sdn_set_dn_byref(suffix, bval->bv_val); ++ ++ if (!slapi_be_issuffix(inst->inst_be, suffix)) { ++ slapi_be_addsuffix(inst->inst_be, suffix); ++ } ++ i = slapi_attr_next_value(attr, i, &sval); ++ } + slapi_sdn_free(&suffix); + } +- continue; +- } else +- if ( !strcasecmp ( attr_name, CB_CONFIG_CHAINING_COMPONENTS )) { +- +- if (apply) { +- slapi_rwlock_wrlock(inst->rwl_config_lock); +- i = slapi_attr_first_value(attr, &sval); ++ continue; ++ } else if ( !strcasecmp ( attr_name, CB_CONFIG_CHAINING_COMPONENTS )) { ++ if (apply) { ++ slapi_rwlock_wrlock(inst->rwl_config_lock); ++ i = slapi_attr_first_value(attr, &sval); + charray_free(inst->chaining_components); + inst->chaining_components=NULL; +- while (i != -1 ) { +- bval = (struct berval *) slapi_value_get_berval(sval); ++ while (i != -1 ) { ++ bval = (struct berval *) slapi_value_get_berval(sval); + charray_add(&inst->chaining_components, +- slapi_dn_normalize(slapi_ch_strdup(bval->bv_val))); +- i = slapi_attr_next_value(attr, i, &sval); +- } +- slapi_rwlock_unlock(inst->rwl_config_lock); +- } +- continue; +- } else +- if ( !strcasecmp ( attr_name, CB_CONFIG_ILLEGAL_ATTRS )) { +- +- if (apply) { +- slapi_rwlock_wrlock(inst->rwl_config_lock); +- i = slapi_attr_first_value(attr, &sval); ++ slapi_dn_normalize(slapi_ch_strdup(bval->bv_val))); ++ i = slapi_attr_next_value(attr, i, &sval); ++ } ++ slapi_rwlock_unlock(inst->rwl_config_lock); ++ } ++ continue; ++ } else if ( !strcasecmp ( attr_name, CB_CONFIG_ILLEGAL_ATTRS )) { ++ if (apply) { ++ slapi_rwlock_wrlock(inst->rwl_config_lock); ++ i = slapi_attr_first_value(attr, &sval); + charray_free(inst->illegal_attributes); + inst->illegal_attributes=NULL; +- while (i != -1 ) { +- bval = (struct berval *) slapi_value_get_berval(sval); ++ while (i != -1 ) { ++ bval = (struct berval *) slapi_value_get_berval(sval); + charray_add(&inst->illegal_attributes, +- slapi_ch_strdup(bval->bv_val)); +- i = slapi_attr_next_value(attr, i, &sval); +- } +- slapi_rwlock_unlock(inst->rwl_config_lock); +- } +- continue; ++ slapi_ch_strdup(bval->bv_val)); ++ i = slapi_attr_next_value(attr, i, &sval); ++ } ++ slapi_rwlock_unlock(inst->rwl_config_lock); ++ } ++ continue; + } + + + if ( !strcasecmp ( attr_name, CB_CONFIG_HOSTURL )) { + urlfound=1; + } +- + +- /* We are assuming that each of these attributes are to have +- * only one value. If they have more than one value, like +- * the nsslapd-suffix attribute, then they need to be +- * handled differently. */ ++ /* ++ * We are assuming that each of these attributes are to have ++ * only one value. If they have more than one value, like ++ * the nsslapd-suffix attribute, then they need to be ++ * handled differently. ++ */ + +- slapi_attr_first_value(attr, &sval); +- bval = (struct berval *) slapi_value_get_berval(sval); +- +- if (cb_instance_config_set((void *) inst, attr_name, ++ slapi_attr_first_value(attr, &sval); ++ bval = (struct berval *) slapi_value_get_berval(sval); ++ ++ if (cb_instance_config_set((void *) inst, attr_name, + cb_the_instance_config, bval, err_buf, phase, apply ) != LDAP_SUCCESS) { +- slapi_log_error( SLAPI_LOG_FATAL, +- CB_PLUGIN_SUBSYSTEM,"Error with config attribute %s : %s\n", ++ slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,"Error with config attribute %s : %s\n", + attr_name, err_buf); +- rc=LDAP_LOCAL_ERROR; +- break; +- } +- if ( !strcasecmp ( attr_name, CB_CONFIG_CONNLIFETIME )) { ++ rc = -1; ++ break; ++ } ++ if ( !strcasecmp ( attr_name, CB_CONFIG_CONNLIFETIME )) { + using_def_connlifetime=0; + } + } +@@ -661,20 +658,17 @@ cb_instance_config_initialize(cb_backend_instance * inst, Slapi_Entry * e , int + + if (LDAP_SUCCESS == rc) { + if (!urlfound) { +- slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, +- "Malformed backend instance entry. Mandatory attr <%s> missing\n", +- CB_CONFIG_HOSTURL); +- rc= LDAP_LOCAL_ERROR; ++ slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, ++ "Malformed backend instance entry. Mandatory attr <%s> missing\n",CB_CONFIG_HOSTURL); ++ rc = -1; + } + + if (apply ) { +- if ( using_def_connlifetime && +- strchr( inst->pool->hostname, ' ' ) != NULL ) { +- +- cb_instance_config_set((void *)inst, CB_CONFIG_CONNLIFETIME, +- cb_the_instance_config, NULL /* use default */, err_buf, ++ if ( using_def_connlifetime && strchr( inst->pool->hostname, ' ' ) != NULL ) { ++ cb_instance_config_set((void *)inst, CB_CONFIG_CONNLIFETIME, ++ cb_the_instance_config, NULL /* use default */, err_buf, + CB_CONFIG_PHASE_INITIALIZATION, 1 ); +- } ++ } + } + } + +@@ -683,15 +677,13 @@ cb_instance_config_initialize(cb_backend_instance * inst, Slapi_Entry * e , int + ** It is forbidden to use directory manager as proxy user + ** due to a bug in the acl check + */ +- +- rootdn=cb_get_rootdn(); ++ rootdn = cb_get_rootdn(); + + if (inst->impersonate && inst->pool && inst->pool->binddn && + !strcmp(inst->pool->binddn,rootdn)) { /* UTF8 aware */ +- slapi_log_error( SLAPI_LOG_FATAL, +- CB_PLUGIN_SUBSYSTEM,"Error with config attribute %s (%s: forbidden value)\n", +- CB_CONFIG_BINDUSER, rootdn); +- rc=LDAP_LOCAL_ERROR; ++ slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, ++ "Error with config attribute %s (%s: forbidden value)\n", CB_CONFIG_BINDUSER, rootdn); ++ rc= -1; + } + slapi_ch_free((void **)&rootdn); + +@@ -1494,7 +1486,7 @@ struct berval *bval, char *err_buf, int phase, int apply_mod) + int use_default; + int int_val; + long long_val; +- int retval=LDAP_LOCAL_ERROR; ++ int retval = -1; + + config = cb_get_config_info(config_array, attr_name); + if (NULL == config) { +-- +1.7.7.6 + diff --git a/0032-Ticket-576-DNA-use-event-queue-for-config-update-onl.patch b/0032-Ticket-576-DNA-use-event-queue-for-config-update-onl.patch new file mode 100644 index 0000000..df5dc29 --- /dev/null +++ b/0032-Ticket-576-DNA-use-event-queue-for-config-update-onl.patch @@ -0,0 +1,240 @@ +From 209da318fec805ca0430f50337e829133ac444a0 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 8 Feb 2013 12:13:14 -0800 +Subject: [PATCH 32/33] Ticket #576 - DNA: use event queue for config update + only at the start up + +https://fedorahosted.org/389/ticket/576 + +Bug description: DNA config updates were always put into the +event queue and executed in 30 seconds, which increased a chance +to conflict with the ordinary modify operations and cause db +deadlocks. + +Fix description: The 30 seconds delay is necessary at the start- +up time when MMR is configured to guarantee the shared config is +logged in the changelog. This patch leaves the behaviour of the +config update at the start-up as it is; the rest won't be queued +but updated immediately. + +Reviewed by Rich (Thank you!!) +(cherry picked from commit 7c11ed17796ba8b17afa5758fcfdf1c937b54ef4) +--- + ldap/servers/plugins/dna/dna.c | 78 +++++++++++++++++++++++++++------------ + 1 files changed, 54 insertions(+), 24 deletions(-) + +diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c +index 36dd936..6babe23 100644 +--- a/ldap/servers/plugins/dna/dna.c ++++ b/ldap/servers/plugins/dna/dna.c +@@ -93,6 +93,7 @@ + #define DNA_SHARED_CFG_DN "dnaSharedCfgDN" + + /* Shared Config */ ++#define DNA_SHAREDCONFIG "dnaSharedConfig" + #define DNA_REMAINING "dnaRemainingValues" + #define DNA_THRESHOLD "dnaThreshold" + #define DNA_HOSTNAME "dnaHostname" +@@ -219,7 +220,7 @@ static int dna_be_txn_preop_init(Slapi_PBlock *pb); + * Local operation functions + * + */ +-static int dna_load_plugin_config(); ++static int dna_load_plugin_config(int use_eventq); + static int dna_parse_config_entry(Slapi_Entry * e, int apply); + static void dna_delete_config(); + static void dna_free_config_entry(struct configEntry ** entry); +@@ -571,7 +572,7 @@ dna_start(Slapi_PBlock * pb) + slapi_ch_calloc(1, sizeof(struct configEntry)); + PR_INIT_CLIST(dna_global_config); + +- if (dna_load_plugin_config() != DNA_SUCCESS) { ++ if (dna_load_plugin_config(1/* use eventq */) != DNA_SUCCESS) { + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_start: unable to load plug-in configuration\n"); + return DNA_FAILURE; +@@ -639,7 +640,7 @@ done: + * ------ cn=etc etc + */ + static int +-dna_load_plugin_config() ++dna_load_plugin_config(int use_eventq) + { + int status = DNA_SUCCESS; + int result; +@@ -649,7 +650,8 @@ dna_load_plugin_config() + Slapi_Entry **entries = NULL; + + slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM, +- "--> dna_load_plugin_config\n"); ++ "--> dna_load_plugin_config %s\n", ++ use_eventq?"using event queue":""); + + dna_write_lock(); + dna_delete_config(); +@@ -681,13 +683,18 @@ dna_load_plugin_config() + dna_parse_config_entry(entries[i], 1); + } + +- /* Setup an event to update the shared config 30 +- * seconds from now. We need to do this since +- * performing the operation at this point when +- * starting up would cause the change to not +- * get changelogged. */ +- time(&now); +- slapi_eq_once(dna_update_config_event, NULL, now + 30); ++ if (use_eventq) { ++ /* Setup an event to update the shared config 30 ++ * seconds from now. We need to do this since ++ * performing the operation at this point when ++ * starting up would cause the change to not ++ * get changelogged. */ ++ time(&now); ++ slapi_eq_once(dna_update_config_event, NULL, now + 30); ++ } else { ++ int nolock = 1; /* no need to lock since dna write lock is held. */ ++ dna_update_config_event(0, &nolock); ++ } + + cleanup: + slapi_free_search_results_internal(search_pb); +@@ -1240,9 +1247,15 @@ dna_update_config_event(time_t event_time, void *arg) + Slapi_PBlock *pb = NULL; + struct configEntry *config_entry = NULL; + PRCList *list = NULL; ++ int nolock = 0; + +- /* Get read lock to prevent config changes */ +- dna_read_lock(); ++ if (arg) { ++ nolock = *(int *)arg; ++ } ++ if (!nolock) { ++ /* Get read lock to prevent config changes */ ++ dna_read_lock(); ++ } + + /* Bail out if the plug-in close function was just called. */ + if (!g_plugin_started) { +@@ -1287,7 +1300,9 @@ dna_update_config_event(time_t event_time, void *arg) + } + + bail: +- dna_unlock(); ++ if (!nolock) { ++ dna_unlock(); ++ } + slapi_pblock_destroy(pb); + } + +@@ -2161,7 +2176,7 @@ dna_update_shared_config(struct configEntry * config_entry) + slapi_entry_init_ext(e, sdn, NULL); /* sdn is copied into e */ + slapi_sdn_free(&sdn); + +- slapi_entry_add_string(e, SLAPI_ATTR_OBJECTCLASS, "dnaSharedConfig"); ++ slapi_entry_add_string(e, SLAPI_ATTR_OBJECTCLASS, DNA_SHAREDCONFIG); + slapi_entry_add_string(e, DNA_HOSTNAME, hostname); + slapi_entry_add_string(e, DNA_PORTNUM, portnum); + if (secureportnum) { +@@ -2770,6 +2785,7 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e, char **errstr) + char **generated_types = NULL; + PRUint64 setval = 0; + int i; ++ int issharedconfig = 0; + + /* Bail out if the plug-in close function was just called. */ + if (!g_plugin_started) { +@@ -2787,7 +2803,12 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e, char **errstr) + * We also check if we need to get the next range of values, and grab them. + * We do this here so we don't have to do it in the be_txn_preop. + */ +- dna_read_lock(); ++ /* Has write lock for config entries. */ ++ issharedconfig = slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS, ++ DNA_SHAREDCONFIG); ++ if (!issharedconfig) { ++ dna_read_lock(); ++ } + + if (!PR_CLIST_IS_EMPTY(dna_global_config)) { + list = PR_LIST_HEAD(dna_global_config); +@@ -2945,7 +2966,9 @@ next: + } + } + +- dna_unlock(); ++ if (!issharedconfig) { ++ dna_unlock(); ++ } + + slapi_ch_array_free(generated_types); + bail: +@@ -3314,7 +3337,7 @@ dna_pre_op(Slapi_PBlock * pb, int modtype) + ret = _dna_pre_op_add(pb, test_e, &errstr); + } else { + if((ret = _dna_pre_op_modify(pb, test_e, smods, &errstr))){ +- slapi_mods_free(&smods); ++ slapi_mods_free(&smods); + } + } + if (ret) { +@@ -3404,6 +3427,7 @@ static int dna_be_txn_pre_op(Slapi_PBlock *pb, int modtype) + char *type = NULL; + int numvals, e_numvals = 0; + int i, len, ret = 0; ++ int issharedconfig = 0; + + slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM, + "--> dna_be_txn_pre_op\n"); +@@ -3439,7 +3463,12 @@ static int dna_be_txn_pre_op(Slapi_PBlock *pb, int modtype) + slapi_mods_init_passin(smods, mods); + } + +- dna_read_lock(); ++ /* Has write lock for config entries. */ ++ issharedconfig = slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS, ++ DNA_SHAREDCONFIG); ++ if (!issharedconfig) { ++ dna_read_lock(); ++ } + + if (!PR_CLIST_IS_EMPTY(dna_global_config)) { + list = PR_LIST_HEAD(dna_global_config); +@@ -3449,7 +3478,7 @@ static int dna_be_txn_pre_op(Slapi_PBlock *pb, int modtype) + + /* Did we already service all of these configured types? */ + if (dna_list_contains_types(generated_types, config_entry->types)) { +- goto next; ++ goto next; + } + + /* is the entry in scope? */ +@@ -3626,12 +3655,13 @@ static int dna_be_txn_pre_op(Slapi_PBlock *pb, int modtype) + } else if (types_to_generate) { + slapi_ch_free((void **)&types_to_generate); + } +- next: ++next: + list = PR_NEXT_LINK(list); + } + } +- dna_unlock(); +- ++ if (!issharedconfig) { ++ dna_unlock(); ++ } + bail: + + if (LDAP_CHANGETYPE_MODIFY == modtype) { +@@ -3669,7 +3699,7 @@ static int dna_config_check_post_op(Slapi_PBlock * pb) + if (!slapi_op_internal(pb)) { /* If internal, no need to check. */ + if ((dn = dna_get_dn(pb))) { + if (dna_dn_is_config(dn)) { +- dna_load_plugin_config(); ++ dna_load_plugin_config(0); + } + } + } +-- +1.7.7.6 + diff --git a/0033-Ticket-579-Error-messages-encountered-when-using-POS.patch b/0033-Ticket-579-Error-messages-encountered-when-using-POS.patch new file mode 100644 index 0000000..4252c2a --- /dev/null +++ b/0033-Ticket-579-Error-messages-encountered-when-using-POS.patch @@ -0,0 +1,68 @@ +From 1e2d920b07f0726c67b0f1543f1a378a6aa8c15a Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 11 Feb 2013 14:49:14 -0800 +Subject: [PATCH 33/33] Ticket #579 - Error messages encountered when using + POSIX winsync + +Bug description: posix_group_fix_memberuid_callback registered by +posixWinsyncCreateMemberOfTask calls an internal modify function +even if there are no attributes to fix up. The attempt fails as +expected, but it logs cryptic errors in the error log: + - slapi_modify_internal_set_pb: NULL parameter + - allow_operation: component identity is NULL + +Fix description: This patch skips calling the fix up internal +modify if there is no attributes to fix up. + +https://fedorahosted.org/389/ticket/579 + +Reviewed by Rich (Thank you!!) +(cherry picked from commit 74423d2eaef50949fd96ded8a2251834663e95e8) +--- + .../plugins/posix-winsync/posix-group-task.c | 21 +++++++++++-------- + 1 files changed, 12 insertions(+), 9 deletions(-) + +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-task.c b/ldap/servers/plugins/posix-winsync/posix-group-task.c +index 92ac342..1d9135d 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-task.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-task.c +@@ -250,6 +250,7 @@ posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data) + + char *dn = slapi_entry_get_dn(e); + Slapi_DN *sdn = slapi_entry_get_sdn(e); ++ LDAPMod **mods = NULL; + + /* Clean out memberuids and dsonlymemberuids without a valid referant */ + rc = slapi_entry_attr_find(e, "memberuid", &muid_attr); +@@ -380,17 +381,19 @@ posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data) + } + } + +- Slapi_PBlock *mod_pb = slapi_pblock_new(); ++ mods = slapi_mods_get_ldapmods_passout(smods); ++ if (mods) { ++ Slapi_PBlock *mod_pb = NULL; ++ mod_pb = slapi_pblock_new(); ++ slapi_modify_internal_set_pb_ext(mod_pb, sdn, mods, 0, 0, ++ posix_winsync_get_plugin_identity(), 0); + +- slapi_modify_internal_set_pb_ext(mod_pb, sdn, slapi_mods_get_ldapmods_passout(smods), 0, 0, +- posix_winsync_get_plugin_identity(), 0); +- +- slapi_pblock_set(mod_pb, SLAPI_TXN, the_cb_data->txn); +- slapi_modify_internal_pb(mod_pb); +- +- slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); +- slapi_pblock_destroy(mod_pb); ++ slapi_pblock_set(mod_pb, SLAPI_TXN, the_cb_data->txn); ++ slapi_modify_internal_pb(mod_pb); + ++ slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); ++ slapi_pblock_destroy(mod_pb); ++ } + slapi_mods_free(&smods); + + slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, +-- +1.7.7.6 + diff --git a/0034-Ticket-518-dse.ldif-is-0-length-after-server-kill-or.patch b/0034-Ticket-518-dse.ldif-is-0-length-after-server-kill-or.patch new file mode 100644 index 0000000..ef48254 --- /dev/null +++ b/0034-Ticket-518-dse.ldif-is-0-length-after-server-kill-or.patch @@ -0,0 +1,167 @@ +From 6f8fde543a757e59c03a09c45b0204aa0df97783 Mon Sep 17 00:00:00 2001 +From: Ludwig Krispenz +Date: Fri, 23 Nov 2012 11:15:52 +0100 +Subject: [PATCH] Ticket 518 - dse.ldif is 0 length after server kill or + machine kill + +Bug Description: If a machine is powered off while slapd is running, dse.ldif can have 0 bytes and + server doesn't start even if a dse.ldif.tmp or dse.ldif.bak exists + +Fix Description: I see no way to prevent a 0 byte ldif in case of a machine crash from slapd code, + but the server should try all avaialble backup dse.ldif files to be able to start, + +https://fedorahosted.org/389/ticket/518 + +Reviewed by: RichM (Thanks) +(cherry picked from commit b3ca9eec5d50c2ca503582e55b6681b9b3ad6ad3) +--- + ldap/servers/slapd/config.c | 32 ++++---------------- + ldap/servers/slapd/dse.c | 60 +++++++++++++++++++++++++------------- + ldap/servers/slapd/proto-slap.h | 1 + + 3 files changed, 47 insertions(+), 46 deletions(-) + +diff --git a/ldap/servers/slapd/config.c b/ldap/servers/slapd/config.c +index d97a575..3edc24b 100644 +--- a/ldap/servers/slapd/config.c ++++ b/ldap/servers/slapd/config.c +@@ -165,6 +165,7 @@ slapd_bootstrap_config(const char *configdir) + char *buf = 0; + char *lastp = 0; + char *entrystr = 0; ++ char tmpfile[MAXPATHLEN+1]; + + if (NULL == configdir) { + slapi_log_error(SLAPI_LOG_FATAL, +@@ -173,33 +174,14 @@ slapd_bootstrap_config(const char *configdir) + } + PR_snprintf(configfile, sizeof(configfile), "%s/%s", configdir, + CONFIG_FILENAME); +- if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS ) +- { +- /* the "real" file does not exist; see if there is a tmpfile */ +- char tmpfile[MAXPATHLEN+1]; +- slapi_log_error(SLAPI_LOG_FATAL, "config", +- "The configuration file %s does not exist\n", configfile); +- PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir, ++ PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir, + CONFIG_FILENAME); +- if ( PR_GetFileInfo( tmpfile, &prfinfo ) == PR_SUCCESS ) { +- rc = PR_Rename(tmpfile, configfile); +- if (rc == PR_SUCCESS) { +- slapi_log_error(SLAPI_LOG_FATAL, "config", +- "The configuration file %s was restored from backup %s\n", +- configfile, tmpfile); +- } else { +- slapi_log_error(SLAPI_LOG_FATAL, "config", +- "The configuration file %s was not restored from backup %s, error %d\n", +- configfile, tmpfile, rc); +- return rc; /* Fail */ +- } +- } else { +- slapi_log_error(SLAPI_LOG_FATAL, "config", +- "The backup configuration file %s does not exist, either.\n", +- tmpfile); +- return rc; /* Fail */ +- } ++ if ( (rc = dse_check_file(configfile, tmpfile)) == 0 ) { ++ PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.bak", configdir, ++ CONFIG_FILENAME); ++ rc = dse_check_file(configfile, tmpfile); + } ++ + if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS ) + { + PRErrorCode prerr = PR_GetError(); +diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c +index 8cf3916..efa64ff 100644 +--- a/ldap/servers/slapd/dse.c ++++ b/ldap/servers/slapd/dse.c +@@ -651,6 +651,40 @@ dse_updateNumSubOfParent(struct dse *pdse, const Slapi_DN *child, int op) + slapi_sdn_done(&parent); + } + ++/* check if a file is valid, or if a provided backup file can be used. ++ * there is no way to determine if the file contents is usable, the only ++ * checks that can be done is that the file exists and that it is not size 0 ++ */ ++int ++dse_check_file(char *filename, char *backupname) ++{ ++ int rc= 0; /* Fail */ ++ PRFileInfo prfinfo; ++ ++ if (PR_GetFileInfo( filename, &prfinfo ) == PR_SUCCESS) { ++ if ( prfinfo.size > 0) ++ return (1); ++ else { ++ rc = PR_Delete (filename); ++ } ++ } ++ ++ if (backupname) ++ rc = PR_Rename (backupname, filename); ++ else ++ return (0); ++ ++ if ( PR_GetFileInfo( filename, &prfinfo ) == PR_SUCCESS && prfinfo.size > 0 ) { ++ slapi_log_error(SLAPI_LOG_FATAL, "dse", ++ "The configuration file %s was restored from backup %s\n", filename, backupname); ++ return (1); ++ } else { ++ slapi_log_error(SLAPI_LOG_FATAL, "dse", ++ "The configuration file %s was not restored from backup %s, error %d\n", ++ filename, backupname, rc); ++ return (0); ++ } ++} + static int + dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb, + int primary_file ) +@@ -669,27 +703,11 @@ dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb, + + if ( (NULL != pdse) && (NULL != filename) ) + { +- if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS ) +- { +- /* the "real" file does not exist; see if there is a tmpfile */ +- if ( pdse->dse_tmpfile && +- PR_GetFileInfo( pdse->dse_tmpfile, &prfinfo ) == PR_SUCCESS ) { +- rc = PR_Rename(pdse->dse_tmpfile, filename); +- if (rc == PR_SUCCESS) { +- slapi_log_error(SLAPI_LOG_FATAL, "dse", +- "The configuration file %s was restored from backup %s\n", +- filename, pdse->dse_tmpfile); +- rc = 1; +- } else { +- slapi_log_error(SLAPI_LOG_FATAL, "dse", +- "The configuration file %s was not restored from backup %s, error %d\n", +- filename, pdse->dse_tmpfile, rc); +- rc = 0; +- } +- } else { +- rc = 0; /* fail */ +- } +- } ++ /* check if the "real" file exists and cam be used, if not try tmp as backup */ ++ rc = dse_check_file(filename, pdse->dse_tmpfile); ++ if (!rc) ++ rc = dse_check_file(filename, pdse->dse_fileback); ++ + if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS ) + { + slapi_log_error(SLAPI_LOG_FATAL, "dse", +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index 2289efa..bdcef9a 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -654,6 +654,7 @@ struct dse *dse_new( char *filename, char *tmpfilename, char *backfilename, char + struct dse *dse_new_with_filelist(char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir, char **filelist); + int dse_deletedse(Slapi_PBlock *pb); + int dse_destroy(struct dse *pdse); ++int dse_check_file(char *filename, char *backupname); + int dse_read_file(struct dse *pdse, Slapi_PBlock *pb); + int dse_bind( Slapi_PBlock *pb ); + int dse_unbind( Slapi_PBlock *pb ); +-- +1.7.7.6 + diff --git a/0035-Ticket-590-ns-slapd-segfaults-while-trying-to-delete.patch b/0035-Ticket-590-ns-slapd-segfaults-while-trying-to-delete.patch new file mode 100644 index 0000000..c1b127b --- /dev/null +++ b/0035-Ticket-590-ns-slapd-segfaults-while-trying-to-delete.patch @@ -0,0 +1,37 @@ +From f32980b436e1844a9f6045b8f432bc38cb75744c Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 20 Feb 2013 13:37:22 -0500 +Subject: [PATCH] Ticket 590 - ns-slapd segfaults while trying to delete a + tombstone entry + +Bug Description: While trying to remove a tombstone entry, ns-slapd + crashed with segfault. + +Fix Description: Check if op_parms->csn is NULL before dereferencing. + This was fixed in master via ticket 532, but this + patch is just part of that fix to avoid the crash. + +https://fedorahosted.org/389/ticket/590 + +Reviewed by: Noriko(Thanks!) +(cherry picked from commit 39f19ae08afe28eb36eabe76b2add1e84c7ed805) +--- + ldap/servers/plugins/replication/repl5_plugins.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c +index f7677dd..e3c3083 100644 +--- a/ldap/servers/plugins/replication/repl5_plugins.c ++++ b/ldap/servers/plugins/replication/repl5_plugins.c +@@ -1064,7 +1064,7 @@ write_changelog_and_ruv (Slapi_PBlock *pb) + op_params->target_address.uniqueid = slapi_ch_strdup (uniqueid); + } + +- if( is_cleaned_rid(csn_get_replicaid(op_params->csn))){ ++ if( op_params->csn && is_cleaned_rid(csn_get_replicaid(op_params->csn))){ + /* this RID has been cleaned */ + object_release (repl_obj); + return 0; +-- +1.7.7.6 + diff --git a/0036-Bugzilla-912964-bug-in-handling-of-LDAPv3-control-da.patch b/0036-Bugzilla-912964-bug-in-handling-of-LDAPv3-control-da.patch new file mode 100644 index 0000000..ea6a724 --- /dev/null +++ b/0036-Bugzilla-912964-bug-in-handling-of-LDAPv3-control-da.patch @@ -0,0 +1,304 @@ +From 0aa523cd16f97160ab406db8958a78253f7e31bc Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 22 Feb 2013 14:40:46 -0800 +Subject: [PATCH] Bugzilla 912964 - bug in handling of LDAPv3 control data + +Bug Description: +If we receive an incorrect control, with non NULL bv_val but +bv_len=0, it can trigger a crash. This bug occurs because +of a call of openldap ber_init with such incorrect control. + +Fix Description: +Before calling ber_init, check that the control lenght is not 0. + +Note: checking in the patch on behalf of "Thierry bordaz" + + +https://bugzilla.redhat.com/show_bug.cgi?id=913228 + +Reviewed by: rmeggins@redhat.com, nhosoi@redhat.com + +Platforms tested: Fedora 18, RHEL 6.4 (RHDS6.4) + +Flag Day: no + +Doc impact: possibly document a security bug +--- + ldap/servers/plugins/chainingdb/cb_controls.c | 6 +--- + ldap/servers/plugins/chainingdb/cb_utils.c | 2 +- + ldap/servers/plugins/deref/deref.c | 2 +- + ldap/servers/plugins/dna/dna.c | 7 +++-- + ldap/servers/plugins/replication/repl5_total.c | 6 ++-- + ldap/servers/plugins/replication/repl_controls.c | 2 +- + ldap/servers/plugins/replication/repl_extop.c | 21 ++++++++++++------- + ldap/servers/plugins/replication/windows_private.c | 7 ++++++ + ldap/servers/slapd/back-ldbm/sort.c | 9 +++---- + ldap/servers/slapd/back-ldbm/vlv.c | 4 +- + ldap/servers/slapd/passwd_extop.c | 2 +- + ldap/servers/slapd/proxyauth.c | 2 +- + ldap/servers/slapd/slapi-plugin.h | 4 +++ + 13 files changed, 44 insertions(+), 30 deletions(-) + +diff --git a/ldap/servers/plugins/chainingdb/cb_controls.c b/ldap/servers/plugins/chainingdb/cb_controls.c +index f079901..2a698a0 100644 +--- a/ldap/servers/plugins/chainingdb/cb_controls.c ++++ b/ldap/servers/plugins/chainingdb/cb_controls.c +@@ -220,10 +220,8 @@ int cb_update_controls( Slapi_PBlock * pb, + ctrls[dCount]=slapi_dup_control(reqControls[cCount]); + dCount++; + +- } else +- if (!strcmp(reqControls[cCount]->ldctl_oid,CB_LDAP_CONTROL_CHAIN_SERVER) && +- reqControls[cCount]->ldctl_value.bv_val) { +- ++ } else if (!strcmp(reqControls[cCount]->ldctl_oid,CB_LDAP_CONTROL_CHAIN_SERVER) && ++ BV_HAS_DATA((&(reqControls[cCount]->ldctl_value)))) { + /* Max hop count reached ? */ + /* Checked earlier by a call to cb_forward_operation() */ + +diff --git a/ldap/servers/plugins/chainingdb/cb_utils.c b/ldap/servers/plugins/chainingdb/cb_utils.c +index 2492226..f28f5d3 100644 +--- a/ldap/servers/plugins/chainingdb/cb_utils.c ++++ b/ldap/servers/plugins/chainingdb/cb_utils.c +@@ -148,7 +148,7 @@ int cb_forward_operation(Slapi_PBlock * pb ) { + int iscritical=0; + + if (slapi_control_present(ctrls,CB_LDAP_CONTROL_CHAIN_SERVER,&ctl_value,&iscritical) && +- ctl_value && ctl_value->bv_val) { ++ BV_HAS_DATA(ctl_value)) { + + /* Decode control data */ + /* hop INTEGER (0 .. maxInt) */ +diff --git a/ldap/servers/plugins/deref/deref.c b/ldap/servers/plugins/deref/deref.c +index 7c502df..51394c8 100644 +--- a/ldap/servers/plugins/deref/deref.c ++++ b/ldap/servers/plugins/deref/deref.c +@@ -382,7 +382,7 @@ deref_parse_ctrl_value(DerefSpecList *speclist, const struct berval *ctrlbv, int + + PR_ASSERT(ctrlbv && ctrlbv->bv_val && ctrlbv->bv_len && ldapcode && ldaperrtext); + +- if (!ctrlbv || !ctrlbv->bv_val) { ++ if (!BV_HAS_DATA(ctrlbv)) { + *ldapcode = LDAP_PROTOCOL_ERROR; + *ldaperrtext = "Empty deref control value"; + return; +diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c +index 6babe23..080e357 100644 +--- a/ldap/servers/plugins/dna/dna.c ++++ b/ldap/servers/plugins/dna/dna.c +@@ -1668,7 +1668,7 @@ static int dna_request_range(struct configEntry *config_entry, + } + + /* Parse response */ +- if (responsedata && responsedata->bv_val) { ++ if (BV_HAS_DATA(responsedata)) { + respber = ber_init(responsedata); + if (ber_scanf(respber, "{aa}", &lower_str, &upper_str) == LBER_ERROR) { + ret = LDAP_PROTOCOL_ERROR; +@@ -3745,14 +3745,15 @@ static int dna_extend_exop(Slapi_PBlock *pb) + + /* Fetch the request data */ + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &reqdata); +- if (!reqdata || !reqdata->bv_val) { ++ if (!BV_HAS_DATA(reqdata)) { + slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM, + "dna_extend_exop: No request data received.\n"); + goto free_and_return; + } + + /* decode the exop */ +- if ((reqdata->bv_val == NULL) || (tmp_bere = ber_init(reqdata)) == NULL) { ++ tmp_bere = ber_init(reqdata); ++ if (tmp_bere == NULL) { + goto free_and_return; + } + +diff --git a/ldap/servers/plugins/replication/repl5_total.c b/ldap/servers/plugins/replication/repl5_total.c +index 99ba838..f22246d 100644 +--- a/ldap/servers/plugins/replication/repl5_total.c ++++ b/ldap/servers/plugins/replication/repl5_total.c +@@ -726,10 +726,10 @@ decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep) + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value); + +- if (NULL == extop_oid || ++ if ((NULL == extop_oid) || + ((strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0) && +- (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) || +- NULL == extop_value || NULL == extop_value->bv_val) ++ (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) || ++ !BV_HAS_DATA(extop_value)) + { + /* Bogus */ + goto loser; +diff --git a/ldap/servers/plugins/replication/repl_controls.c b/ldap/servers/plugins/replication/repl_controls.c +index 980bdd8..e6aeaaa 100644 +--- a/ldap/servers/plugins/replication/repl_controls.c ++++ b/ldap/servers/plugins/replication/repl_controls.c +@@ -216,7 +216,7 @@ decode_NSDS50ReplUpdateInfoControl(LDAPControl **controlsp, + if (slapi_control_present(controlsp, REPL_NSDS50_UPDATE_INFO_CONTROL_OID, + &ctl_value, &iscritical)) + { +- if ((ctl_value->bv_val == NULL) || (tmp_bere = ber_init(ctl_value)) == NULL) ++ if (!BV_HAS_DATA(ctl_value) || (tmp_bere = ber_init(ctl_value)) == NULL) + { + rc = -1; + goto loser; +diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c +index e842c62..68aed62 100644 +--- a/ldap/servers/plugins/replication/repl_extop.c ++++ b/ldap/servers/plugins/replication/repl_extop.c +@@ -343,10 +343,10 @@ decode_startrepl_extop(Slapi_PBlock *pb, char **protocol_oid, char **repl_root, + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value); + +- if (NULL == extop_oid || ++ if ((NULL == extop_oid) || + ((strcmp(extop_oid, REPL_START_NSDS50_REPLICATION_REQUEST_OID) != 0) && +- (strcmp(extop_oid, REPL_START_NSDS90_REPLICATION_REQUEST_OID) != 0)) || +- NULL == extop_value || NULL == extop_value->bv_val) ++ (strcmp(extop_oid, REPL_START_NSDS90_REPLICATION_REQUEST_OID) != 0)) || ++ !BV_HAS_DATA(extop_value)) + { + /* bogus */ + rc = -1; +@@ -480,9 +480,9 @@ decode_endrepl_extop(Slapi_PBlock *pb, char **repl_root) + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value); + +- if (NULL == extop_oid || +- strcmp(extop_oid, REPL_END_NSDS50_REPLICATION_REQUEST_OID) != 0 || +- NULL == extop_value || NULL == extop_value->bv_val) ++ if ((NULL == extop_oid) || ++ (strcmp(extop_oid, REPL_END_NSDS50_REPLICATION_REQUEST_OID) != 0) || ++ !BV_HAS_DATA(extop_value)) + { + /* bogus */ + rc = -1; +@@ -545,8 +545,8 @@ decode_repl_ext_response(struct berval *bvdata, int *response_code, + PR_ASSERT(NULL != response_code); + PR_ASSERT(NULL != ruv_bervals); + +- if (NULL == bvdata || NULL == response_code || NULL == ruv_bervals || +- NULL == data_guid || NULL == data || NULL == bvdata->bv_val) ++ if ((NULL == response_code) || (NULL == ruv_bervals) || ++ (NULL == data_guid) || (NULL == data) || !BV_HAS_DATA(bvdata)) + { + return_value = -1; + } +@@ -1412,6 +1412,11 @@ decode_cleanruv_payload(struct berval *extop_value, char **payload) + { + BerElement *tmp_bere = NULL; + int rc = 0; ++ ++ if (!BV_HAS_DATA(extop_value)) { ++ rc = -1; ++ goto free_and_return; ++ } + + if ((tmp_bere = ber_init(extop_value)) == NULL){ + rc = -1; +diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c +index 355abd5..20360a3 100644 +--- a/ldap/servers/plugins/replication/windows_private.c ++++ b/ldap/servers/plugins/replication/windows_private.c +@@ -782,6 +782,13 @@ void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **co + dirsync = slapi_dup_control( controls[i-1]); + } + ++ if (!dirsync || !BV_HAS_DATA((&(dirsync->ldctl_value)))) { ++#ifdef FOR_DEBUGGING ++ return_value = LDAP_CONTROL_NOT_FOUND; ++#endif ++ goto choke; ++ } ++ + ber = ber_init( &dirsync->ldctl_value ) ; + + if (ber_scanf( ber, "{iiO}", &hasMoreData, &maxAttributeCount, &serverCookie) == LBER_ERROR) +diff --git a/ldap/servers/slapd/back-ldbm/sort.c b/ldap/servers/slapd/back-ldbm/sort.c +index 501765c..6984467 100644 +--- a/ldap/servers/slapd/back-ldbm/sort.c ++++ b/ldap/servers/slapd/back-ldbm/sort.c +@@ -299,15 +299,14 @@ int parse_sort_spec(struct berval *sort_spec_ber, sort_spec **ps) + char *matchrule = NULL; + int rc = LDAP_SUCCESS; + +- if (NULL == sort_spec_ber->bv_val) { ++ if (!BV_HAS_DATA(sort_spec_ber)) { + return LDAP_PROTOCOL_ERROR; + } + + ber = ber_init(sort_spec_ber); +- if(ber==NULL) +- { +- return -1; +- } ++ if (ber == NULL) { ++ return -1; ++ } + + /* Work our way along the BER, one sort spec at a time */ + for ( tag = ber_first_element( ber, &len, &last ); !term_tag(tag); tag = ber_next_element( ber, &len, last )) { +diff --git a/ldap/servers/slapd/back-ldbm/vlv.c b/ldap/servers/slapd/back-ldbm/vlv.c +index 39d16bf..2c09531 100644 +--- a/ldap/servers/slapd/back-ldbm/vlv.c ++++ b/ldap/servers/slapd/back-ldbm/vlv.c +@@ -1861,11 +1861,11 @@ vlv_parse_request_control( backend *be, struct berval *vlv_spec_ber,struct vlv_r + */ + BerElement *ber = NULL; + int return_value = LDAP_SUCCESS; +- ++ + vlvp->value.bv_len = 0; + vlvp->value.bv_val = NULL; + +- if (NULL == vlv_spec_ber->bv_val) ++ if (!BV_HAS_DATA(vlv_spec_ber)) + { + return_value= LDAP_OPERATIONS_ERROR; + return return_value; +diff --git a/ldap/servers/slapd/passwd_extop.c b/ldap/servers/slapd/passwd_extop.c +index 3c050d6..4aebee3 100644 +--- a/ldap/servers/slapd/passwd_extop.c ++++ b/ldap/servers/slapd/passwd_extop.c +@@ -534,7 +534,7 @@ passwd_modify_extop( Slapi_PBlock *pb ) + /* Get the ber value of the extended operation */ + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value); + +- if (extop_value->bv_val == NULL) ++ if (!BV_HAS_DATA(extop_value)) + { + /* The request field wasn't provided. We'll + * now try to determine the userid and verify +diff --git a/ldap/servers/slapd/proxyauth.c b/ldap/servers/slapd/proxyauth.c +index fe36cf1..562ac93 100644 +--- a/ldap/servers/slapd/proxyauth.c ++++ b/ldap/servers/slapd/proxyauth.c +@@ -96,7 +96,7 @@ parse_LDAPProxyAuth(struct berval *spec_ber, int version, char **errtextp, + break; + } + +- if ( !spec_ber || !spec_ber->bv_val ) { ++ if (!BV_HAS_DATA(spec_ber)) { + break; + } + +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h +index 4962b2a..f78787e 100644 +--- a/ldap/servers/slapd/slapi-plugin.h ++++ b/ldap/servers/slapd/slapi-plugin.h +@@ -107,6 +107,10 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...) + #define BERLEN_T "u" + #endif + ++/* Common check on berval before accessing the contents. */ ++/* bv is a struct berval *bv */ ++#define BV_HAS_DATA(bv) ((bv != NULL) && (bv->bv_len > 0) && (bv->bv_val != NULL)) ++ + /* + * The slapi_attr_get_flags() routine returns a bitmap that contains one or + * more of these values. +-- +1.7.7.6 + diff --git a/0037-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch b/0037-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch new file mode 100644 index 0000000..6ffdbdf --- /dev/null +++ b/0037-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch @@ -0,0 +1,181 @@ +From caa4c40e88032c97d8c928debd5d1b34078d60a3 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 19 Mar 2013 15:17:51 -0400 +Subject: [PATCH 37/42] Ticket 623 - cleanAllRUV task fails to cleanup config + upon completion + +Bug Description: Since multiple tasks can be run at once. When a task + completes we need to remove a attribute from the replication + configuration. We were manually building the attribute + value, and under certain circumstances this would not work + correctly. This would leave the attribute in the replication + config, and after a restart the task would fire off again. + +Fix Description: Do not manually build the attribute value, but instead search + cn=config and grab the exact value we need to delete. + +https://fedorahosted.org/389/ticket/623 + +Reviewed by: nhosoi(Thanks!) +(cherry picked from commit fa7972a5f01be7cedcd65c4c19af9602d2f7848f) +--- + .../plugins/replication/repl5_replica_config.c | 106 +++++++++++++++------ + 1 file changed, 75 insertions(+), 31 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index e234c15..8710c04 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -2351,57 +2351,100 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){ + static void + delete_cleaned_rid_config(cleanruv_data *clean_data) + { +- Slapi_PBlock *pb; ++ Slapi_PBlock *pb = slapi_pblock_new(); ++ Slapi_Entry **entries = NULL; + LDAPMod *mods[2]; + LDAPMod mod; + struct berval *vals[2]; + struct berval val; + char data[CSN_STRSIZE + 15]; + char *csnstr = NULL; ++ char *iter = NULL; + char *dn; +- int rc; ++ int found = 0, i; ++ int rc, ret, rid; + + /* +- * Prepare the mods for the config entry ++ * If there is no maxcsn, set the proper csnstr + */ + csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr); +- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", (int)clean_data->rid, csnstr, clean_data->force); ++ if(csnstr == NULL || csn_get_replicaid(clean_data->maxcsn) == 0){ ++ csnstr = slapi_ch_strdup("00000000000000000000"); ++ } ++ /* ++ * Search the config for the exact attribute value to delete ++ */ + dn = replica_get_dn(clean_data->replica); +- pb = slapi_pblock_new(); ++ slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_SUBTREE, "nsds5ReplicaCleanRUV=*", NULL, 0, NULL, NULL, ++ (void *)plugin_get_default_component_id(), 0); ++ slapi_search_internal_pb(pb); ++ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret); ++ if (ret != LDAP_SUCCESS){ ++ /* ++ * Search failed, manually build the attr value ++ */ ++ val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", ++ (int)clean_data->rid, csnstr, clean_data->force); ++ slapi_pblock_destroy(pb); ++ } else { ++ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); ++ if (entries == NULL || entries[0] == NULL){ ++ /* ++ * Entry not found, manually build the attr value ++ */ ++ val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", ++ (int)clean_data->rid, csnstr, clean_data->force); ++ } else { ++ char **attr_val = slapi_entry_attr_get_charray(entries[0], "nsds5ReplicaCleanRUV"); ++ ++ for (i = 0; attr_val && attr_val[i] && !found; i++){ ++ /* make a copy to retain the full value after toking */ ++ char *aval = slapi_ch_strdup(attr_val[i]); ++ ++ rid = atoi(ldap_utf8strtok_r(attr_val[i], ":", &iter)); ++ if(rid == clean_data->rid){ ++ /* found it */ ++ found = 1; ++ val.bv_len = PR_snprintf(data, sizeof(data), "%s", aval); ++ } ++ slapi_ch_free_string(&aval); ++ } ++ if(!found){ ++ /* ++ * No match, manually build the attr value ++ */ ++ val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", ++ (int)clean_data->rid, csnstr, clean_data->force); ++ } ++ slapi_ch_array_free(attr_val); ++ } ++ slapi_free_search_results_internal(pb); ++ slapi_pblock_destroy(pb); ++ } ++ ++ /* ++ * Now delete the attribute ++ */ + mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; +- mod.mod_type = (char *)type_replicaAbortCleanRUV; + mod.mod_type = (char *)type_replicaCleanRUV; + mod.mod_bvalues = vals; + vals [0] = &val; + vals [1] = NULL; + val.bv_val = data; +- + mods[0] = &mod; + mods[1] = NULL; ++ pb = slapi_pblock_new(); + slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); + slapi_modify_internal_pb (pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); +- if (rc != LDAP_SUCCESS){ +- /* +- * When aborting a task, we don't know if the "force" option was used. +- * So we assume it is set to "no", but if this op fails, we'll try "yes" +- */ +- slapi_pblock_destroy (pb); +- pb = slapi_pblock_new(); +- memset(data,'0',sizeof(data)); +- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:yes", (int)clean_data->rid, csnstr); +- slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); +- slapi_modify_internal_pb (pb); +- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); +- if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config " +- "(%d), rid (%d)\n", rc, clean_data->rid); +- } +- } +- slapi_pblock_destroy (pb); +- slapi_ch_free_string(&dn); +- slapi_ch_free_string(&csnstr); +- } ++ if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config " ++ "(%d), rid (%d)\n", rc, clean_data->rid); ++ } ++ slapi_pblock_destroy(pb); ++ slapi_ch_free_string(&dn); ++ slapi_ch_free_string(&csnstr); ++} + + /* + * Remove the rid from our list, and the config +@@ -2762,8 +2805,8 @@ replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int che + /* extop was accepted */ + rc = 0; + } else { +- cleanruv_log(clean_data->task, CLEANALLRUV_ID,"Replica %s does not support the CLEANALLRUV task. Sending replica CLEANRUV task...", +- slapi_sdn_get_dn(agmt_get_dn_byref(ra))); ++ cleanruv_log(clean_data->task, CLEANALLRUV_ID,"Replica %s does not support the CLEANALLRUV task. " ++ "Sending replica CLEANRUV task...", slapi_sdn_get_dn(agmt_get_dn_byref(ra))); + /* + * Ok, this replica doesn't know about CLEANALLRUV, so just manually + * add the CLEANRUV task to the replica. +@@ -2841,7 +2884,8 @@ replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn) + /* we could not find any maxcsn's - already cleaned? */ + return NULL; + } +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: Not all replicas online, retrying in %d seconds\n",interval); ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: " ++ "Not all replicas online, retrying in %d seconds\n", interval); + PR_Lock( notify_lock ); + PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) ); + PR_Unlock( notify_lock ); +-- +1.8.1.4 + diff --git a/0038-Coverity-issue-13091.patch b/0038-Coverity-issue-13091.patch new file mode 100644 index 0000000..3d2fc2e --- /dev/null +++ b/0038-Coverity-issue-13091.patch @@ -0,0 +1,38 @@ +From b1f6eac2792f5d774b0a4b30cea0da28d11bf08b Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 24 Sep 2012 11:26:49 -0400 +Subject: [PATCH 38/42] Coverity issue 13091 + +Bug Description: Local var array "mychange" can go out of scope + +Fix Description: Declare "mychange" at the top of the function so it does not go out of scope. + +Reviewed by: nkinder(Thanks!) +(cherry picked from commit d58ae20b75ccae99b2122a4a0d4fcf773a51115a) +--- + ldap/servers/slapd/plugin_acl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/plugin_acl.c b/ldap/servers/slapd/plugin_acl.c +index 3bc3f21..eebc292 100644 +--- a/ldap/servers/slapd/plugin_acl.c ++++ b/ldap/servers/slapd/plugin_acl.c +@@ -136,6 +136,7 @@ plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype ) + struct slapdplugin *p; + int rc = 0; + void *change = NULL; ++ void *mychange[2]; + Slapi_Entry *te = NULL; + Slapi_DN *sdn = NULL; + Operation *operation; +@@ -158,7 +159,6 @@ plugin_call_acl_mods_update ( Slapi_PBlock *pb, int optype ) + break; + case SLAPI_OPERATION_MODRDN: + { +- void *mychange[2]; + char *newrdn = NULL; + Slapi_DN *psdn = NULL; + char *pdn = NULL; +-- +1.8.1.4 + diff --git a/0039-Ticket-634-Deadlock-in-DNA-plug-in.patch b/0039-Ticket-634-Deadlock-in-DNA-plug-in.patch new file mode 100644 index 0000000..2f70e2b --- /dev/null +++ b/0039-Ticket-634-Deadlock-in-DNA-plug-in.patch @@ -0,0 +1,165 @@ +From a65b2927980028eba4574f59f9c216ffb0347356 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Wed, 20 Mar 2013 18:25:41 -0700 +Subject: [PATCH 39/42] Ticket #634 - Deadlock in DNA plug-in + +Bug description: Fix for Ticket #576 - +DNA: use event queue for config update only at the start up +(commit 7c11ed17796ba8b17afa5758fcfdf1c937b54ef4) +modified the timing of updating the shared config in the +database. The write operation was no need to be in the DNA +write lock, but it was located in it, which caused the dead- +lock. + +Fix description: This patch releases the dna write lock before +updating the shared config in the database. + +https://fedorahosted.org/389/ticket/634 + +Reviewed by Nathan (Thank you!!) +--- + ldap/servers/plugins/dna/dna.c | 45 +++++++++++------------------------------- + 1 file changed, 11 insertions(+), 34 deletions(-) + +diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c +index 080e357..d3dfa52 100644 +--- a/ldap/servers/plugins/dna/dna.c ++++ b/ldap/servers/plugins/dna/dna.c +@@ -666,6 +666,7 @@ dna_load_plugin_config(int use_eventq) + + if (LDAP_SUCCESS != result) { + status = DNA_FAILURE; ++ dna_unlock(); + goto cleanup; + } + +@@ -673,6 +674,7 @@ dna_load_plugin_config(int use_eventq) + &entries); + if (NULL == entries || NULL == entries[0]) { + status = DNA_SUCCESS; ++ dna_unlock(); + goto cleanup; + } + +@@ -682,6 +684,7 @@ dna_load_plugin_config(int use_eventq) + * looking for valid ones. */ + dna_parse_config_entry(entries[i], 1); + } ++ dna_unlock(); + + if (use_eventq) { + /* Setup an event to update the shared config 30 +@@ -692,14 +695,13 @@ dna_load_plugin_config(int use_eventq) + time(&now); + slapi_eq_once(dna_update_config_event, NULL, now + 30); + } else { +- int nolock = 1; /* no need to lock since dna write lock is held. */ +- dna_update_config_event(0, &nolock); ++ int arg = 0; /* not used. */ ++ dna_update_config_event(0, &arg); + } + + cleanup: + slapi_free_search_results_internal(search_pb); + slapi_pblock_destroy(search_pb); +- dna_unlock(); + slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM, + "<-- dna_load_plugin_config\n"); + +@@ -1247,15 +1249,8 @@ dna_update_config_event(time_t event_time, void *arg) + Slapi_PBlock *pb = NULL; + struct configEntry *config_entry = NULL; + PRCList *list = NULL; +- int nolock = 0; + +- if (arg) { +- nolock = *(int *)arg; +- } +- if (!nolock) { +- /* Get read lock to prevent config changes */ +- dna_read_lock(); +- } ++ dna_read_lock(); + + /* Bail out if the plug-in close function was just called. */ + if (!g_plugin_started) { +@@ -1300,9 +1295,7 @@ dna_update_config_event(time_t event_time, void *arg) + } + + bail: +- if (!nolock) { +- dna_unlock(); +- } ++ dna_unlock(); + slapi_pblock_destroy(pb); + } + +@@ -2785,7 +2778,6 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e, char **errstr) + char **generated_types = NULL; + PRUint64 setval = 0; + int i; +- int issharedconfig = 0; + + /* Bail out if the plug-in close function was just called. */ + if (!g_plugin_started) { +@@ -2803,12 +2795,7 @@ _dna_pre_op_add(Slapi_PBlock *pb, Slapi_Entry *e, char **errstr) + * We also check if we need to get the next range of values, and grab them. + * We do this here so we don't have to do it in the be_txn_preop. + */ +- /* Has write lock for config entries. */ +- issharedconfig = slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS, +- DNA_SHAREDCONFIG); +- if (!issharedconfig) { +- dna_read_lock(); +- } ++ dna_read_lock(); + + if (!PR_CLIST_IS_EMPTY(dna_global_config)) { + list = PR_LIST_HEAD(dna_global_config); +@@ -2966,9 +2953,7 @@ next: + } + } + +- if (!issharedconfig) { +- dna_unlock(); +- } ++ dna_unlock(); + + slapi_ch_array_free(generated_types); + bail: +@@ -3427,7 +3412,6 @@ static int dna_be_txn_pre_op(Slapi_PBlock *pb, int modtype) + char *type = NULL; + int numvals, e_numvals = 0; + int i, len, ret = 0; +- int issharedconfig = 0; + + slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM, + "--> dna_be_txn_pre_op\n"); +@@ -3463,12 +3447,7 @@ static int dna_be_txn_pre_op(Slapi_PBlock *pb, int modtype) + slapi_mods_init_passin(smods, mods); + } + +- /* Has write lock for config entries. */ +- issharedconfig = slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS, +- DNA_SHAREDCONFIG); +- if (!issharedconfig) { +- dna_read_lock(); +- } ++ dna_read_lock(); + + if (!PR_CLIST_IS_EMPTY(dna_global_config)) { + list = PR_LIST_HEAD(dna_global_config); +@@ -3659,9 +3638,7 @@ next: + list = PR_NEXT_LINK(list); + } + } +- if (!issharedconfig) { +- dna_unlock(); +- } ++ dna_unlock(); + bail: + + if (LDAP_CHANGETYPE_MODIFY == modtype) { +-- +1.8.1.4 + diff --git a/0040-Ticket-627-ns-slapd-crashes-sporadically-with-segmen.patch b/0040-Ticket-627-ns-slapd-crashes-sporadically-with-segmen.patch new file mode 100644 index 0000000..dc2d61e --- /dev/null +++ b/0040-Ticket-627-ns-slapd-crashes-sporadically-with-segmen.patch @@ -0,0 +1,422 @@ +From e2ee8bba6ff5e0f733142889e0ccaa08cebbdb75 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 25 Mar 2013 14:37:18 -0700 +Subject: [PATCH 40/42] Ticket #627 - ns-slapd crashes sporadically with + segmentation fault in libslapd.so + +Bug Description: Schema reload task (schema-reload.pl) was not +thread safe. + +Fix Description: Attribute Syntax is stored in the hash and +retrieved based upon the attribute syntax. When Schema reload +task is invoked, the attribute syntax objects were completely +replaced ignoring the lock protection. This patch protects +the attribute syntax replacement (attr_syntax_delete_all_for_ +schemareload) with the write lock. Also, attribute syntax +object maintains the reference count. The schema reload +respects the reference count instead of blindly deleting them. + +https://fedorahosted.org/389/ticket/627 + +Reviewed by Rich (Thank you!!) +(cherry picked from commit 81b997480956b2b6fa3a5d0e8d6abf5113a06400) +--- + ldap/servers/slapd/attrsyntax.c | 116 +++++++++++++++++++++++++++++----------- + ldap/servers/slapd/proto-slap.h | 3 ++ + ldap/servers/slapd/schema.c | 48 ++++++++++------- + 3 files changed, 117 insertions(+), 50 deletions(-) + +diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c +index ff137a8..2dabf1f 100644 +--- a/ldap/servers/slapd/attrsyntax.c ++++ b/ldap/servers/slapd/attrsyntax.c +@@ -96,12 +96,27 @@ attr_syntax_read_lock(void) + } + + void ++attr_syntax_write_lock(void) ++{ ++ if (0 != attr_syntax_init()) return; ++ ++ AS_LOCK_WRITE(oid2asi_lock); ++ AS_LOCK_WRITE(name2asi_lock); ++} ++ ++void + attr_syntax_unlock_read(void) + { +- if(name2asi_lock) AS_UNLOCK_READ(name2asi_lock); +- if(oid2asi_lock) AS_UNLOCK_READ(oid2asi_lock); ++ AS_UNLOCK_READ(name2asi_lock); ++ AS_UNLOCK_READ(oid2asi_lock); + } + ++void ++attr_syntax_unlock_write(void) ++{ ++ AS_UNLOCK_WRITE(name2asi_lock); ++ AS_UNLOCK_WRITE(oid2asi_lock); ++} + + + #if 0 +@@ -255,13 +270,17 @@ attr_syntax_get_by_oid_locking_optional( const char *oid, PRBool use_lock ) + struct asyntaxinfo *asi = 0; + if (oid2asi) + { +- if ( use_lock ) AS_LOCK_READ(oid2asi_lock); ++ if ( use_lock ) { ++ AS_LOCK_READ(oid2asi_lock); ++ } + asi = (struct asyntaxinfo *)PL_HashTableLookup_const(oid2asi, oid); + if (asi) + { + PR_AtomicIncrement( &asi->asi_refcnt ); + } +- if ( use_lock ) AS_UNLOCK_READ(oid2asi_lock); ++ if ( use_lock ) { ++ AS_UNLOCK_READ(oid2asi_lock); ++ } + } + + return asi; +@@ -279,13 +298,15 @@ attr_syntax_add_by_oid(const char *oid, struct asyntaxinfo *a, int lock) + { + if (0 != attr_syntax_init()) return; + +- if (lock) ++ if (lock) { + AS_LOCK_WRITE(oid2asi_lock); ++ } + + PL_HashTableAdd(oid2asi, oid, a); + +- if (lock) ++ if (lock) { + AS_UNLOCK_WRITE(oid2asi_lock); ++ } + } + + /* +@@ -317,12 +338,16 @@ attr_syntax_get_by_name_locking_optional(const char *name, PRBool use_lock) + struct asyntaxinfo *asi = 0; + if (name2asi) + { +- if ( use_lock ) AS_LOCK_READ(name2asi_lock); ++ if ( use_lock ) { ++ AS_LOCK_READ(name2asi_lock); ++ } + asi = (struct asyntaxinfo *)PL_HashTableLookup_const(name2asi, name); + if ( NULL != asi ) { + PR_AtomicIncrement( &asi->asi_refcnt ); + } +- if ( use_lock ) AS_UNLOCK_READ(name2asi_lock); ++ if ( use_lock ) { ++ AS_UNLOCK_READ(name2asi_lock); ++ } + } + if (!asi) /* given name may be an OID */ + asi = attr_syntax_get_by_oid_locking_optional(name, use_lock); +@@ -344,30 +369,38 @@ attr_syntax_return( struct asyntaxinfo *asi ) + } + + void +-attr_syntax_return_locking_optional( struct asyntaxinfo *asi, PRBool use_lock ) ++attr_syntax_return_locking_optional(struct asyntaxinfo *asi, PRBool use_lock) + { ++ int locked = 0; ++ if(use_lock) { ++ AS_LOCK_READ(name2asi_lock); ++ locked = 1; ++ } + if ( NULL != asi ) { +- if ( 0 == PR_AtomicDecrement( &asi->asi_refcnt )) +- { +- PRBool delete_it; +- +- if(use_lock) AS_LOCK_READ(name2asi_lock); ++ PRBool delete_it = PR_FALSE; ++ if ( 0 == PR_AtomicDecrement( &asi->asi_refcnt )) { + delete_it = asi->asi_marked_for_delete; +- if(use_lock) AS_UNLOCK_READ(name2asi_lock); +- +- if ( delete_it ) +- { +- AS_LOCK_WRITE(name2asi_lock); /* get a write lock */ +- if ( asi->asi_marked_for_delete ) /* one final check */ +- { +- /* ref count is 0 and it's flagged for +- * deletion, so it's safe to free now */ +- attr_syntax_free(asi); ++ } ++ ++ if (delete_it) { ++ if ( asi->asi_marked_for_delete ) { /* one final check */ ++ if(use_lock) { ++ AS_UNLOCK_READ(name2asi_lock); ++ AS_LOCK_WRITE(name2asi_lock); ++ } ++ /* ref count is 0 and it's flagged for ++ * deletion, so it's safe to free now */ ++ attr_syntax_free(asi); ++ if(use_lock) { ++ AS_UNLOCK_WRITE(name2asi_lock); ++ locked = 0; + } +- AS_UNLOCK_WRITE(name2asi_lock); + } + } + } ++ if(locked) { ++ AS_UNLOCK_READ(name2asi_lock); ++ } + } + + /* +@@ -384,8 +417,9 @@ attr_syntax_add_by_name(struct asyntaxinfo *a, int lock) + { + if (0 != attr_syntax_init()) return; + +- if (lock) ++ if (lock) { + AS_LOCK_WRITE(name2asi_lock); ++ } + + PL_HashTableAdd(name2asi, a->asi_name, a); + if ( a->asi_aliases != NULL ) { +@@ -396,8 +430,9 @@ attr_syntax_add_by_name(struct asyntaxinfo *a, int lock) + } + } + +- if (lock) ++ if (lock) { + AS_UNLOCK_WRITE(name2asi_lock); ++ } + } + + +@@ -943,11 +978,11 @@ attr_syntax_enumerate_attrs(AttrEnumFunc aef, void *arg, PRBool writelock ) + attr_syntax_enumerate_attrs_ext(oid2asi, aef, arg); + + if ( writelock ) { +- AS_UNLOCK_WRITE(oid2asi_lock); + AS_UNLOCK_WRITE(name2asi_lock); ++ AS_UNLOCK_WRITE(oid2asi_lock); + } else { +- AS_UNLOCK_READ(oid2asi_lock); + AS_UNLOCK_READ(name2asi_lock); ++ AS_UNLOCK_READ(oid2asi_lock); + } + } + +@@ -1045,6 +1080,21 @@ attr_syntax_delete_all() + (void *)&fi, PR_TRUE ); + } + ++/* ++ * Delete all attribute definitions without attr_syntax lock. ++ * The caller is responsible for the lock. ++ */ ++void ++attr_syntax_delete_all_for_schemareload(unsigned long flag) ++{ ++ struct attr_syntax_enum_flaginfo fi; ++ ++ memset(&fi, 0, sizeof(fi)); ++ fi.asef_flag = flag; ++ attr_syntax_enumerate_attrs_ext(oid2asi, attr_syntax_delete_if_not_flagged, ++ (void *)&fi); ++} ++ + static int + attr_syntax_init(void) + { +@@ -1165,13 +1215,19 @@ static int + attr_syntax_internal_asi_add(struct asyntaxinfo *asip, void *arg) + { + struct asyntaxinfo *asip_copy; ++ int rc = 0; ++ + if (!asip) { + return 1; + } + /* Copy is needed since when reloading the schema, + * existing syntax info is cleaned up. */ + asip_copy = attr_syntax_dup(asip); +- return attr_syntax_add(asip_copy); ++ rc = attr_syntax_add(asip_copy); ++ if (LDAP_SUCCESS != rc) { ++ attr_syntax_free(asip_copy); ++ } ++ return rc; + } + + /* Reload internal attribute syntax stashed in the internalasi hashtable. */ +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index bdcef9a..5112471 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -113,7 +113,9 @@ int attrlist_replace_with_flags(Slapi_Attr **alist, const char *type, struct ber + * attrsyntax.c + */ + void attr_syntax_read_lock(void); ++void attr_syntax_write_lock(void); + void attr_syntax_unlock_read(void); ++void attr_syntax_unlock_write(void); + int attr_syntax_exists (const char *attr_name); + void attr_syntax_delete ( struct asyntaxinfo *asip ); + #define SLAPI_SYNTAXLENGTH_NONE (-1) /* for syntaxlength parameter */ +@@ -139,6 +141,7 @@ struct asyntaxinfo *attr_syntax_get_by_name_locking_optional ( const char *name, + void attr_syntax_return( struct asyntaxinfo *asi ); + void attr_syntax_return_locking_optional( struct asyntaxinfo *asi, PRBool use_lock ); + void attr_syntax_delete_all(void); ++void attr_syntax_delete_all_for_schemareload(unsigned long flag); + + /* + * value.c +diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c +index 12f11c3..1768c7e 100644 +--- a/ldap/servers/slapd/schema.c ++++ b/ldap/servers/slapd/schema.c +@@ -1406,7 +1406,7 @@ slapi_schema_list_attribute_names(unsigned long flag) + aew.flag=flag; + + attr_syntax_enumerate_attrs(schema_list_attributes_callback, &aew, +- PR_FALSE); ++ PR_FALSE); + return aew.attrs; + } + +@@ -2409,8 +2409,9 @@ static int + schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf, + size_t errorbufsize ) + { +- int i, rc = LDAP_SUCCESS; +- struct asyntaxinfo *newasip, *oldasip; ++ int i, rc = LDAP_SUCCESS; ++ struct asyntaxinfo *newasip, *oldasip; ++ PRUint32 schema_flags = 0; + + if ( NULL == mod->mod_bvalues ) { + schema_create_errormsg( errorbuf, errorbufsize, schema_errprefix_at, +@@ -2418,8 +2419,11 @@ schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf, + return LDAP_UNWILLING_TO_PERFORM; + } + +- /* clear all of the "keep" flags */ +- attr_syntax_all_clear_flag( SLAPI_ATTR_FLAG_KEEP ); ++ slapi_pblock_get(pb, SLAPI_SCHEMA_FLAGS, &schema_flags); ++ if (!(schema_flags & (DSE_SCHEMA_NO_LOAD|DSE_SCHEMA_NO_CHECK))) { ++ /* clear all of the "keep" flags unless it's from schema-reload */ ++ attr_syntax_all_clear_flag( SLAPI_ATTR_FLAG_KEEP ); ++ } + + for ( i = 0; mod->mod_bvalues[i] != NULL; ++i ) { + if ( LDAP_SUCCESS != ( rc = read_at_ldif( mod->mod_bvalues[i]->bv_val, +@@ -2477,12 +2481,14 @@ schema_replace_attributes ( Slapi_PBlock *pb, LDAPMod *mod, char *errorbuf, + * XXXmcs: we should consider reporting an error if any read only types + * remain.... + */ +- attr_syntax_delete_all_not_flagged( SLAPI_ATTR_FLAG_KEEP +- | SLAPI_ATTR_FLAG_STD_ATTR ); ++ attr_syntax_delete_all_not_flagged( SLAPI_ATTR_FLAG_KEEP | ++ SLAPI_ATTR_FLAG_STD_ATTR ); + + clean_up_and_return: +- /* clear all of the "keep" flags */ +- attr_syntax_all_clear_flag( SLAPI_ATTR_FLAG_KEEP ); ++ if (!(schema_flags & (DSE_SCHEMA_NO_LOAD|DSE_SCHEMA_NO_CHECK))) { ++ /* clear all of the "keep" flags unless it's from schema-reload */ ++ attr_syntax_all_clear_flag( SLAPI_ATTR_FLAG_KEEP ); ++ } + + return rc; + } +@@ -3898,14 +3904,12 @@ load_schema_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *ignored, + int primary_file = 0; /* this is the primary (writeable) schema file */ + int schema_ds4x_compat = config_get_ds4_compatible_schema(); + PRUint32 flags = *(PRUint32 *)arg; +- flags |= DSE_SCHEMA_NO_GLOCK; /* don't lock global resources +- during initialization */ + + *returncode = 0; + + /* + * Note: there is no need to call schema_lock_write() here because this +- * function is only called during server startup. ++ * function is only called during server startup. + */ + + slapi_pblock_get( pb, SLAPI_DSE_IS_PRIMARY_FILE, &primary_file ); +@@ -3947,6 +3951,8 @@ load_schema_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *ignored, + if (*returncode) + return SLAPI_DSE_CALLBACK_ERROR; + ++ flags |= DSE_SCHEMA_NO_GLOCK; /* don't lock global resources ++ during initialization */ + if (!slapi_entry_attr_find(e, "objectclasses", &attr) && attr) + { + /* enumerate the values in attr */ +@@ -4017,7 +4023,6 @@ load_schema_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *ignored, + * DSE_SCHEMA_NO_CHECK -- schema won't be checked + * DSE_SCHEMA_NO_BACKEND -- don't add as backend + * DSE_SCHEMA_LOCKED -- already locked; no further lock needed +- + */ + static int + init_schema_dse_ext(char *schemadir, Slapi_Backend *be, +@@ -4123,7 +4128,7 @@ init_schema_dse_ext(char *schemadir, Slapi_Backend *be, + "DESC 'Standard schema for LDAP' SYNTAX " + "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )", + NULL, errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, +- DSE_SCHEMA_NO_GLOCK|schema_flags, 0, 0, 0); ++ schema_flags, 0, 0, 0); + } + if (rc) + { +@@ -4196,7 +4201,7 @@ init_schema_dse(const char *configdir) + { + schemadir = slapi_ch_smprintf("%s/%s", configdir, SCHEMA_SUBDIR_NAME); + } +- rc = init_schema_dse_ext(schemadir, NULL, &pschemadse, 0); ++ rc = init_schema_dse_ext(schemadir, NULL, &pschemadse, DSE_SCHEMA_NO_GLOCK); + slapi_ch_free_string(&schemadir); + return rc; + } +@@ -4860,14 +4865,14 @@ slapi_validate_schema_files(char *schemadir) + { + struct dse *my_pschemadse = NULL; + int rc = init_schema_dse_ext(schemadir, NULL, &my_pschemadse, +- DSE_SCHEMA_NO_LOAD | DSE_SCHEMA_NO_BACKEND); ++ DSE_SCHEMA_NO_LOAD | DSE_SCHEMA_NO_BACKEND); + dse_destroy(my_pschemadse); /* my_pschemadse was created just to +- validate the schema */ ++ validate the schema */ + if (rc) { + return LDAP_SUCCESS; + } else { + slapi_log_error( SLAPI_LOG_FATAL, "schema_reload", +- "schema file validation failed\n" ); ++ "schema file validation failed\n" ); + return LDAP_OBJECT_CLASS_VIOLATION; + } + } +@@ -4893,10 +4898,13 @@ slapi_reload_schema_files(char *schemadir) + } + slapi_be_Wlock(be); /* be lock must be outer of schemafile lock */ + reload_schemafile_lock(); +- attr_syntax_delete_all(); ++ /* Exclude attr_syntax not to grab from the hash table while cleaning up */ ++ attr_syntax_write_lock(); ++ attr_syntax_delete_all_for_schemareload(SLAPI_ATTR_FLAG_KEEP); + oc_delete_all_nolock(); ++ attr_syntax_unlock_write(); + rc = init_schema_dse_ext(schemadir, be, &my_pschemadse, +- DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_LOCKED); ++ DSE_SCHEMA_NO_CHECK | DSE_SCHEMA_LOCKED); + if (rc) { + dse_destroy(pschemadse); + pschemadse = my_pschemadse; +-- +1.8.1.4 + diff --git a/0041-Ticket-628-crash-in-aci-evaluation.patch b/0041-Ticket-628-crash-in-aci-evaluation.patch new file mode 100644 index 0000000..9182aa8 --- /dev/null +++ b/0041-Ticket-628-crash-in-aci-evaluation.patch @@ -0,0 +1,81 @@ +From d362196eda904e95cf99e7c784b7dfda36b05e21 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 25 Mar 2013 10:35:31 -0400 +Subject: [PATCH 41/42] Ticket 628 - crash in aci evaluation + +Bug Description: When trying to get effective rights on a entry that does not exist, + can lead to a crash from dereferencing a NULL pointer. + +Fix Description: Check for NULL entry pointers and return the appropriate error. + +https://fedorahosted.org/389/ticket/628 + +Reviewed by: nhosoi(Thanks Noriko!) +(cherry picked from commit ac8ceb91e42c31672147018d9d654879970dd38d) +--- + ldap/servers/slapd/entry.c | 28 +++++++++++++++++----------- + 1 file changed, 17 insertions(+), 11 deletions(-) + +diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c +index 58a9d51..1926417 100644 +--- a/ldap/servers/slapd/entry.c ++++ b/ldap/servers/slapd/entry.c +@@ -2312,7 +2312,11 @@ slapi_entry_next_attr( const Slapi_Entry *e, Slapi_Attr *prevattr, Slapi_Attr ** + int + slapi_entry_attr_find( const Slapi_Entry *e, const char *type, Slapi_Attr **a ) + { +- int r= -1; ++ int r = -1; ++ ++ if(e == NULL){ ++ return r; ++ } + *a = attrlist_find( e->e_attrs, type ); + if (*a != NULL) + { +@@ -2323,11 +2327,11 @@ slapi_entry_attr_find( const Slapi_Entry *e, const char *type, Slapi_Attr **a ) + * Our state information storage scheme can cause this, since + * we have to hang onto the deleted value state information. + */ +- *a= NULL; ++ *a = NULL; + } + else + { +- r= 0; ++ r = 0; + } + } + return r; +@@ -2951,18 +2955,20 @@ slapi_entry_attr_has_syntax_value(const Slapi_Entry *e, + const char *type, + const Slapi_Value *value) + { +- int r= 0; +- Slapi_Attr *attr; ++ int r = 0; ++ Slapi_Attr *attr; + ++ if(e == NULL){ ++ return r; ++ } + if(slapi_entry_attr_find(e, type, &attr)==0) + { +- const struct berval *bv = slapi_value_get_berval(value); ++ const struct berval *bv = slapi_value_get_berval(value); + +- if ( bv != NULL) { +- r = (slapi_attr_value_find(attr, bv) == 0); +- } +- +- } ++ if ( bv != NULL) { ++ r = (slapi_attr_value_find(attr, bv) == 0); ++ } ++ } + + return r; + } +-- +1.8.1.4 + diff --git a/0042-Ticket-47308-unintended-information-exposure-when-an.patch b/0042-Ticket-47308-unintended-information-exposure-when-an.patch new file mode 100644 index 0000000..71d64fb --- /dev/null +++ b/0042-Ticket-47308-unintended-information-exposure-when-an.patch @@ -0,0 +1,40 @@ +From 4062dd1bd7c34b04208a51181af5573b4e257f9d Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 28 Mar 2013 11:08:18 -0700 +Subject: [PATCH 42/42] Ticket #47308 - unintended information exposure when + anonymous access is set to rootdse + +Bug description: The actual search base was not being checked +at all. There was a check for the search base when this feature +was initially implemented, but it was inadvertently removed when +changes were made to reduce the DN normalization throughout the +source tree (commit f6397113666f06848412bb12f754f04258cfa5fa). + +Fix description: This patch adds the search base check back. + +Note: CVE-2013-1897 + +https://fedorahosted.org/389/ticket/47308 + +Reviewed by Rich, Noriko and Mark. +(cherry picked from commit 4b2d700b77c1d4a0a2ad6592e2296068a200cbdd) +--- + ldap/servers/slapd/search.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c +index c3d51d6..7719727 100644 +--- a/ldap/servers/slapd/search.c ++++ b/ldap/servers/slapd/search.c +@@ -141,7 +141,7 @@ do_search( Slapi_PBlock *pb ) + /* If anonymous access is only allowed for searching the root DSE, + * we need to reject any other anonymous search attempts. */ + if ((slapi_sdn_get_dn(&(operation->o_sdn)) == NULL) && +- (scope != LDAP_SCOPE_BASE) && ++ ((rawbase && strlen(rawbase) > 0) || (scope != LDAP_SCOPE_BASE)) && + (config_get_anon_access_switch() == SLAPD_ANON_ACCESS_ROOTDSE)) { + op_shared_log_error_access(pb, "SRCH", rawbase?rawbase:"", + "anonymous search not allowed"); +-- +1.8.1.4 + diff --git a/0043-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch b/0043-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch new file mode 100644 index 0000000..04585f0 --- /dev/null +++ b/0043-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch @@ -0,0 +1,35 @@ +From 77f1a1314a267c9f5b7a395344cfb3af57dcd3d6 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 28 Mar 2013 15:30:13 -0700 +Subject: [PATCH] Ticket 623 - cleanAllRUV task fails to cleanup config upon + completion + +Bug description: coverity reported "13158 - Logically dead code' + +Fix description: csn_as_string returns allocated csn string, +which needs to be reassigned to csnstr. + +https://fedorahosted.org/389/ticket/623 + +Reviewed by Nathan (Thank you!!) +(cherry picked from commit d5fe6ba773ef2655845df5152901fd5bb6a9d4e9) +--- + ldap/servers/plugins/replication/repl5_replica_config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 8710c04..0e29c6f 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -2367,7 +2367,7 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + /* + * If there is no maxcsn, set the proper csnstr + */ +- csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr); ++ csnstr = csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr); + if(csnstr == NULL || csn_get_replicaid(clean_data->maxcsn) == 0){ + csnstr = slapi_ch_strdup("00000000000000000000"); + } +-- +1.8.1.4 + diff --git a/0044-Coverity-fix.patch b/0044-Coverity-fix.patch new file mode 100644 index 0000000..752f9e9 --- /dev/null +++ b/0044-Coverity-fix.patch @@ -0,0 +1,27 @@ +From 90e031b5937eacf76485befb67f9c4e35c8c1413 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 9 Apr 2013 16:48:54 -0700 +Subject: [PATCH 44/47] Coverity fix 13139 - Dereference after NULL check in + slapi_attr_value_normalize_ext() + +--- + ldap/servers/slapd/plugin_syntax.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/ldap/servers/slapd/plugin_syntax.c b/ldap/servers/slapd/plugin_syntax.c +index 840fa7a..1635e53 100644 +--- a/ldap/servers/slapd/plugin_syntax.c ++++ b/ldap/servers/slapd/plugin_syntax.c +@@ -968,8 +968,7 @@ slapi_attr_value_normalize_ext( + break; + } + +- if (!norm_fn) { +- /* no matching rule specific normalizer specified - use syntax default */ ++ if (!norm_fn && sattr->a_plugin) { + norm_fn = sattr->a_plugin->plg_syntax_normalize; + } + if (norm_fn) { +-- +1.8.1.4 + diff --git a/0045-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch b/0045-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch new file mode 100644 index 0000000..ab27cb9 --- /dev/null +++ b/0045-Ticket-623-cleanAllRUV-task-fails-to-cleanup-config-.patch @@ -0,0 +1,38 @@ +From 9d5fc8a90860aa3411f7a300f23acad855de2e67 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Wed, 10 Apr 2013 11:01:12 -0700 +Subject: [PATCH 45/47] Ticket 623 - cleanAllRUV task fails to cleanup config + upon completion + +Coverity defect: 13161: Resource leak + +Description: commit d5fe6ba773ef2655845df5152901fd5bb6a9d4e9 +(coverity fix for "13158 - Logically dead code') introduced +this resource leak. Free csnstr before assiging strdup'ed +string. + +https://fedorahosted.org/389/ticket/623 + +Reviewed by Rich (Thank you!!) +(cherry picked from commit 288fb33afc715cb5399c600a8065247bb852d87c) +--- + ldap/servers/plugins/replication/repl5_replica_config.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 0e29c6f..bbbe87e 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -2368,7 +2368,8 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + * If there is no maxcsn, set the proper csnstr + */ + csnstr = csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr); +- if(csnstr == NULL || csn_get_replicaid(clean_data->maxcsn) == 0){ ++ if ((csnstr == NULL) || (csn_get_replicaid(clean_data->maxcsn) == 0)) { ++ slapi_ch_free_string(&csnstr); /* no problem to pass NULL */ + csnstr = slapi_ch_strdup("00000000000000000000"); + } + /* +-- +1.8.1.4 + diff --git a/0046-Ticket-47385-DS-not-shutting-down-when-disk-monitori.patch b/0046-Ticket-47385-DS-not-shutting-down-when-disk-monitori.patch new file mode 100644 index 0000000..bed7f3d --- /dev/null +++ b/0046-Ticket-47385-DS-not-shutting-down-when-disk-monitori.patch @@ -0,0 +1,238 @@ +From 5b5f57e8f008a342d82c7aa2d6a6574df7a3f14e Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 6 Jun 2013 15:30:41 -0400 +Subject: [PATCH] Ticket 47385 - DS not shutting down when disk monitoring threshold is reached + +Bug Description: If verbose logging is enabled, it fails to correctly + identify that the logging was disabled, and it gets + stuck in an endless loop - never shutting the server down. + + Also, whe the server does shutdown due to a disk full, the + pid file is not removed. + +Fix Description: Check for the two possible error log levels that indicate + verbose logging is disabled. There were also logic errors + when determining if it was ok to disable access/audit logging, + and if to delete rotated logs. + + Also removed the "nsslapd-disk-monitoring-preserve-logging" + setting, as it really didn't served a purpose because it was + basically the same as "nsslapd-disk-monitoring-logging-critical". + + Lastly, if the server is being shutdown from a "disk full" + condition, then we need to manually remove the pidfile. + +https://fedorahosted.org/389/ticket/47385 + +Reviewed by: Noriko(Thanks!) +--- + ldap/servers/slapd/daemon.c | 31 ++++++++++++++++++++----------- + ldap/servers/slapd/libglobs.c | 28 ---------------------------- + ldap/servers/slapd/proto-slap.h | 2 -- + ldap/servers/slapd/slap.h | 2 -- + 4 files changed, 20 insertions(+), 43 deletions(-) + +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index b611f5c..5cc643a 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -711,7 +711,6 @@ disk_monitoring_thread(void *nothing) + time_t now = 0; + int deleted_rotated_logs = 0; + int logging_critical = 0; +- int preserve_logging = 0; + int passed_threshold = 0; + int verbose_logging = 0; + int using_accesslog = 0; +@@ -741,7 +740,6 @@ disk_monitoring_thread(void *nothing) + * Get the config settings, as they could have changed + */ + logging_critical = config_get_disk_logging_critical(); +- preserve_logging = config_get_disk_preserve_logging(); + grace_period = 60 * config_get_disk_grace_period(); /* convert it to seconds */ + verbose_logging = config_get_errorlog_level(); + threshold = config_get_disk_threshold(); +@@ -798,18 +796,21 @@ disk_monitoring_thread(void *nothing) + } + /* + * If we are low, see if we are using verbose error logging, and turn it off ++ * if logging is not critical + */ +- if(verbose_logging){ ++ if(verbose_logging != 0 && verbose_logging != LDAP_DEBUG_ANY){ + LDAPDebug(LDAP_DEBUG_ANY, "Disk space is low on disk (%s), remaining space: %d Kb, " +- "setting error loglevel to zero.\n", dirstr, (disk_space / 1024), 0); +- config_set_errorlog_level(CONFIG_LOGLEVEL_ATTRIBUTE, 0, errorbuf, CONFIG_APPLY); ++ "temporarily setting error loglevel to zero.\n", dirstr, ++ (disk_space / 1024), 0); ++ /* Setting the log level back to zero, actually sets the value to LDAP_DEBUG_ANY */ ++ config_set_errorlog_level(CONFIG_LOGLEVEL_ATTRIBUTE, "0", errorbuf, CONFIG_APPLY); + continue; + } + /* + * If we are low, there's no verbose logging, logs are not critical, then disable the + * access/audit logs, log another error, and continue. + */ +- if(!logs_disabled && (!preserve_logging || !logging_critical)){ ++ if(!logs_disabled && !logging_critical){ + if(disk_space < previous_mark){ + LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, " + "disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0); +@@ -823,7 +824,7 @@ disk_monitoring_thread(void *nothing) + * If we are low, we turned off verbose logging, logs are not critical, and we disabled + * access/audit logging, then delete the rotated logs, log another error, and continue. + */ +- if(!deleted_rotated_logs && (!preserve_logging || !logging_critical)){ ++ if(!deleted_rotated_logs && !logging_critical){ + if(disk_space < previous_mark){ + LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, " + "deleting rotated logs.\n", dirstr, (disk_space / 1024), 0); +@@ -872,10 +873,10 @@ disk_monitoring_thread(void *nothing) + */ + LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now acceptable (%d bytes). Aborting" + " shutdown, and restoring the log settings.\n",disk_space,0,0); +- if(!preserve_logging && using_accesslog){ ++ if(logs_disabled && using_accesslog){ + config_set_accesslog_enabled(LOGGING_ON); + } +- if(!preserve_logging && using_auditlog){ ++ if(logs_disabled && using_auditlog){ + config_set_auditlog_enabled(LOGGING_ON); + } + deleted_rotated_logs = 0; +@@ -892,7 +893,7 @@ disk_monitoring_thread(void *nothing) + */ + LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb." + " Signaling slapd for shutdown...\n", dirstr, (disk_space / 1024), 0); +- g_set_shutdown( SLAPI_SHUTDOWN_EXIT ); ++ g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL ); + return; + } + time(&now); +@@ -909,7 +910,8 @@ disk_monitoring_thread(void *nothing) + */ + LDAPDebug(LDAP_DEBUG_ANY, "Disk space is still too low (%d Kb). Signaling slapd for shutdown...\n", + (disk_space / 1024), 0, 0); +- g_set_shutdown( SLAPI_SHUTDOWN_EXIT ); ++ g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL ); ++ + return; + } + } +@@ -1379,6 +1381,13 @@ void slapd_daemon( daemon_ports_t *ports ) + + #ifdef _WIN32 + WSACleanup(); ++#else ++ if ( g_get_shutdown() == SLAPI_SHUTDOWN_DISKFULL ){ ++ /* This is a server-induced shutdown, we need to manually remove the pid file */ ++ if( unlink(get_pid_file()) ){ ++ LDAPDebug( LDAP_DEBUG_ANY, "Failed to remove pid file %s\n", get_pid_file(), 0, 0 ); ++ } ++ } + #endif + } + +diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c +index 3226ede..02e9df1 100644 +--- a/ldap/servers/slapd/libglobs.c ++++ b/ldap/servers/slapd/libglobs.c +@@ -687,10 +687,6 @@ static struct config_get_and_set { + NULL, 0, + (void**)&global_slapdFrontendConfig.disk_logging_critical, + CONFIG_ON_OFF, (ConfigGetFunc)config_get_disk_logging_critical}, +- {CONFIG_DISK_PRESERVE_LOGGING, config_set_disk_preserve_logging, +- NULL, 0, +- (void**)&global_slapdFrontendConfig.disk_preserve_logging, +- CONFIG_ON_OFF, (ConfigGetFunc)config_get_disk_preserve_logging}, + #ifdef MEMPOOL_EXPERIMENTAL + ,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch, + NULL, 0, +@@ -1090,7 +1086,6 @@ FrontendConfig_init () { + cfg->disk_monitoring = LDAP_OFF; + cfg->disk_threshold = 2097152; /* 2 mb */ + cfg->disk_grace_period = 60; /* 1 hour */ +- cfg->disk_preserve_logging = LDAP_OFF; + cfg->disk_logging_critical = LDAP_OFF; + + #ifdef MEMPOOL_EXPERIMENTAL +@@ -1259,17 +1254,6 @@ config_set_disk_threshold( const char *attrname, char *value, char *errorbuf, in + } + + int +-config_set_disk_preserve_logging( const char *attrname, char *value, char *errorbuf, int apply ) +-{ +- slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); +- int retVal = LDAP_SUCCESS; +- +- retVal = config_set_onoff ( attrname, value, &(slapdFrontendConfig->disk_preserve_logging), +- errorbuf, apply); +- return retVal; +-} +- +-int + config_set_disk_logging_critical( const char *attrname, char *value, char *errorbuf, int apply ) + { + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); +@@ -3742,18 +3726,6 @@ config_get_disk_monitoring(){ + } + + int +-config_get_disk_preserve_logging(){ +- slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); +- int retVal; +- +- CFG_LOCK_READ(slapdFrontendConfig); +- retVal = slapdFrontendConfig->disk_preserve_logging; +- CFG_UNLOCK_READ(slapdFrontendConfig); +- +- return retVal; +-} +- +-int + config_get_disk_logging_critical(){ + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int retVal; +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index 5112471..17b1e99 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -388,7 +388,6 @@ int config_set_default_naming_context( const char *attrname, char *value, char * + int config_set_disk_monitoring( const char *attrname, char *value, char *errorbuf, int apply ); + int config_set_disk_threshold( const char *attrname, char *value, char *errorbuf, int apply ); + int config_set_disk_grace_period( const char *attrname, char *value, char *errorbuf, int apply ); +-int config_set_disk_preserve_logging( const char *attrname, char *value, char *errorbuf, int apply ); + int config_set_disk_logging_critical( const char *attrname, char *value, char *errorbuf, int apply ); + int config_set_auditlog_unhashed_pw(const char *attrname, char *value, char *errorbuf, int apply); + +@@ -544,7 +543,6 @@ int config_get_accesslog_logging_enabled(); + int config_get_disk_monitoring(); + long config_get_disk_threshold(); + int config_get_disk_grace_period(); +-int config_get_disk_preserve_logging(); + int config_get_disk_logging_critical(); + + int is_abspath(const char *); +diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h +index eea025a..e0b261d 100644 +--- a/ldap/servers/slapd/slap.h ++++ b/ldap/servers/slapd/slap.h +@@ -2001,7 +2001,6 @@ typedef struct _slapdEntryPoints { + #define CONFIG_DISK_MONITORING "nsslapd-disk-monitoring" + #define CONFIG_DISK_THRESHOLD "nsslapd-disk-monitoring-threshold" + #define CONFIG_DISK_GRACE_PERIOD "nsslapd-disk-monitoring-grace-period" +-#define CONFIG_DISK_PRESERVE_LOGGING "nsslapd-disk-monitoring-preserve-logging" + #define CONFIG_DISK_LOGGING_CRITICAL "nsslapd-disk-monitoring-logging-critical" + + #ifdef MEMPOOL_EXPERIMENTAL +@@ -2236,7 +2235,6 @@ typedef struct _slapdFrontendConfig { + int disk_monitoring; + int disk_threshold; + int disk_grace_period; +- int disk_preserve_logging; + int disk_logging_critical; + } slapdFrontendConfig_t; + +-- +1.7.1 + diff --git a/0047-CVE-2013-2219-ACLs-inoperative-in-some-search-scenar.patch b/0047-CVE-2013-2219-ACLs-inoperative-in-some-search-scenar.patch new file mode 100644 index 0000000..f2b2614 --- /dev/null +++ b/0047-CVE-2013-2219-ACLs-inoperative-in-some-search-scenar.patch @@ -0,0 +1,98 @@ +From 16b2868a1314660f00afadaaf94a73e0346203e9 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 1 Jul 2013 14:25:16 -0400 +Subject: [PATCH] CVE-2013-2219 ACLs inoperative in some search scenarios + +--- + ldap/servers/plugins/acl/acl.c | 6 +++++- + ldap/servers/plugins/acl/acl.h | 1 + + ldap/servers/plugins/acl/aclutil.c | 11 +++++++++++ + ldap/servers/slapd/filterentry.c | 14 ++++++++++---- + 4 files changed, 27 insertions(+), 5 deletions(-) + +diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c +index 3389404..4516cf8 100644 +--- a/ldap/servers/plugins/acl/acl.c ++++ b/ldap/servers/plugins/acl/acl.c +@@ -2136,7 +2136,11 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int * + * calculated from the targetdn and stored judiciously there + */ + matched_val = (char *)acl_ht_lookup( aclpb->aclpb_macro_ht, +- (PLHashNumber)aci->aci_index); ++ (PLHashNumber)aci->aci_index); ++ } else { ++ /* new entry, remove macro evaluation from hash table */ ++ acl_ht_remove_and_free( aclpb->aclpb_macro_ht, ++ (PLHashNumber)aci->aci_index); + } + if ( matched_val == NULL && + (aclpb->aclpb_res_type & (ACLPB_NEW_ENTRY | ACLPB_EFFECTIVE_RIGHTS))) { +diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h +index 28c38e7..e2b04c3 100644 +--- a/ldap/servers/plugins/acl/acl.h ++++ b/ldap/servers/plugins/acl/acl.h +@@ -928,6 +928,7 @@ int aclutil_str_append_ext(char **dest, size_t *dlen, const char *src, size_t sl + + /* acl hash table functions */ + void acl_ht_add_and_freeOld(acl_ht_t * acl_ht, PLHashNumber key,char *value); ++void acl_ht_remove_and_free(acl_ht_t * acl_ht, PLHashNumber key); + acl_ht_t *acl_ht_new(void); + void acl_ht_free_all_entries_and_values( acl_ht_t *acl_ht); + void acl_ht_remove( acl_ht_t *acl_ht, PLHashNumber key); +diff --git a/ldap/servers/plugins/acl/aclutil.c b/ldap/servers/plugins/acl/aclutil.c +index 7097540..77ec35f 100644 +--- a/ldap/servers/plugins/acl/aclutil.c ++++ b/ldap/servers/plugins/acl/aclutil.c +@@ -1396,6 +1396,17 @@ void acl_ht_add_and_freeOld(acl_ht_t * acl_ht, + PL_HashTableAdd( acl_ht, (const void *)pkey, value); + } + ++void acl_ht_remove_and_free(acl_ht_t * acl_ht, ++ PLHashNumber key){ ++ char *old_value = NULL; ++ uintptr_t pkey = (uintptr_t)key; ++ ++ if ( (old_value = (char *)acl_ht_lookup( acl_ht, key)) != NULL ) { ++ acl_ht_remove( acl_ht, key); ++ slapi_ch_free_string(&old_value); ++ } ++} ++ + /* + * Return a new acl_ht_t * + */ +diff --git a/ldap/servers/slapd/filterentry.c b/ldap/servers/slapd/filterentry.c +index 549bac7..880169a 100644 +--- a/ldap/servers/slapd/filterentry.c ++++ b/ldap/servers/slapd/filterentry.c +@@ -1037,8 +1037,11 @@ vattr_test_filter_list( + for ( f = flist; f != NULL; f = f->f_next ) { + if ( slapi_vattr_filter_test_ext_internal( pb, e, f, verify_access, only_check_access, access_check_done ) != 0 ) { + /* optimize AND evaluation */ +- if ( ftype == LDAP_FILTER_AND ) { +- /* one false is failure */ ++ if ( ftype == LDAP_FILTER_AND || verify_access) { ++ /* one false is failure ++ * for AND all components need to match ++ * and for AND and OR access to ALL filter attributes is required ++ */ + nomatch = 1; + break; + } +@@ -1046,8 +1049,11 @@ vattr_test_filter_list( + nomatch = 0; + + /* optimize OR evaluation too */ +- if ( ftype == LDAP_FILTER_OR ) { +- /* only one needs to be true */ ++ if ( ftype == LDAP_FILTER_OR && !verify_access) { ++ /* access to all atributes needs to be evaluated ++ * for filter matching ++ * only one needs to be true ++ */ + break; + } + } +-- +1.7.1 + diff --git a/0048-Tickets-47427-47385-Disk-Monitoring-Fixes.patch b/0048-Tickets-47427-47385-Disk-Monitoring-Fixes.patch new file mode 100644 index 0000000..ac03f0c --- /dev/null +++ b/0048-Tickets-47427-47385-Disk-Monitoring-Fixes.patch @@ -0,0 +1,227 @@ +From 6fb1ca2bc3f601b33f5dd69e5892175bae123d7c Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 12 Jul 2013 16:52:57 -0400 +Subject: [PATCH] Tickets 47427 & 47385 - Disk Monitoring Fixes + +Bug Description: + + 47427 - Overflow of treshold setting + 47385 - Server not shutting down as expected when disks fill up. + +Fix Description: + + 47427 - Change data type from "int" to PRUint64 for thresold and other size related variables + 47385 - removed unnecessary checks(if free disk space is continuing to drop). + +https://fedorahosted.org/389/ticket/47385 +https://fedorahosted.org/389/ticket/47427 + +Reviewed by: richm & nhosoi(Thanks!!) +--- + ldap/servers/slapd/daemon.c | 50 ++++++++++++++++++--------------------- + ldap/servers/slapd/libglobs.c | 11 ++++---- + ldap/servers/slapd/proto-slap.h | 2 +- + ldap/servers/slapd/slap.h | 2 +- + 4 files changed, 31 insertions(+), 34 deletions(-) + +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index 5cc643a..b161ae6 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -638,16 +638,16 @@ disk_mon_get_dirs(char ***list, int logs_critical){ + * directory. + */ + char * +-disk_mon_check_diskspace(char **dirs, PRInt64 threshold, PRInt64 *disk_space) ++disk_mon_check_diskspace(char **dirs, PRUint64 threshold, PRUint64 *disk_space) + { + #ifdef LINUX + struct statfs buf; + #else + struct statvfs buf; + #endif +- PRInt64 worst_disk_space = threshold; +- PRInt64 freeBytes = 0; +- PRInt64 blockSize = 0; ++ PRUint64 worst_disk_space = threshold; ++ PRUint64 freeBytes = 0; ++ PRUint64 blockSize = 0; + char *worst_dir = NULL; + int hit_threshold = 0; + int i = 0; +@@ -704,9 +704,10 @@ disk_monitoring_thread(void *nothing) + char errorbuf[BUFSIZ]; + char **dirs = NULL; + char *dirstr = NULL; +- PRInt64 previous_mark = 0; +- PRInt64 disk_space = 0; +- PRInt64 threshold = 0; ++ PRUint64 previous_mark = 0; ++ PRUint64 disk_space = 0; ++ PRUint64 threshold = 0; ++ PRUint64 halfway = 0; + time_t start = 0; + time_t now = 0; + int deleted_rotated_logs = 0; +@@ -718,7 +719,6 @@ disk_monitoring_thread(void *nothing) + int logs_disabled = 0; + int grace_period = 0; + int first_pass = 1; +- int halfway = 0; + int ok_now = 0; + + while(!g_get_shutdown()) { +@@ -789,7 +789,7 @@ disk_monitoring_thread(void *nothing) + * Check if we are already critical + */ + if(disk_space < 4096){ /* 4 k */ +- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb. " ++ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %" NSPRIu64 " Kb. " + "Signaling slapd for shutdown...\n", dirstr , (disk_space / 1024), 0); + g_set_shutdown( SLAPI_SHUTDOWN_EXIT ); + return; +@@ -799,7 +799,7 @@ disk_monitoring_thread(void *nothing) + * if logging is not critical + */ + if(verbose_logging != 0 && verbose_logging != LDAP_DEBUG_ANY){ +- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is low on disk (%s), remaining space: %d Kb, " ++ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is low on disk (%s), remaining space: %" NSPRIu64 " Kb, " + "temporarily setting error loglevel to zero.\n", dirstr, + (disk_space / 1024), 0); + /* Setting the log level back to zero, actually sets the value to LDAP_DEBUG_ANY */ +@@ -811,13 +811,11 @@ disk_monitoring_thread(void *nothing) + * access/audit logs, log another error, and continue. + */ + if(!logs_disabled && !logging_critical){ +- if(disk_space < previous_mark){ +- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, " +- "disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0); +- config_set_accesslog_enabled(LOGGING_OFF); +- config_set_auditlog_enabled(LOGGING_OFF); +- logs_disabled = 1; +- } ++ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %" NSPRIu64 " Kb, " ++ "disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0); ++ config_set_accesslog_enabled(LOGGING_OFF); ++ config_set_auditlog_enabled(LOGGING_OFF); ++ logs_disabled = 1; + continue; + } + /* +@@ -825,19 +823,17 @@ disk_monitoring_thread(void *nothing) + * access/audit logging, then delete the rotated logs, log another error, and continue. + */ + if(!deleted_rotated_logs && !logging_critical){ +- if(disk_space < previous_mark){ +- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, " +- "deleting rotated logs.\n", dirstr, (disk_space / 1024), 0); +- log__delete_rotated_logs(); +- deleted_rotated_logs = 1; +- } ++ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %" NSPRIu64 " Kb, " ++ "deleting rotated logs.\n", dirstr, (disk_space / 1024), 0); ++ log__delete_rotated_logs(); ++ deleted_rotated_logs = 1; + continue; + } + /* + * Ok, we've done what we can, log a message if we continue to lose available disk space + */ + if(disk_space < previous_mark){ +- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb\n", ++ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %" NSPRIu64 " Kb\n", + dirstr, (disk_space / 1024), 0); + } + /* +@@ -849,7 +845,7 @@ disk_monitoring_thread(void *nothing) + * + */ + if(disk_space < halfway){ +- LDAPDebug(LDAP_DEBUG_ANY, "Disk space on (%s) is too far below the threshold(%d bytes). " ++ LDAPDebug(LDAP_DEBUG_ANY, "Disk space on (%s) is too far below the threshold(%" NSPRIu64 " bytes). " + "Waiting %d minutes for disk space to be cleaned up before shutting slapd down...\n", + dirstr, threshold, (grace_period / 60)); + time(&start); +@@ -871,7 +867,7 @@ disk_monitoring_thread(void *nothing) + /* + * Excellent, we are back to acceptable levels, reset everything... + */ +- LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now acceptable (%d bytes). Aborting" ++ LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now acceptable (%" NSPRIu64 " bytes). Aborting" + " shutdown, and restoring the log settings.\n",disk_space,0,0); + if(logs_disabled && using_accesslog){ + config_set_accesslog_enabled(LOGGING_ON); +@@ -891,7 +887,7 @@ disk_monitoring_thread(void *nothing) + /* + * Disk space is critical, log an error, and shut it down now! + */ +- LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb." ++ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %" NSPRIu64 " Kb." + " Signaling slapd for shutdown...\n", dirstr, (disk_space / 1024), 0); + g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL ); + return; +diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c +index 02e9df1..db0a221 100644 +--- a/ldap/servers/slapd/libglobs.c ++++ b/ldap/servers/slapd/libglobs.c +@@ -1228,17 +1228,18 @@ config_set_disk_threshold( const char *attrname, char *value, char *errorbuf, in + { + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int retVal = LDAP_SUCCESS; +- long threshold = 0; ++ PRUint64 threshold = 0; + char *endp = NULL; + + if ( config_value_is_null( attrname, value, errorbuf, 0 )) { + return LDAP_OPERATIONS_ERROR; + } + +- threshold = strtol(value, &endp, 10); ++ errno = 0; ++ threshold = strtoll(value, &endp, 10); + +- if ( *endp != '\0' || threshold < 2048 ) { +- PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: \"%s\" is invalid, threshold must be greater than 2048 and less then %ld", ++ if ( *endp != '\0' || threshold < 4096 || errno == ERANGE ) { ++ PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: \"%s\" is invalid, threshold must be greater than 4096 and less then %lu", + attrname, value, LONG_MAX ); + retVal = LDAP_OPERATIONS_ERROR; + return retVal; +@@ -3749,7 +3750,7 @@ config_get_disk_grace_period(){ + return retVal; + } + +-long ++PRUint64 + config_get_disk_threshold(){ + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + long retVal; +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index 17b1e99..9d3a16d 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -541,7 +541,7 @@ void config_set_accesslog_enabled(int value); + void config_set_auditlog_enabled(int value); + int config_get_accesslog_logging_enabled(); + int config_get_disk_monitoring(); +-long config_get_disk_threshold(); ++PRUint64 config_get_disk_threshold(); + int config_get_disk_grace_period(); + int config_get_disk_logging_critical(); + +diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h +index e0b261d..403ea8a 100644 +--- a/ldap/servers/slapd/slap.h ++++ b/ldap/servers/slapd/slap.h +@@ -2233,7 +2233,7 @@ typedef struct _slapdFrontendConfig { + + /* disk monitoring */ + int disk_monitoring; +- int disk_threshold; ++ PRUint64 disk_threshold; + int disk_grace_period; + int disk_logging_critical; + } slapdFrontendConfig_t; +-- +1.7.1 + diff --git a/0049-Ticket-47427-Overflow-in-nsslapd-disk-monitoring-thr.patch b/0049-Ticket-47427-Overflow-in-nsslapd-disk-monitoring-thr.patch new file mode 100644 index 0000000..0aa7811 --- /dev/null +++ b/0049-Ticket-47427-Overflow-in-nsslapd-disk-monitoring-thr.patch @@ -0,0 +1,36 @@ +From 5c8353f8d66177dbfee234a04a147ec60cbbdb8b Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 25 Jul 2013 17:27:16 -0400 +Subject: [PATCH 49/99] Ticket 47427 - Overflow in + nsslapd-disk-monitoring-threshold + + Bug Description: If you directory try and set the threshold to -2, + the server allows it, but it should be rejected. + + Fix Description: Use a signed int when parsing the value. + + https://fedorahosted.org/389/ticket/47427 + https://bugzilla.redhat.com/show_bug.cgi?id=984970 + + Reviewed by: richm(Thanks!) +(cherry picked from commit 920bb3f883b5e678ab95fd8e9bcf25e92dbb7e84) +--- + ldap/servers/slapd/libglobs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c +index 0dc4cf5..cf1f73e 100644 +--- a/ldap/servers/slapd/libglobs.c ++++ b/ldap/servers/slapd/libglobs.c +@@ -1228,7 +1228,7 @@ config_set_disk_threshold( const char *attrname, char *value, char *errorbuf, in + { + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int retVal = LDAP_SUCCESS; +- PRUint64 threshold = 0; ++ PRInt64 threshold = 0; + char *endp = NULL; + + if ( config_value_is_null( attrname, value, errorbuf, 0 )) { +-- +1.8.1.4 + diff --git a/0050-Disk-Monitoring-fix-log-output-Ticket-47427.patch b/0050-Disk-Monitoring-fix-log-output-Ticket-47427.patch new file mode 100644 index 0000000..8e438bc --- /dev/null +++ b/0050-Disk-Monitoring-fix-log-output-Ticket-47427.patch @@ -0,0 +1,28 @@ +From 07c8338606c8c4cd223ebfacaeac857dff0bf03e Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 25 Jul 2013 17:38:12 -0400 +Subject: [PATCH 50/99] Disk Monitoring - fix log output (Ticket 47427) (cherry + picked from commit adb834c7c5dbc114868a68e9baa3d835cfb64cc1) + +--- + ldap/servers/slapd/daemon.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index b161ae6..0304e4a 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -867,8 +867,8 @@ disk_monitoring_thread(void *nothing) + /* + * Excellent, we are back to acceptable levels, reset everything... + */ +- LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now acceptable (%" NSPRIu64 " bytes). Aborting" +- " shutdown, and restoring the log settings.\n",disk_space,0,0); ++ LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now above the threshold. Aborting" ++ " shutdown, and restoring the log settings.\n",0,0,0); + if(logs_disabled && using_accesslog){ + config_set_accesslog_enabled(LOGGING_ON); + } +-- +1.8.1.4 + diff --git a/0051-Ticket-47427-limits-check-reported-wrong-value.patch b/0051-Ticket-47427-limits-check-reported-wrong-value.patch new file mode 100644 index 0000000..7a3c4b2 --- /dev/null +++ b/0051-Ticket-47427-limits-check-reported-wrong-value.patch @@ -0,0 +1,31 @@ +From 730df16e51923cb373a9796dabbd4ce4d2c447e8 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 26 Jul 2013 12:23:54 -0400 +Subject: [PATCH 51/99] Ticket 47427 - limits check reported wrong value + +Description: There was a formating error that displayed the wrong value for LONG_MAX + +https://fedorahosted.org/389/ticket/47427 +(cherry picked from commit e456f868f91d1075777a2ac43fb8145fdd289036) +--- + ldap/servers/slapd/libglobs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c +index cf1f73e..413351d 100644 +--- a/ldap/servers/slapd/libglobs.c ++++ b/ldap/servers/slapd/libglobs.c +@@ -1239,8 +1239,8 @@ config_set_disk_threshold( const char *attrname, char *value, char *errorbuf, in + threshold = strtoll(value, &endp, 10); + + if ( *endp != '\0' || threshold < 4096 || errno == ERANGE ) { +- PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: \"%s\" is invalid, threshold must be greater than 4096 and less then %lu", +- attrname, value, LONG_MAX ); ++ PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: \"%s\" is invalid, threshold must be greater than 4096 and less then %lld", ++ attrname, value, (long long int)LONG_MAX ); + retVal = LDAP_OPERATIONS_ERROR; + return retVal; + } +-- +1.8.1.4 + diff --git a/0052-Ticket-47412-Modify-RUV-should-be-serialized-in-ldbm.patch b/0052-Ticket-47412-Modify-RUV-should-be-serialized-in-ldbm.patch new file mode 100644 index 0000000..082a212 --- /dev/null +++ b/0052-Ticket-47412-Modify-RUV-should-be-serialized-in-ldbm.patch @@ -0,0 +1,70 @@ +From b73c70b03a5dcde754ec95307c62c6cf15977cff Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 28 Jun 2013 13:34:54 -0700 +Subject: [PATCH 52/99] Ticket #47412 - Modify RUV should be serialized in + ldbm_back_modify/add + +Bug Description: Current ldbm_back_modify and _add allow RUV to +update without respecting other threads in the backend's critical +area. It gives a chance for 2 threads trying to modify RUV at the +same time in the 2 different transactions which causes the DB +deadlocks. + +Fix Description: This patch changes the policy for RUV to skip +the backend serial lock. + +https://fedorahosted.org/389/ticket/47412 + +Reviewed by Rich (Thank you!!) +(cherry picked from commit bc62f8276924f836613a311a0f133c9b548fad9a) +--- + ldap/servers/slapd/back-ldbm/ldbm_add.c | 2 +- + ldap/servers/slapd/back-ldbm/ldbm_modify.c | 12 +++++++++--- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c +index 158dc8e..78ca565 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c +@@ -159,7 +159,7 @@ ldbm_back_add( Slapi_PBlock *pb ) + * operations that the URP code in the Replication + * plugin generates. + */ +- if(SERIALLOCK(li) && !is_fixup_operation) ++ if(SERIALLOCK(li) && (!is_fixup_operation || is_ruv)) + { + dblayer_lock_backend(be); + dblock_acquired= 1; +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +index 5c9585f..66b8ab8 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +@@ -394,7 +394,7 @@ ldbm_back_modify( Slapi_PBlock *pb ) + * operations that the URP code in the Replication + * plugin generates. + */ +- if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP)) { ++ if(SERIALLOCK(li) && (!is_fixup_operation || is_ruv)) { + dblayer_lock_backend(be); + dblock_acquired= 1; + } +@@ -405,8 +405,14 @@ ldbm_back_modify( Slapi_PBlock *pb ) + goto error_return; /* error result sent by find_entry2modify() */ + } + +- if ( !is_fixup_operation ) +- { ++ if (!is_fixup_operation) { ++ if (slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE)) { ++ ldap_result_code = LDAP_UNWILLING_TO_PERFORM; ++ ldap_result_message = "Operation not allowed on tombstone entry."; ++ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modify", ++ "Attempt to modify a tombstone entry %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const( e->ep_entry ))); ++ goto error_return; ++ } + opcsn = operation_get_csn (operation); + if (NULL == opcsn && operation->o_csngen_handler) + { +-- +1.8.1.4 + diff --git a/0053-Ticket-632-389-ds-base-cannot-handle-Kerberos-ticket.patch b/0053-Ticket-632-389-ds-base-cannot-handle-Kerberos-ticket.patch new file mode 100644 index 0000000..ce84005 --- /dev/null +++ b/0053-Ticket-632-389-ds-base-cannot-handle-Kerberos-ticket.patch @@ -0,0 +1,187 @@ +From 59b853372d3e06636620a192e1fdad6d89e8cc0e Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 22 Mar 2013 13:18:28 -0400 +Subject: [PATCH 53/99] Ticket 632 - 389-ds-base cannot handle Kerberos tickets + with PAC + + Bug Description: When FreeIPA is configured with AD trust support, Kerberos + tickets may also contain PAC which makes them bigger than + usually expected (bigger than 2048 B) + + Fix Description: Make the default 64k(65536), and allow it to be configurable + using: nsslapd-sasl-max-buffer-size + + https://fedorahosted.org/389/ticket/632 + + Reviewed by: nkinder(Thanks!) +(cherry picked from commit 6a2b0b1741ce6cdcceea06e630141673d47c6012) +--- + ldap/schema/01core389.ldif | 13 +++++++++++++ + ldap/servers/slapd/libglobs.c | 43 +++++++++++++++++++++++++++++++++++++++++ + ldap/servers/slapd/proto-slap.h | 2 ++ + ldap/servers/slapd/saslbind.c | 2 +- + ldap/servers/slapd/slap.h | 2 ++ + 5 files changed, 61 insertions(+), 1 deletion(-) + +diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif +index d9d1c33..c99c34c 100644 +--- a/ldap/schema/01core389.ldif ++++ b/ldap/schema/01core389.ldif +@@ -139,6 +139,19 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2136 NAME 'nsds5ReplicaCleanRUVNotified' + attributeTypes: ( 2.16.840.1.113730.3.1.2137 NAME 'nsds5ReplicaAbortCleanRUV' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.2111 NAME 'tombstoneNumSubordinates' DESC 'count of immediate subordinates for tombstone entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation X-ORIGIN '389 directory server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.2138 NAME 'nsslapd-readonly' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2143 NAME 'nsslapd-sasl-mapping-fallback' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2144 NAME 'rootdn-open-time' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2145 NAME 'rootdn-close-time' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2146 NAME 'rootdn-days-allowed' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2147 NAME 'rootdn-allow-host' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2148 NAME 'rootdn-deny-host' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2149 NAME 'rootdn-allow-ip' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2150 NAME 'rootdn-deny-ip' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2151 NAME 'nsslapd-plugin-depends-on-type' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2152 NAME 'nsds5ReplicaProtocolTimeout' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2154 NAME 'nsds5ReplicaBackoffMin' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2155 NAME 'nsds5ReplicaBackoffMax' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2156 NAME 'nsslapd-sasl-max-buffer-size' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) + # + # objectclasses + # +diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c +index 413351d..5bfd665 100644 +--- a/ldap/servers/slapd/libglobs.c ++++ b/ldap/servers/slapd/libglobs.c +@@ -83,6 +83,8 @@ + #include "plhash.h" + + #define REMOVE_CHANGELOG_CMD "remove" ++#define DEFAULT_SASL_MAXBUFSIZE "65536" ++#define SLAPD_DEFAULT_SASL_MAXBUFSIZE 65536 + + /* On UNIX, there's only one copy of slapd_ldap_debug */ + /* On NT, each module keeps its own module_ldap_debug, which */ +@@ -687,6 +689,10 @@ static struct config_get_and_set { + NULL, 0, + (void**)&global_slapdFrontendConfig.disk_logging_critical, + CONFIG_ON_OFF, (ConfigGetFunc)config_get_disk_logging_critical}, ++ {CONFIG_SASL_MAXBUFSIZE, config_set_sasl_maxbufsize, ++ NULL, 0, ++ (void**)&global_slapdFrontendConfig.sasl_max_bufsize, ++ CONFIG_INT, (ConfigGetFunc)config_get_sasl_maxbufsize}, + #ifdef MEMPOOL_EXPERIMENTAL + ,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch, + NULL, 0, +@@ -1087,6 +1093,7 @@ FrontendConfig_init () { + cfg->disk_threshold = 2097152; /* 2 mb */ + cfg->disk_grace_period = 60; /* 1 hour */ + cfg->disk_logging_critical = LDAP_OFF; ++ cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE; + + #ifdef MEMPOOL_EXPERIMENTAL + cfg->mempool_switch = LDAP_ON; +@@ -1295,6 +1302,29 @@ config_set_disk_grace_period( const char *attrname, char *value, char *errorbuf, + return retVal; + } + ++int ++config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply ) ++{ ++ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); ++ int retVal = LDAP_SUCCESS; ++ int default_size = atoi(DEFAULT_SASL_MAXBUFSIZE); ++ int size; ++ ++ size = atoi(value); ++ if(size < default_size){ ++ PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "nsslapd-sasl-max-buffer-size is too low (%d), " ++ "setting to default value (%d).\n",size, default_size); ++ size = default_size; ++ } ++ if(apply){ ++ CFG_LOCK_WRITE(slapdFrontendConfig); ++ slapdFrontendConfig->sasl_max_bufsize = size; ++ CFG_UNLOCK_WRITE(slapdFrontendConfig); ++ } ++ ++ return retVal; ++} ++ + int + config_set_port( const char *attrname, char *port, char *errorbuf, int apply ) { + long nPort; +@@ -3715,6 +3745,19 @@ config_get_port(){ + } + + int ++config_get_sasl_maxbufsize() ++{ ++ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); ++ int retVal; ++ ++ CFG_LOCK_READ(slapdFrontendConfig); ++ retVal = slapdFrontendConfig->sasl_max_bufsize; ++ CFG_UNLOCK_READ(slapdFrontendConfig); ++ ++ return retVal; ++} ++ ++int + config_get_disk_monitoring(){ + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int retVal; +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index 9d3a16d..a68c2d9 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -390,6 +390,7 @@ int config_set_disk_threshold( const char *attrname, char *value, char *errorbuf + int config_set_disk_grace_period( const char *attrname, char *value, char *errorbuf, int apply ); + int config_set_disk_logging_critical( const char *attrname, char *value, char *errorbuf, int apply ); + int config_set_auditlog_unhashed_pw(const char *attrname, char *value, char *errorbuf, int apply); ++int config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply ); + + #if !defined(_WIN32) && !defined(AIX) + int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply ); +@@ -544,6 +545,7 @@ int config_get_disk_monitoring(); + PRUint64 config_get_disk_threshold(); + int config_get_disk_grace_period(); + int config_get_disk_logging_critical(); ++int config_get_sasl_maxbufsize(); + + int is_abspath(const char *); + char* rel2abspath( char * ); +diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c +index f75e977..2d6ec0a 100644 +--- a/ldap/servers/slapd/saslbind.c ++++ b/ldap/servers/slapd/saslbind.c +@@ -659,7 +659,7 @@ void ids_sasl_server_new(Connection *conn) + } + + /* Enable security for this connection */ +- secprops.maxbufsize = 2048; /* DBDB: hack */ ++ secprops.maxbufsize = config_get_sasl_maxbufsize(); + secprops.max_ssf = 0xffffffff; + secprops.min_ssf = config_get_minssf(); + /* If anonymous access is disabled, set the appropriate flag */ +diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h +index 403ea8a..d290c92 100644 +--- a/ldap/servers/slapd/slap.h ++++ b/ldap/servers/slapd/slap.h +@@ -2002,6 +2002,7 @@ typedef struct _slapdEntryPoints { + #define CONFIG_DISK_THRESHOLD "nsslapd-disk-monitoring-threshold" + #define CONFIG_DISK_GRACE_PERIOD "nsslapd-disk-monitoring-grace-period" + #define CONFIG_DISK_LOGGING_CRITICAL "nsslapd-disk-monitoring-logging-critical" ++#define CONFIG_SASL_MAXBUFSIZE "nsslapd-sasl-max-buffer-size" + + #ifdef MEMPOOL_EXPERIMENTAL + #define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool" +@@ -2230,6 +2231,7 @@ typedef struct _slapdFrontendConfig { + char *entryusn_import_init; /* Entry USN: determine the initital value of import */ + int pagedsizelimit; + char *default_naming_context; /* Default naming context (normalized) */ ++ int sasl_max_bufsize; /* The max receive buffer size for SASL */ + + /* disk monitoring */ + int disk_monitoring; +-- +1.8.1.4 + diff --git a/0054-Ticket-47367-phase-1-ldapdelete-returns-non-leaf-ent.patch b/0054-Ticket-47367-phase-1-ldapdelete-returns-non-leaf-ent.patch new file mode 100644 index 0000000..4c973d2 --- /dev/null +++ b/0054-Ticket-47367-phase-1-ldapdelete-returns-non-leaf-ent.patch @@ -0,0 +1,385 @@ +From b6220eb610c92ead1a7e789317e158cfcb8def90 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 6 Jun 2013 16:52:14 -0700 +Subject: [PATCH 54/99] Ticket #47367 - (phase 1) ldapdelete returns non-leaf + entry error while trying to remove a leaf entry + +Bug description: Replication conflict confuses the numsubordinate +count, which leaves an entry that cannot be deleted even its +subordinate entries are all removed. + +Fix description: +[urp.c] get_dn_plus_uniqueid: a logic to create a conflict DN + had a bug. It used to call slapi_sdn_get_rdn to get the rdn. + The function slapi_sdn_get_rdn blindly returned the "dn" field + without checking whether the field is NULL or not. Instead, + this patch changes the interface of the helper function get_ + dn_plus_uniqueid and use the original Slapi_DN with slapi_ + sdn_get_dn, then generates the conflict DN "nsuniqueid=...+ + ,". +[ldbm_delete.c] There is a case a parent of a delete-candidate + entry runs into a conflict and multiple parent entries exist. + Once it occurs, a parent entry found by the parent dn string + may not be the entry which manages the numsubordinate count + the delete-candidate entry belonging to. It confuses the + numsubordinate counts and leaves an entry which cannot be + deleted due to the numsubordinate count mismatch. This patch + retrieves parent entry by parent id if it is available. +[ldbm_entryrdn.c] When traversing the DIT, a special treatment + is needed for a tombstone entry. I.e, 2 RDNs (nsuniqueid=..., + ) is treated as one RDN. It should decrement the index + (rdnidx) one more to point to the right position of the RDN + array in Slapi_RDN. +[ldbm_search.c] When checking the scope of an entry in ldbm_ + back_next_search_entry_ext, a tombstone entry was not properly + examined. This patch introduces a new slapi api slapi_sdn_ + scope_test_ext. +[dn.c] In slapi_sdn_get_rdn, use slapi_sdn_get_dn to get the + dn value of Slapi_DN. It was one cause of the problem in + get_dn_plus_uniqueid (urp.c). + This patch adds slapi_sdn_scope_test_ext, which takes flags + to indicates the first argument dn is a tombstone sdn. + Also, this patch replaces "malloc + strcpy + strcat" with + slapi_ch_smprintf to improve the readability of the code. +[rdn.c] This patch replaces "malloc + strcpy + strcat" with + slapi_create_dn_string to normalize the newly added rdn and + improve the readability of the code. + +Reviewed by Rich (Thank you!!) + +https://fedorahosted.org/389/ticket/47367 +(cherry picked from commit c2c64017e0e25a4376139debe29b4f587964710f) +--- + ldap/servers/plugins/replication/urp.c | 18 ++++----- + ldap/servers/slapd/back-ldbm/ldbm_delete.c | 35 ++++++++++++----- + ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 2 + + ldap/servers/slapd/back-ldbm/ldbm_search.c | 2 +- + ldap/servers/slapd/dn.c | 59 +++++++++++++++++++++++++--- + ldap/servers/slapd/rdn.c | 24 ++++------- + ldap/servers/slapd/slapi-plugin.h | 18 +++++++++ + 7 files changed, 116 insertions(+), 42 deletions(-) + +diff --git a/ldap/servers/plugins/replication/urp.c b/ldap/servers/plugins/replication/urp.c +index 1d8799a..e236541 100644 +--- a/ldap/servers/plugins/replication/urp.c ++++ b/ldap/servers/plugins/replication/urp.c +@@ -57,7 +57,7 @@ static int urp_annotate_dn (char *sessionid, Slapi_Entry *entry, CSN *opcsn, con + static int urp_naming_conflict_removal (Slapi_PBlock *pb, char *sessionid, CSN *opcsn, const char *optype); + static int mod_namingconflict_attr (const char *uniqueid, const Slapi_DN *entrysdn, const Slapi_DN *conflictsdn, CSN *opcsn); + static int del_replconflict_attr (Slapi_Entry *entry, CSN *opcsn, int opflags); +-static char *get_dn_plus_uniqueid(char *sessionid,const char *olddn,const char *uniqueid); ++static char *get_dn_plus_uniqueid(char *sessionid,const Slapi_DN *oldsdn,const char *uniqueid); + static char *get_rdn_plus_uniqueid(char *sessionid,const char *olddn,const char *uniqueid); + static int is_suffix_entry (Slapi_PBlock *pb, Slapi_Entry *entry, Slapi_DN **parenddn); + +@@ -180,7 +180,7 @@ urp_add_operation( Slapi_PBlock *pb ) + if (r<0) + { + /* Entry to be added is a loser */ +- char *newdn= get_dn_plus_uniqueid (sessionid, basedn, adduniqueid); ++ char *newdn = get_dn_plus_uniqueid (sessionid, (const Slapi_DN *)addentry, adduniqueid); + if(newdn==NULL) + { + op_result= LDAP_OPERATIONS_ERROR; +@@ -1222,16 +1222,15 @@ bailout: + + /* The returned value is either null or "uniqueid=+" */ + static char * +-get_dn_plus_uniqueid(char *sessionid, const char *olddn, const char *uniqueid) ++get_dn_plus_uniqueid(char *sessionid, const Slapi_DN *oldsdn, const char *uniqueid) + { +- Slapi_DN *sdn= slapi_sdn_new_dn_byval(olddn); + Slapi_RDN *rdn= slapi_rdn_new(); + char *newdn; + + PR_ASSERT(uniqueid!=NULL); + + /* Check if the RDN already contains the Unique ID */ +- slapi_sdn_get_rdn(sdn,rdn); ++ slapi_rdn_set_dn(rdn, slapi_sdn_get_dn(oldsdn)); + if(slapi_rdn_contains(rdn,SLAPI_ATTR_UNIQUEID,uniqueid,strlen(uniqueid))) + { + /* The Unique ID is already in the RDN. +@@ -1241,16 +1240,15 @@ get_dn_plus_uniqueid(char *sessionid, const char *olddn, const char *uniqueid) + * require admin intercession + */ + slapi_log_error(SLAPI_LOG_FATAL, sessionid, +- "Annotated DN %s has naming conflict\n", olddn ); ++ "Annotated DN %s has naming conflict\n", slapi_sdn_get_dn(oldsdn) ); + newdn= NULL; + } + else + { +- slapi_rdn_add(rdn,SLAPI_ATTR_UNIQUEID,uniqueid); +- slapi_sdn_set_rdn(sdn, rdn); +- newdn= slapi_ch_strdup(slapi_sdn_get_dn(sdn)); ++ char *parentdn = slapi_dn_parent(slapi_sdn_get_dn(oldsdn)); ++ slapi_rdn_add(rdn, SLAPI_ATTR_UNIQUEID, uniqueid); ++ newdn = slapi_ch_smprintf("%s,%s", slapi_rdn_get_rdn(rdn), parentdn); + } +- slapi_sdn_free(&sdn); + slapi_rdn_free(&rdn); + return newdn; + } +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +index 528693e..d80c54e 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +@@ -242,14 +242,12 @@ ldbm_back_delete( Slapi_PBlock *pb ) + */ + is_tombstone_entry = slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE); + if (delete_tombstone_entry) { +- PR_ASSERT(is_tombstone_entry); + if (!is_tombstone_entry) { + slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete", + "Attempt to delete a non-tombstone entry %s\n", dn); + delete_tombstone_entry = 0; + } + } else { +- PR_ASSERT(!is_tombstone_entry); + if (is_tombstone_entry) { + slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete", + "Attempt to Tombstone again a tombstone entry %s\n", dn); +@@ -328,12 +326,31 @@ ldbm_back_delete( Slapi_PBlock *pb ) + if ( !slapi_sdn_isempty(&parentsdn) ) + { + struct backentry *parent = NULL; +- entry_address parent_addr; ++ char *pid_str = slapi_entry_attr_get_charptr(e->ep_entry, LDBM_PARENTID_STR); ++ if (pid_str) { ++ /* First, try to get the direct parent. */ ++ /* ++ * Although a rare case, multiple parents from repl conflict could exist. ++ * In such case, if a parent entry is found just by parentsdn ++ * (find_entry2modify_only_ext), a wrong parent could be found, ++ * and numsubordinate count could get confused. ++ */ ++ ID pid = (ID)strtol(pid_str, (char **)NULL, 10); ++ parent = id2entry(be, pid ,NULL, &retval); ++ if (parent && cache_lock_entry(&inst->inst_cache, parent)) { ++ /* Failed to obtain parent entry's entry lock */ ++ CACHE_RETURN(&(inst->inst_cache), &parent); ++ goto error_return; ++ } ++ } ++ if (NULL == parent) { ++ entry_address parent_addr; + +- parent_addr.sdn = &parentsdn; +- parent_addr.uniqueid = NULL; +- parent = find_entry2modify_only_ext(pb, be, &parent_addr, +- TOMBSTONE_INCLUDED, &txn); ++ parent_addr.sdn = &parentsdn; ++ parent_addr.uniqueid = NULL; ++ parent = find_entry2modify_only_ext(pb, be, &parent_addr, ++ TOMBSTONE_INCLUDED, &txn); ++ } + if (NULL != parent) { + int isglue; + size_t haschildren = 0; +@@ -1171,9 +1188,9 @@ common_return: + } + + diskfull_return: +- if(ldap_result_code!=-1) ++ if(ldap_result_code!=-1) + { +- slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL ); ++ slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL ); + } + modify_term(&parent_modify_c,be); + if(dblock_acquired) +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +index e50b930..4329b16 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +@@ -3164,6 +3164,7 @@ _entryrdn_index_read(backend *be, + /* Node might be a tombstone. */ + rc = _entryrdn_get_tombstone_elem(cursor, tmpsrdn, + &key, nrdn, elem); ++ rdnidx--; /* consider nsuniqueid=.., one RDN */ + } + if (rc || NULL == *elem) { + slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG, +@@ -3270,6 +3271,7 @@ _entryrdn_index_read(backend *be, + } + goto bail; + } ++ rdnidx--; /* consider nsuniqueid=.., one RDN */ + } else { + slapi_ch_free((void **)&tmpelem); + if (DB_NOTFOUND != rc) { +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c +index 5fbea24..f86f27c 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c +@@ -1610,7 +1610,7 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + * just forget about it, since we don't want to return anything at all. */ + { + if ( slapi_uniqueIDCompareString(target_uniqueid, e->ep_entry->e_uniqueid) || +- slapi_sdn_scope_test( backentry_get_sdn(e), basesdn, scope )) ++ slapi_sdn_scope_test_ext( backentry_get_sdn(e), basesdn, scope, e->ep_entry->e_flags )) + { + /* check size limit */ + if ( slimit >= 0 ) +diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c +index 35c0700..2f50e97 100644 +--- a/ldap/servers/slapd/dn.c ++++ b/ldap/servers/slapd/dn.c +@@ -2114,10 +2114,7 @@ slapi_sdn_add_rdn(Slapi_DN *sdn, const Slapi_RDN *rdn) + { + /* NewDN= NewRDN + DN */ + const char *dn= slapi_sdn_get_dn(sdn); +- char *newdn= slapi_ch_malloc(strlen(rawrdn)+1+strlen(dn)+1); +- strcpy( newdn, rawrdn ); +- strcat( newdn, "," ); +- strcat( newdn, dn ); ++ char *newdn = slapi_ch_smprintf("%s,%s", rawrdn, dn); + slapi_sdn_set_dn_passin(sdn,newdn); + } + return sdn; +@@ -2345,7 +2342,7 @@ slapi_sdn_get_backend_parent(const Slapi_DN *sdn,Slapi_DN *sdn_parent,const Slap + void + slapi_sdn_get_rdn(const Slapi_DN *sdn,Slapi_RDN *rdn) + { +- slapi_rdn_set_dn(rdn,sdn->dn); ++ slapi_rdn_set_dn(rdn, slapi_sdn_get_dn(sdn)); + } + + Slapi_DN * +@@ -2516,6 +2513,47 @@ slapi_sdn_scope_test( const Slapi_DN *dn, const Slapi_DN *base, int scope ) + return rc; + } + ++/* ++ * Return non-zero if "dn" matches the scoping criteria ++ * given by "base" and "scope". ++ * If SLAPI_ENTRY_FLAG_TOMBSTONE is set to flags, ++ * DN without "nsuniqueid=...," is examined. ++ */ ++int ++slapi_sdn_scope_test_ext( const Slapi_DN *dn, const Slapi_DN *base, int scope, int flags ) ++{ ++ int rc = 0; ++ ++ switch ( scope ) { ++ case LDAP_SCOPE_BASE: ++ if (flags & SLAPI_ENTRY_FLAG_TOMBSTONE) { ++ Slapi_DN parent; ++ slapi_sdn_init(&parent); ++ slapi_sdn_get_parent(dn, &parent); ++ rc = ( slapi_sdn_compare( dn, &parent ) == 0 ); ++ slapi_sdn_done(&parent); ++ } else { ++ rc = ( slapi_sdn_compare( dn, base ) == 0 ); ++ } ++ break; ++ case LDAP_SCOPE_ONELEVEL: ++ if (flags & SLAPI_ENTRY_FLAG_TOMBSTONE) { ++ Slapi_DN parent; ++ slapi_sdn_init(&parent); ++ slapi_sdn_get_parent(dn, &parent); ++ rc = ( slapi_sdn_isparent( base, &parent ) != 0 ); ++ slapi_sdn_done(&parent); ++ } else { ++ rc = ( slapi_sdn_isparent( base, dn ) != 0 ); ++ } ++ break; ++ case LDAP_SCOPE_SUBTREE: ++ rc = ( slapi_sdn_issuffix( dn, base ) != 0 ); ++ break; ++ } ++ return rc; ++} ++ + /* + * build the new dn of an entry for moddn operations + */ +@@ -2563,7 +2601,16 @@ size_t + slapi_sdn_get_size(const Slapi_DN *sdn) + { + size_t sz = sizeof(Slapi_DN); ++ /* slapi_sdn_get_ndn_len returns the normalized dn length ++ * if dn or ndn exists. If both does not exist, it ++ * normalizes udn and set it to dn and returns the length. ++ */ + sz += slapi_sdn_get_ndn_len(sdn); +- sz += strlen(sdn->dn) + 1; ++ if (sdn->dn && sdn->ndn) { ++ sz += slapi_sdn_get_ndn_len(sdn); ++ } ++ if (sdn->udn) { ++ sz += strlen(sdn->udn) + 1; ++ } + return sz; + } +diff --git a/ldap/servers/slapd/rdn.c b/ldap/servers/slapd/rdn.c +index d408f0e..fe2fae0 100644 +--- a/ldap/servers/slapd/rdn.c ++++ b/ldap/servers/slapd/rdn.c +@@ -479,25 +479,17 @@ slapi_rdn_add(Slapi_RDN *rdn, const char *type, const char *value) + PR_ASSERT(NULL != value); + if(rdn->rdn==NULL) + { +- /* type=value '\0' */ +- rdn->rdn= slapi_ch_malloc(strlen(type)+1+strlen(value)+1); +- strcpy( rdn->rdn, type ); +- strcat( rdn->rdn, "=" ); +- strcat( rdn->rdn, value ); ++ /* type=value '\0' */ ++ rdn->rdn = slapi_create_dn_string("%s=%s", type, value); + } + else + { +- /* type=value+rdn '\0' */ +- char *newrdn= slapi_ch_malloc(strlen(type)+1+strlen(value)+1+strlen(rdn->rdn)+1); +- strcpy( newrdn, type ); +- strcat( newrdn, "=" ); +- strcat( newrdn, value ); +- strcat( newrdn, "+" ); +- strcat( newrdn, rdn->rdn ); +- slapi_ch_free((void**)&rdn->rdn); +- rdn->rdn= newrdn; +- } +- slapi_unsetbit_uchar(rdn->flag,FLAG_RDNS); ++ /* type=value+rdn '\0' */ ++ char *newrdn = slapi_create_dn_string("%s=%s+%s", type, value, rdn->rdn); ++ slapi_ch_free_string(&rdn->rdn); ++ rdn->rdn = newrdn; ++ } ++ slapi_unsetbit_uchar(rdn->flag,FLAG_RDNS); + return 1; + } + +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h +index f78787e..0f69c0a 100644 +--- a/ldap/servers/slapd/slapi-plugin.h ++++ b/ldap/servers/slapd/slapi-plugin.h +@@ -2698,6 +2698,24 @@ int slapi_sdn_get_ndn_len(const Slapi_DN *sdn); + int slapi_sdn_scope_test( const Slapi_DN *dn, const Slapi_DN *base, int scope ); + + /** ++ * Checks if a DN is within a specified scope under a specified base DN. ++ * This api adjusts tombstoned DN when comparing with the base dn. ++ * ++ * \param dn A pointer to the \c Slapi_DN structure to test. ++ * \param base The base DN against which \c dn is going to be tested. ++ * \param scope The scope tested. Valid scopes are: ++ * \arg \c LDAP_SCOPE_BASE ++ * \arg \c LDAP_SCOPE_ONELEVEL ++ * \arg \c LDAP_SCOPE_SUBTREE ++ * \param flags 0 or SLAPI_ENTRY_FLAG_TOMBSTONE ++ * \return non-zero if \c dn matches the scoping criteria given by \c base and \c scope. ++ * \see slapi_sdn_compare() ++ * \see slapi_sdn_isparent() ++ * \see slapi_sdn_issuffix() ++ */ ++int slapi_sdn_scope_test_ext( const Slapi_DN *dn, const Slapi_DN *base, int scope, int flags ); ++ ++/** + * Retreives the RDN from a given DN. + * + * This function takes the DN stored in the \c Slapi_DN structure pointed to +-- +1.8.1.4 + diff --git a/0055-Ticket-47327-error-syncing-group-if-group-member-use.patch b/0055-Ticket-47327-error-syncing-group-if-group-member-use.patch new file mode 100644 index 0000000..b37481b --- /dev/null +++ b/0055-Ticket-47327-error-syncing-group-if-group-member-use.patch @@ -0,0 +1,104 @@ +From fddf90faf5f0722653811957eb1e1870e487a1aa Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 21 May 2013 12:16:52 -0700 +Subject: [PATCH 55/99] Ticket #47327 - error syncing group if group member + user is not synced + +Bug description: Windows Sync synchronizes member attributes +in a group entry if the member entry itself is synchronized. +The entries in the sync scope are basically to be synchronized. +But there is an exception such as a container in the scope is +not synchronized due to the objecttype constraints. Such an +unsync'ed entry could have users in it. Users are the target +of Windows Sync. But since the parent container is not synch- +ronized, the users in the container are not, neither. If a +group contains such special user as a member, synchronization +failed there and the other normal members are failed to get +synchronized. + +Fix description: Windows Sync has a helper function +is_subject_of_agreement_remote, which checks if the entry is +in the scope to be synchronized. This patch adds the check +if the checking entry's parent locally exists in the DS. If +it does not exist, it considers the entry is out of scope. +AD strictly checks if the entry exists prior to adding it +to a group entry as a member. That is, a member to be added +is supposed to be in the server, as well as its parent is. +With this change, the AD user which is not synchronized to +the DS is just skipped to add to the group in the DS in the +same manner as an user out of scope is. + +https://fedorahosted.org/389/ticket/47327 + +Reviewed by Rich (Thanks!!) +(cherry picked from commit 9b0834c07888aa1ee88b52141460a3b4e80d1962) +(cherry picked from commit ec592bb9b320a74c1525671770b63294a8e7f64a) +--- + .../plugins/replication/windows_protocol_util.c | 35 +++++++++++++++++++--- + 1 file changed, 31 insertions(+), 4 deletions(-) + +diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c +index d831fa0..1bafa9a 100644 +--- a/ldap/servers/plugins/replication/windows_protocol_util.c ++++ b/ldap/servers/plugins/replication/windows_protocol_util.c +@@ -3799,8 +3799,11 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int + windows_private_get_windows_subtree(ra)); + } + } +- new_dn = slapi_sdn_new_dn_byval(new_dn_string); +- PR_smprintf_free(new_dn_string); ++ /* ++ * new_dn_string is created by slapi_create_dn_string, ++ * which is normalized. Thus, we can use _normdn_. ++ */ ++ new_dn = slapi_sdn_new_normdn_passin(new_dn_string); + slapi_ch_free_string(&container_str); + /* Clear any earlier error */ + retval = 0; +@@ -3895,6 +3898,7 @@ is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt *ra) + int retval = 0; + int is_in_subtree = 0; + const Slapi_DN *agreement_subtree = NULL; ++ const Slapi_DN *sdn; + + /* First test for the sync'ed subtree */ + agreement_subtree = windows_private_get_windows_subtree(ra); +@@ -3902,10 +3906,33 @@ is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt *ra) + { + goto error; + } +- is_in_subtree = slapi_sdn_scope_test(slapi_entry_get_sdn_const(e), agreement_subtree, LDAP_SCOPE_SUBTREE); ++ sdn = slapi_entry_get_sdn_const(e); ++ is_in_subtree = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE); + if (is_in_subtree) + { +- retval = 1; ++ Slapi_DN psdn = {0}; ++ Slapi_Entry *pentry = NULL; ++ /* ++ * Check whether the parent of the entry exists or not. ++ * If it does not, treat the entry e is out of scope. ++ * For instance, agreement_subtree is cn=USER, ++ * cn=container,cn=USER, is not synchronized. ++ * If 'e' is uid=test,cn=container,cn=USER,, ++ * the entry is not synchronized, either. We treat ++ * 'e' as out of scope. ++ */ ++ slapi_sdn_get_parent(sdn, &psdn); ++ if (0 == slapi_sdn_compare(&psdn, agreement_subtree)) { ++ retval = 1; ++ } else { ++ /* If parent entry is not local, the entry is out of scope */ ++ int rc = windows_get_local_entry(&psdn, &pentry); ++ if ((0 == rc) && pentry) { ++ retval = 1; ++ slapi_entry_free(pentry); ++ } ++ } ++ slapi_sdn_done(&psdn); + } + error: + return retval; +-- +1.8.1.4 + diff --git a/0056-Ticket-47376-DESC-should-not-be-empty-as-per-RFC-225.patch b/0056-Ticket-47376-DESC-should-not-be-empty-as-per-RFC-225.patch new file mode 100644 index 0000000..80abc86 --- /dev/null +++ b/0056-Ticket-47376-DESC-should-not-be-empty-as-per-RFC-225.patch @@ -0,0 +1,732 @@ +From f7fa6b1b952847137424a42758681a59b3bd8df2 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 7 Jun 2013 14:48:07 -0400 +Subject: [PATCH 56/99] Ticket 47376 - DESC should not be empty as per RFC 2252 + (ldapv3) + +Bug Description: RFC 2252 (ldapv3), DESC, defined as a qdstring, should not + be an empty string. In the standard schema there are + several attributes/objectclasses that have " DESC '' ", + which violates the RFC. + +Fix Description: Set all empty DESC's with values. + +https://fedorahosted.org/389/ticket/47376 + +Reviewed by: richm & nkinder (Thanks!!) +(cherry picked from commit 9f73f01a408cef05f112f4ec406949f3d48afe78) +(cherry picked from commit 4a29fe1a3fae5a81007c7dec126f48baa03948e0) +--- + ldap/schema/50ns-mail.ldif | 10 ++-- + ldap/schema/60qmail.ldif | 20 +++---- + ldap/schema/60radius.ldif | 132 ++++++++++++++++++++++----------------------- + ldap/schema/60samba3.ldif | 2 +- + 4 files changed, 82 insertions(+), 82 deletions(-) + +diff --git a/ldap/schema/50ns-mail.ldif b/ldap/schema/50ns-mail.ldif +index 8d06119..27006e0 100644 +--- a/ldap/schema/50ns-mail.ldif ++++ b/ldap/schema/50ns-mail.ldif +@@ -73,8 +73,8 @@ attributeTypes: ( 2.16.840.1.113730.3.1.17 NAME ( 'mailForwardingAddress' ) DESC + attributeTypes: ( 2.16.840.1.113730.3.1.32 NAME ( 'mgrpMsgMaxSize' ) DESC 'Netscape Messaging Server 4.x defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Messaging Server 4.x' ) + attributeTypes: ( 2.16.840.1.113730.3.1.29 NAME ( 'mgrpMsgRejectText' ) DESC 'Netscape Messaging Server 4.x defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Messaging Server 4.x' ) + attributeTypes: ( 2.16.840.1.113730.3.1.789 NAME ( 'mgrpNoDuplicateChecks' ) DESC 'Netscape Messaging Server 4.x defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Messaging Server 4.x' ) +-objectclasses: ( 2.16.840.1.113730.3.2.3 NAME 'mailRecipient' DESC '' SUP top AUXILIARY MUST ( objectClass ) MAY ( cn $ mail $ mailAlternateAddress $ mailHost $ mailRoutingAddress $ mailAccessDomain $ mailAutoReplyMode $ mailAutoReplyText $ mailDeliveryOption $ mailForwardingAddress $ mailMessageStore $ mailProgramDeliveryInfo $ mailQuota $ multiLineDescription $ uid $ userPassword ) X-ORIGIN 'Netscape Messaging Server 4.x' ) +-objectclasses: ( 2.16.840.113730.3.2.37 NAME 'nsMessagingServerUser' DESC '' SUP top AUXILIARY MUST ( objectClass ) MAY ( cn $ mailAccessDomain $ mailAutoReplyMode $ mailAutoReplyText $ mailDeliveryOption $ mailForwardingAddress $ mailMessageStore $ mailProgramDeliveryInfo $ mailQuota $ nsmsgDisallowAccess $ nsmsgNumMsgQuota $ nswmExtendedUserPrefs $ vacationstartdate $ vacationenddate ) X-ORIGIN 'Netscape Messaging Server 4.x' ) +-objectclasses: ( 2.16.840.1.113730.3.2.4 NAME 'mailGroup' DESC '' SUP top AUXILIARY MUST ( objectClass ) MAY ( cn $ mail $ mailAlternateAddress $ mailHost $ mailRoutingAddress $ mgrpAddHeader $ mgrpAllowedBroadcaster $ mgrpAllowedDomain $ mgrpApprovePassword $ mgrpBroadcasterPolicy $ mgrpDeliverTo $ mgrpErrorsTo $ mgrpModerator $ mgrpMsgMaxSize $ mgrpMsgRejectAction $ mgrpMsgRejectText $ mgrpNoDuplicateChecks $ mgrpRemoveHeader $ mgrpRFC822MailMember $ owner ) X-ORIGIN 'Netscape Messaging Server 4.x' ) +-objectclasses: ( 2.16.840.1.113730.3.2.5 NAME 'groupOfMailEnhancedUniqueNames' DESC '' SUP top AUXILIARY MUST ( objectClass $ cn ) MAY ( businessCategory $ description $ mailEnhancedUniqueMember $ o $ ou $ owner $ seeAlso ) X-ORIGIN 'Netscape Messaging Server 4.x' ) +-objectclasses: ( 2.16.840.1.113730.3.2.24 NAME 'netscapeMailServer' DESC '' SUP top AUXILIARY MUST ( objectClass ) X-ORIGIN 'Netscape Messaging Server 4.x' ) ++objectclasses: ( 2.16.840.1.113730.3.2.3 NAME 'mailRecipient' DESC 'Netscape Messaging Server 4.x defined objectclass' SUP top AUXILIARY MUST ( objectClass ) MAY ( cn $ mail $ mailAlternateAddress $ mailHost $ mailRoutingAddress $ mailAccessDomain $ mailAutoReplyMode $ mailAutoReplyText $ mailDeliveryOption $ mailForwardingAddress $ mailMessageStore $ mailProgramDeliveryInfo $ mailQuota $ multiLineDescription $ uid $ userPassword ) X-ORIGIN 'Netscape Messaging Server 4.x' ) ++objectclasses: ( 2.16.840.113730.3.2.37 NAME 'nsMessagingServerUser' DESC 'Netscape Messaging Server 4.x defined objectclass' SUP top AUXILIARY MUST ( objectClass ) MAY ( cn $ mailAccessDomain $ mailAutoReplyMode $ mailAutoReplyText $ mailDeliveryOption $ mailForwardingAddress $ mailMessageStore $ mailProgramDeliveryInfo $ mailQuota $ nsmsgDisallowAccess $ nsmsgNumMsgQuota $ nswmExtendedUserPrefs $ vacationstartdate $ vacationenddate ) X-ORIGIN 'Netscape Messaging Server 4.x' ) ++objectclasses: ( 2.16.840.1.113730.3.2.4 NAME 'mailGroup' DESC 'Netscape Messaging Server 4.x defined objectclass' SUP top AUXILIARY MUST ( objectClass ) MAY ( cn $ mail $ mailAlternateAddress $ mailHost $ mailRoutingAddress $ mgrpAddHeader $ mgrpAllowedBroadcaster $ mgrpAllowedDomain $ mgrpApprovePassword $ mgrpBroadcasterPolicy $ mgrpDeliverTo $ mgrpErrorsTo $ mgrpModerator $ mgrpMsgMaxSize $ mgrpMsgRejectAction $ mgrpMsgRejectText $ mgrpNoDuplicateChecks $ mgrpRemoveHeader $ mgrpRFC822MailMember $ owner ) X-ORIGIN 'Netscape Messaging Server 4.x' ) ++objectclasses: ( 2.16.840.1.113730.3.2.5 NAME 'groupOfMailEnhancedUniqueNames' DESC 'Netscape Messaging Server 4.x defined objectclass' SUP top AUXILIARY MUST ( objectClass $ cn ) MAY ( businessCategory $ description $ mailEnhancedUniqueMember $ o $ ou $ owner $ seeAlso ) X-ORIGIN 'Netscape Messaging Server 4.x' ) ++objectclasses: ( 2.16.840.1.113730.3.2.24 NAME 'netscapeMailServer' DESC 'Netscape Messaging Server 4.x defined objectclass' SUP top AUXILIARY MUST ( objectClass ) X-ORIGIN 'Netscape Messaging Server 4.x' ) +diff --git a/ldap/schema/60qmail.ldif b/ldap/schema/60qmail.ldif +index b1bc391..98d0810 100644 +--- a/ldap/schema/60qmail.ldif ++++ b/ldap/schema/60qmail.ldif +@@ -308,7 +308,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.1 + NAME 'qladnmanager' +- DESC '' ++ DESC 'qladnmanager' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + ) +@@ -318,7 +318,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.2 + NAME 'qlaDomainList' +- DESC '' ++ DESC 'qlaDomainList' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} +@@ -329,7 +329,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.3 + NAME 'qlaUidPrefix' +- DESC '' ++ DESC 'qlaUidPrefix' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} +@@ -341,7 +341,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.4 + NAME 'qlaQmailUid' +- DESC '' ++ DESC 'qlaQmailUid' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE +@@ -352,7 +352,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.5 + NAME 'qlaQmailGid' +- DESC '' ++ DESC 'qlaQmailGid' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE +@@ -363,7 +363,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.6 + NAME 'qlaMailMStorePrefix' +- DESC '' ++ DESC 'qlaMailMStorePrefix' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} +@@ -375,7 +375,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.7 + NAME 'qlaMailQuotaSize' +- DESC '' ++ DESC 'qlaMailQuotaSize' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE +@@ -386,7 +386,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.8 + NAME 'qlaMailQuotaCount' +- DESC '' ++ DESC 'qlaMailQuotaCount' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE +@@ -397,7 +397,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.9 + NAME 'qlaMailSizeMax' +- DESC '' ++ DESC 'qlaMailSizeMax' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE +@@ -408,7 +408,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7914.1.4.1.10 + NAME 'qlaMailHostList' +- DESC '' ++ DESC 'qlaMailHostList' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} +diff --git a/ldap/schema/60radius.ldif b/ldap/schema/60radius.ldif +index 93a5ba3..3350a9c 100644 +--- a/ldap/schema/60radius.ldif ++++ b/ldap/schema/60radius.ldif +@@ -14,7 +14,7 @@ dn: cn=schema + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.1 + NAME 'radiusArapFeatures' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -22,7 +22,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.2 + NAME 'radiusArapSecurity' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -30,7 +30,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.3 + NAME 'radiusArapZoneAccess' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -38,7 +38,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.44 + NAME 'radiusAuthType' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -46,7 +46,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.4 + NAME 'radiusCallbackId' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -54,7 +54,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.5 + NAME 'radiusCallbackNumber' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -62,7 +62,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.6 + NAME 'radiusCalledStationId' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -70,7 +70,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.7 + NAME 'radiusCallingStationId' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -78,14 +78,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.8 + NAME 'radiusClass' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.45 + NAME 'radiusClientIPAddress' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -93,14 +93,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.9 + NAME 'radiusFilterId' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.10 + NAME 'radiusFramedAppleTalkLink' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -108,14 +108,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.11 + NAME 'radiusFramedAppleTalkNetwork' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.12 + NAME 'radiusFramedAppleTalkZone' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -123,14 +123,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.13 + NAME 'radiusFramedCompression' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.14 + NAME 'radiusFramedIPAddress' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -138,7 +138,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.15 + NAME 'radiusFramedIPNetmask' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -146,7 +146,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.16 + NAME 'radiusFramedIPXNetwork' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -154,7 +154,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.17 + NAME 'radiusFramedMTU' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -162,7 +162,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.18 + NAME 'radiusFramedProtocol' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -170,14 +170,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.19 + NAME 'radiusFramedRoute' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.20 + NAME 'radiusFramedRouting' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -185,14 +185,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.46 + NAME 'radiusGroupName' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.47 + NAME 'radiusHint' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -200,14 +200,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.48 + NAME 'radiusHuntgroupName' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.21 + NAME 'radiusIdleTimeout' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -215,14 +215,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.22 + NAME 'radiusLoginIPHost' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.23 + NAME 'radiusLoginLATGroup' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -230,7 +230,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.24 + NAME 'radiusLoginLATNode' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -238,7 +238,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.25 + NAME 'radiusLoginLATPort' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -246,7 +246,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.26 + NAME 'radiusLoginLATService' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -254,7 +254,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.27 + NAME 'radiusLoginService' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -262,7 +262,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.28 + NAME 'radiusLoginTCPPort' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -270,7 +270,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.29 + NAME 'radiusPasswordRetry' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -278,7 +278,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.30 + NAME 'radiusPortLimit' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -286,7 +286,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.49 + NAME 'radiusProfileDn' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE +@@ -294,7 +294,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.31 + NAME 'radiusPrompt' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -302,7 +302,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.50 + NAME 'radiusProxyToRealm' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -310,7 +310,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.51 + NAME 'radiusReplicateToRealm' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -318,7 +318,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.52 + NAME 'radiusRealm' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -326,7 +326,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.32 + NAME 'radiusServiceType' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -334,7 +334,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.33 + NAME 'radiusSessionTimeout' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -342,7 +342,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.34 + NAME 'radiusTerminationAction' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -350,21 +350,21 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.35 + NAME 'radiusTunnelAssignmentId' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.36 + NAME 'radiusTunnelMediumType' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.37 + NAME 'radiusTunnelPassword' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -372,42 +372,42 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.38 + NAME 'radiusTunnelPreference' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.39 + NAME 'radiusTunnelPrivateGroupId' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.40 + NAME 'radiusTunnelServerEndpoint' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.41 + NAME 'radiusTunnelType' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.42 + NAME 'radiusVSA' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.43 + NAME 'radiusTunnelClientEndpoint' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +@@ -415,14 +415,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.53 + NAME 'radiusSimultaneousUse' +- DESC '' ++ DESC 'radiusAttribute' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.54 + NAME 'radiusLoginTime' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -430,7 +430,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.55 + NAME 'radiusUserCategory' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -438,14 +438,14 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.56 + NAME 'radiusStripUserName' +- DESC '' ++ DESC 'radiusAttribute' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.57 + NAME 'dialupAccess' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -453,7 +453,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.58 + NAME 'radiusExpiration' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -461,21 +461,21 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.59 + NAME 'radiusCheckItem' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.60 + NAME 'radiusReplyItem' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.61 + NAME 'radiusNASIpAddress' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -483,7 +483,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.62 + NAME 'radiusReplyMessage' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +@@ -491,7 +491,7 @@ objectClasses: + ( 1.3.6.1.4.1.3317.4.3.2.1 + NAME 'radiusprofile' + SUP top AUXILIARY +- DESC '' ++ DESC 'radiusObjectclass' + MUST uid + MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ + radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ +@@ -529,7 +529,7 @@ objectClasses: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.64 + NAME 'radiusClientSecret' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -537,7 +537,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.65 + NAME 'radiusClientNASType' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE +@@ -545,7 +545,7 @@ attributeTypes: + attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.66 + NAME 'radiusClientShortName' +- DESC '' ++ DESC 'radiusAttribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +diff --git a/ldap/schema/60samba3.ldif b/ldap/schema/60samba3.ldif +index 5dd5f31..91c17be 100644 +--- a/ldap/schema/60samba3.ldif ++++ b/ldap/schema/60samba3.ldif +@@ -204,7 +204,7 @@ attributeTypes: ( + attributeTypes: ( + 1.3.6.1.4.1.7165.2.1.47 + NAME 'sambaMungedDial' +- DESC '' ++ DESC 'sambaMungedDial' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} + ) +-- +1.8.1.4 + diff --git a/0057-Ticket-47349-DS-instance-crashes-under-a-high-load.patch b/0057-Ticket-47349-DS-instance-crashes-under-a-high-load.patch new file mode 100644 index 0000000..45c492b --- /dev/null +++ b/0057-Ticket-47349-DS-instance-crashes-under-a-high-load.patch @@ -0,0 +1,82 @@ +From 899662a8fc635997586e9891f3d93629b479dc96 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 24 Apr 2013 20:36:37 -0600 +Subject: [PATCH 57/99] Ticket #47349 - DS instance crashes under a high load + +https://fedorahosted.org/389/ticket/47349 +Reviewed by: nkinder (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: handle_new_connection initializes the connection object, +then calls connection_table_move_connection_on_to_active_list to put it +on the list of active connections, then unlocks the c_mutex, then calls +connection_new_private to allocate c_private. If another thread +interrupts after the conn has been moved to the active list, but before +c_private has been allocated, the new conn will be available via +connection_table_iterate_active_connections where table_iterate_function +will attempt to dereference the NULL c_private. +The fix is to move connection_new_private inside the c_mutex lock, and to +move connection_table_move_connection_on_to_active_list to be the very last +thing before releasing the c_mutex lock. Once the conn is on the active +list it is live and we cannot do anything else to it. +Note: I have still not been able to reproduce the problem in a non-debug +optimized build. +Platforms tested: RHEL6 x86_64 +Note: Before patch, server would crash within 5 minutes. After patch, server +has been running for several days in customer environment. +Flag Day: no +Doc impact: no +(cherry picked from commit 05d209432571dc64b242ae47113ae4cbb43607d2) +(cherry picked from commit 11c0f99aaa2deead80bde7e35dd9f9aabac5cc20) +(cherry picked from commit d1754414bffca63ceec42812387e233c717fe14e) +--- + ldap/servers/slapd/daemon.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index 0304e4a..0a87293 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -2685,16 +2685,6 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i + /* Call the plugin extension constructors */ + conn->c_extension = factory_create_extension(connection_type,conn,NULL /* Parent */); + +- +- /* Add this connection slot to the doubly linked list of active connections. This +- * list is used to find the connections that should be used in the poll call. This +- * connection will be added directly after slot 0 which serves as the head of the list */ +- if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL ) +- { +- /* Now give the new connection to the connection code */ +- connection_table_move_connection_on_to_active_list(the_connection_table,conn); +- } +- + #if defined(ENABLE_LDAPI) + #if !defined( XP_WIN32 ) + /* ldapi */ +@@ -2707,10 +2697,21 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i + #endif + #endif /* ENABLE_LDAPI */ + +- PR_Unlock( conn->c_mutex ); +- + connection_new_private(conn); + ++ /* Add this connection slot to the doubly linked list of active connections. This ++ * list is used to find the connections that should be used in the poll call. This ++ * connection will be added directly after slot 0 which serves as the head of the list. ++ * This must be done as the very last thing before we unlock the mutex, because once it ++ * is added to the active list, it is live. */ ++ if ( conn != NULL && conn->c_next == NULL && conn->c_prev == NULL ) ++ { ++ /* Now give the new connection to the connection code */ ++ connection_table_move_connection_on_to_active_list(the_connection_table,conn); ++ } ++ ++ PR_Unlock( conn->c_mutex ); ++ + g_increment_current_conn_count(); + + return 0; +-- +1.8.1.4 + diff --git a/0058-Ticket-47347-Simple-paged-results-should-support-asy.patch b/0058-Ticket-47347-Simple-paged-results-should-support-asy.patch new file mode 100644 index 0000000..2a870a9 --- /dev/null +++ b/0058-Ticket-47347-Simple-paged-results-should-support-asy.patch @@ -0,0 +1,1127 @@ +From 3efa97aae09f5228bff773809c35db30fa602dfd Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 26 Apr 2013 15:24:22 -0700 +Subject: [PATCH 58/99] Ticket #47347 - Simple paged results should support + async search + +Bug description: Simple paged results serialized the request +even for a series of asynchronous search requests, and it +returned error 53 (unwilling to perform) if the second request +comes in while the first one is being processed. + +Fix description: This patch implements the asynchronous support +for the Simple paged results search. +- Removed pagedresults_check_or_set_processing which was + used to Simple paged results requests exclusive. Instead, + pagedresults_lock is introduced to protect the PagedResults + object from the other threads sharing the same cookie. +- If any error including hitting the sizelimit or timelimit, + search result set was released immediately in ldbm_back_ + next_search_entry_ext, which could cause the race condition + among multiple asynchronous search requests. To prevent it, + the search result set is untouched if the operation is a + Simple paged result search, and let its clean up function + to handle it. +- Sizelimit was evaluated in the accumulative way instead of + on the each page size. For instance, if the sizelimit was + 101 AND the page size is 100, as soon as getting the 2nd page, + it hit the sizelimit and the search failed. This patch fixes + it so that as long as the requested page size is less than 101, + the requests successfully continue without getting an error 4 + (LDAP_SIZELIMIT_EXCEEDED). To fulfill the requirement, the + current size needs to be managed per operation instead of the + search result set or PagedResults object. For the purpose, + introduced o_pagedresults_sizelimit to Slapi_Operation. +- When shutting down, connection_table_free could use backend + callback (e.g., be_search_results_release). Therefore, moved + be_cleanupall after connection_table_free. +- Each Simple paged results helper functions checks if the + operation is really a Simple paged result request control is + associated with to prevent any unexpected behaviour. + +https://fedorahosted.org/389/ticket/47347 + +Reviewed by Rich (Thank you!!) +(cherry picked from commit d53e8221f77ac325123e3bb4f61cf6de67dce646) +(cherry picked from commit 96535a6756b8a556897fb643a31421c7f5068166) +--- + ldap/servers/slapd/back-ldbm/filterindex.c | 11 +- + ldap/servers/slapd/back-ldbm/ldbm_search.c | 117 ++++++++++---------- + ldap/servers/slapd/back-ldbm/vlv.c | 2 +- + ldap/servers/slapd/daemon.c | 13 ++- + ldap/servers/slapd/operation.c | 9 +- + ldap/servers/slapd/opshared.c | 85 +++++++++------ + ldap/servers/slapd/pagedresults.c | 165 ++++++++++++++++++++++++++--- + ldap/servers/slapd/proto-slap.h | 46 +++++--- + ldap/servers/slapd/slap.h | 2 + + ldap/servers/slapd/sort.c | 6 +- + 10 files changed, 320 insertions(+), 136 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c +index 27b20ec..995a62e 100644 +--- a/ldap/servers/slapd/back-ldbm/filterindex.c ++++ b/ldap/servers/slapd/back-ldbm/filterindex.c +@@ -317,7 +317,7 @@ ava_candidates( + if ( unindexed ) { + unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); +- pagedresults_set_unindexed( pb->pb_conn, pr_idx ); ++ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx ); + } + + /* We don't use valuearray_free here since the valueset, berval +@@ -349,7 +349,7 @@ ava_candidates( + if ( unindexed ) { + unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); +- pagedresults_set_unindexed( pb->pb_conn, pr_idx ); ++ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx ); + } + valuearray_free( &ivals ); + LDAPDebug( LDAP_DEBUG_TRACE, "<= ava_candidates %lu\n", +@@ -390,7 +390,7 @@ presence_candidates( + unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); + slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx); +- pagedresults_set_unindexed( pb->pb_conn, pr_idx ); ++ pagedresults_set_unindexed(pb->pb_conn, pb->pb_op, pr_idx); + } + + if (idl != NULL && ALLIDS(idl) && strcasecmp(type, "nscpentrydn") == 0) { +@@ -504,6 +504,7 @@ extensible_candidates( + SLAPI_PAGED_RESULTS_INDEX, + &pr_idx ); + pagedresults_set_unindexed( glob_pb->pb_conn, ++ glob_pb->pb_op, + pr_idx ); + } + if (idl2 == NULL) +@@ -916,7 +917,7 @@ substring_candidates( + slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx); + if ( ivals == NULL || *ivals == NULL ) { + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); +- pagedresults_set_unindexed( pb->pb_conn, pr_idx ); ++ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx ); + LDAPDebug( LDAP_DEBUG_TRACE, + "<= sub_candidates ALLIDS (no keys)\n", 0, 0, 0 ); + return( idl_allids( be ) ); +@@ -930,7 +931,7 @@ substring_candidates( + idl = keys2idl( be, type, indextype_SUB, ivals, err, &unindexed, &txn, allidslimit ); + if ( unindexed ) { + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); +- pagedresults_set_unindexed( pb->pb_conn, pr_idx ); ++ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx ); + } + valuearray_free( &ivals ); + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c +index f86f27c..670f627 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c +@@ -53,7 +53,7 @@ static int build_candidate_list( Slapi_PBlock *pb, backend *be, + static IDList *base_candidates( Slapi_PBlock *pb, struct backentry *e ); + static IDList *onelevel_candidates( Slapi_PBlock *pb, backend *be, const char *base, struct backentry *e, Slapi_Filter *filter, int managedsait, int *lookup_returned_allidsp, int *err ); + static back_search_result_set* new_search_result_set(IDList* idl,int vlv, int lookthroughlimit); +-static void delete_search_result_set( back_search_result_set **sr ); ++static void delete_search_result_set(Slapi_PBlock *pb, back_search_result_set **sr); + static int can_skip_filter_test( Slapi_PBlock *pb, struct slapi_filter *f, + int scope, IDList *idl ); + +@@ -165,6 +165,7 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb, + int estimate = 0; /* estimated search result count */ + backend *be; + ldbm_instance *inst; ++ back_search_result_set *sr = NULL; + + slapi_pblock_get( pb, SLAPI_BACKEND, &be ); + inst = (ldbm_instance *) be->be_instance_info; +@@ -178,19 +179,14 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb, + { + slapi_send_ldap_result( pb, ldap_result, NULL, ldap_result_description, 0, NULL ); + } +- { +- /* hack hack --- code to free the result set if we don't need it */ +- /* We get it and check to see if the structure was ever used */ +- back_search_result_set *sr = NULL; +- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr ); +- if ( (NULL != sr) && (function_result != 0) ) { +- int pr_idx = -1; +- slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx ); +- /* in case paged results, clean up the conn */ +- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx ); +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL ); +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate ); +- delete_search_result_set(&sr); ++ /* code to free the result set if we don't need it */ ++ /* We get it and check to see if the structure was ever used */ ++ slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr); ++ if (sr) { ++ if (function_result) { ++ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate); ++ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL); ++ delete_search_result_set(pb, &sr); + } + } + if (vlv_request_control) +@@ -853,7 +849,7 @@ ldbm_back_search( Slapi_PBlock *pb ) + + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); + slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx ); +- pagedresults_set_unindexed( pb->pb_conn, pr_idx ); ++ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx ); + } + + sr->sr_candidates = candidates; +@@ -1341,13 +1337,24 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + int estimate = 0; /* estimated search result count */ + back_txn txn = {NULL}; + int pr_idx = -1; ++ Slapi_Connection *conn; ++ Slapi_Operation *op; + ++ slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &basesdn ); ++ if (NULL == basesdn) { ++ slapi_send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL, ++ "Null target DN", 0, NULL ); ++ return( -1 ); ++ } ++ slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr ); ++ if (NULL == sr) { ++ goto bail; ++ } + slapi_pblock_get( pb, SLAPI_BACKEND, &be ); + slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li ); + slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ); + slapi_pblock_get( pb, SLAPI_MANAGEDSAIT, &managedsait ); + slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ); +- slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &basesdn ); + slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries ); + slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &slimit ); + slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit ); +@@ -1355,32 +1362,30 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot ); + slapi_pblock_get( pb, SLAPI_SEARCH_REFERRALS, &urls ); + slapi_pblock_get( pb, SLAPI_TARGET_UNIQUEID, &target_uniqueid ); +- slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr ); + slapi_pblock_get( pb, SLAPI_TXN, &txn.back_txn_txn ); +- slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx ); ++ slapi_pblock_get( pb, SLAPI_CONNECTION, &conn ); ++ slapi_pblock_get( pb, SLAPI_OPERATION, &op ); + + if ( !txn.back_txn_txn ) { + dblayer_txn_init( li, &txn ); + slapi_pblock_set( pb, SLAPI_TXN, txn.back_txn_txn ); + } + +- if (NULL == sr) { +- goto bail; +- } +- + if (sr->sr_norm_filter) { + int val = 1; + slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &val ); + filter = sr->sr_norm_filter; + } + +- if (NULL == basesdn) { +- slapi_send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL, +- "Null target DN", 0, NULL ); +- return( -1 ); +- } +- +- if (sr->sr_current_sizelimit >= 0) { ++ if (op_is_pagedresults(op)) { ++ int myslimit; ++ /* On Simple Paged Results search, sizelimit is appied for each page. */ ++ slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx); ++ myslimit = pagedresults_get_sizelimit(conn, op, pr_idx); ++ if (myslimit >= 0) { ++ slimit = myslimit; ++ } ++ } else if (sr->sr_current_sizelimit >= 0) { + /* + * sr_current_sizelimit contains the current sizelimit. + * In case of paged results, getting one page is one operation, +@@ -1397,8 +1402,7 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + /* Return to the cache the entry we handed out last time */ + /* If we are using the extension, the front end will tell + * us when to do this so we don't do it now */ +- if ( !use_extension ) +- { ++ if (sr->sr_entry && !use_extension) { + CACHE_RETURN( &inst->inst_cache, &(sr->sr_entry) ); + sr->sr_entry = NULL; + } +@@ -1422,15 +1426,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + /* check for abandon */ + if ( slapi_op_abandoned( pb ) || (NULL == sr) ) + { +- /* in case paged results, clean up the conn */ +- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx ); +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL ); + 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( &sr ); ++ delete_search_result_set(pb, &sr); + rc = SLAPI_FAIL_GENERAL; + goto bail; + } +@@ -1439,15 +1440,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + curtime = current_time(); + if ( tlimit != -1 && curtime > stoptime ) + { +- /* in case paged results, clean up the conn */ +- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx ); +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL ); + 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( &sr ); ++ delete_search_result_set(pb, &sr); + rc = SLAPI_FAIL_GENERAL; + slapi_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, urls ); + goto bail; +@@ -1456,15 +1454,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + /* check lookthrough limit */ + if ( llimit != -1 && sr->sr_lookthroughcount >= llimit ) + { +- /* in case paged results, clean up the conn */ +- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx ); +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL ); + 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( &sr ); ++ delete_search_result_set(pb, &sr); + rc = SLAPI_FAIL_GENERAL; + slapi_send_ldap_result( pb, LDAP_ADMINLIMIT_EXCEEDED, NULL, NULL, nentries, urls ); + goto bail; +@@ -1476,15 +1471,12 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + { + /* No more entries */ + /* destroy back_search_result_set */ +- /* in case paged results, clean up the conn */ +- pagedresults_set_search_result( pb->pb_conn, NULL, 0, pr_idx ); +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL ); + 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( &sr ); ++ delete_search_result_set(pb, &sr); + rc = 0; + goto bail; + } +@@ -1617,17 +1609,20 @@ ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension ) + { + if ( --slimit < 0 ) { + CACHE_RETURN( &inst->inst_cache, &e ); +- /* in case paged results, clean up the conn */ +- pagedresults_set_search_result( pb->pb_conn, NULL, +- 0, pr_idx); +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL ); + slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate ); +- delete_search_result_set( &sr ); ++ delete_search_result_set(pb, &sr); + slapi_send_ldap_result( pb, LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, nentries, urls ); + rc = SLAPI_FAIL_GENERAL; + goto bail; + } + slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, &slimit ); ++ if (op_is_pagedresults(op)) { ++ /* ++ * On Simple Paged Results search, ++ * sizelimit is appied to each page. ++ */ ++ pagedresults_set_sizelimit(conn, op, slimit, pr_idx); ++ } + sr->sr_current_sizelimit = slimit; + } + if ( (filter_test != 0) && sr->sr_virtuallistview) +@@ -1734,13 +1729,20 @@ new_search_result_set(IDList *idl, int vlv, int lookthroughlimit) + } + + static void +-delete_search_result_set( back_search_result_set **sr ) ++delete_search_result_set( Slapi_PBlock *pb, back_search_result_set **sr ) + { + int rc = 0, filt_errs = 0; +- if ( NULL == sr || NULL == *sr) ++ if ( NULL == sr || NULL == *sr ) + { + return; + } ++ if (pb) { ++ if (op_is_pagedresults(pb->pb_op)) { ++ /* If the op is pagedresults, let the module clean up sr. */ ++ return; ++ } ++ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL); ++ } + if ( NULL != (*sr)->sr_candidates ) + { + idl_free( (*sr)->sr_candidates ); +@@ -1755,12 +1757,17 @@ delete_search_result_set( back_search_result_set **sr ) + slapi_filter_free((*sr)->sr_norm_filter, 1); + memset( *sr, 0, sizeof( back_search_result_set ) ); + slapi_ch_free( (void**)sr ); ++ return; + } + ++/* ++ * This function is called from pagedresults free/cleanup functions. ++ */ + void + ldbm_back_search_results_release( void **sr ) + { +- delete_search_result_set( (back_search_result_set **)sr ); ++ /* passing NULL pb forces to delete the search result set */ ++ delete_search_result_set( NULL, (back_search_result_set **)sr ); + } + + int +diff --git a/ldap/servers/slapd/back-ldbm/vlv.c b/ldap/servers/slapd/back-ldbm/vlv.c +index 2c09531..dcc42fa 100644 +--- a/ldap/servers/slapd/back-ldbm/vlv.c ++++ b/ldap/servers/slapd/back-ldbm/vlv.c +@@ -1156,7 +1156,7 @@ vlv_search_build_candidate_list(Slapi_PBlock *pb, const Slapi_DN *base, int *vlv + slapi_pblock_get( pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx ); + slapi_rwlock_unlock(be->vlvSearchList_lock); + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); +- pagedresults_set_unindexed( pb->pb_conn, pr_idx ); ++ pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx ); + rc = VLV_FIND_SEARCH_FAILED; + } else if((*vlv_rc=vlvIndex_accessallowed(pi, pb)) != LDAP_SUCCESS) { + slapi_rwlock_unlock(be->vlvSearchList_lock); +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index 0a87293..75a83c0 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -1363,14 +1363,19 @@ void slapd_daemon( daemon_ports_t *ports ) + mapping_tree_free (); + } + ++ /* ++ * connection_table_free could use callbacks in the backend. ++ * (e.g., be_search_results_release) ++ * Thus, it needs to be called before be_cleanupall. ++ */ ++ connection_table_free(the_connection_table); ++ the_connection_table= NULL; ++ + be_cleanupall (); +- LDAPDebug( LDAP_DEBUG_TRACE, "slapd shutting down - backends closed down\n", ++ LDAPDebug( LDAP_DEBUG_TRACE, "slapd shutting down - backends closed down\n", + 0, 0, 0 ); + referrals_free(); + +- connection_table_free(the_connection_table); +- the_connection_table= NULL; +- + /* tell the time thread to shutdown and then wait for it */ + time_shutdown = 1; + PR_JoinThread( time_thread_p ); +diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c +index 13e05c1..01ebfef 100644 +--- a/ldap/servers/slapd/operation.c ++++ b/ldap/servers/slapd/operation.c +@@ -201,10 +201,11 @@ operation_new(int flags) + o->o_next = NULL; + o->o_flags= flags; + if ( config_get_accesslog_level() & LDAP_DEBUG_TIMING ) { +- o->o_interval = PR_IntervalNow(); +- } else { +- o->o_interval = (PRIntervalTime)0; +- } ++ o->o_interval = PR_IntervalNow(); ++ } else { ++ o->o_interval = (PRIntervalTime)0; ++ } ++ o->o_pagedresults_sizelimit = -1; + } + return o; + } +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index fabe8a4..a96b950 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -245,7 +245,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + int internal_op; + Slapi_DN *basesdn = NULL; + Slapi_DN *sdn = NULL; +- Slapi_Operation *operation; ++ Slapi_Operation *operation = NULL; + Slapi_Entry *referral = NULL; + char *proxydn = NULL; + char *proxystr = NULL; +@@ -271,7 +271,6 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + int curr_search_count = 0; + Slapi_Backend *pr_be = NULL; + void *pr_search_result = NULL; +- int pr_reset_processing = 0; + int pr_idx = -1; + Slapi_DN *orig_sdn = NULL; + int free_sdn = 0; +@@ -469,23 +468,16 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + if ((LDAP_SUCCESS == rc) || + (LDAP_CANCELLED == rc) || (0 == pagesize)) { + unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED; +- if (pagedresults_check_or_set_processing(pb->pb_conn, pr_idx)) { +- send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, +- NULL, "Simple Paged Results Search " +- "already in progress on this connection", +- 0, NULL); +- goto free_and_return_nolock; +- } +- /* need to reset after we are done with this op */ +- pr_reset_processing = 1; + 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 (pagedresults_get_unindexed(pb->pb_conn, pr_idx)) { ++ if (pagedresults_get_unindexed(pb->pb_conn, operation, pr_idx)) { + opnote |= SLAPI_OP_NOTE_UNINDEXED; + } + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); +@@ -640,7 +632,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + 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, time_up, pr_idx); ++ 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 */ +@@ -694,12 +686,25 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + if (op_is_pagedresults(operation) && pr_search_result) { + void *sr = NULL; + /* PAGED RESULTS and already have the search results from the prev op */ +- slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result ); +- rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat); ++ pagedresults_lock(pb->pb_conn, pr_idx); ++ /* ++ * 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); ++ 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); + +- /* 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, 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; ++ } ++ pagedresults_unlock(pb->pb_conn, pr_idx); + + if (PAGEDRESULTS_SEARCH_END == pr_stat) { + /* no more entries to send in the backend */ +@@ -720,14 +725,18 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + } + pagedresults_set_response_control(pb, 0, estimate, + curr_search_count, pr_idx); +- if (pagedresults_get_with_sort(pb->pb_conn, pr_idx)) { ++ if (pagedresults_get_with_sort(pb->pb_conn, operation, pr_idx)) { + sort_make_sort_response_control(pb, CONN_GET_SORT_RESULT_CODE, NULL); + } + pagedresults_set_search_result_set_size_estimate(pb->pb_conn, ++ operation, + estimate, pr_idx); + next_be = NULL; /* to break the loop */ + if (curr_search_count == -1) { +- pagedresults_free_one(pb->pb_conn, pr_idx); ++ 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); ++ pagedresults_unlock(pb->pb_conn, pr_idx); + } + } else { + /* be_suffix null means that we are searching the default backend +@@ -849,7 +858,11 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + int with_sort = operation->o_flags & OP_FLAG_SERVER_SIDE_SORTING; + + 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 */ ++ be->be_search_results_release(&sr); ++ } + if (NULL == next_be) { + /* no more entries && no more backends */ + curr_search_count = -1; +@@ -861,24 +874,31 @@ op_shared_search (Slapi_PBlock *pb, int send_result) + } + } else { + curr_search_count = pnentries; +- slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr); + slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate); +- if (pagedresults_set_current_be(pb->pb_conn, be, pr_idx) < 0 || +- pagedresults_set_search_result(pb->pb_conn, sr, 0, pr_idx) < 0 || +- pagedresults_set_search_result_count(pb->pb_conn, +- curr_search_count, pr_idx) < 0 || +- pagedresults_set_search_result_set_size_estimate(pb->pb_conn, +- estimate, pr_idx) < 0 || +- pagedresults_set_with_sort(pb->pb_conn, with_sort, pr_idx) < 0) { ++ 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_unlock(pb->pb_conn, pr_idx); + goto free_and_return; + } ++ 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 (curr_search_count == -1) { +- pagedresults_free_one(pb->pb_conn, pr_idx); ++ pagedresults_free_one(pb->pb_conn, operation, pr_idx); + } + } + +@@ -1007,9 +1027,6 @@ free_and_return_nolock: + + slapi_ch_free_string(&proxydn); + slapi_ch_free_string(&proxystr); +- if (pr_reset_processing) { +- pagedresults_reset_processing(pb->pb_conn, pr_idx); +- } + } + + /* Returns 1 if this processing on this entry is finished +@@ -1257,7 +1274,7 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, + + *pnentries = 0; + +- while (!done) ++ while (!done) + { + Slapi_Entry *gerentry = NULL; + Slapi_Operation *operation; +@@ -1275,7 +1292,7 @@ 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, 0, pr_idx); ++ 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 9b294eb..78bd6b0 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -131,6 +131,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + } + } + conn->c_pagedresults.prl_count++; ++ conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock(); + } else { + /* Repeated paged results request. + * PagedResults is already allocated. */ +@@ -140,6 +141,8 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + *index = strtol(ptr, NULL, 10); + slapi_ch_free_string(&ptr); + } ++ /* reset sizelimit */ ++ op->o_pagedresults_sizelimit = -1; + slapi_ch_free((void **)&cookie.bv_val); + + if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) { +@@ -243,10 +246,13 @@ bailout: + } + + int +-pagedresults_free_one( Connection *conn, int index ) ++pagedresults_free_one( Connection *conn, Operation *op, int index ) + { + int rc = -1; + ++ if (!op_is_pagedresults(op)) { ++ return 0; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_free_one: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -256,13 +262,19 @@ pagedresults_free_one( Connection *conn, 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)); + } ++ 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; + conn->c_pagedresults.prl_count--; + rc = 0; + } +@@ -348,9 +360,12 @@ pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index) + } + + void * +-pagedresults_get_search_result(Connection *conn, int index) ++pagedresults_get_search_result(Connection *conn, Operation *op, int index) + { + void *sr = NULL; ++ if (!op_is_pagedresults(op)) { ++ return sr; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_get_search_result: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -366,20 +381,31 @@ pagedresults_get_search_result(Connection *conn, int index) + } + + int +-pagedresults_set_search_result(Connection *conn, void *sr, ++pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, + int locked, int index) + { + int rc = -1; ++ if (!op_is_pagedresults(op)) { ++ return 0; /* noop */ ++ } + LDAPDebug2Args(LDAP_DEBUG_TRACE, + "--> pagedresults_set_search_result: idx=%d, sr=%p\n", + index, sr); + if (conn && (index > -1)) { + if (!locked) PR_Lock(conn->c_mutex); + if (index < conn->c_pagedresults.prl_maxlen) { +- conn->c_pagedresults.prl_list[index].pr_search_result_set = sr; ++ 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; ++ } + } + if (!locked) PR_Unlock(conn->c_mutex); +- rc = 0; + } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "<-- pagedresults_set_search_result: %d\n", rc); +@@ -387,9 +413,12 @@ pagedresults_set_search_result(Connection *conn, void *sr, + } + + int +-pagedresults_get_search_result_count(Connection *conn, int index) ++pagedresults_get_search_result_count(Connection *conn, Operation *op, int index) + { + int count = 0; ++ if (!op_is_pagedresults(op)) { ++ return count; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_get_search_result_count: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -405,9 +434,13 @@ pagedresults_get_search_result_count(Connection *conn, int index) + } + + int +-pagedresults_set_search_result_count(Connection *conn, int count, int index) ++pagedresults_set_search_result_count(Connection *conn, Operation *op, ++ int count, int index) + { + int rc = -1; ++ if (!op_is_pagedresults(op)) { ++ return rc; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_set_search_result_count: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -424,9 +457,14 @@ pagedresults_set_search_result_count(Connection *conn, int count, int index) + } + + int +-pagedresults_get_search_result_set_size_estimate(Connection *conn, int index) ++pagedresults_get_search_result_set_size_estimate(Connection *conn, ++ Operation *op, ++ int index) + { + int count = 0; ++ if (!op_is_pagedresults(op)) { ++ return count; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_get_search_result_set_size_estimate: " + "idx=%d\n", index); +@@ -445,9 +483,13 @@ pagedresults_get_search_result_set_size_estimate(Connection *conn, int index) + + int + pagedresults_set_search_result_set_size_estimate(Connection *conn, ++ Operation *op, + int count, int index) + { + int rc = -1; ++ if (!op_is_pagedresults(op)) { ++ return rc; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_set_search_result_set_size_estimate: " + "idx=%d\n", index); +@@ -466,9 +508,12 @@ pagedresults_set_search_result_set_size_estimate(Connection *conn, + } + + int +-pagedresults_get_with_sort(Connection *conn, int index) ++pagedresults_get_with_sort(Connection *conn, Operation *op, int index) + { + int flags = 0; ++ if (!op_is_pagedresults(op)) { ++ return flags; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_get_with_sort: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -484,9 +529,13 @@ pagedresults_get_with_sort(Connection *conn, int index) + } + + int +-pagedresults_set_with_sort(Connection *conn, int flags, int index) ++pagedresults_set_with_sort(Connection *conn, Operation *op, ++ int flags, int index) + { + int rc = -1; ++ if (!op_is_pagedresults(op)) { ++ return rc; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_set_with_sort: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -505,9 +554,12 @@ pagedresults_set_with_sort(Connection *conn, int flags, int index) + } + + int +-pagedresults_get_unindexed(Connection *conn, int index) ++pagedresults_get_unindexed(Connection *conn, Operation *op, int index) + { + int flags = 0; ++ if (!op_is_pagedresults(op)) { ++ return flags; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_get_unindexed: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -523,9 +575,12 @@ pagedresults_get_unindexed(Connection *conn, int index) + } + + int +-pagedresults_set_unindexed(Connection *conn, int index) ++pagedresults_set_unindexed(Connection *conn, Operation *op, int index) + { + int rc = -1; ++ if (!op_is_pagedresults(op)) { ++ return rc; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_set_unindexed: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -543,9 +598,12 @@ pagedresults_set_unindexed(Connection *conn, int index) + } + + int +-pagedresults_get_sort_result_code(Connection *conn, int index) ++pagedresults_get_sort_result_code(Connection *conn, Operation *op, int index) + { + int code = LDAP_OPERATIONS_ERROR; ++ if (!op_is_pagedresults(op)) { ++ return code; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_get_sort_result_code: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -561,9 +619,13 @@ pagedresults_get_sort_result_code(Connection *conn, int index) + } + + int +-pagedresults_set_sort_result_code(Connection *conn, int code, int index) ++pagedresults_set_sort_result_code(Connection *conn, Operation *op, ++ int code, int index) + { + int rc = -1; ++ if (!op_is_pagedresults(op)) { ++ return rc; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_set_sort_result_code: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -580,9 +642,13 @@ pagedresults_set_sort_result_code(Connection *conn, int code, int index) + } + + int +-pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index) ++pagedresults_set_timelimit(Connection *conn, Operation *op, ++ time_t timelimit, int index) + { + int rc = -1; ++ if (!op_is_pagedresults(op)) { ++ return rc; /* noop */ ++ } + LDAPDebug1Arg(LDAP_DEBUG_TRACE, + "--> pagedresults_set_timelimit: idx=%d\n", index); + if (conn && (index > -1)) { +@@ -597,6 +663,35 @@ pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index) + return rc; + } + ++int ++pagedresults_set_sizelimit(Connection *conn, Operation *op, ++ int sizelimit, int index) ++{ ++ int rc = -1; ++ if (!op_is_pagedresults(op)) { ++ return rc; /* noop */ ++ } ++ LDAPDebug1Arg(LDAP_DEBUG_TRACE, ++ "--> pagedresults_set_sizelimit: idx=%d\n", index); ++ op->o_pagedresults_sizelimit = sizelimit; ++ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_set_sizelimit: %d\n", rc); ++ return rc; ++} ++ ++int ++pagedresults_get_sizelimit(Connection *conn, Operation *op, int index) ++{ ++ int sizelimit = -1; ++ if (!op_is_pagedresults(op)) { ++ return sizelimit; /* noop */ ++ } ++ LDAPDebug1Arg(LDAP_DEBUG_TRACE, ++ "--> pagedresults_get_sizelimit: idx=%d\n", index); ++ sizelimit = op->o_pagedresults_sizelimit; ++ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- pagedresults_get_sizelimit\n"); ++ return sizelimit; ++} ++ + /* + * pagedresults_cleanup cleans up the pagedresults list; + * it does not free the list. +@@ -629,6 +724,9 @@ pagedresults_cleanup(Connection *conn, int needlock) + prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set)); + rc = 1; + } ++ if (prp->pr_mutex) { ++ PR_DestroyLock(prp->pr_mutex); ++ } + memset(prp, '\0', sizeof(PagedResults)); + } + conn->c_pagedresults.prl_count = 0; +@@ -665,6 +763,9 @@ pagedresults_cleanup_all(Connection *conn, int needlock) + for (i = 0; conn->c_pagedresults.prl_list && + i < conn->c_pagedresults.prl_maxlen; i++) { + prp = conn->c_pagedresults.prl_list + i; ++ if (prp->pr_mutex) { ++ PR_DestroyLock(prp->pr_mutex); ++ } + 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)); +@@ -681,6 +782,7 @@ pagedresults_cleanup_all(Connection *conn, int needlock) + return rc; + } + ++#if 0 /* Stopped using it (#47347) */ + /* + * check to see if this connection is currently processing + * a pagedresults search - if it is, return True - if not, +@@ -734,6 +836,7 @@ pagedresults_reset_processing(Connection *conn, int index) + "<-- pagedresults_reset_processing: %d\n", ret); + return ret; + } ++#endif + + /* Are all the paged results requests timed out? */ + int +@@ -819,3 +922,35 @@ op_set_pagedresults(Operation *op) + } + op->o_flags |= OP_FLAG_PAGED_RESULTS; + } ++ ++/* ++ * pagedresults_lock/unlock -- introduced to protect search results for the ++ * asynchronous searches. ++ */ ++void ++pagedresults_lock( Connection *conn, int index ) ++{ ++ PagedResults *prp; ++ if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) { ++ return; ++ } ++ prp = conn->c_pagedresults.prl_list + index; ++ if (prp->pr_mutex) { ++ PR_Lock(prp->pr_mutex); ++ } ++ return; ++} ++ ++void ++pagedresults_unlock( Connection *conn, int index ) ++{ ++ PagedResults *prp; ++ if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) { ++ return; ++ } ++ prp = conn->c_pagedresults.prl_list + index; ++ if (prp->pr_mutex) { ++ PR_Unlock(prp->pr_mutex); ++ } ++ return; ++} +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index a68c2d9..911dadd 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -1405,34 +1405,48 @@ void pagedresults_set_response_control(Slapi_PBlock *pb, int iscritical, + 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); +-void *pagedresults_get_search_result(Connection *conn, int index); +-int pagedresults_set_search_result(Connection *conn, void *sr, ++void *pagedresults_get_search_result(Connection *conn, Operation *op, ++ int index); ++int pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, + int locked, int index); +-int pagedresults_get_search_result_count(Connection *conn, int index); +-int pagedresults_set_search_result_count(Connection *conn, int cnt, int index); +-int pagedresults_get_search_result_set_size_estimate(Connection *conn, ++int pagedresults_get_search_result_count(Connection *conn, Operation *op, ++ int index); ++int pagedresults_set_search_result_count(Connection *conn, Operation *op, int cnt, int index); ++int pagedresults_get_search_result_set_size_estimate(Connection *conn, ++ Operation *op, + int index); +-int pagedresults_set_search_result_set_size_estimate(Connection *conn, int cnt, ++int pagedresults_set_search_result_set_size_estimate(Connection *conn, ++ Operation *op, int cnt, + int index); +-int pagedresults_get_with_sort(Connection *conn, int index); +-int pagedresults_set_with_sort(Connection *conn, int flags, int index); +-int pagedresults_get_unindexed(Connection *conn, int index); +-int pagedresults_set_unindexed(Connection *conn, int index); +-int pagedresults_get_sort_result_code(Connection *conn, int index); +-int pagedresults_set_sort_result_code(Connection *conn, int code, int index); +-int pagedresults_set_timelimit(Connection *conn, time_t timelimit, int index); ++int pagedresults_get_with_sort(Connection *conn, Operation *op, int index); ++int pagedresults_set_with_sort(Connection *conn, Operation *op, ++ int flags, int index); ++int pagedresults_get_unindexed(Connection *conn, Operation *op, int index); ++int pagedresults_set_unindexed(Connection *conn, Operation *op, int index); ++int pagedresults_get_sort_result_code(Connection *conn, Operation *op, ++ int index); ++int pagedresults_set_sort_result_code(Connection *conn, Operation *op, ++ int code, int index); ++int pagedresults_set_timelimit(Connection *conn, Operation *op, ++ time_t timelimit, int index); ++int pagedresults_get_sizelimit(Connection *conn, Operation *op, int index); ++int pagedresults_set_sizelimit(Connection *conn, Operation *op, ++ int sizelimit, int index); + int pagedresults_cleanup(Connection *conn, int needlock); ++#if 0 /* Stopped using it (#47347) */ + int pagedresults_check_or_set_processing(Connection *conn, int index); + int pagedresults_reset_processing(Connection *conn, int index); ++#endif + int pagedresults_is_timedout_nolock(Connection *conn); + int pagedresults_reset_timedout_nolock(Connection *conn); + int pagedresults_in_use_nolock(Connection *conn); +-int pagedresults_free_one(Connection *conn, int index); +-int pagedresults_free_one_msgid_nolock( Connection *conn, ber_int_t msgid ); ++int pagedresults_free_one(Connection *conn, Operation *op, int index); ++int pagedresults_free_one_msgid_nolock(Connection *conn, ber_int_t msgid); + int op_is_pagedresults(Operation *op); + 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); + + /* + * sort.c +diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h +index d290c92..ef986e2 100644 +--- a/ldap/servers/slapd/slap.h ++++ b/ldap/servers/slapd/slap.h +@@ -1339,6 +1339,7 @@ typedef struct op { + unsigned long o_abandoned_op; /* operation abandoned by this operation - used to decide which plugins to invoke */ + struct slapi_operation_parameters o_params; + struct slapi_operation_results o_results; ++ int o_pagedresults_sizelimit; + } Operation; + + /* +@@ -1367,6 +1368,7 @@ typedef struct _paged_results { + time_t pr_timelimit; /* time limit for this request */ + int pr_flags; + ber_int_t pr_msgid; /* msgid of the request; to abandon */ ++ PRLock *pr_mutex; /* protect each conn structure */ + } PagedResults; + + /* array of simple paged structure stashed in connection */ +diff --git a/ldap/servers/slapd/sort.c b/ldap/servers/slapd/sort.c +index 903fa6f..72c9ec9 100644 +--- a/ldap/servers/slapd/sort.c ++++ b/ldap/servers/slapd/sort.c +@@ -58,12 +58,14 @@ sort_make_sort_response_control ( Slapi_PBlock *pb, int code, char *error_type) + slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx); + + if (code == CONN_GET_SORT_RESULT_CODE) { +- code = pagedresults_get_sort_result_code(pb->pb_conn, pr_idx); ++ code = pagedresults_get_sort_result_code(pb->pb_conn, ++ pb->pb_op, pr_idx); + } else { + Slapi_Operation *operation; + slapi_pblock_get (pb, SLAPI_OPERATION, &operation); + if (op_is_pagedresults(operation)) { +- pagedresults_set_sort_result_code(pb->pb_conn, code, pr_idx); ++ pagedresults_set_sort_result_code(pb->pb_conn, ++ pb->pb_op, code, pr_idx); + } + } + +-- +1.8.1.4 + diff --git a/0059-Trac-Ticket-531-loading-an-entry-from-the-database-s.patch b/0059-Trac-Ticket-531-loading-an-entry-from-the-database-s.patch new file mode 100644 index 0000000..dfdedac --- /dev/null +++ b/0059-Trac-Ticket-531-loading-an-entry-from-the-database-s.patch @@ -0,0 +1,72 @@ +From 5bfd8890e549659ac5255699731085a88f7dcc31 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 10 Dec 2012 15:08:05 -0800 +Subject: [PATCH 59/99] Trac Ticket #531 - loading an entry from the database + should use str2entry_f + +https://fedorahosted.org/389/ticket/531 + +Description: Based upon the comments by Rich Megginson (Thanks!!), +changing the newly introduced macro to all upper case. Plus, it +was pointed out that the meaning of the macro name was opposite. +Fixing these 2 issues, this patch replaces the macro str2entry_ +can_use_fast with STR2ENTRY_CANNOT_USE_FAST. +(cherry picked from commit b3a0ab786091705883bec5315c9b74e025ad211a) +(cherry picked from commit b5dc3dbd1b7af9436014067441ae949809d5daf2) +--- + ldap/servers/slapd/entry.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c +index 1926417..f38c39e 100644 +--- a/ldap/servers/slapd/entry.c ++++ b/ldap/servers/slapd/entry.c +@@ -1315,6 +1315,8 @@ free_and_return: + | SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES \ + | SLAPI_STR2ENTRY_TOMBSTONE_CHECK \ + | SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT \ ++ | SLAPI_STR2ENTRY_NO_ENTRYDN \ ++ | SLAPI_STR2ENTRY_DN_NORMALIZED \ + ) + + #define SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST \ +@@ -1322,6 +1324,14 @@ free_and_return: + | SLAPI_STRENTRY_FLAGS_HANDLED_IN_SLAPI_STR2ENTRY \ + ) + ++/* ++ * If well-formed LDIF has not been provided OR if a flag that is ++ * not handled by str2entry_fast() has been passed in, call the ++ * slower but more forgiving str2entry_dupcheck() function. ++ */ ++#define STR2ENTRY_CANNOT_USE_FAST(flags) \ ++ (((flags) & SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF) || \ ++ ((flags) & ~SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST)) + + Slapi_Entry * + slapi_str2entry( char *s, int flags ) +@@ -1339,9 +1349,8 @@ slapi_str2entry( char *s, int flags ) + * not handled by str2entry_fast() has been passed in, call the + * slower but more forgiving str2entry_dupcheck() function. + */ +- if ( 0 != ( flags & SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ) || +- 0 != ( flags & ~SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST )) +- { ++ if (STR2ENTRY_CANNOT_USE_FAST(flags)) ++ { + e= str2entry_dupcheck( NULL/*dn*/, s, flags, read_stateinfo ); + } + else +@@ -1401,8 +1410,7 @@ slapi_str2entry_ext( const char *normdn, char *s, int flags ) + * not handled by str2entry_fast() has been passed in, call the + * slower but more forgiving str2entry_dupcheck() function. + */ +- if ( 0 != ( flags & SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ) || +- 0 != ( flags & ~SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST )) ++ if (STR2ENTRY_CANNOT_USE_FAST(flags)) + { + e = str2entry_dupcheck( normdn, s, + flags|SLAPI_STR2ENTRY_DN_NORMALIZED, read_stateinfo ); +-- +1.8.1.4 + diff --git a/0060-Ticket-47362-ipa-upgrade-selinuxusermap-data-not-rep.patch b/0060-Ticket-47362-ipa-upgrade-selinuxusermap-data-not-rep.patch new file mode 100644 index 0000000..8047096 --- /dev/null +++ b/0060-Ticket-47362-ipa-upgrade-selinuxusermap-data-not-rep.patch @@ -0,0 +1,163 @@ +From 84c69dee99ae60b9a571b41bb84514a15eec7b74 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 15 May 2013 19:39:24 -0600 +Subject: [PATCH 60/99] Ticket #47362 - ipa upgrade selinuxusermap data not + replicating + +https://fedorahosted.org/389/ticket/47362 +Reviewed by: nhosoi (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: When nsslapd-port is set to 0, this causes the +replica purl to be "ldap://hostname:0". At startup, the MMR code looks to +see if this replica purl is in the RUV, by doing a string comparison of this +purl with the ruv replica purl. If it is not there, the MMR code wipes out +this ruv element. Later the code in replica_check_for_data_reload() uses +this RUV to see if it needs to reinit the changelog. Since the RUV doesn't +match the changelog RUV any more, the changelog is erased, which erases +any changes that were made in the meantime. The missing RUV element causes +the supplier to attempt to send over changes which may already exist on the +consumer. If one of these is an ADD, the urp code will correctly flag this +as an attempt to add an entry that already exists, and will turn this into +a replConflict entry. A subsequent attempt to replicate the same ADD will +cause an error in the urp code which will cause it to return err=53. +Replication will then become stuck on this update - it will keep trying to +send it over and over again, and will not be able to proceed. +The only workaround is a replica reinit of the replica, to get the database +RUV and changelog in a consistent state. +I've also added some additional RUV debugging when using the REPL log level. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 0c194eb79aa381bf4e4cd05082956218512115a4) +--- + .../plugins/replication/repl5_inc_protocol.c | 38 ++++++++++++++++++++++ + ldap/servers/plugins/replication/repl5_ruv.c | 32 ++++++++++++++++++ + 2 files changed, 70 insertions(+) + +diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c +index 743be57..82b121c 100644 +--- a/ldap/servers/plugins/replication/repl5_inc_protocol.c ++++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c +@@ -1931,6 +1931,44 @@ repl5_inc_stop(Private_Repl_Protocol *prp) + agmt_get_long_name(prp->agmt), + PR_IntervalToSeconds(now-start)); + } ++ if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) { ++ if (NULL == prp->replica_object) { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "%s: repl5_inc_stop: protocol replica_object is NULL\n", ++ agmt_get_long_name(prp->agmt)); ++ } else { ++ Replica *replica; ++ object_acquire(prp->replica_object); ++ replica = object_get_data(prp->replica_object); ++ if (NULL == replica) { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "%s: repl5_inc_stop: replica is NULL\n", ++ agmt_get_long_name(prp->agmt)); ++ } else { ++ Object *ruv_obj = replica_get_ruv(replica); ++ if (NULL == ruv_obj) { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "%s: repl5_inc_stop: ruv_obj is NULL\n", ++ agmt_get_long_name(prp->agmt)); ++ } else { ++ RUV *ruv; ++ object_acquire(ruv_obj); ++ ruv = (RUV*)object_get_data (ruv_obj); ++ if (NULL == ruv) { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "%s: repl5_inc_stop: ruv is NULL\n", ++ agmt_get_long_name(prp->agmt)); ++ ++ } else { ++ ruv_dump(ruv, "Database RUV", NULL); ++ } ++ object_release(ruv_obj); ++ } ++ } ++ object_release(prp->replica_object); ++ } ++ ++ } + return return_value; + } + +diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c +index b52dd49..8fbd89c 100644 +--- a/ldap/servers/plugins/replication/repl5_ruv.c ++++ b/ldap/servers/plugins/replication/repl5_ruv.c +@@ -208,6 +208,9 @@ ruv_init_from_slapi_attr_and_check_purl(Slapi_Attr *attr, RUV **ruv, ReplicaId * + Slapi_Value *value; + const struct berval *bval; + const char *purl = NULL; ++ char *localhost = get_localhost_DNS(); ++ size_t localhostlen = localhost ? strlen(localhost) : 0; ++ int port = config_get_port(); + + return_value = RUV_SUCCESS; + +@@ -236,16 +239,30 @@ ruv_init_from_slapi_attr_and_check_purl(Slapi_Attr *attr, RUV **ruv, ReplicaId * + RUVElement *ruve = get_ruvelement_from_berval(bval); + if (NULL != ruve) + { ++ char *ptr; + /* Is the local purl already in the ruv ? */ + if ( (*contain_purl==0) && ruve->replica_purl && purl && (strncmp(ruve->replica_purl, purl, strlen(purl))==0) ) + { + *contain_purl = ruve->rid; + } ++ /* ticket 47362 - nsslapd-port: 0 causes replication to break */ ++ else if ((*contain_purl==0) && ruve->replica_purl && (port == 0) && localhost && ++ (ptr = strstr(ruve->replica_purl, localhost)) && (ptr != ruve->replica_purl) && ++ (*(ptr - 1) == '/') && (*(ptr+localhostlen) == ':')) ++ { ++ /* same hostname, but port number may have been temporarily set to 0 ++ * just allow it with whatever port number is already in the replica_purl ++ * do not reset the port number, do not tell the configure_ruv code that there ++ * is anything wrong ++ */ ++ *contain_purl = ruve->rid; ++ } + dl_add ((*ruv)->elements, ruve); + } + } + } + } ++ slapi_ch_free_string(&localhost); + } + } + return return_value; +@@ -1279,6 +1296,11 @@ ruv_compare_ruv(const RUV *ruv1, const char *ruv1name, const RUV *ruv2, const ch + const char *ruvbnames[] = {ruv2name, ruv1name}; + const int nitems = 2; + ++ if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) { ++ ruv_dump(ruv1, (char *)ruv1name, NULL); ++ ruv_dump(ruv2, (char *)ruv2name, NULL); ++ } ++ + /* compare replica generations first */ + if (ruv1->replGen == NULL || ruv2->replGen == NULL) { + slapi_log_error(loglevel, repl_plugin_name, +@@ -1335,7 +1357,17 @@ ruv_compare_ruv(const RUV *ruv1, const char *ruv1name, const RUV *ruv2, const ch + "than the max CSN [%s] from RUV [%s] for element [%s]\n", + csnstrb, ruvbname, csnstra, ruvaname, ruvelem); + rc = RUV_COMP_CSN_DIFFERS; ++ } else { ++ csn_as_string(replicaa->csn, PR_FALSE, csnstra); ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "ruv_compare_ruv: the max CSN [%s] from RUV [%s] is less than " ++ "or equal to the max CSN [%s] from RUV [%s] for element [%s]\n", ++ csnstrb, ruvbname, csnstra, ruvaname, ruvelem); + } ++ } else { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "ruv_compare_ruv: RUV [%s] has an empty CSN\n", ++ ruvbname); + } + } + } +-- +1.8.1.4 + diff --git a/0061-Ticket-47361-Empty-control-list-causes-LDAP-protocol.patch b/0061-Ticket-47361-Empty-control-list-causes-LDAP-protocol.patch new file mode 100644 index 0000000..50ff43a --- /dev/null +++ b/0061-Ticket-47361-Empty-control-list-causes-LDAP-protocol.patch @@ -0,0 +1,78 @@ +From 5b66557b5f389ae4d1902121ee1076ed3587bbf9 Mon Sep 17 00:00:00 2001 +From: "Thierry bordaz (tbordaz)" +Date: Thu, 16 May 2013 15:28:47 +0200 +Subject: [PATCH 61/99] Ticket 47361 - Empty control list causes LDAP protocol + error is thrown + +Bug Description: + + If a request contains a list of controls containing zero control, it does + not conform RFC http://tools.ietf.org/html/rfc4511#section-4.1.11. Then the + server returns a Protocol Error. + This is too restrictive for some applications. + Note: such application needs to be linked with old version of mozldap or openldap + because recent version skip sending empty list of controls + +Fix Description: + The fix is to ignore this error and let the operation complete + +https://fedorahosted.org/389/ticket/47361 + +Reviewed by: Rich Megginson (thanks Rich !) + +Platforms tested: F17 (unit + acceptance vlv/proxy/managed/psearch/tls/bindcontrol) + +Flag Day: no + +Doc impact: no +(cherry picked from commit 76c87bd8c4d8b075b9615858b74f2caf7a95b2d5) +--- + ldap/servers/slapd/control.c | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +diff --git a/ldap/servers/slapd/control.c b/ldap/servers/slapd/control.c +index fc3ab9f..e614d50 100644 +--- a/ldap/servers/slapd/control.c ++++ b/ldap/servers/slapd/control.c +@@ -354,17 +354,27 @@ get_ldapmessage_controls_ext( + len = -1; /* reset for next loop iter */ + } + +- if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) ) { +- goto free_and_return; +- } +- +- slapi_pblock_set( pb, SLAPI_REQCONTROLS, ctrls ); +- managedsait = slapi_control_present( ctrls, +- LDAP_CONTROL_MANAGEDSAIT, NULL, NULL ); +- slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, &managedsait ); +- pwpolicy_ctrl = slapi_control_present( ctrls, +- LDAP_X_CONTROL_PWPOLICY_REQUEST, NULL, NULL ); +- slapi_pblock_set( pb, SLAPI_PWPOLICY, &pwpolicy_ctrl ); ++ if (curcontrols == 0) { ++ int ctrl_not_found = 0; /* means that a given control is not present in the request */ ++ ++ slapi_pblock_set(pb, SLAPI_REQCONTROLS, NULL); ++ slapi_pblock_set(pb, SLAPI_MANAGEDSAIT, &ctrl_not_found); ++ slapi_pblock_set(pb, SLAPI_PWPOLICY, &ctrl_not_found); ++ slapi_log_error(SLAPI_LOG_CONNS, "connection", "Warning: conn=%d op=%d contains an empty list of controls\n", ++ pb->pb_conn->c_connid, pb->pb_op->o_opid); ++ } else { ++ if ((tag != LBER_END_OF_SEQORSET) && (len != -1)) { ++ goto free_and_return; ++ } ++ ++ slapi_pblock_set(pb, SLAPI_REQCONTROLS, ctrls); ++ managedsait = slapi_control_present(ctrls, ++ LDAP_CONTROL_MANAGEDSAIT, NULL, NULL); ++ slapi_pblock_set(pb, SLAPI_MANAGEDSAIT, &managedsait); ++ pwpolicy_ctrl = slapi_control_present(ctrls, ++ LDAP_X_CONTROL_PWPOLICY_REQUEST, NULL, NULL); ++ slapi_pblock_set(pb, SLAPI_PWPOLICY, &pwpolicy_ctrl); ++ } + + if ( controlsp != NULL ) { + *controlsp = ctrls; +-- +1.8.1.4 + diff --git a/0062-Ticket-47359-new-ldap-connections-can-block-ldaps-an.patch b/0062-Ticket-47359-new-ldap-connections-can-block-ldaps-an.patch new file mode 100644 index 0000000..b06e2d1 --- /dev/null +++ b/0062-Ticket-47359-new-ldap-connections-can-block-ldaps-an.patch @@ -0,0 +1,283 @@ +From 43c715dfb8a72bd61e8cf2fd43324b7d3b1b5143 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Fri, 10 May 2013 15:11:13 -0600 +Subject: [PATCH 62/99] Ticket #47359 - new ldap connections can block ldaps + and ldapi connections + +https://fedorahosted.org/389/ticket/47359 +Reviewed by: lkrispen, nhosoi (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: description +In the polling thread, first process all of the new connection requests from +the listening sockets, then process any new operation read requests +The listener_idxs keeps track of the index of the active listeners in the +poll fd array, and keeps a pointer to the listenfd object for that +listener. This allows us to very quickly scan through the poll fd array +and find the ready listeners. The work of scanning through the array +and handling the new connection requests has been moved to a new function +handle_listeners(). +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 115ab1d9a3f026e8523b91bf62245a25454a3e8a) +(cherry picked from commit 24b751cc724468a7bce5f86848a82e4b03e24a3c) +(cherry picked from commit 5226ed9f2e585dc3d561f9286555efc7e3eea6b6) +(cherry picked from commit e0328aba6ed9254cf537f85927c55cbbb82cae77) +(cherry picked from commit 8a1fd0711e060aca3943ca346005bb43eddf82c4) +--- + ldap/servers/slapd/daemon.c | 115 ++++++++++++++++++++++++-------------------- + 1 file changed, 62 insertions(+), 53 deletions(-) + +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index 75a83c0..93ebe4a 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -136,6 +136,15 @@ void disk_monitoring_stop(); + + #define FDS_SIGNAL_PIPE 0 + ++typedef struct listener_info { ++ int idx; /* index of this listener in the ct->fd array */ ++ PRFileDesc *listenfd; /* the listener fd */ ++ int secure; ++ int local; ++} listener_info; ++ ++#define SLAPD_POLL_LISTEN_READY(xxflagsxx) (xxflagsxx & PR_POLL_READ) ++ + static int get_configured_connection_table_size(); + #ifdef RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS + static void get_loopback_by_addr( void ); +@@ -149,7 +158,7 @@ static PRFileDesc **createprlistensockets(unsigned short port, + static const char *netaddr2string(const PRNetAddr *addr, char *addrbuf, + size_t addrbuflen); + static void set_shutdown (int); +-static void setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read); ++static void setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read, listener_info *listener_idxs, int max_listeners); + + #ifdef HPUX10 + static void* catch_signals(); +@@ -913,6 +922,30 @@ disk_monitoring_thread(void *nothing) + } + } + ++static void ++handle_listeners(Connection_Table *ct, listener_info *listener_idxs, int n_listeners) ++{ ++ int idx; ++ for (idx = 0; idx < n_listeners; ++idx) { ++ int fdidx = listener_idxs[idx].idx; ++ PRFileDesc *listenfd = listener_idxs[idx].listenfd; ++ int secure = listener_idxs[idx].secure; ++ int local = listener_idxs[idx].local; ++ if (fdidx && listenfd) { ++ if (SLAPD_POLL_LISTEN_READY(ct->fd[fdidx].out_flags)) { ++ /* accept() the new connection, put it on the active list for handle_pr_read_ready */ ++ int rc = handle_new_connection(ct, SLAPD_INVALID_SOCKET, listenfd, secure, local); ++ if (rc) { ++ LDAPDebug1Arg(LDAP_DEBUG_CONNS, "Error accepting new connection listenfd=%d\n", ++ PR_FileDesc2NativeHandle(listenfd)); ++ continue; ++ } ++ } ++ } ++ } ++ return; ++} ++ + void slapd_daemon( daemon_ports_t *ports ) + { + /* We are passed some ports---one for regular connections, one +@@ -929,7 +962,6 @@ void slapd_daemon( daemon_ports_t *ports ) + int s_tcps_native = 0; + PRFileDesc *s_tcps = NULL; + #else +- PRFileDesc *tcps = 0; + PRFileDesc **n_tcps = NULL; + PRFileDesc **s_tcps = NULL; + PRFileDesc **i_unix = NULL; +@@ -940,6 +972,8 @@ void slapd_daemon( daemon_ports_t *ports ) + PRThread *time_thread_p; + int threads; + int in_referral_mode = config_check_referral_mode(); ++ int n_listeners = 0; /* number of listener sockets */ ++ listener_info *listener_idxs = NULL; /* array of indexes of listener sockets in the ct->fd array */ + + int connection_table_size = get_configured_connection_table_size(); + the_connection_table= connection_table_new(connection_table_size); +@@ -1054,6 +1088,7 @@ void slapd_daemon( daemon_ports_t *ports ) + netaddr2string(&ports->n_listenaddr, addrbuf, sizeof(addrbuf)), + ports->n_port, oserr, slapd_system_strerror( oserr ) ); + g_set_shutdown( SLAPI_SHUTDOWN_EXIT ); ++ n_listeners++; + } + #else + if ( n_tcps != NULL ) { +@@ -1071,6 +1106,7 @@ void slapd_daemon( daemon_ports_t *ports ) + slapd_pr_strerror( prerr )); + g_set_shutdown( SLAPI_SHUTDOWN_EXIT ); + } ++ n_listeners++; + } + } + #endif +@@ -1090,6 +1126,7 @@ void slapd_daemon( daemon_ports_t *ports ) + slapd_pr_strerror( prerr )); + g_set_shutdown( SLAPI_SHUTDOWN_EXIT ); + } ++ n_listeners++; + } + } + +@@ -1108,11 +1145,13 @@ void slapd_daemon( daemon_ports_t *ports ) + slapd_pr_strerror( prerr )); + g_set_shutdown( SLAPI_SHUTDOWN_EXIT ); + } ++ n_listeners++; + } + } + #endif /* ENABLE_LDAPI */ + #endif + ++ listener_idxs = (listener_info *)slapi_ch_calloc(n_listeners, sizeof(*listener_idxs)); + /* Now we write the pid file, indicating that the server is finally and listening for connections */ + write_pid_file(); + +@@ -1125,9 +1164,6 @@ void slapd_daemon( daemon_ports_t *ports ) + int oserr; + #endif + int select_return = 0; +- int secure = 0; /* is a new connection an SSL one ? */ +- int local = 0; /* is new connection an ldapi one? */ +- int i; + + #ifndef _WIN32 + PRErrorCode prerr; +@@ -1139,7 +1175,7 @@ void slapd_daemon( daemon_ports_t *ports ) + /* This select needs to timeout to give the server a chance to test for shutdown */ + select_return = select(connection_table_size, &readfds, NULL, 0, &wakeup_timer); + #else +- setup_pr_read_pds(the_connection_table,n_tcps,s_tcps,i_unix,&num_poll); ++ setup_pr_read_pds(the_connection_table,n_tcps,s_tcps,i_unix,&num_poll,listener_idxs,n_listeners); + select_return = POLL_FN(the_connection_table->fd, num_poll, pr_timeout); + #endif + switch (select_return) { +@@ -1175,52 +1211,8 @@ void slapd_daemon( daemon_ports_t *ports ) + handle_read_ready(the_connection_table,&readfds); + clear_signal(&readfds); + #else +- tcps = NULL; +- /* info for n_tcps is always in fd[n_tcps ~ n_tcpe] */ +- if( NULL != n_tcps ) { +- for (i = the_connection_table->n_tcps; +- i < the_connection_table->n_tcpe; i++) { +- if (the_connection_table->fd[i].out_flags & +- SLAPD_POLL_FLAGS ) { +- /* tcps = n_tcps[i - the_connection_table->n_tcps]; */ +- tcps = the_connection_table->fd[i].fd; +- break; +- } +- } +- } +- /* info for s_tcps is always in fd[s_tcps ~ s_tcpe] */ +- if ( NULL == tcps && NULL != s_tcps ) { +- for (i = the_connection_table->s_tcps; +- i < the_connection_table->s_tcpe; i++) { +- if (the_connection_table->fd[i].out_flags & +- SLAPD_POLL_FLAGS ) { +- /* tcps = s_tcps[i - the_connection_table->s_tcps]; */ +- tcps = the_connection_table->fd[i].fd; +- secure = 1; +- break; +- } +- } +- } +-#if defined(ENABLE_LDAPI) +- /* info for i_unix is always in fd[i_unixs ~ i_unixe] */ +- if ( NULL == tcps && NULL != i_unix ) { +- for (i = the_connection_table->i_unixs; +- i < the_connection_table->i_unixe; i++) { +- if (the_connection_table->fd[i].out_flags & +- SLAPD_POLL_FLAGS ) { +- /* tcps = i_unix[i - the_connection_table->i_unixs]; */ +- tcps = the_connection_table->fd[i].fd; +- local = 1; +- break; +- } +- } +- } +-#endif /* ENABLE_LDAPI */ +- +- /* If so, then handle a new connection */ +- if ( tcps != NULL ) { +- handle_new_connection(the_connection_table,SLAPD_INVALID_SOCKET,tcps,secure,local); +- } ++ /* handle new connections from the listeners */ ++ handle_listeners(the_connection_table, listener_idxs, n_listeners); + /* handle new data ready */ + handle_pr_read_ready(the_connection_table, connection_table_size); + clear_signal(the_connection_table->fd); +@@ -1548,7 +1540,7 @@ static void setup_read_fds(Connection_Table *ct, fd_set *readfds, int n_tcps, in + static int first_time_setup_pr_read_pds = 1; + static int listen_addr_count = 0; + static void +-setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read) ++setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps, PRFileDesc **i_unix, PRIntn *num_to_read, listener_info *listener_idxs, int max_listeners) + { + Connection *c= NULL; + Connection *next= NULL; +@@ -1558,6 +1550,7 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps + PRIntn count = 0; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int max_threads_per_conn = config_get_maxthreadsperconn(); ++ int n_listeners = 0; + + accept_new_connections = ((ct->size - g_get_current_conn_count()) + > slapdFrontendConfig->reservedescriptors); +@@ -1609,6 +1602,9 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps + ct->fd[count].fd = *fdesc; + ct->fd[count].in_flags = SLAPD_POLL_FLAGS; + ct->fd[count].out_flags = 0; ++ listener_idxs[n_listeners].listenfd = *fdesc; ++ listener_idxs[n_listeners].idx = count; ++ n_listeners++; + LDAPDebug( LDAP_DEBUG_HOUSE, + "listening for connections on %d\n", socketdesc, 0, 0 ); + } +@@ -1627,6 +1623,10 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps + ct->fd[count].fd = *fdesc; + ct->fd[count].in_flags = SLAPD_POLL_FLAGS; + ct->fd[count].out_flags = 0; ++ listener_idxs[n_listeners].listenfd = *fdesc; ++ listener_idxs[n_listeners].idx = count; ++ listener_idxs[n_listeners].secure = 1; ++ n_listeners++; + LDAPDebug( LDAP_DEBUG_HOUSE, + "listening for SSL connections on %d\n", socketdesc, 0, 0 ); + } +@@ -1648,6 +1648,10 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps + ct->fd[count].fd = *fdesc; + ct->fd[count].in_flags = SLAPD_POLL_FLAGS; + ct->fd[count].out_flags = 0; ++ listener_idxs[n_listeners].listenfd = *fdesc; ++ listener_idxs[n_listeners].idx = count; ++ listener_idxs[n_listeners].local = 1; ++ n_listeners++; + LDAPDebug( LDAP_DEBUG_HOUSE, + "listening for LDAPI connections on %d\n", socketdesc, 0, 0 ); + } +@@ -1661,6 +1665,11 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps + + first_time_setup_pr_read_pds = 0; + listen_addr_count = count; ++ ++ if (n_listeners < max_listeners) { ++ listener_idxs[n_listeners].idx = 0; ++ listener_idxs[n_listeners].listenfd = NULL; ++ } + } + + /* count is the number of entries we've place in the fds array. +-- +1.8.1.4 + diff --git a/0063-Ticket-580-Wrong-error-code-return-when-using-EXTERN.patch b/0063-Ticket-580-Wrong-error-code-return-when-using-EXTERN.patch new file mode 100644 index 0000000..b7242e7 --- /dev/null +++ b/0063-Ticket-580-Wrong-error-code-return-when-using-EXTERN.patch @@ -0,0 +1,79 @@ +From e0c007c4cd7ffb54a5d587eb74dfa1ab9e5e1a3f Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 3 May 2013 15:42:01 -0400 +Subject: [PATCH 63/99] Ticket 580 - Wrong error code return when using + EXTERNAL SASL and no client certificate + +Bug Description: When doing a SASL EXTERNAL bind, and no client certificate is provided, + the bind succeeds(as anonymous). However, the bind should fail with + an error 48. + +Fix Description: Check for the missing client certificate and return the appropriate + error. + +https://fedorahosted.org/389/ticket/580 + +Reviewed by: Noriko(Thanks!) +(cherry picked from commit 2a81336e582c68fe0326a76a2f156b469688cc9b) +(cherry picked from commit 9bea04c9578f0e1fc48bc2b316b1daf1cf384d42) +--- + ldap/servers/slapd/bind.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c +index d4d3b49..e92add5 100644 +--- a/ldap/servers/slapd/bind.c ++++ b/ldap/servers/slapd/bind.c +@@ -403,10 +403,12 @@ do_bind( Slapi_PBlock *pb ) + supported = slapi_get_supported_saslmechanisms_copy(); + if ( (pmech = supported) != NULL ) while (1) { + if (*pmech == NULL) { +- /* As we call the safe function, we receive a strdup'd saslmechanisms +- charray. Therefore, we need to remove it instead of NULLing it */ +- charray_free(supported); +- pmech = supported = NULL; ++ /* ++ * As we call the safe function, we receive a strdup'd saslmechanisms ++ * charray. Therefore, we need to remove it instead of NULLing it ++ */ ++ charray_free(supported); ++ pmech = supported = NULL; + break; + } + if (!strcasecmp (saslmech, *pmech)) break; +@@ -450,11 +452,21 @@ do_bind( Slapi_PBlock *pb ) + } + + /* ++ * Check for the client certificate. ++ */ ++ if( NULL == pb->pb_conn->c_client_cert){ ++ send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL, ++ "missing client certificate", 0, NULL ); ++ /* call postop plugins */ ++ plugin_call_plugins( pb, SLAPI_PLUGIN_POST_BIND_FN ); ++ goto free_and_return; ++ } ++ ++ /* + * if the client sent us a certificate but we could not map it + * to an LDAP DN, fail and return an invalidCredentials error. + */ +- if ( NULL != pb->pb_conn->c_client_cert && +- NULL == pb->pb_conn->c_external_dn ) { ++ if ( NULL == pb->pb_conn->c_external_dn ) { + send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL, + "client certificate mapping failed", 0, NULL ); + /* call postop plugins */ +@@ -463,7 +475,7 @@ do_bind( Slapi_PBlock *pb ) + } + + if (!isroot ) { +- /* check if the account is locked */ ++ /* check if the account is locked */ + bind_target_entry = get_entry(pb, pb->pb_conn->c_external_dn); + if ( bind_target_entry != NULL && slapi_check_account_lock(pb, bind_target_entry, + pw_response_requested, 1 /*check password policy*/, 1 /*send ldap result*/) == 1) { +-- +1.8.1.4 + diff --git a/0064-Ticket-47375-flush_ber-error-sending-back-start_tls-.patch b/0064-Ticket-47375-flush_ber-error-sending-back-start_tls-.patch new file mode 100644 index 0000000..5a892de --- /dev/null +++ b/0064-Ticket-47375-flush_ber-error-sending-back-start_tls-.patch @@ -0,0 +1,349 @@ +From 29b29d7c014111ff7624a22a598182079e95eb1a Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 29 May 2013 18:44:26 -0600 +Subject: [PATCH 64/99] Ticket #47375 - flush_ber error sending back start_tls + response will deadlock + +https://fedorahosted.org/389/ticket/47375 +Reviewed by: nkinder (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: The deadlock is caused by the client (or intermediary network +device) closing the connection while the server is attempting to write to the +client, to send back the start tls "success" response. The server will lock +the c_mutex to disconnect the connection in this error case. Since the c_mutex +has already been locked in start_tls(), the server will deadlock. The polling +thread will also attempt to lock c_mutex, deadlocking it too, and the server +will become completely unresponsive. The fix for this part is to make sure +never to call send_ldap_result with c_mutex locked. +After the server sends back the "success" response, if the +client immediately issues a TLS session negotiation, the server may not +have yet completely set up the socket for TLS, and will attempt to use the +partially setup socket, which can crash. The fix for this is to setup the +socket for TLS IO using a Conn_IO_Layer callback, to establish the TLS IO +for the connection before the next read() operation. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 01f7e5b10a70701b7af790e63cc56d39bc73efa4) +--- + ldap/servers/slapd/start_tls_extop.c | 230 +++++++++++++++++------------------ + 1 file changed, 110 insertions(+), 120 deletions(-) + +diff --git a/ldap/servers/slapd/start_tls_extop.c b/ldap/servers/slapd/start_tls_extop.c +index dffaeea..1efa657 100644 +--- a/ldap/servers/slapd/start_tls_extop.c ++++ b/ldap/servers/slapd/start_tls_extop.c +@@ -72,7 +72,85 @@ + Slapi_PluginDesc exopdesc = { "start_tls_plugin", VENDOR, DS_PACKAGE_VERSION, + "Start TLS extended operation plugin" }; + ++static int ++start_tls_io_enable(Connection *c, void *data /* UNUSED */) ++{ ++ int secure = 1; ++ PRFileDesc *newsocket; ++ int rv = -1; ++ int ns; ++ ++ /* So far we have set up the environment for deploying SSL. It's now time to import the socket ++ * into SSL and to configure it consequently. */ ++ ++ if ( slapd_ssl_listener_is_initialized() != 0 ) { ++ PRFileDesc * ssl_listensocket; ++ ++ ssl_listensocket = get_ssl_listener_fd(); ++ if ( ssl_listensocket == (PRFileDesc *) NULL ) { ++ slapi_log_error( SLAPI_LOG_FATAL, "start_tls", ++ "SSL listener socket not found.\n" ); ++ goto done; ++ } ++ newsocket = slapd_ssl_importFD( ssl_listensocket, c->c_prfd ); ++ if ( newsocket == (PRFileDesc *) NULL ) { ++ slapi_log_error( SLAPI_LOG_FATAL, "start_tls", ++ "SSL socket import failed.\n" ); ++ goto done; ++ } ++ } else { ++ if ( slapd_ssl_init2( &c->c_prfd, 1 ) != 0 ) { ++ slapi_log_error( SLAPI_LOG_FATAL, "start_tls", ++ "SSL socket import or configuration failed.\n" ); ++ goto done; ++ } ++ newsocket = c->c_prfd; ++ } ++ ++ ++ rv = slapd_ssl_resetHandshake( newsocket, 1 ); ++ if ( rv != SECSuccess ) { ++ slapi_log_error( SLAPI_LOG_FATAL, "start_tls", ++ "Unable to set socket ready for SSL handshake.\n" ); ++ goto done; ++ } ++ ++ ++ /* From here on, messages will be sent through the SSL layer, so we need to get our ++ * connection ready. */ ++ ++ ns = configure_pr_socket( &newsocket, secure, 0 /*never local*/ ); ++ ++ c->c_flags |= CONN_FLAG_SSL; ++ c->c_flags |= CONN_FLAG_START_TLS; ++ c->c_sd = ns; ++ c->c_prfd = newsocket; ++ ++ /* Get the effective key length */ ++ SSL_SecurityStatus(c->c_prfd, NULL, NULL, NULL, &(c->c_ssl_ssf), NULL, NULL); + ++ rv = slapd_ssl_handshakeCallback (c->c_prfd, (void *)handle_handshake_done, c); ++ ++ if ( rv < 0 ) { ++ PRErrorCode prerr = PR_GetError(); ++ slapi_log_error( SLAPI_LOG_FATAL, "start_tls", ++ "SSL_HandshakeCallback() %d " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", ++ rv, prerr, slapd_pr_strerror( prerr ) ); ++ } ++ ++ if ( config_get_SSLclientAuth() != SLAPD_SSLCLIENTAUTH_OFF ) { ++ rv = slapd_ssl_badCertHook (c->c_prfd, (void *)handle_bad_certificate, c); ++ if ( rv < 0 ) { ++ PRErrorCode prerr = PR_GetError(); ++ slapi_log_error( SLAPI_LOG_FATAL, "start_tls", ++ "SSL_BadCertHook(%i) %i " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", ++ c->c_sd, rv, prerr, slapd_pr_strerror( prerr ) ); ++ } ++ } ++ ++done: ++ return rv; ++} + + + /* Start TLS Extended operation plugin function */ +@@ -82,13 +160,12 @@ start_tls( Slapi_PBlock *pb ) + + char *oid; + Connection *conn; +- PRFileDesc *oldsocket, *newsocket; +- int secure; +- int ns; + #ifdef _WIN32 ++ PRFileDesc *oldsocket; + int oldnativesocket; + #endif +- int rv; ++ int ldaprc = LDAP_SUCCESS; ++ char *ldapmsg = NULL; + + /* Get the pb ready for sending Start TLS Extended Responses back to the client. + * The only requirement is to set the LDAP OID of the extended response to the START_TLS_OID. */ +@@ -133,23 +210,23 @@ start_tls( Slapi_PBlock *pb ) + + conn = pb->pb_conn; + PR_Lock( conn->c_mutex ); ++ /* cannot call slapi_send_ldap_result with mutex locked - will deadlock if ber_flush returns error */ + #ifndef _WIN32 +- oldsocket = conn->c_prfd; +- if ( oldsocket == (PRFileDesc *) NULL ) { +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "Connection socket not available.\n" ); +- slapi_send_ldap_result( pb, LDAP_UNAVAILABLE, NULL, +- "Connection socket not available.", 0, NULL ); ++ if ( conn->c_prfd == (PRFileDesc *) NULL ) { ++ slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", ++ "Connection socket not available.\n" ); ++ ldaprc = LDAP_UNAVAILABLE; ++ ldapmsg = "Connection socket not available."; + goto unlock_and_return; + } + #else + oldnativesocket = conn->c_sd; + oldsocket = PR_ImportTCPSocket(oldnativesocket); + if ( oldsocket == (PRFileDesc *) NULL ) { +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "Failed to import NT native socket into NSPR.\n" ); +- slapi_send_ldap_result( pb, LDAP_UNAVAILABLE, NULL, +- "Failed to import NT native socket into NSPR.", 0, NULL ); ++ slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", ++ "Failed to import NT native socket into NSPR.\n" ); ++ ldaprc = LDAP_UNAVAILABLE; ++ ldapmsg = "Failed to import NT native socket into NSPR."; + goto unlock_and_return; + } + #endif +@@ -160,8 +237,8 @@ start_tls( Slapi_PBlock *pb ) + 1 /* check for ops where result not yet sent */ )) { + slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", + "Other operations are still pending on the connection.\n" ); +- slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, +- "Other operations are still pending on the connection.", 0, NULL ); ++ ldaprc = LDAP_OPERATIONS_ERROR; ++ ldapmsg = "Other operations are still pending on the connection."; + goto unlock_and_return; + } + +@@ -171,8 +248,8 @@ start_tls( Slapi_PBlock *pb ) + /* slapi_send_ldap_result( pb, LDAP_REFERRAL, NULL, msg, 0, url ); */ + slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", + "SSL not supported by this server.\n" ); +- slapi_send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, +- "SSL not supported by this server.", 0, NULL ); ++ ldaprc = LDAP_PROTOCOL_ERROR; ++ ldapmsg = "SSL not supported by this server."; + goto unlock_and_return; + } + +@@ -180,16 +257,16 @@ start_tls( Slapi_PBlock *pb ) + if ( conn->c_flags & CONN_FLAG_SSL ) { + slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", + "SSL connection already established.\n" ); +- slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, +- "SSL connection already established.", 0, NULL ); ++ ldaprc = LDAP_OPERATIONS_ERROR; ++ ldapmsg = "SSL connection already established."; + goto unlock_and_return; + } + + if ( conn->c_flags & CONN_FLAG_SASL_CONTINUE ) { + slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", + "SASL multi-stage bind in progress.\n" ); +- slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, +- "SASL multi-stage bind in progress.", 0, NULL ); ++ ldaprc = LDAP_OPERATIONS_ERROR; ++ ldapmsg = "SASL multi-stage bind in progress."; + goto unlock_and_return; + } + +@@ -197,8 +274,8 @@ start_tls( Slapi_PBlock *pb ) + if ( conn->c_flags & CONN_FLAG_CLOSING ) { + slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", + "Connection being closed at this moment.\n" ); +- slapi_send_ldap_result( pb, LDAP_UNAVAILABLE, NULL, +- "Connection being closed at this moment.", 0, NULL ); ++ ldaprc = LDAP_UNAVAILABLE; ++ ldapmsg = "Connection being closed at this moment."; + goto unlock_and_return; + } + +@@ -208,110 +285,23 @@ start_tls( Slapi_PBlock *pb ) + * So, we may as well try initialising SSL. */ + + if ( slapd_security_library_is_initialized() == 0 ) { +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "NSS libraries not initialised.\n" ); +- slapi_send_ldap_result( pb, LDAP_UNAVAILABLE, NULL, +- "NSS libraries not initialised.", 0, NULL ); +- goto unlock_and_return; ++ slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", ++ "NSS libraries not initialised.\n" ); ++ ldaprc = LDAP_UNAVAILABLE; ++ ldapmsg = "NSS libraries not initialised."; ++ goto unlock_and_return; + } + + ++ /* Enable TLS I/O on the connection */ ++ connection_set_io_layer_cb(conn, start_tls_io_enable, NULL, NULL); + + /* Since no specific argument for denying the Start TLS request has been found, + * we send a success response back to the client. */ +- +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "Start TLS request accepted.Server willing to negotiate SSL.\n" ); +- slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, +- "Start TLS request accepted.Server willing to negotiate SSL.", 0, NULL ); +- +- +- /* So far we have set up the environment for deploying SSL. It's now time to import the socket +- * into SSL and to configure it consequently. */ +- +- if ( slapd_ssl_listener_is_initialized() != 0 ) { +- PRFileDesc * ssl_listensocket; +- +- ssl_listensocket = get_ssl_listener_fd(); +- if ( ssl_listensocket == (PRFileDesc *) NULL ) { +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "SSL listener socket not found.\n" ); +- slapi_send_ldap_result( pb, LDAP_UNAVAILABLE, NULL, +- "SSL listener socket not found.", 0, NULL ); +- goto unlock_and_return; +- } +- newsocket = slapd_ssl_importFD( ssl_listensocket, oldsocket ); +- if ( newsocket == (PRFileDesc *) NULL ) { +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "SSL socket import failed.\n" ); +- slapi_send_ldap_result( pb, LDAP_UNAVAILABLE, NULL, +- "SSL socket import failed.", 0, NULL ); +- goto unlock_and_return; +- } +- } else { +- if ( slapd_ssl_init2( &oldsocket, 1 ) != 0 ) { +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "SSL socket import or configuration failed.\n" ); +- slapi_send_ldap_result( pb, LDAP_UNAVAILABLE, NULL, +- "SSL socket import or configuration failed.", 0, NULL ); +- goto unlock_and_return; +- } +- newsocket = oldsocket; +- } +- +- +- rv = slapd_ssl_resetHandshake( newsocket, 1 ); +- if ( rv != SECSuccess ) { +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "Unable to set socket ready for SSL handshake.\n" ); +- slapi_send_ldap_result( pb, LDAP_UNAVAILABLE, NULL, +- "Unable to set socket ready for SSL handshake.", 0, NULL ); +- goto unlock_and_return; +- } +- +- +- +- /* From here on, messages will be sent through the SSL layer, so we need to get our +- * connection ready. */ +- +- secure = 1; +- ns = configure_pr_socket( &newsocket, secure, 0 /*never local*/ ); +- +- conn->c_flags |= CONN_FLAG_SSL; +- conn->c_flags |= CONN_FLAG_START_TLS; +- conn->c_sd = ns; +- conn->c_prfd = newsocket; +- +- /* Get the effective key length */ +- SSL_SecurityStatus(conn->c_prfd, NULL, NULL, NULL, &(conn->c_ssl_ssf), NULL, NULL); +- +- rv = slapd_ssl_handshakeCallback (conn->c_prfd, (void *)handle_handshake_done, conn); +- +- if ( rv < 0 ) { +- PRErrorCode prerr = PR_GetError(); +- slapi_log_error( SLAPI_LOG_FATAL, "start_tls", +- "SSL_HandshakeCallback() %d " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", +- rv, prerr, slapd_pr_strerror( prerr ) ); +- } +- +- if ( config_get_SSLclientAuth() != SLAPD_SSLCLIENTAUTH_OFF ) { +- rv = slapd_ssl_badCertHook (conn->c_prfd, (void *)handle_bad_certificate, conn); +- if ( rv < 0 ) { +- PRErrorCode prerr = PR_GetError(); +- slapi_log_error( SLAPI_LOG_FATAL, "start_tls", +- "SSL_BadCertHook(%i) %i " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", +- conn->c_sd, rv, prerr, slapd_pr_strerror( prerr ) ); +- } +- } +- +- +- /* Once agreed in starting TLS, the handshake must be carried out. */ +- +- slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls", +- "Starting SSL Handshake.\n" ); +- ++ ldapmsg = "Start TLS request accepted.Server willing to negotiate SSL."; + unlock_and_return: + PR_Unlock( conn->c_mutex ); ++ slapi_send_ldap_result( pb, ldaprc, NULL, ldapmsg, 0, NULL ); + + return( SLAPI_PLUGIN_EXTENDED_SENT_RESULT ); + +-- +1.8.1.4 + diff --git a/0065-Ticket-47377-make-listen-backlog-size-configurable.patch b/0065-Ticket-47377-make-listen-backlog-size-configurable.patch new file mode 100644 index 0000000..7ba390b --- /dev/null +++ b/0065-Ticket-47377-make-listen-backlog-size-configurable.patch @@ -0,0 +1,184 @@ +From 9992230f8a4e515078048f301c84dc9f4f9947d8 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Tue, 16 Apr 2013 08:26:03 -0600 +Subject: [PATCH 65/99] Ticket #47377 - make listen backlog size configurable + +https://fedorahosted.org/389/ticket/47377 +Reviewed by: nkinder (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: Add the attribute nsslapd-listen-backlog-size - this controls +the listening socket connection backlog maximum size. This corresponds to +the backlog parameter of the listen() system call. The default value is 128. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: yes - need to doc the new attribute +(cherry picked from commit 18ff7203323fef9c7bd01222c6775e82ff979922) +--- + ldap/servers/slapd/daemon.c | 16 ++++------------ + ldap/servers/slapd/libglobs.c | 31 +++++++++++++++++++++++++++++++ + ldap/servers/slapd/proto-slap.h | 2 ++ + ldap/servers/slapd/slap.h | 10 ++++++++++ + 4 files changed, 47 insertions(+), 12 deletions(-) + +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index 93ebe4a..c67067b 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -99,14 +99,6 @@ + #include "getsocketpeer.h" + #endif /* ENABLE_LDAPI */ + +-/* +- * Define the backlog number for use in listen() call. +- * We use the same definition as in ldapserver/include/base/systems.h +- */ +-#ifndef DAEMON_LISTEN_SIZE +-#define DAEMON_LISTEN_SIZE 128 +-#endif +- + #if defined (LDAP_IOCP) + #define SLAPD_WAKEUP_TIMER 250 + #else +@@ -1079,7 +1071,7 @@ void slapd_daemon( daemon_ports_t *ports ) + /* We are now ready to accept incoming connections */ + #if defined( XP_WIN32 ) + if ( n_tcps != SLAPD_INVALID_SOCKET +- && listen( n_tcps, DAEMON_LISTEN_SIZE ) == -1 ) { ++ && listen( n_tcps, config_get_listen_backlog_size() ) == -1 ) { + int oserr = errno; + char addrbuf[ 256 ]; + +@@ -1095,7 +1087,7 @@ void slapd_daemon( daemon_ports_t *ports ) + PRFileDesc **fdesp; + PRNetAddr **nap = ports->n_listenaddr; + for (fdesp = n_tcps; fdesp && *fdesp; fdesp++, nap++) { +- if ( PR_Listen( *fdesp, DAEMON_LISTEN_SIZE ) == PR_FAILURE ) { ++ if ( PR_Listen( *fdesp, config_get_listen_backlog_size() ) == PR_FAILURE ) { + PRErrorCode prerr = PR_GetError(); + char addrbuf[ 256 ]; + +@@ -1115,7 +1107,7 @@ void slapd_daemon( daemon_ports_t *ports ) + PRFileDesc **fdesp; + PRNetAddr **sap = ports->s_listenaddr; + for (fdesp = s_tcps; fdesp && *fdesp; fdesp++, sap++) { +- if ( PR_Listen( *fdesp, DAEMON_LISTEN_SIZE ) == PR_FAILURE ) { ++ if ( PR_Listen( *fdesp, config_get_listen_backlog_size() ) == PR_FAILURE ) { + PRErrorCode prerr = PR_GetError(); + char addrbuf[ 256 ]; + +@@ -1136,7 +1128,7 @@ void slapd_daemon( daemon_ports_t *ports ) + PRFileDesc **fdesp; + PRNetAddr **iap = ports->i_listenaddr; + for (fdesp = i_unix; fdesp && *fdesp; fdesp++, iap++) { +- if ( PR_Listen(*fdesp, DAEMON_LISTEN_SIZE) == PR_FAILURE) { ++ if ( PR_Listen(*fdesp, config_get_listen_backlog_size()) == PR_FAILURE) { + PRErrorCode prerr = PR_GetError(); + slapi_log_error(SLAPI_LOG_FATAL, "slapd_daemon", + "listen() on %s failed: error %d (%s)\n", +diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c +index 5bfd665..aaee33a 100644 +--- a/ldap/servers/slapd/libglobs.c ++++ b/ldap/servers/slapd/libglobs.c +@@ -693,6 +693,10 @@ static struct config_get_and_set { + NULL, 0, + (void**)&global_slapdFrontendConfig.sasl_max_bufsize, + CONFIG_INT, (ConfigGetFunc)config_get_sasl_maxbufsize}, ++ {CONFIG_LISTEN_BACKLOG_SIZE, config_set_listen_backlog_size, ++ NULL, 0, ++ (void**)&global_slapdFrontendConfig.listen_backlog_size, CONFIG_INT, ++ (ConfigGetFunc)config_get_listen_backlog_size} + #ifdef MEMPOOL_EXPERIMENTAL + ,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch, + NULL, 0, +@@ -1095,6 +1099,7 @@ FrontendConfig_init () { + cfg->disk_logging_critical = LDAP_OFF; + cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE; + ++ cfg->listen_backlog_size = DAEMON_LISTEN_SIZE; + #ifdef MEMPOOL_EXPERIMENTAL + cfg->mempool_switch = LDAP_ON; + cfg->mempool_maxfreelist = 1024; +@@ -6184,6 +6189,32 @@ config_set_default_naming_context(const char *attrname, + return LDAP_SUCCESS; + } + ++int ++config_set_listen_backlog_size( const char *attrname, char *value, ++ char *errorbuf, int apply ) ++{ ++ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); ++ ++ if ( config_value_is_null( attrname, value, errorbuf, 0 )) { ++ return LDAP_OPERATIONS_ERROR; ++ } ++ ++ if ( apply ) { ++ slapdFrontendConfig->listen_backlog_size = atoi(value); ++ } ++ return LDAP_SUCCESS; ++} ++ ++int ++config_get_listen_backlog_size() ++{ ++ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); ++ int retVal; ++ ++ retVal = slapdFrontendConfig->listen_backlog_size; ++ return retVal; ++} ++ + /* + * This function is intended to be used from the dse code modify callback. It + * is "optimized" for that case because it takes a berval** of values, which is +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index 911dadd..a15c0cc 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -391,6 +391,7 @@ int config_set_disk_grace_period( const char *attrname, char *value, char *error + int config_set_disk_logging_critical( const char *attrname, char *value, char *errorbuf, int apply ); + int config_set_auditlog_unhashed_pw(const char *attrname, char *value, char *errorbuf, int apply); + int config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply ); ++int config_set_listen_backlog_size(const char *attrname, char *value, char *errorbuf, int apply); + + #if !defined(_WIN32) && !defined(AIX) + int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply ); +@@ -546,6 +547,7 @@ PRUint64 config_get_disk_threshold(); + int config_get_disk_grace_period(); + int config_get_disk_logging_critical(); + int config_get_sasl_maxbufsize(); ++int config_get_listen_backlog_size(void); + + int is_abspath(const char *); + char* rel2abspath( char * ); +diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h +index ef986e2..eaa1fee 100644 +--- a/ldap/servers/slapd/slap.h ++++ b/ldap/servers/slapd/slap.h +@@ -2005,6 +2005,15 @@ typedef struct _slapdEntryPoints { + #define CONFIG_DISK_GRACE_PERIOD "nsslapd-disk-monitoring-grace-period" + #define CONFIG_DISK_LOGGING_CRITICAL "nsslapd-disk-monitoring-logging-critical" + #define CONFIG_SASL_MAXBUFSIZE "nsslapd-sasl-max-buffer-size" ++#define CONFIG_LISTEN_BACKLOG_SIZE "nsslapd-listen-backlog-size" ++ ++/* ++ * Define the backlog number for use in listen() call. ++ * We use the same definition as in ldapserver/include/base/systems.h ++ */ ++#ifndef DAEMON_LISTEN_SIZE ++#define DAEMON_LISTEN_SIZE 128 ++#endif + + #ifdef MEMPOOL_EXPERIMENTAL + #define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool" +@@ -2218,6 +2227,7 @@ typedef struct _slapdFrontendConfig { + int minssf_exclude_rootdse; /* ON: minssf is ignored when searching rootdse */ + size_t maxsasliosize; /* limit incoming SASL IO packet size */ + char *anon_limits_dn; /* template entry for anonymous resource limits */ ++ int listen_backlog_size; /* size of backlog parameter to PR_Listen */ + #ifndef _WIN32 + struct passwd *localuserinfo; /* userinfo of localuser */ + #endif /* _WIN32 */ +-- +1.8.1.4 + diff --git a/0066-Ticket-47383-connections-attribute-in-cn-snmp-cn-mon.patch b/0066-Ticket-47383-connections-attribute-in-cn-snmp-cn-mon.patch new file mode 100644 index 0000000..d8b4ced --- /dev/null +++ b/0066-Ticket-47383-connections-attribute-in-cn-snmp-cn-mon.patch @@ -0,0 +1,170 @@ +From 6f8a10320f6436c76bae3cd46a496e36cb034409 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 7 Jun 2013 11:41:38 -0400 +Subject: [PATCH 66/99] Ticket 47383 - connections attribute in + cn=snmp,cn=monitor is counted twice + +Bug Description: In disconnect_server_nomutex() we increment, instead of decrement + the connection counter. + +Fix Description: Decrement the counter. Also did some code cleanup. + +https://fedorahosted.org/389/ticket/47383 + +Reviewed by: Richm(Thanks!) +(cherry picked from commit 202c9831194558a7439da815f6627993ce1a17db) +(cherry picked from commit accea11ad4e16ad57b319b7c7091301adf33a99e) +--- + ldap/servers/slapd/connection.c | 129 ++++++++++++++++++++-------------------- + 1 file changed, 65 insertions(+), 64 deletions(-) + +diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c +index a3b1df5..1d1adac 100644 +--- a/ldap/servers/slapd/connection.c ++++ b/ldap/servers/slapd/connection.c +@@ -2737,77 +2737,78 @@ void + disconnect_server_nomutex( Connection *conn, PRUint64 opconnid, int opid, PRErrorCode reason, PRInt32 error ) + { + if ( ( conn->c_sd != SLAPD_INVALID_SOCKET && +- conn->c_connid == opconnid ) && !(conn->c_flags & CONN_FLAG_CLOSING) ) { +- +- /* +- * PR_Close must be called before anything else is done because +- * of NSPR problem on NT which requires that the socket on which +- * I/O timed out is closed before any other I/O operation is +- * attempted by the thread. +- * WARNING : As of today the current code does not fulfill the +- * requirements above. +- */ ++ conn->c_connid == opconnid ) && !(conn->c_flags & CONN_FLAG_CLOSING) ) ++ { ++ /* ++ * PR_Close must be called before anything else is done because ++ * of NSPR problem on NT which requires that the socket on which ++ * I/O timed out is closed before any other I/O operation is ++ * attempted by the thread. ++ * WARNING : As of today the current code does not fulfill the ++ * requirements above. ++ */ + +- /* Mark that the socket should be closed on this connection. +- * We don't want to actually close the socket here, because +- * the listener thread could be PR_Polling over it right now. +- * The last thread to stop using the connection will do the closing. +- */ +- conn->c_flags |= CONN_FLAG_CLOSING; +- g_decrement_current_conn_count(); ++ /* Mark that the socket should be closed on this connection. ++ * We don't want to actually close the socket here, because ++ * the listener thread could be PR_Polling over it right now. ++ * The last thread to stop using the connection will do the closing. ++ */ ++ conn->c_flags |= CONN_FLAG_CLOSING; ++ g_decrement_current_conn_count(); + +- /* +- * Print the error captured above. +- */ +- if (error && (EPIPE != error) ) { +- slapi_log_access( LDAP_DEBUG_STATS, +- "conn=%" NSPRIu64 " op=%d fd=%d closed error %d (%s) - %s\n", +- conn->c_connid, opid, conn->c_sd, error, +- slapd_system_strerror(error), +- slapd_pr_strerror(reason)); +- } else { +- slapi_log_access( LDAP_DEBUG_STATS, +- "conn=%" NSPRIu64 " op=%d fd=%d closed - %s\n", +- conn->c_connid, opid, conn->c_sd, +- slapd_pr_strerror(reason)); +- } ++ /* ++ * Print the error captured above. ++ */ ++ if (error && (EPIPE != error) ) { ++ slapi_log_access( LDAP_DEBUG_STATS, ++ "conn=%" NSPRIu64 " op=%d fd=%d closed error %d (%s) - %s\n", ++ conn->c_connid, opid, conn->c_sd, error, ++ slapd_system_strerror(error), ++ slapd_pr_strerror(reason)); ++ } else { ++ slapi_log_access( LDAP_DEBUG_STATS, ++ "conn=%" NSPRIu64 " op=%d fd=%d closed - %s\n", ++ conn->c_connid, opid, conn->c_sd, ++ slapd_pr_strerror(reason)); ++ } + +- if (! config_check_referral_mode()) { +- slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsConnections); +- } ++ if (! config_check_referral_mode()) { ++ slapi_counter_decrement(g_get_global_snmp_vars()->ops_tbl.dsConnections); ++ } + +- conn->c_gettingber = 0; +- connection_abandon_operations( conn ); +- /* needed here to ensure simple paged results timeout properly and +- * don't impact subsequent ops */ +- pagedresults_reset_timedout_nolock(conn); ++ conn->c_gettingber = 0; ++ connection_abandon_operations( conn ); ++ /* needed here to ensure simple paged results timeout properly and ++ * don't impact subsequent ops */ ++ pagedresults_reset_timedout_nolock(conn); + +- if (! config_check_referral_mode()) { +- /* +- * If any of the outstanding operations on this +- * connection were persistent searches, then +- * ding all the persistent searches to get them +- * to notice that their operations have been abandoned. +- */ +- int found_ps = 0; +- Operation *o; ++ if (! config_check_referral_mode()) { ++ /* ++ * If any of the outstanding operations on this ++ * connection were persistent searches, then ++ * ding all the persistent searches to get them ++ * to notice that their operations have been abandoned. ++ */ ++ int found_ps = 0; ++ Operation *o; + +- for ( o = conn->c_ops; !found_ps && o != NULL; o = o->o_next ) { +- if ( o->o_flags & OP_FLAG_PS ) { +- found_ps = 1; +- } +- } +- if ( found_ps ) { +- if ( NULL == ps_wakeup_all_fn ) { +- if ( get_entry_point( ENTRY_POINT_PS_WAKEUP_ALL, +- (caddr_t *)(&ps_wakeup_all_fn )) == 0 ) { +- (ps_wakeup_all_fn)(); +- } +- } else { +- (ps_wakeup_all_fn)(); ++ for ( o = conn->c_ops; !found_ps && o != NULL; o = o->o_next ) { ++ if ( o->o_flags & OP_FLAG_PS ) { ++ found_ps = 1; ++ } ++ } ++ if ( found_ps ) { ++ if ( NULL == ps_wakeup_all_fn ) { ++ if ( get_entry_point( ENTRY_POINT_PS_WAKEUP_ALL, ++ (caddr_t *)(&ps_wakeup_all_fn )) == 0 ) ++ { ++ (ps_wakeup_all_fn)(); ++ } ++ } else { ++ (ps_wakeup_all_fn)(); ++ } ++ } + } +- } +- } + } + } + +-- +1.8.1.4 + diff --git a/0067-Ticket-47392-ldbm-errors-when-adding-modifying-delet.patch b/0067-Ticket-47392-ldbm-errors-when-adding-modifying-delet.patch new file mode 100644 index 0000000..71a0858 --- /dev/null +++ b/0067-Ticket-47392-ldbm-errors-when-adding-modifying-delet.patch @@ -0,0 +1,689 @@ +From 4f722eff41b69dbfc17266ef6545c680b9f7c544 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Tue, 9 Jul 2013 11:38:39 -0600 +Subject: [PATCH 67/99] Ticket #47392 - ldbm errors when + adding/modifying/deleting entries + +https://fedorahosted.org/389/ticket/47392 +Reviewed by: lkrispenz (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: The problem is caused by cache consistency issues with the +RUV entry. Before the txn starts, we grab a pointer to the RUV entry in +the cache. When DNA (or any betxnpreop plugin) updates the database, it +will also grab a pointer to the cached RUV entry and modify it, out from +under the parent txn. This can also cause the max CSN in the RUV to go +backwards - the nested txn will have a later CSN which will be +overwritten by the earlier CSN from the parent txn. +The fix is to move the ldbm_ruv_txn code inside the transaction loop after +the betxnpreop plugins have been run. Also have to add modify_term inside +the retry logic to cancel the modify ruv txn stuff in order to retry. +The other part of the fix is to tell the code that updates the max CSN +in the RUV to skip changes that would cause the RUV to go backwards, +and return a code to the caller that tells the caller that the CSN is +already covered. The code that updates the RUV for the txn will skip +the modify operations in that case. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 9bf5ac83289dcadc922a628c652aebabc4725231) +(cherry picked from commit 42abece92028193530296b5d96a6cb5261d9aa61) +--- + ldap/servers/plugins/replication/repl5.h | 4 +- + ldap/servers/plugins/replication/repl5_plugins.c | 29 ++++++-- + ldap/servers/plugins/replication/repl5_replica.c | 84 ++++++++++++++++------ + .../plugins/replication/repl5_replica_config.c | 4 +- + ldap/servers/plugins/replication/repl5_ruv.c | 55 ++++++++------ + ldap/servers/plugins/replication/repl5_ruv.h | 1 + + ldap/servers/slapd/back-ldbm/ldbm_add.c | 31 ++++---- + ldap/servers/slapd/back-ldbm/ldbm_delete.c | 32 +++++---- + ldap/servers/slapd/back-ldbm/ldbm_modify.c | 32 +++++---- + ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 31 ++++---- + ldap/servers/slapd/back-ldbm/misc.c | 1 + + 11 files changed, 205 insertions(+), 99 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h +index bd582bc..780b198 100644 +--- a/ldap/servers/plugins/replication/repl5.h ++++ b/ldap/servers/plugins/replication/repl5.h +@@ -538,7 +538,7 @@ void replica_replace_flags (Replica *r, PRUint32 flags); + void replica_dump(Replica *r); + void replica_set_enabled (Replica *r, PRBool enable); + Object *replica_get_replica_from_dn (const Slapi_DN *dn); +-void replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl); ++int replica_update_ruv(Replica *replica, const CSN *csn, const char *replica_purl); + Object *replica_get_replica_for_op (Slapi_PBlock *pb); + /* the functions below manipulate replica hash */ + int replica_init_name_hash (); +@@ -570,7 +570,7 @@ void replica_set_purge_delay (Replica *r, PRUint32 purge_delay); + void replica_set_tombstone_reap_interval (Replica *r, long interval); + void replica_update_ruv_consumer (Replica *r, RUV *supplier_ruv); + void replica_set_ruv_dirty (Replica *r); +-void replica_write_ruv (Replica *r); ++int replica_write_ruv (Replica *r); + char *replica_get_dn(Replica *r); + void replica_check_for_tasks(Replica*r, Slapi_Entry *e); + +diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c +index e3c3083..7aa2e2c 100644 +--- a/ldap/servers/plugins/replication/repl5_plugins.c ++++ b/ldap/servers/plugins/replication/repl5_plugins.c +@@ -932,14 +932,15 @@ copy_operation_parameters(Slapi_PBlock *pb) + * locally-processed update. This is called for both replicated + * and non-replicated operations. + */ +-static void ++static int + update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb) + { + PRBool legacy; + char *purl; ++ int rc = RUV_NOTFOUND; + + if (!replica || !opcsn) +- return; ++ return rc; + + /* Replica configured, so update its ruv */ + legacy = replica_is_legacy_consumer (replica); +@@ -948,12 +949,13 @@ update_ruv_component(Replica *replica, CSN *opcsn, Slapi_PBlock *pb) + else + purl = (char*)replica_get_purl_for_op (replica, pb, opcsn); + +- replica_update_ruv(replica, opcsn, purl); ++ rc = replica_update_ruv(replica, opcsn, purl); + + if (legacy) + { + slapi_ch_free ((void**)&purl); + } ++ return rc; + } + + /* +@@ -1115,11 +1117,30 @@ write_changelog_and_ruv (Slapi_PBlock *pb) + just read from the changelog in either the supplier or consumer ruv + */ + if (0 == return_value) { ++ char csn_str[CSN_STRSIZE]; + CSN *opcsn; ++ int rc; + + slapi_pblock_get( pb, SLAPI_OPERATION, &op ); + opcsn = operation_get_csn(op); +- update_ruv_component(r, opcsn, pb); ++ rc = update_ruv_component(r, opcsn, pb); ++ if (RUV_COVERS_CSN == rc) { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "write_changelog_and_ruv: RUV already covers csn for " ++ "%s (uniqid: %s, optype: %lu) csn %s\n", ++ REPL_GET_DN(&op_params->target_address), ++ op_params->target_address.uniqueid, ++ op_params->operation_type, ++ csn_as_string(op_params->csn, PR_FALSE, csn_str)); ++ } else if (rc != RUV_SUCCESS) { ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, ++ "write_changelog_and_ruv: failed to update RUV for " ++ "%s (uniqid: %s, optype: %lu) to changelog csn %s\n", ++ REPL_GET_DN(&op_params->target_address), ++ op_params->target_address.uniqueid, ++ op_params->operation_type, ++ csn_as_string(op_params->csn, PR_FALSE, csn_str)); ++ } + } + + object_release (repl_obj); +diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c +index b3df831..8187be9 100644 +--- a/ldap/servers/plugins/replication/repl5_replica.c ++++ b/ldap/servers/plugins/replication/repl5_replica.c +@@ -657,10 +657,11 @@ replica_set_ruv (Replica *r, RUV *ruv) + * inbound replication session operation, and needs to update its + * local RUV. + */ +-void ++int + replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl) + { + char csn_str[CSN_STRSIZE]; ++ int rc = RUV_SUCCESS; + + PR_ASSERT(NULL != r); + PR_ASSERT(NULL != updated_csn); +@@ -673,11 +674,13 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: replica " + "is NULL\n"); ++ rc = RUV_BAD_DATA; + } + else if (NULL == updated_csn) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: csn " + "is NULL when updating replica %s\n", slapi_sdn_get_dn(r->repl_root)); ++ rc = RUV_BAD_DATA; + } + else + { +@@ -710,8 +713,17 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl) + } + } + /* Update max csn for local and remote replicas */ +- if (ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid) +- != RUV_SUCCESS) ++ rc = ruv_update_ruv (ruv, updated_csn, replica_purl, rid == r->repl_rid); ++ if (RUV_COVERS_CSN == rc) ++ { ++ slapi_log_error(SLAPI_LOG_REPL, ++ repl_plugin_name, "replica_update_ruv: RUV " ++ "for replica %s already covers max_csn = %s\n", ++ slapi_sdn_get_dn(r->repl_root), ++ csn_as_string(updated_csn, PR_FALSE, csn_str)); ++ /* RUV is not dirty - no write needed */ ++ } ++ else if (RUV_SUCCESS != rc) + { + slapi_log_error(SLAPI_LOG_FATAL, + repl_plugin_name, "replica_update_ruv: unable " +@@ -719,14 +731,18 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl) + slapi_sdn_get_dn(r->repl_root), + csn_as_string(updated_csn, PR_FALSE, csn_str)); + } +- +- r->repl_ruv_dirty = PR_TRUE; ++ else ++ { ++ /* RUV updated - mark as dirty */ ++ r->repl_ruv_dirty = PR_TRUE; ++ } + } + else + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "replica_update_ruv: unable to get RUV object for replica " + "%s\n", slapi_sdn_get_dn(r->repl_root)); ++ rc = RUV_NOTFOUND; + } + } + else +@@ -734,9 +750,11 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl) + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_update_ruv: " + "unable to initialize RUV for replica %s\n", + slapi_sdn_get_dn(r->repl_root)); ++ rc = RUV_NOTFOUND; + } + PR_Unlock(r->repl_lock); + } ++ return rc; + } + + /* +@@ -2400,7 +2418,11 @@ _replica_update_state (time_t when, void *arg) + { + /* EY: the consumer needs to flush ruv to disk. */ + PR_Unlock(r->repl_lock); +- replica_write_ruv(r); ++ if (replica_write_ruv(r)) { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "_replica_update_state: failed write RUV for %s\n", ++ slapi_sdn_get_dn (r->repl_root)); ++ } + goto done; + } + +@@ -2471,7 +2493,11 @@ _replica_update_state (time_t when, void *arg) + } + + /* update RUV - performs its own locking */ +- replica_write_ruv (r); ++ if (replica_write_ruv(r)) { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "_replica_update_state: failed write RUV for %s\n", ++ slapi_sdn_get_dn (r->repl_root)); ++ } + + /* since this is the only place this value is changed and we are + guaranteed that only one thread enters the function, its ok +@@ -2487,10 +2513,10 @@ done: + object_release (replica_object); + } + +-void ++int + replica_write_ruv (Replica *r) + { +- int rc; ++ int rc = LDAP_SUCCESS; + Slapi_Mod smod; + Slapi_Mod smod_last_modified; + LDAPMod *mods [3]; +@@ -2503,7 +2529,7 @@ replica_write_ruv (Replica *r) + if (!r->repl_ruv_dirty) + { + PR_Unlock(r->repl_lock); +- return; ++ return rc; + } + + PR_ASSERT (r->repl_ruv); +@@ -2560,6 +2586,8 @@ replica_write_ruv (Replica *r) + slapi_mod_done (&smod); + slapi_mod_done (&smod_last_modified); + slapi_pblock_destroy (pb); ++ ++ return rc; + } + + +@@ -2580,6 +2608,7 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods + Slapi_Mod smod_last_modified; + Slapi_Operation *op; + Slapi_Entry *target_entry = NULL; ++ int rc = 0; + + slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &target_entry); + if (target_entry && is_ruv_tombstone_entry(target_entry)) { +@@ -2618,19 +2647,32 @@ replica_ruv_smods_for_op( Slapi_PBlock *pb, char **uniqueid, Slapi_Mods **smods + object_release (ruv_obj); + object_release (replica_obj); + +- ruv_set_max_csn( ruv_copy, opcsn, NULL ); +- +- ruv_to_smod( ruv_copy, &smod ); +- ruv_last_modified_to_smod( ruv_copy, &smod_last_modified ); ++ rc = ruv_set_max_csn_ext( ruv_copy, opcsn, NULL, PR_TRUE ); ++ if (rc == RUV_COVERS_CSN) { /* change would "revert" RUV - ignored */ ++ rc = 0; /* tell caller to ignore */ ++ } else if (rc == RUV_SUCCESS) { ++ rc = 1; /* tell caller success */ ++ } else { /* error */ ++ rc = -1; /* tell caller error */ ++ } + ++ if (rc == 1) { ++ ruv_to_smod( ruv_copy, &smod ); ++ ruv_last_modified_to_smod( ruv_copy, &smod_last_modified ); ++ } + ruv_destroy( &ruv_copy ); + +- *smods = slapi_mods_new(); +- slapi_mods_add_smod(*smods, &smod); +- slapi_mods_add_smod(*smods, &smod_last_modified); +- *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID ); ++ if (rc == 1) { ++ *smods = slapi_mods_new(); ++ slapi_mods_add_smod(*smods, &smod); ++ slapi_mods_add_smod(*smods, &smod_last_modified); ++ *uniqueid = slapi_ch_strdup( RUV_STORAGE_ENTRY_UNIQUEID ); ++ } else { ++ *smods = NULL; ++ *uniqueid = NULL; ++ } + +- return (1); ++ return rc; + } + + +@@ -3375,7 +3417,9 @@ replica_strip_cleaned_rids(Replica *r) + while(rid[i] != 0){ + ruv_delete_replica(ruv, rid[i]); + replica_set_ruv_dirty(r); +- replica_write_ruv(r); ++ if (replica_write_ruv(r)) { ++ slapi_log_error (SLAPI_LOG_REPL, "replica_strip_cleaned_rids", "failed to write RUV\n"); ++ } + i++; + } + object_release(RUVObj); +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index bbbe87e..7c625eb 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -1200,7 +1200,9 @@ replica_execute_cleanruv_task (Object *r, ReplicaId rid, char *returntext /* not + } + rc = ruv_delete_replica(local_ruv, rid); + replica_set_ruv_dirty(replica); +- replica_write_ruv(replica); ++ if (replica_write_ruv(replica)) { ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "cleanruv_task: could not write RUV\n"); ++ } + object_release(RUVObj); + + /* Update Mapping Tree to reflect RUV changes */ +diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c +index 8fbd89c..2808c58 100644 +--- a/ldap/servers/plugins/replication/repl5_ruv.c ++++ b/ldap/servers/plugins/replication/repl5_ruv.c +@@ -665,26 +665,34 @@ set_min_csn_nolock(RUV *ruv, const CSN *min_csn, const char *replica_purl) + } + + static int +-set_max_csn_nolock(RUV *ruv, const CSN *max_csn, const char *replica_purl) ++set_max_csn_nolock_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater) + { +- int return_value; ++ int return_value = RUV_SUCCESS; + ReplicaId rid = csn_get_replicaid (max_csn); + RUVElement *replica = ruvGetReplica (ruv, rid); +- if (NULL == replica) +- { +- replica = ruvAddReplica (ruv, max_csn, replica_purl); +- if (replica) +- return_value = RUV_SUCCESS; +- else +- return_value = RUV_MEMORY_ERROR; +- } +- else +- { +- if (replica_purl && replica->replica_purl == NULL) +- replica->replica_purl = slapi_ch_strdup (replica_purl); +- csn_free(&replica->csn); +- replica->csn = csn_dup(max_csn); +- replica->last_modified = current_time(); ++ if (NULL == replica) { ++ replica = ruvAddReplica (ruv, max_csn, replica_purl); ++ if (replica) ++ return_value = RUV_SUCCESS; ++ else ++ return_value = RUV_MEMORY_ERROR; ++ } else { ++ if (replica_purl && replica->replica_purl == NULL) ++ replica->replica_purl = slapi_ch_strdup (replica_purl); ++ if (!must_be_greater || (csn_compare(replica->csn, max_csn) < 0)) { ++ csn_free(&replica->csn); ++ replica->csn = csn_dup(max_csn); ++ replica->last_modified = current_time(); ++ } else { ++ char csn1[CSN_STRSIZE+1]; ++ char csn2[CSN_STRSIZE+1]; ++ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, ++ "set_max_csn_nolock_ext: new CSN [%s] for replica ID [%d] " ++ "is less than the existing max CSN [%s] - ignoring\n", ++ csn_as_string(max_csn, PR_FALSE, csn1), rid, ++ csn_as_string(replica->csn, PR_FALSE, csn2)); ++ return_value = RUV_COVERS_CSN; ++ } + return_value = RUV_SUCCESS; + } + return return_value; +@@ -704,9 +712,15 @@ ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl) + int + ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl) + { ++ return ruv_set_max_csn_ext(ruv, max_csn, replica_purl, PR_FALSE); ++} ++ ++int ++ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater) ++{ + int return_value; + slapi_rwlock_wrlock (ruv->lock); +- return_value = set_max_csn_nolock(ruv, max_csn, replica_purl); ++ return_value = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, must_be_greater); + slapi_rwlock_unlock (ruv->lock); + return return_value; + } +@@ -1654,8 +1668,9 @@ int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool i + * generated by this replica, we need to set the first_csn as the min csn in the + * ruv */ + set_min_csn_nolock(ruv, first_csn, replica_purl); +- } +- set_max_csn_nolock(ruv, max_csn, replica_purl); ++ } ++ /* only update the max_csn in the RUV if it is greater than the existing one */ ++ rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */); + /* It is possible that first_csn points to max_csn. + We need to free it once */ + if (max_csn != first_csn) { +diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h +index 944f5ed..fdc8af2 100644 +--- a/ldap/servers/plugins/replication/repl5_ruv.h ++++ b/ldap/servers/plugins/replication/repl5_ruv.h +@@ -108,6 +108,7 @@ int ruv_get_smallest_csn_for_replica(const RUV *ruv, ReplicaId rid, CSN **csn); + int ruv_set_csns(RUV *ruv, const CSN *csn, const char *replica_purl); + int ruv_set_csns_keep_smallest(RUV *ruv, const CSN *csn); + int ruv_set_max_csn(RUV *ruv, const CSN *max_csn, const char *replica_purl); ++int ruv_set_max_csn_ext(RUV *ruv, const CSN *max_csn, const char *replica_purl, PRBool must_be_greater); + int ruv_set_min_csn(RUV *ruv, const CSN *min_csn, const char *replica_purl); + const char *ruv_get_purl_for_replica(const RUV *ruv, ReplicaId rid); + char *ruv_get_replica_generation (const RUV *ruv); +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c +index 78ca565..554822c 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c +@@ -668,19 +668,6 @@ ldbm_back_add( Slapi_PBlock *pb ) + parententry = NULL; + } + +- if (!is_ruv && !is_fixup_operation) { +- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); +- if (-1 == ruv_c_init) { +- LDAPDebug( LDAP_DEBUG_ANY, +- "ldbm_back_add: ldbm_txn_ruv_modify_context " +- "failed to construct RUV modify context\n", +- 0, 0, 0); +- ldap_result_code= LDAP_OPERATIONS_ERROR; +- retval = 0; +- goto error_return; +- } +- } +- + if ( (originalentry = backentry_dup(addingentry )) == NULL ) { + ldap_result_code= LDAP_OPERATIONS_ERROR; + goto error_return; +@@ -718,6 +705,11 @@ ldbm_back_add( Slapi_PBlock *pb ) + goto error_return; + } + } ++ if (ruv_c_init) { ++ /* reset the ruv txn stuff */ ++ modify_term(&ruv_c, be); ++ ruv_c_init = 0; ++ } + + /* We're re-trying */ + LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "Add Retrying Transaction\n"); +@@ -910,6 +902,19 @@ ldbm_back_add( Slapi_PBlock *pb ) + } + } + ++ if (!is_ruv && !is_fixup_operation) { ++ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); ++ if (-1 == ruv_c_init) { ++ LDAPDebug( LDAP_DEBUG_ANY, ++ "ldbm_back_add: ldbm_txn_ruv_modify_context " ++ "failed to construct RUV modify context\n", ++ 0, 0, 0); ++ ldap_result_code= LDAP_OPERATIONS_ERROR; ++ retval = 0; ++ goto error_return; ++ } ++ } ++ + if (ruv_c_init) { + retval = modify_update_all( be, pb, &ruv_c, &txn ); + if (DB_LOCK_DEADLOCK == retval) { +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +index d80c54e..3cf58f4 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +@@ -451,19 +451,6 @@ ldbm_back_delete( Slapi_PBlock *pb ) + } + } + +- if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) { +- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); +- if (-1 == ruv_c_init) { +- LDAPDebug( LDAP_DEBUG_ANY, +- "ldbm_back_delete: ldbm_txn_ruv_modify_context " +- "failed to construct RUV modify context\n", +- 0, 0, 0); +- ldap_result_code= LDAP_OPERATIONS_ERROR; +- retval = 0; +- goto error_return; +- } +- } +- + /* + * So, we believe that no code up till here actually added anything + * to the persistent store. From now on, we're transacted +@@ -511,6 +498,12 @@ ldbm_back_delete( Slapi_PBlock *pb ) + e_in_cache = 1; + } + ++ if (ruv_c_init) { ++ /* reset the ruv txn stuff */ ++ modify_term(&ruv_c, be); ++ ruv_c_init = 0; ++ } ++ + /* We're re-trying */ + LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, + "Delete Retrying Transaction\n"); +@@ -991,6 +984,19 @@ ldbm_back_delete( Slapi_PBlock *pb ) + } + } + ++ if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) { ++ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); ++ if (-1 == ruv_c_init) { ++ LDAPDebug( LDAP_DEBUG_ANY, ++ "ldbm_back_delete: ldbm_txn_ruv_modify_context " ++ "failed to construct RUV modify context\n", ++ 0, 0, 0); ++ ldap_result_code= LDAP_OPERATIONS_ERROR; ++ retval = 0; ++ goto error_return; ++ } ++ } ++ + if (ruv_c_init) { + retval = modify_update_all( be, pb, &ruv_c, &txn ); + if (DB_LOCK_DEADLOCK == retval) { +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +index 66b8ab8..32510ab 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c +@@ -476,19 +476,6 @@ ldbm_back_modify( Slapi_PBlock *pb ) + goto error_return; + } + +- if (!is_ruv && !is_fixup_operation) { +- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); +- if (-1 == ruv_c_init) { +- LDAPDebug( LDAP_DEBUG_ANY, +- "ldbm_back_modify: ldbm_txn_ruv_modify_context " +- "failed to construct RUV modify context\n", +- 0, 0, 0); +- ldap_result_code= LDAP_OPERATIONS_ERROR; +- retval = 0; +- goto error_return; +- } +- } +- + /* + * Grab a copy of the mods and the entry in case the be_txn_preop changes + * the them. If we have a failure, then we need to reset the mods to their +@@ -526,6 +513,12 @@ ldbm_back_modify( Slapi_PBlock *pb ) + goto error_return; + } + ++ if (ruv_c_init) { ++ /* reset the ruv txn stuff */ ++ modify_term(&ruv_c, be); ++ ruv_c_init = 0; ++ } ++ + LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, + "Modify Retrying Transaction\n"); + #ifndef LDBM_NO_BACKOFF_DELAY +@@ -638,6 +631,19 @@ ldbm_back_modify( Slapi_PBlock *pb ) + + } + ++ if (!is_ruv && !is_fixup_operation) { ++ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); ++ if (-1 == ruv_c_init) { ++ LDAPDebug( LDAP_DEBUG_ANY, ++ "ldbm_back_modify: ldbm_txn_ruv_modify_context " ++ "failed to construct RUV modify context\n", ++ 0, 0, 0); ++ ldap_result_code= LDAP_OPERATIONS_ERROR; ++ retval = 0; ++ goto error_return; ++ } ++ } ++ + if (ruv_c_init) { + retval = modify_update_all( be, pb, &ruv_c, &txn ); + if (DB_LOCK_DEADLOCK == retval) { +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +index 69fc053..b5cb90b 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +@@ -712,19 +712,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) + /* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */ + } + +- if (!is_ruv && !is_fixup_operation) { +- ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); +- if (-1 == ruv_c_init) { +- LDAPDebug( LDAP_DEBUG_ANY, +- "ldbm_back_modrdn: ldbm_txn_ruv_modify_context " +- "failed to construct RUV modify context\n", +- 0, 0, 0); +- ldap_result_code = LDAP_OPERATIONS_ERROR; +- retval = 0; +- goto error_return; +- } +- } +- + /* + * make copies of the originals, no need to copy the mods because + * we have already copied them +@@ -826,6 +813,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) + goto error_return; + } + ++ if (ruv_c_init) { ++ /* reset the ruv txn stuff */ ++ modify_term(&ruv_c, be); ++ ruv_c_init = 0; ++ } + /* We're re-trying */ + LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, + "Modrdn Retrying Transaction\n"); +@@ -1028,6 +1020,19 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) + goto error_return; + } + ++ if (!is_ruv && !is_fixup_operation) { ++ ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); ++ if (-1 == ruv_c_init) { ++ LDAPDebug( LDAP_DEBUG_ANY, ++ "ldbm_back_modrdn: ldbm_txn_ruv_modify_context " ++ "failed to construct RUV modify context\n", ++ 0, 0, 0); ++ ldap_result_code = LDAP_OPERATIONS_ERROR; ++ retval = 0; ++ goto error_return; ++ } ++ } ++ + if (ruv_c_init) { + retval = modify_update_all( be, pb, &ruv_c, &txn ); + if (DB_LOCK_DEADLOCK == retval) { +diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c +index fd62df9..7a90742 100644 +--- a/ldap/servers/slapd/back-ldbm/misc.c ++++ b/ldap/servers/slapd/back-ldbm/misc.c +@@ -420,6 +420,7 @@ ldbm_txn_ruv_modify_context( Slapi_PBlock *pb, modify_context *mc ) + /* Either something went wrong when the RUV callback tried to assemble + * the updates for us, or there were no updates because the op doesn't + * target a replica. */ ++ /* or, the CSN is already covered by the RUV */ + if (1 != rc || NULL == smods || NULL == uniqueid) { + return (rc); + } +-- +1.8.1.4 + diff --git a/0068-fix-coverity-11895-null-deref-caused-by-fix-to-ticke.patch b/0068-fix-coverity-11895-null-deref-caused-by-fix-to-ticke.patch new file mode 100644 index 0000000..1237579 --- /dev/null +++ b/0068-fix-coverity-11895-null-deref-caused-by-fix-to-ticke.patch @@ -0,0 +1,60 @@ +From 496b3bc1eced77b8a34f9a6c4ba86da58349c682 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 31 Jul 2013 10:49:18 -0600 +Subject: [PATCH 68/99] fix coverity 11895 - null deref - caused by fix to + ticket 47392 + +reviewed by: nhosoi (Thanks!) +(cherry picked from commit b61143cc79cb5c3e23f403c4980f8a03ab7426c0) +(cherry picked from commit 03a67b1432bbafe5eb7a82a8afd0832f220c229b) +(cherry picked from commit 877fee5b6228faf471eefed9a073dff13074b224) +(cherry picked from commit 89a98eb66264718e3d7431a4cda92afe08371a84) +--- + ldap/servers/plugins/replication/repl5_plugins.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c +index 7aa2e2c..afb0364 100644 +--- a/ldap/servers/plugins/replication/repl5_plugins.c ++++ b/ldap/servers/plugins/replication/repl5_plugins.c +@@ -1117,9 +1117,13 @@ write_changelog_and_ruv (Slapi_PBlock *pb) + just read from the changelog in either the supplier or consumer ruv + */ + if (0 == return_value) { +- char csn_str[CSN_STRSIZE]; ++ char csn_str[CSN_STRSIZE] = {'\0'}; + CSN *opcsn; + int rc; ++ const char *dn = op_params ? REPL_GET_DN(&op_params->target_address) : "unknown"; ++ char *uniqueid = op_params ? op_params->target_address.uniqueid : "unknown"; ++ unsigned long optype = op_params ? op_params->operation_type : 0; ++ CSN *oppcsn = op_params ? op_params->csn : NULL; + + slapi_pblock_get( pb, SLAPI_OPERATION, &op ); + opcsn = operation_get_csn(op); +@@ -1128,18 +1132,14 @@ write_changelog_and_ruv (Slapi_PBlock *pb) + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "write_changelog_and_ruv: RUV already covers csn for " + "%s (uniqid: %s, optype: %lu) csn %s\n", +- REPL_GET_DN(&op_params->target_address), +- op_params->target_address.uniqueid, +- op_params->operation_type, +- csn_as_string(op_params->csn, PR_FALSE, csn_str)); ++ dn, uniqueid, optype, ++ csn_as_string(oppcsn, PR_FALSE, csn_str)); + } else if (rc != RUV_SUCCESS) { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "write_changelog_and_ruv: failed to update RUV for " + "%s (uniqid: %s, optype: %lu) to changelog csn %s\n", +- REPL_GET_DN(&op_params->target_address), +- op_params->target_address.uniqueid, +- op_params->operation_type, +- csn_as_string(op_params->csn, PR_FALSE, csn_str)); ++ dn, uniqueid, optype, ++ csn_as_string(oppcsn, PR_FALSE, csn_str)); + } + } + +-- +1.8.1.4 + diff --git a/0069-Ticket-47391-deleting-and-adding-userpassword-fails-.patch b/0069-Ticket-47391-deleting-and-adding-userpassword-fails-.patch new file mode 100644 index 0000000..2f07789 --- /dev/null +++ b/0069-Ticket-47391-deleting-and-adding-userpassword-fails-.patch @@ -0,0 +1,39 @@ +From cda4bf23fbe1a88008894024effb12f4860de70f Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 17 Jun 2013 14:33:16 -0700 +Subject: [PATCH 69/99] Ticket #47391 - deleting and adding userpassword fails + to update the password + +Bug description: Deleting and adding password operation causes +the crash since once an entry is written to and retrieved from +DB, it does not have unhashed#user#password in the entry any +more. The delete userpassword internally invokes delete unhashed +existed in the entry. + +Fix description: This patch adds the stricter check for the NULL +reference. + +https://fedorahosted.org/389/ticket/47391 + +Reviewed by Nathan (Thanks!!) +(cherry picked from commit 9d9e9a6f132eb7bcbac3d3d6d39b27e38b6abb6b) +--- + ldap/servers/slapd/back-ldbm/index.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c +index 5948717..62a58a7 100644 +--- a/ldap/servers/slapd/back-ldbm/index.c ++++ b/ldap/servers/slapd/back-ldbm/index.c +@@ -694,7 +694,7 @@ index_add_mods( + /* Check if the any values being deleted + * also exist in a subtype. + */ +- for ( j=0; deleted_valueArray[j] != NULL; j++) { ++ for (j = 0; deleted_valueArray && deleted_valueArray[j]; j++) { + if ( valuearray_find(curr_attr, evals, deleted_valueArray[j]) == -1 ) { + /* If the equality flag isn't already set, set it */ + if (!(flags & BE_INDEX_EQUALITY)) { +-- +1.8.1.4 + diff --git a/0070-Ticket-47391-deleting-and-adding-userpassword-fails-.patch b/0070-Ticket-47391-deleting-and-adding-userpassword-fails-.patch new file mode 100644 index 0000000..7e71d42 --- /dev/null +++ b/0070-Ticket-47391-deleting-and-adding-userpassword-fails-.patch @@ -0,0 +1,71 @@ +From 1e75376f7895d4d2de294ee2ae1343c7e1a08584 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 17 Jun 2013 13:02:10 -0700 +Subject: [PATCH 70/99] Ticket #47391 - deleting and adding userpassword fails + to update the password (additional fix) + +Bug description: ldapmodify with changetype "modify" is supposed +to skip checking unhashed password in acl_check_mods. "delete" +and "replace" were being skipped, but not "add". + +Fix description: "add" also skips to check unhashed password. + +https://fedorahosted.org/389/ticket/47391 + +Reviewed by Rich (Thank you!!) +(cherry picked from commit 5337dcfa67827ac46df68a2f817eade638eb352d) +(cherry picked from commit 7d8bddd281294b6f2dcdc0ed431680e505ed5e1a) +--- + ldap/servers/plugins/acl/acl.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c +index 4516cf8..09f28ee 100644 +--- a/ldap/servers/plugins/acl/acl.c ++++ b/ldap/servers/plugins/acl/acl.c +@@ -1358,6 +1358,9 @@ acl_check_mods( + for (mod = slapi_mods_get_first_mod(&smods); + mod != NULL; + mod = slapi_mods_get_next_mod(&smods)) { ++ if (0 == strcmp(mod->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) { ++ continue; ++ } + switch (mod->mod_op & ~LDAP_MOD_BVALUES ) { + + case LDAP_MOD_DELETE: +@@ -1382,9 +1385,7 @@ acl_check_mods( + } + if (lastmod && + (strcmp (mod->mod_type, "modifiersname")== 0 || +- strcmp (mod->mod_type, "modifytimestamp")== 0 || +- strcmp (mod->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)== 0) +- ) { ++ strcmp (mod->mod_type, "modifytimestamp")== 0)) { + continue; + } + +@@ -1396,9 +1397,9 @@ acl_check_mods( + while(k != -1) { + attrVal = slapi_value_get_berval(sval); + rv = slapi_access_allowed (pb, e, +- mod->mod_type, +- (struct berval *)attrVal, /* XXXggood had to cast away const - BAD */ +- ACLPB_SLAPI_ACL_WRITE_DEL); /* was SLAPI_ACL_WRITE */ ++ mod->mod_type, ++ (struct berval *)attrVal, /* XXXggood had to cast away const - BAD */ ++ ACLPB_SLAPI_ACL_WRITE_DEL); /* was SLAPI_ACL_WRITE */ + if ( rv != LDAP_SUCCESS) { + acl_gen_err_msg ( + SLAPI_ACL_WRITE, +@@ -1430,7 +1431,7 @@ acl_check_mods( + } + break; + +- default: ++ default: /* including LDAP_MOD_ADD */ + break; + } /* switch */ + +-- +1.8.1.4 + diff --git a/0071-Ticket-47395-47397-v2-correct-behaviour-of-account-p.patch b/0071-Ticket-47395-47397-v2-correct-behaviour-of-account-p.patch new file mode 100644 index 0000000..dc65d64 --- /dev/null +++ b/0071-Ticket-47395-47397-v2-correct-behaviour-of-account-p.patch @@ -0,0 +1,169 @@ +From 93ec3fe4e4ec04994bc471a8190978076b6b2954 Mon Sep 17 00:00:00 2001 +From: Ludwig Krispenz +Date: Thu, 20 Jun 2013 17:59:09 +0200 +Subject: [PATCH 71/99] Ticket 47395 47397 v2 correct behaviour of account + policy if only stateattr is configured or no alternate attr is + configured + +Bug Description: The tickets relate to two specific configurations of + the account policy plugin + 1] if createtimestamp is configured as stateattr it is treated like a + normal timstamp attribute and is updated, which should not happen. + As a side effect the account is not locked out based on the original + createtimestamp + 2] if no altstateattr is configured, always createtimestamp is used, but + the intention was to base account inactivation only on lastlogintime + +Fix Description: 1] prevent update of createtimestamp, even if used as stateattr + 2] if no altstateattr is configured still use the default, but + accept "1.1" as null value and check only stateattr + +https://fedorahosted.org/389/ticket/47395 +https://fedorahosted.org/389/ticket/47397 + +Reviewed by: ? +(cherry picked from commit b4cc0f6b31d8221677950a703a78b02e0cbc7e30) +--- + ldap/servers/plugins/acctpolicy/acct_config.c | 13 ++++++++++++- + ldap/servers/plugins/acctpolicy/acct_init.c | 2 +- + ldap/servers/plugins/acctpolicy/acct_plugin.c | 18 +++++++++++++----- + ldap/servers/plugins/acctpolicy/acct_util.c | 13 +++++++++++++ + ldap/servers/plugins/acctpolicy/acctpolicy.h | 5 +++++ + 5 files changed, 44 insertions(+), 7 deletions(-) + +diff --git a/ldap/servers/plugins/acctpolicy/acct_config.c b/ldap/servers/plugins/acctpolicy/acct_config.c +index 3da338a..8dfde0b 100644 +--- a/ldap/servers/plugins/acctpolicy/acct_config.c ++++ b/ldap/servers/plugins/acctpolicy/acct_config.c +@@ -82,12 +82,23 @@ acct_policy_entry2config( Slapi_Entry *e, acctPluginCfg *newcfg ) { + newcfg->state_attr_name = get_attr_string_val( e, CFG_LASTLOGIN_STATE_ATTR ); + if( newcfg->state_attr_name == NULL ) { + newcfg->state_attr_name = slapi_ch_strdup( DEFAULT_LASTLOGIN_STATE_ATTR ); ++ } else if (!update_is_allowed_attr(newcfg->state_attr_name)) { ++ /* log a warning that this attribute cannot be updated */ ++ slapi_log_error( SLAPI_LOG_FATAL, PLUGIN_NAME, ++ "The configured state attribute [%s] cannot be updated, accounts will always become inactive.\n", ++ newcfg->state_attr_name ); + } + + newcfg->alt_state_attr_name = get_attr_string_val( e, CFG_ALT_LASTLOGIN_STATE_ATTR ); ++ /* alt_state_attr_name should be optional, but for backward compatibility, ++ * if not specified use a default. If the attribute is "1.1", no fallback ++ * will be used ++ */ + if( newcfg->alt_state_attr_name == NULL ) { + newcfg->alt_state_attr_name = slapi_ch_strdup( DEFAULT_ALT_LASTLOGIN_STATE_ATTR ); +- } ++ } else if ( !strcmp( newcfg->alt_state_attr_name, "1.1" ) ) { ++ slapi_ch_free_string( &newcfg->alt_state_attr_name ); /*none - NULL */ ++ } /* else use configured value */ + + newcfg->spec_attr_name = get_attr_string_val( e, CFG_SPEC_ATTR ); + if( newcfg->spec_attr_name == NULL ) { +diff --git a/ldap/servers/plugins/acctpolicy/acct_init.c b/ldap/servers/plugins/acctpolicy/acct_init.c +index af29140..52e0cfa 100644 +--- a/ldap/servers/plugins/acctpolicy/acct_init.c ++++ b/ldap/servers/plugins/acctpolicy/acct_init.c +@@ -132,7 +132,7 @@ acct_policy_start( Slapi_PBlock *pb ) { + slapi_log_error( SLAPI_LOG_PLUGIN, PLUGIN_NAME, "acct_policy_start config: " + "stateAttrName=%s altStateAttrName=%s specAttrName=%s limitAttrName=%s " + "alwaysRecordLogin=%d\n", +- cfg->state_attr_name, cfg->alt_state_attr_name, cfg->spec_attr_name, ++ cfg->state_attr_name, cfg->alt_state_attr_name?cfg->alt_state_attr_name:"not configured", cfg->spec_attr_name, + cfg->limit_attr_name, cfg->always_record_login); + return( CALLBACK_OK ); + } +diff --git a/ldap/servers/plugins/acctpolicy/acct_plugin.c b/ldap/servers/plugins/acctpolicy/acct_plugin.c +index 508fb23..b4db811 100644 +--- a/ldap/servers/plugins/acctpolicy/acct_plugin.c ++++ b/ldap/servers/plugins/acctpolicy/acct_plugin.c +@@ -44,14 +44,16 @@ acct_inact_limit( Slapi_PBlock *pb, const char *dn, Slapi_Entry *target_entry, a + cfg->state_attr_name ) ) != NULL ) { + slapi_log_error( SLAPI_LOG_PLUGIN, PRE_PLUGIN_NAME, + "\"%s\" login timestamp is %s\n", dn, lasttimestr ); +- } else if( ( lasttimestr = get_attr_string_val( target_entry, +- cfg->alt_state_attr_name ) ) != NULL ) { ++ } else if( cfg->alt_state_attr_name && (( lasttimestr = get_attr_string_val( target_entry, ++ cfg->alt_state_attr_name ) ) != NULL) ) { + slapi_log_error( SLAPI_LOG_PLUGIN, PRE_PLUGIN_NAME, + "\"%s\" alternate timestamp is %s\n", dn, lasttimestr ); + } else { ++ /* the primary or alternate attribute might not yet exist eg. ++ * if only lastlogintime is specified and it id the first login ++ */ + slapi_log_error( SLAPI_LOG_PLUGIN, PRE_PLUGIN_NAME, +- "\"%s\" has no login or creation timestamp\n", dn ); +- rc = -1; ++ "\"%s\" has no value for stateattr or altstateattr \n", dn ); + goto done; + } + +@@ -105,6 +107,13 @@ acct_record_login( const char *dn ) + int skip_mod_attrs = 1; /* value doesn't matter as long as not NULL */ + + cfg = get_config(); ++ ++ /* if we are not allowed to modify the state attr we're done ++ * this could be intentional, so just return ++ */ ++ if (! update_is_allowed_attr(cfg->state_attr_name) ) ++ return rc; ++ + plugin_id = get_identity(); + + timestr = epochtimeToGentime( time( (time_t*)0 ) ); +@@ -283,7 +292,6 @@ acct_bind_postop( Slapi_PBlock *pb ) + } else { + if( target_entry && has_attr( target_entry, + cfg->spec_attr_name, NULL ) ) { +- /* This account has a policy specifier */ + tracklogin = 1; + } + } +diff --git a/ldap/servers/plugins/acctpolicy/acct_util.c b/ldap/servers/plugins/acctpolicy/acct_util.c +index 8e220c3..a02382f 100644 +--- a/ldap/servers/plugins/acctpolicy/acct_util.c ++++ b/ldap/servers/plugins/acctpolicy/acct_util.c +@@ -255,3 +255,16 @@ epochtimeToGentime( time_t epochtime ) { + return( gentimestr ); + } + ++int update_is_allowed_attr (const char *attr) ++{ ++ int i; ++ ++ /* check list of attributes that cannot be used for login recording */ ++ for (i = 0; protected_attrs_login_recording[i]; i ++) { ++ if (strcasecmp (attr, protected_attrs_login_recording[i]) == 0) { ++ /* this attribute is not allowed */ ++ return 0; ++ } ++ } ++ return 1; ++} +diff --git a/ldap/servers/plugins/acctpolicy/acctpolicy.h b/ldap/servers/plugins/acctpolicy/acctpolicy.h +index e6f1497..78412cd 100644 +--- a/ldap/servers/plugins/acctpolicy/acctpolicy.h ++++ b/ldap/servers/plugins/acctpolicy/acctpolicy.h +@@ -35,6 +35,10 @@ Hewlett-Packard Development Company, L.P. + #define DEFAULT_INACT_LIMIT_ATTR "accountInactivityLimit" + #define DEFAULT_RECORD_LOGIN 1 + ++/* attributes that no clients are allowed to add or modify */ ++static char *protected_attrs_login_recording [] = { "createTimestamp", ++ NULL }; ++ + #define PLUGIN_VENDOR "Hewlett-Packard Company" + #define PLUGIN_VERSION "1.0" + #define PLUGIN_CONFIG_DN "cn=config,cn=Account Policy Plugin,cn=plugins,cn=config" +@@ -74,6 +78,7 @@ void* get_identity(); + void set_identity(void*); + time_t gentimeToEpochtime( char *gentimestr ); + char* epochtimeToGentime( time_t epochtime ); ++int update_is_allowed_attr (const char *attr); + + /* acct_config.c */ + int acct_policy_load_config_startup( Slapi_PBlock* pb, void* plugin_id ); +-- +1.8.1.4 + diff --git a/0072-Fix-compiler-warnings-for-Ticket-47395-and-47397.patch b/0072-Fix-compiler-warnings-for-Ticket-47395-and-47397.patch new file mode 100644 index 0000000..562b9d5 --- /dev/null +++ b/0072-Fix-compiler-warnings-for-Ticket-47395-and-47397.patch @@ -0,0 +1,48 @@ +From 099becdc1261561631ae3eb1ba6c0663bc919da2 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 31 Jul 2013 09:53:03 -0600 +Subject: [PATCH 72/99] Fix compiler warnings for Ticket 47395 and 47397 + +Ticket 47395 47397 v2 correct behaviour of account policy if only stateattr + is configured or no alternate attr is configured +(cherry picked from commit ce4e813f3f446bdd746ec288f33d1effcb3bf919) +(cherry picked from commit 2bd9ced46f395513e0aaded8f8eea5962337bffc) +(cherry picked from commit 12d47a25879456f8527505ded5a001f68302a877) +--- + ldap/servers/plugins/acctpolicy/acct_util.c | 4 ++++ + ldap/servers/plugins/acctpolicy/acctpolicy.h | 4 ---- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/ldap/servers/plugins/acctpolicy/acct_util.c b/ldap/servers/plugins/acctpolicy/acct_util.c +index a02382f..850cc42 100644 +--- a/ldap/servers/plugins/acctpolicy/acct_util.c ++++ b/ldap/servers/plugins/acctpolicy/acct_util.c +@@ -29,6 +29,10 @@ Hewlett-Packard Development Company, L.P. + /* Globals */ + static void* plugin_id = NULL; + ++/* attributes that no clients are allowed to add or modify */ ++static char *protected_attrs_login_recording [] = { "createTimestamp", ++ NULL }; ++ + /* + Checks whether an entry has a particular attribute type, and optionally + returns the value. Only for use with single-valued attributes - it returns +diff --git a/ldap/servers/plugins/acctpolicy/acctpolicy.h b/ldap/servers/plugins/acctpolicy/acctpolicy.h +index 78412cd..5c202d3 100644 +--- a/ldap/servers/plugins/acctpolicy/acctpolicy.h ++++ b/ldap/servers/plugins/acctpolicy/acctpolicy.h +@@ -35,10 +35,6 @@ Hewlett-Packard Development Company, L.P. + #define DEFAULT_INACT_LIMIT_ATTR "accountInactivityLimit" + #define DEFAULT_RECORD_LOGIN 1 + +-/* attributes that no clients are allowed to add or modify */ +-static char *protected_attrs_login_recording [] = { "createTimestamp", +- NULL }; +- + #define PLUGIN_VENDOR "Hewlett-Packard Company" + #define PLUGIN_VERSION "1.0" + #define PLUGIN_CONFIG_DN "cn=config,cn=Account Policy Plugin,cn=plugins,cn=config" +-- +1.8.1.4 + diff --git a/0073-Ticket-47396-crash-on-modrdn-of-tombstone.patch b/0073-Ticket-47396-crash-on-modrdn-of-tombstone.patch new file mode 100644 index 0000000..c4f79b5 --- /dev/null +++ b/0073-Ticket-47396-crash-on-modrdn-of-tombstone.patch @@ -0,0 +1,42 @@ +From 7b35b724f8a874a200154d1e3626ed14cc5b8245 Mon Sep 17 00:00:00 2001 +From: Ludwig Krispenz +Date: Mon, 24 Jun 2013 10:19:53 +0200 +Subject: [PATCH 73/99] Ticket 47396 - crash on modrdn of tombstone + + Bug Description: a client modrdn operation on a tombstone entry can crash the server + + Fix Description: client modrdns and modifies on tombstone entries should not be + accepted. Tombstones aer internally kept for eventual conflict resolution, normal + clients should not touch them. + an exception would be to force purging of tombstones or a kind of "undo" for + a delete, which could resurrect a tombstone, but this is not in the scope of this ticket + + https://fedorahosted.org/389/ticket/47396 + + Reviewed by: Rich, thanks +(cherry picked from commit d1d6245d6ab894cf56e2529cb5c5dc941f4843cd) +--- + ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +index b5cb90b..c539463 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +@@ -352,6 +352,13 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) + goto error_return; /* error result sent by find_entry2modify() */ + } + e_in_cache = 1; /* e is in the cache and locked */ ++ if (slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE) ) { ++ ldap_result_code = LDAP_UNWILLING_TO_PERFORM; ++ ldap_result_message = "Operation not allowed on tombstone entry."; ++ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modrdn", ++ "Attempt to rename a tombstone entry %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const( e->ep_entry ))); ++ goto error_return; ++ } + /* Check that an entry with the same DN doesn't already exist. */ + { + Slapi_Entry *entry; +-- +1.8.1.4 + diff --git a/0074-Ticket-47393-Attribute-are-not-encrypted-on-a-consum.patch b/0074-Ticket-47393-Attribute-are-not-encrypted-on-a-consum.patch new file mode 100644 index 0000000..25da040 --- /dev/null +++ b/0074-Ticket-47393-Attribute-are-not-encrypted-on-a-consum.patch @@ -0,0 +1,132 @@ +From 4da5a8086797d0584fdf5e5d222c531dc3369b9f Mon Sep 17 00:00:00 2001 +From: "Thierry bordaz (tbordaz)" +Date: Mon, 17 Jun 2013 14:42:34 +0200 +Subject: [PATCH 74/99] Ticket 47393 - Attribute are not encrypted on a + consumer after a full initialization + +Bug Description: + During online initialization of a replica encrypted attributes are not encrypted by the import. + This is because the import job flag job->encrypt is not set. + +Fix Description: + The fix consist to add the config backend attribute "nsslapd-online-import-encrypt" that is by default set to "on". + During online 'ldbm_back_wire_import' the config attribute is set into the pblock and set into the job->encrypt + +https://bugzilla.redhat.com/show_bug.cgi?id=893178 + +Reviewed by: Rich Meggison (thanks Rich) + +Platforms tested: fedora 17 + +Flag Day: no + +Doc impact: no +(cherry picked from commit 856cdf8ac5e3730335332d6a122262ee10abc59a) +--- + ldap/servers/slapd/back-ldbm/back-ldbm.h | 16 +++++++++------- + ldap/servers/slapd/back-ldbm/import-threads.c | 2 ++ + ldap/servers/slapd/back-ldbm/ldbm_config.c | 21 +++++++++++++++++++++ + ldap/servers/slapd/back-ldbm/ldbm_config.h | 1 + + 4 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h +index aed57cf..3330449 100644 +--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h +@@ -644,13 +644,15 @@ struct ldbminfo { + int li_fat_lock; /* 608146 -- make this configurable, first */ + int li_legacy_errcode; /* 615428 -- in case legacy err code is expected */ + Slapi_Counter *li_global_usn_counter; /* global USN counter */ +- int li_reslimit_allids_handle; /* allids aka idlistscan */ +- int li_pagedlookthroughlimit; +- int li_pagedallidsthreshold; +- int li_reslimit_pagedlookthrough_handle; +- int li_reslimit_pagedallids_handle; /* allids aka idlistscan */ +- int li_rangelookthroughlimit; +- int li_reslimit_rangelookthrough_handle; ++ int li_reslimit_allids_handle; /* allids aka idlistscan */ ++ int li_pagedlookthroughlimit; ++ int li_pagedallidsthreshold; ++ int li_reslimit_pagedlookthrough_handle; ++ int li_reslimit_pagedallids_handle; /* allids aka idlistscan */ ++ int li_rangelookthroughlimit; ++ int li_reslimit_rangelookthrough_handle; ++ int li_online_import_encrypt; /* toggle attribute encryption during ldbm_back_wire_import */ ++ + }; + + /* li_flags could store these bits defined in ../slapi-plugin.h +diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c +index 60dbb5f..b85f073 100644 +--- a/ldap/servers/slapd/back-ldbm/import-threads.c ++++ b/ldap/servers/slapd/back-ldbm/import-threads.c +@@ -2715,6 +2715,7 @@ static int bulk_import_start(Slapi_PBlock *pb) + } + + slapi_pblock_get(pb, SLAPI_BACKEND, &be); ++ slapi_pblock_get(pb, SLAPI_LDIF2DB_ENCRYPT, &job->encrypt); + PR_ASSERT(be != NULL); + li = (struct ldbminfo *)(be->be_database->plg_private); + job->inst = (ldbm_instance *)be->be_instance_info; +@@ -3046,6 +3047,7 @@ int ldbm_back_wire_import(Slapi_PBlock *pb) + PR_ASSERT(be != NULL); + li = (struct ldbminfo *)(be->be_database->plg_private); + slapi_pblock_get(pb, SLAPI_BULK_IMPORT_STATE, &state); ++ slapi_pblock_set(pb, SLAPI_LDIF2DB_ENCRYPT, &li->li_online_import_encrypt); + if (state == SLAPI_BI_STATE_START) { + /* starting a new import */ + int rc = bulk_import_start(pb); +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c +index 232af54..eeae22b 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c +@@ -865,6 +865,26 @@ static int ldbm_config_db_private_mem_set(void *arg, void *value, char *errorbuf + return retval; + } + ++static void *ldbm_config_db_online_import_encrypt_get(void *arg) ++{ ++ struct ldbminfo *li = (struct ldbminfo *) arg; ++ ++ return (void *) ((uintptr_t)li->li_online_import_encrypt); ++} ++ ++static int ldbm_config_db_online_import_encrypt_set(void *arg, void *value, char *errorbuf, int phase, int apply) ++{ ++ struct ldbminfo *li = (struct ldbminfo *) arg; ++ int retval = LDAP_SUCCESS; ++ int val = (int) ((uintptr_t)value); ++ ++ if (apply) { ++ li->li_online_import_encrypt = val; ++ } ++ ++ return retval; ++} ++ + static void *ldbm_config_db_private_import_mem_get(void *arg) + { + struct ldbminfo *li = (struct ldbminfo *) arg; +@@ -1339,6 +1359,7 @@ static config_info ldbm_config[] = { + {CONFIG_DB_LOCK, CONFIG_TYPE_INT, "10000", &ldbm_config_db_lock_get, &ldbm_config_db_lock_set, 0}, + {CONFIG_DB_PRIVATE_MEM, CONFIG_TYPE_ONOFF, "off", &ldbm_config_db_private_mem_get, &ldbm_config_db_private_mem_set, 0}, + {CONFIG_DB_PRIVATE_IMPORT_MEM, CONFIG_TYPE_ONOFF, "on", &ldbm_config_db_private_import_mem_get, &ldbm_config_db_private_import_mem_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, ++ {CONDIF_DB_ONLINE_IMPORT_ENCRYPT, CONFIG_TYPE_ONOFF, "on", &ldbm_config_db_online_import_encrypt_get, &ldbm_config_db_online_import_encrypt_set, 0}, + {CONFIG_DB_SHM_KEY, CONFIG_TYPE_LONG, "389389", &ldbm_config_db_shm_key_get, &ldbm_config_db_shm_key_set, 0}, + {CONFIG_DB_CACHE, CONFIG_TYPE_INT, "0", &ldbm_config_db_cache_get, &ldbm_config_db_cache_set, 0}, + {CONFIG_DB_DEBUG_CHECKPOINTING, CONFIG_TYPE_ONOFF, "off", &ldbm_config_db_debug_checkpointing_get, &ldbm_config_db_debug_checkpointing_set, 0}, +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.h b/ldap/servers/slapd/back-ldbm/ldbm_config.h +index a5830e3..33eb078 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_config.h ++++ b/ldap/servers/slapd/back-ldbm/ldbm_config.h +@@ -136,6 +136,7 @@ struct config_info { + #define CONFIG_DB_HOME_DIRECTORY "nsslapd-db-home-directory" + #define CONFIG_DB_LOCKDOWN "nsslapd-db-lockdown" + #define CONFIG_DB_TX_MAX "nsslapd-db-tx-max" ++#define CONDIF_DB_ONLINE_IMPORT_ENCRYPT "nsslapd-online-import-encrypt" + + #define CONFIG_IDL_SWITCH "nsslapd-idl-switch" + #define CONFIG_BYPASS_FILTER_TEST "nsslapd-search-bypass-filter-test" +-- +1.8.1.4 + diff --git a/0075-Ticket-47410-changelog-db-deadlocks-with-DNA-and-rep.patch b/0075-Ticket-47410-changelog-db-deadlocks-with-DNA-and-rep.patch new file mode 100644 index 0000000..c96bbfb --- /dev/null +++ b/0075-Ticket-47410-changelog-db-deadlocks-with-DNA-and-rep.patch @@ -0,0 +1,115 @@ +From 3712b35b7a61154be53649341885f49dce2820f4 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 26 Jun 2013 13:35:39 -0600 +Subject: [PATCH 75/99] Ticket #47410 - changelog db deadlocks with DNA and + replication + +https://fedorahosted.org/389/ticket/47410 +Reviewed by: mreynolds (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: The deadlock is caused by having an outer and an inner +transaction in one thread, and a replication reader in another thread. The +outer transaction acquires a write lock on certain changelog db (cldb) pages +as a result of a previous nested transaction (e.g. a DNA shared config +area update). The changelog reader in the cursor positioning operation +acquires read locks on certain other pages. When another inner write +transaction occurs, it may attempt to acquire a write lock on a page held +by a read lock in the reader thread. This will eventually fail because +the reader will not release its lock on the page until the outer transaction +releases the write lock on the page. +The solution is to change the way the deadlock detection thread works, to +use a different deadlock rejection policy. When using DB_LOCK_MINWRITE +instead of the default DB_LOCK_YOUNGEST, the reader thread lock request is +rejected. This means the code that positions the changelog cursor has to be +able to handle a DB_LOCK_DEADLOCK return. +Changing the deadlock rejection policy globally to DB_LOCK_MINWRITE has the +potential to cause any search to get a DB_LOCK_DEADLOCK from a db or cursor +get(), so this will need to be tested a great deal to make sure we can handle +all such cases. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit b573d80d9c3acc6dba1bd60bdf7bf3fe4f4168df) +(cherry picked from commit 2e1d6331a294378650bef9af8a5f24bd338ae01e) +(cherry picked from commit 1987727066e6248cac978139779193d0f56ff9ce) +(cherry picked from commit 489de18b135c4019d93a3cf89a108b2c3c4cc3d9) +--- + ldap/servers/plugins/replication/cl5.h | 2 ++ + ldap/servers/plugins/replication/cl5_api.c | 1 - + ldap/servers/plugins/replication/cl5_clcache.c | 20 +++++++++++++++++++- + 3 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/ldap/servers/plugins/replication/cl5.h b/ldap/servers/plugins/replication/cl5.h +index 4c92ecd..33f8140 100644 +--- a/ldap/servers/plugins/replication/cl5.h ++++ b/ldap/servers/plugins/replication/cl5.h +@@ -73,4 +73,6 @@ void changelog5_config_done (changelog5Config *config); + /* frees the content and the config structure */ + void changelog5_config_free (changelog5Config **config); + ++#define MAX_TRIALS 50 /* number of retries on db operations */ ++ + #endif +diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c +index 175eb80..e24cead 100644 +--- a/ldap/servers/plugins/replication/cl5_api.c ++++ b/ldap/servers/plugins/replication/cl5_api.c +@@ -67,7 +67,6 @@ + + #define GUARDIAN_FILE "guardian" /* name of the guardian file */ + #define VERSION_FILE "DBVERSION" /* name of the version file */ +-#define MAX_TRIALS 50 /* number of retries on db operations */ + #define V_5 5 /* changelog entry version */ + #define CHUNK_SIZE 64*1024 + #define DBID_SIZE 64 +diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c +index 202cb64..5329b4b 100644 +--- a/ldap/servers/plugins/replication/cl5_clcache.c ++++ b/ldap/servers/plugins/replication/cl5_clcache.c +@@ -380,6 +380,7 @@ clcache_load_buffer_bulk ( CLC_Buffer *buf, int flag ) + DB_TXN *txn = NULL; + DBC *cursor = NULL; + int rc = 0; ++ int tries = 0; + + #if 0 /* txn control seems not improving anything so turn it off */ + if ( *(_pool->pl_dbenv) ) { +@@ -401,6 +402,7 @@ clcache_load_buffer_bulk ( CLC_Buffer *buf, int flag ) + } + + PR_Lock ( buf->buf_busy_list->bl_lock ); ++retry: + if ( 0 == ( rc = clcache_open_cursor ( txn, buf, &cursor )) ) { + + if ( flag == DB_NEXT ) { +@@ -422,10 +424,26 @@ clcache_load_buffer_bulk ( CLC_Buffer *buf, int flag ) + + /* + * Don't keep a cursor open across the whole replication session. +- * That had caused noticable DB resource contention. ++ * That had caused noticeable DB resource contention. + */ + if ( cursor ) { + cursor->c_close ( cursor ); ++ cursor = NULL; ++ } ++ if ((rc == DB_LOCK_DEADLOCK) && (tries < MAX_TRIALS)) { ++ PRIntervalTime interval; ++ ++ tries++; ++ slapi_log_error ( SLAPI_LOG_TRACE, "clcache_load_buffer_bulk", ++ "deadlock number [%d] - retrying\n", tries ); ++ /* back off */ ++ interval = PR_MillisecondsToInterval(slapi_rand() % 100); ++ DS_Sleep(interval); ++ goto retry; ++ } ++ if ((rc == DB_LOCK_DEADLOCK) && (tries >= MAX_TRIALS)) { ++ slapi_log_error ( SLAPI_LOG_REPL, "clcache_load_buffer_bulk", ++ "could not load buffer from changelog after %d tries\n", tries ); + } + + #if 0 /* txn control seems not improving anything so turn it off */ +-- +1.8.1.4 + diff --git a/0076-Ticket-47402-Attribute-names-are-incorrect-in-search.patch b/0076-Ticket-47402-Attribute-names-are-incorrect-in-search.patch new file mode 100644 index 0000000..6a2ba0e --- /dev/null +++ b/0076-Ticket-47402-Attribute-names-are-incorrect-in-search.patch @@ -0,0 +1,52 @@ +From 336aedd43f38447e8b9868d2789cf2b083b88894 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 20 Jun 2013 14:05:35 -0700 +Subject: [PATCH 76/99] Ticket #47402 - Attribute names are incorrect in search + results + +Bug Description: Attribute list given by a client to ldapsearch +is first copied to op->o_searchattrs to respect the client input. +Then the attribute types are normalized and if the list contains +any forbidden attributes, they are removed from the list. When +the search result is returned, the internal normalized attribute +types are replaced with the original input op->o_searchattrs, +respectively. Since forbidden attributes are in op->o_searchattrs +but not in the internal attribute list, wrong type from copy is +associated to the value and returned to the client. + +Fix Description: This patch removes the forbidden attribute +before copying the original attribute list to op->o_searchattrs. + +https://fedorahosted.org/389/ticket/47402 + +Reviewed by Nathan (Thank you!!) +(cherry picked from commit 29236cd1000f5f9391db4a39511603b8bed707f2) +--- + ldap/servers/slapd/search.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c +index 7719727..1a824b2 100644 +--- a/ldap/servers/slapd/search.c ++++ b/ldap/servers/slapd/search.c +@@ -329,6 +329,8 @@ do_search( Slapi_PBlock *pb ) + gerattrs[gerattridx] = NULL; + } + ++ /* Set attrs to SLAPI_SEARCH_ATTRS once to get rid of the forbidden attrs */ ++ slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS, attrs ); + operation->o_searchattrs = cool_charray_dup( attrs ); + for ( i = 0; attrs[i] != NULL; i++ ) { + char *type; +@@ -338,7 +340,7 @@ do_search( Slapi_PBlock *pb ) + attrs[i] = type; + } + } +- if ( slapd_ldap_debug & LDAP_DEBUG_ARGS ) { ++ if ( slapd_ldap_debug & LDAP_DEBUG_ARGS ) { + char abuf[ 1024 ], *astr; + + if ( NULL == attrs ) { +-- +1.8.1.4 + diff --git a/0077-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch b/0077-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch new file mode 100644 index 0000000..e77bde1 --- /dev/null +++ b/0077-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch @@ -0,0 +1,163 @@ +From dd322d94a9449915e511b07a5bd0c342e5f72b63 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Tue, 25 Jun 2013 19:48:17 -0600 +Subject: [PATCH 77/99] Ticket #47409 - allow setting db deadlock rejection + policy + +https://fedorahosted.org/389/ticket/47409 +Reviewed by: nhosoi (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: Add the db config attribute nsslapd-db-deadlock-policy. This +takes values from 1-9. The values correspond to the deadlock detector modes +in db.h. These are the valid values to pass to the DBENV->lock_detect +method for the atype parameter. The default value is 9 (DB_LOCK_YOUNGEST) - +select the youngest locker and reject it. A value of 0 (DB_LOCK_NORUN) means +to disable deadlock detection and rejection - not recommended except for +testing purposes. Attempting to use other values will cause an error. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: yes - document new config parameter +(cherry picked from commit d62cd9b69c8a4a852e7bea0345285dc8c3e1e547) +(cherry picked from commit 42a3ef2644d31355da4d82e1f11b2b2eada554a7) +(cherry picked from commit f7548908d4749db429f17e23c01624475c121def) +--- + ldap/servers/slapd/back-ldbm/dblayer.c | 19 +++++++++++----- + ldap/servers/slapd/back-ldbm/dblayer.h | 1 + + ldap/servers/slapd/back-ldbm/ldbm_config.c | 35 ++++++++++++++++++++++++++++++ + ldap/servers/slapd/back-ldbm/ldbm_config.h | 2 ++ + ldap/servers/slapd/slapi-plugin.h | 3 +++ + 5 files changed, 54 insertions(+), 6 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c +index 2fd2110..85e4a18 100644 +--- a/ldap/servers/slapd/back-ldbm/dblayer.c ++++ b/ldap/servers/slapd/back-ldbm/dblayer.c +@@ -4206,6 +4206,7 @@ static int deadlock_threadmain(void *param) + dblayer_private *priv = NULL; + struct ldbminfo *li = NULL; + PRIntervalTime interval; /*NSPR timeout stuffy*/ ++ u_int32_t flags = 0; + + PR_ASSERT(NULL != param); + li = (struct ldbminfo*)param; +@@ -4220,13 +4221,19 @@ static int deadlock_threadmain(void *param) + { + if (priv->dblayer_enable_transactions) + { +- if (dblayer_db_uses_locking(priv->dblayer_env->dblayer_DB_ENV)) { +- int aborted; +- if ((rval = LOCK_DETECT(priv->dblayer_env->dblayer_DB_ENV, +- 0, DB_LOCK_YOUNGEST, &aborted)) != 0) { ++ DB_ENV *db_env = priv->dblayer_env->dblayer_DB_ENV; ++ u_int32_t deadlock_policy = priv->dblayer_deadlock_policy; ++ ++ if (dblayer_db_uses_locking(db_env) && (deadlock_policy > DB_LOCK_NORUN)) { ++ int rejected = 0; ++ ++ if ((rval = LOCK_DETECT(db_env, 0, deadlock_policy, &rejected)) != 0) { + LDAPDebug(LDAP_DEBUG_ANY, +- "Serious Error---Failed in deadlock detect (aborted at 0x%x), err=%d (%s)\n", +- aborted, rval, dblayer_strerror(rval)); ++ "Serious Error---Failed in deadlock detect (aborted at 0x%x), err=%d (%s)\n", ++ rejected, rval, dblayer_strerror(rval)); ++ } else if (rejected) { ++ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "deadlock_threadmain: found and rejected %d lock requests\n", rejected); ++ + } + } + } +diff --git a/ldap/servers/slapd/back-ldbm/dblayer.h b/ldap/servers/slapd/back-ldbm/dblayer.h +index ab9a85d..7f3200c 100644 +--- a/ldap/servers/slapd/back-ldbm/dblayer.h ++++ b/ldap/servers/slapd/back-ldbm/dblayer.h +@@ -178,6 +178,7 @@ struct dblayer_private + PRCondVar *thread_count_cv; /* condition variable for housekeeping thread shutdown */ + int dblayer_lockdown; /* use DB_LOCKDOWN */ + int dblayer_lock_config; ++ u_int32_t dblayer_deadlock_policy; /* i.e. the atype to DB_ENV->lock_detect in deadlock_threadmain */ + }; + + #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4300 +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c +index eeae22b..44ccf78 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c +@@ -1326,6 +1326,40 @@ static int ldbm_config_db_tx_max_set( + return retval; + } + ++static void *ldbm_config_db_deadlock_policy_get(void *arg) ++{ ++ struct ldbminfo *li = (struct ldbminfo *) arg; ++ ++ return (void *) ((uintptr_t)li->li_dblayer_private->dblayer_deadlock_policy); ++} ++ ++static int ldbm_config_db_deadlock_policy_set(void *arg, void *value, char *errorbuf, int phase, int apply) ++{ ++ struct ldbminfo *li = (struct ldbminfo *) arg; ++ int retval = LDAP_SUCCESS; ++ u_int32_t val = (u_int32_t) ((uintptr_t)value); ++ ++ if ((val < DB_LOCK_NORUN) || (val > DB_LOCK_YOUNGEST)) { ++ PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, ++ "Error: Invalid value for %s (%d). Must be between %d and %d inclusive", ++ CONFIG_DB_DEADLOCK_POLICY, val, DB_LOCK_DEFAULT, DB_LOCK_YOUNGEST); ++ LDAPDebug1Arg(LDAP_DEBUG_ANY, "%s\n", errorbuf); ++ return LDAP_UNWILLING_TO_PERFORM; ++ } ++ if (val == DB_LOCK_NORUN) { ++ PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, ++ "Warning: Setting value for %s to (%d) will disable deadlock detection", ++ CONFIG_DB_DEADLOCK_POLICY, val); ++ LDAPDebug1Arg(LDAP_DEBUG_ANY, "%s\n", errorbuf); ++ } ++ ++ if (apply) { ++ li->li_dblayer_private->dblayer_deadlock_policy = val; ++ } ++ ++ return retval; ++} ++ + + /*------------------------------------------------------------------------ + * Configuration array for ldbm and dblayer variables +@@ -1385,6 +1419,7 @@ static config_info ldbm_config[] = { + {CONFIG_PAGEDLOOKTHROUGHLIMIT, CONFIG_TYPE_INT, "0", &ldbm_config_pagedlookthroughlimit_get, &ldbm_config_pagedlookthroughlimit_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, + {CONFIG_PAGEDIDLISTSCANLIMIT, CONFIG_TYPE_INT, "0", &ldbm_config_pagedallidsthreshold_get, &ldbm_config_pagedallidsthreshold_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, + {CONFIG_RANGELOOKTHROUGHLIMIT, CONFIG_TYPE_INT, "5000", &ldbm_config_rangelookthroughlimit_get, &ldbm_config_rangelookthroughlimit_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, ++ {CONFIG_DB_DEADLOCK_POLICY, CONFIG_TYPE_INT, STRINGIFYDEFINE(DB_LOCK_YOUNGEST), &ldbm_config_db_deadlock_policy_get, &ldbm_config_db_deadlock_policy_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, + {NULL, 0, NULL, NULL, NULL, 0} + }; + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.h b/ldap/servers/slapd/back-ldbm/ldbm_config.h +index 33eb078..553d387 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_config.h ++++ b/ldap/servers/slapd/back-ldbm/ldbm_config.h +@@ -159,6 +159,8 @@ struct config_info { + + #define CONFIG_USE_LEGACY_ERRORCODE "nsslapd-do-not-use-vlv-error" + ++#define CONFIG_DB_DEADLOCK_POLICY "nsslapd-db-deadlock-policy" ++ + #define CONFIG_LDBM_DN "cn=config,cn=ldbm database,cn=plugins,cn=config" + + #define LDBM_INSTANCE_CONFIG_DONT_WRITE 1 +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h +index 0f69c0a..5b3e1ab 100644 +--- a/ldap/servers/slapd/slapi-plugin.h ++++ b/ldap/servers/slapd/slapi-plugin.h +@@ -107,6 +107,9 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...) + #define BERLEN_T "u" + #endif + ++#define DEFINETOSTR(xxx) #xxx ++#define STRINGIFYDEFINE(xxx) DEFINETOSTR(xxx) ++ + /* Common check on berval before accessing the contents. */ + /* bv is a struct berval *bv */ + #define BV_HAS_DATA(bv) ((bv != NULL) && (bv->bv_len > 0) && (bv->bv_val != NULL)) +-- +1.8.1.4 + diff --git a/0078-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch b/0078-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch new file mode 100644 index 0000000..9d49a6e --- /dev/null +++ b/0078-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch @@ -0,0 +1,37 @@ +From ab4b93abbf08e172825ce13daed4e586b49ec212 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Fri, 28 Jun 2013 11:37:05 -0600 +Subject: [PATCH 78/99] Ticket #47409 - allow setting db deadlock rejection + policy + +https://fedorahosted.org/389/ticket/47409 +Reviewed by: nhosoi (Thanks!) +Branch: master +Fix Description: Forgot to add flags parameter to last commit. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: yes - document new config parameter +(cherry picked from commit 67cbb2eac1300ae57acf75f4c3299103046a3323) +(cherry picked from commit ceaa9ac5267c04c23e3fb8e366e17295ffd6b93c) +(cherry picked from commit e535ff5a45601c4279a14e92eaf1d68729866d38) +(cherry picked from commit 6c1a71310292e5992aa1fcc8c203a6b6d595ebe3) +--- + ldap/servers/slapd/back-ldbm/dblayer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c +index 85e4a18..8696834 100644 +--- a/ldap/servers/slapd/back-ldbm/dblayer.c ++++ b/ldap/servers/slapd/back-ldbm/dblayer.c +@@ -4227,7 +4227,7 @@ static int deadlock_threadmain(void *param) + if (dblayer_db_uses_locking(db_env) && (deadlock_policy > DB_LOCK_NORUN)) { + int rejected = 0; + +- if ((rval = LOCK_DETECT(db_env, 0, deadlock_policy, &rejected)) != 0) { ++ if ((rval = LOCK_DETECT(db_env, flags, deadlock_policy, &rejected)) != 0) { + LDAPDebug(LDAP_DEBUG_ANY, + "Serious Error---Failed in deadlock detect (aborted at 0x%x), err=%d (%s)\n", + rejected, rval, dblayer_strerror(rval)); +-- +1.8.1.4 + diff --git a/0079-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch b/0079-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch new file mode 100644 index 0000000..d0038f4 --- /dev/null +++ b/0079-Ticket-47409-allow-setting-db-deadlock-rejection-pol.patch @@ -0,0 +1,38 @@ +From 2dd6692669017c97d488a511caafa39d994ed14a Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Tue, 2 Jul 2013 14:40:00 -0600 +Subject: [PATCH 79/99] Ticket #47409 - allow setting db deadlock rejection + policy + +https://fedorahosted.org/389/ticket/47409 +Reviewed by: nhosoi (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: Fix coverity CID 11893 (#1 of 1): Unsigned compared against 0 (NO_EFFECT) +val is u_int32_t which is never less than 0 +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: yes - document new config parameter +(cherry picked from commit 989a30bb2d63ee6b9157a9eb6a3d2ff6828abc60) +(cherry picked from commit 75b9e42a6555073d902526c20a606d17fd11f967) +(cherry picked from commit 1baa10dd3c14c6cdc29aae5d114547df812b5c17) +(cherry picked from commit d1aef99989c498cde20fc311b05780702efee653) +--- + ldap/servers/slapd/back-ldbm/ldbm_config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c +index 44ccf78..b713f73 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c +@@ -1339,7 +1339,7 @@ static int ldbm_config_db_deadlock_policy_set(void *arg, void *value, char *erro + int retval = LDAP_SUCCESS; + u_int32_t val = (u_int32_t) ((uintptr_t)value); + +- if ((val < DB_LOCK_NORUN) || (val > DB_LOCK_YOUNGEST)) { ++ if (val > DB_LOCK_YOUNGEST) { + PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, + "Error: Invalid value for %s (%d). Must be between %d and %d inclusive", + CONFIG_DB_DEADLOCK_POLICY, val, DB_LOCK_DEFAULT, DB_LOCK_YOUNGEST); +-- +1.8.1.4 + diff --git a/0080-Ticket-47424-Replication-problem-with-add-delete-req.patch b/0080-Ticket-47424-Replication-problem-with-add-delete-req.patch new file mode 100644 index 0000000..fc6086b --- /dev/null +++ b/0080-Ticket-47424-Replication-problem-with-add-delete-req.patch @@ -0,0 +1,342 @@ +From 3aac2e421bb6c2543b2ff2795664ba50a7ceeec9 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 17 Jul 2013 17:51:36 -0600 +Subject: [PATCH 80/99] Ticket #47424 - Replication problem with add-delete + requests on single-valued attributes + +https://fedorahosted.org/389/ticket/47424 +Reviewed by: lkrispenz (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: Change the single master resolve attr code to handle the +specific case of doing +add: newvalue +delete: oldvalue +Had to add a new API function - csn_compare_ext - to be able to compare CSNs +without the subsequence number. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit bf53a29af973648c520b005ad37f7a83db4b905b) +--- + ldap/servers/slapd/csn.c | 12 +++- + ldap/servers/slapd/entrywsi.c | 122 +++++++++++++++++++++---------------- + ldap/servers/slapd/slapi-private.h | 2 + + 3 files changed, 83 insertions(+), 53 deletions(-) + +diff --git a/ldap/servers/slapd/csn.c b/ldap/servers/slapd/csn.c +index 9fb5b4a..5c31689 100644 +--- a/ldap/servers/slapd/csn.c ++++ b/ldap/servers/slapd/csn.c +@@ -298,7 +298,7 @@ csn_as_attr_option_string(CSNType t,const CSN *csn,char *ss) + } + + int +-csn_compare(const CSN *csn1, const CSN *csn2) ++csn_compare_ext(const CSN *csn1, const CSN *csn2, unsigned int flags) + { + PRInt32 retVal; + if(csn1!=NULL && csn2!=NULL) +@@ -321,7 +321,7 @@ csn_compare(const CSN *csn1, const CSN *csn2) + retVal = -1; + else if (csn1->rid > csn2->rid) + retVal = 1; +- else ++ else if (!(flags & CSN_COMPARE_SKIP_SUBSEQ)) + { + if (csn1->subseqnum < csn2->subseqnum) + retVal = -1; +@@ -330,6 +330,8 @@ csn_compare(const CSN *csn1, const CSN *csn2) + else + retVal = 0; + } ++ else ++ retVal = 0; + } + } + +@@ -350,6 +352,12 @@ csn_compare(const CSN *csn1, const CSN *csn2) + return(retVal); + } + ++int ++csn_compare(const CSN *csn1, const CSN *csn2) ++{ ++ return csn_compare_ext(csn1, csn2, 0); ++} ++ + time_t csn_time_difference(const CSN *csn1, const CSN *csn2) + { + return csn_get_time(csn1) - csn_get_time(csn2); +diff --git a/ldap/servers/slapd/entrywsi.c b/ldap/servers/slapd/entrywsi.c +index 971e9e3..6c37f45 100644 +--- a/ldap/servers/slapd/entrywsi.c ++++ b/ldap/servers/slapd/entrywsi.c +@@ -423,8 +423,8 @@ static int + entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags) + { + int retVal= LDAP_SUCCESS; +- Slapi_Value **valuestoadd = NULL; +- valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */ ++ Slapi_Value **valuestoadd = NULL; ++ valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */ + if(!valuearray_isempty(valuestoadd)) + { + Slapi_Attr *a= NULL; +@@ -437,7 +437,7 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **b + slapi_attr_init(a, type); + attrlist_add(&e->e_attrs, a); + } +- a_flags_orig = a->a_flags; ++ a_flags_orig = a->a_flags; + a->a_flags |= flags; + /* Check if the type of the to-be-added values has DN syntax or not. */ + if (slapi_attr_is_dn_syntax_attr(a)) { +@@ -558,8 +558,8 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval + else + { + /* delete some specific values */ +- Slapi_Value **valuestodelete= NULL; +- valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */ ++ Slapi_Value **valuestodelete= NULL; ++ valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */ + /* Check if the type of the to-be-deleted values has DN syntax + * or not. */ + if (slapi_attr_is_dn_syntax_attr(a)) { +@@ -575,8 +575,7 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval + there are present values with a later CSN - otherwise, even though + the value will be updated with a VDCSN which is later than the VUCSN, + the attribute will not be deleted */ +- if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE) && valuesupdated && +- *valuesupdated) ++ if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE) && valueset_isempty(&a->a_present_values)) + { + attr_set_deletion_csn(a,csn); + } +@@ -626,8 +625,8 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval + if ( retVal==LDAP_OPERATIONS_ERROR ) + { + LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate " +- "value for attribute type %s found in " +- "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 ); ++ "value for attribute type %s found in " ++ "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 ); + } + } + valuearray_free(&valuestodelete); +@@ -683,7 +682,7 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval + will add it back to the present list in the non urp case, + or determine if the attribute needs to be added + or not in the urp case +- */ ++ */ + entry_add_deleted_attribute_wsi(e, a); + } + } +@@ -1103,6 +1102,7 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu + Slapi_Value *new_value= NULL; + const CSN *current_value_vucsn; + const CSN *pending_value_vucsn; ++ const CSN *pending_value_vdcsn; + const CSN *adcsn; + int i; + +@@ -1116,27 +1116,47 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu + slapi_attr_next_value(a,i,&new_value); + } + attr_first_deleted_value(a,&pending_value); +- + /* purge_attribute_state_single_valued */ + adcsn= attr_get_deletion_csn(a); + current_value_vucsn= value_get_csn(current_value, CSN_TYPE_VALUE_UPDATED); + pending_value_vucsn= value_get_csn(pending_value, CSN_TYPE_VALUE_UPDATED); +- if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) || +- (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0))) ++ pending_value_vdcsn= value_get_csn(pending_value, CSN_TYPE_VALUE_DELETED); ++ if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) || ++ (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0))) + { + attr_set_deletion_csn(a,NULL); + adcsn= NULL; +- } ++ } + +- if(new_value==NULL) ++ /* in the case of the following: ++ * add: value2 ++ * delete: value1 ++ * we will have current_value with VUCSN CSN1 ++ * and pending_value with VDCSN CSN2 ++ * and new_value == NULL ++ * current_value != pending_value ++ * and ++ * VUCSN == VDCSN (ignoring subseq) ++ * even though value1.VDCSN > value2.VUCSN ++ * value2 should still win because the value is _different_ ++ */ ++ if (current_value && pending_value && !new_value && !adcsn && ++ (0 != slapi_value_compare(a, current_value, pending_value)) && ++ (0 == csn_compare_ext(current_value_vucsn, pending_value_vdcsn, CSN_COMPARE_SKIP_SUBSEQ))) + { +- /* check if the pending value should become the current value */ +- if(pending_value!=NULL) ++ /* just remove the deleted value */ ++ entry_deleted_value_to_zapped_value(a,pending_value); ++ pending_value = NULL; ++ } ++ else if(new_value==NULL) ++ { ++ /* check if the pending value should become the current value */ ++ if(pending_value!=NULL) + { + if(!value_distinguished_at_csn(e,a,current_value,pending_value_vucsn)) + { +- /* attribute.current_value = attribute.pending_value; */ +- /* attribute.pending_value = NULL; */ ++ /* attribute.current_value = attribute.pending_value; */ ++ /* attribute.pending_value = NULL; */ + entry_present_value_to_zapped_value(a,current_value); + entry_deleted_value_to_present_value(a,pending_value); + current_value= pending_value; +@@ -1145,12 +1165,12 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu + pending_value_vucsn= NULL; + } + } +- /* check if the current value should be deleted */ +- if(current_value!=NULL) ++ /* check if the current value should be deleted */ ++ if(current_value!=NULL) + { + if(csn_compare(adcsn,current_value_vucsn)>0) /* check if the attribute was deleted after the value was last updated */ + { +- if(!value_distinguished_at_csn(e,a,current_value,current_value_vucsn)) ++ if(!value_distinguished_at_csn(e,a,current_value,current_value_vucsn)) + { + entry_present_value_to_zapped_value(a,current_value); + current_value= NULL; +@@ -1162,17 +1182,17 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu + else /* addition of a new value */ + { + const CSN *new_value_vucsn= value_get_csn(new_value,CSN_TYPE_VALUE_UPDATED); +- if(csn_compare(new_value_vucsn,current_value_vucsn)<0) ++ if(csn_compare(new_value_vucsn,current_value_vucsn)<0) + { +- /* +- * if the new value was distinguished at the time the current value was added +- * then the new value should become current +- */ +- if(value_distinguished_at_csn(e,a,new_value,current_value_vucsn)) ++ /* ++ * if the new value was distinguished at the time the current value was added ++ * then the new value should become current ++ */ ++ if(value_distinguished_at_csn(e,a,new_value,current_value_vucsn)) + { +- /* attribute.pending_value = attribute.current_value */ +- /* attribute.current_value = new_value */ +- if(pending_value==NULL) ++ /* attribute.pending_value = attribute.current_value */ ++ /* attribute.current_value = new_value */ ++ if(pending_value==NULL) + { + entry_present_value_to_deleted_value(a,current_value); + } +@@ -1188,63 +1208,63 @@ resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribu + } + else + { +- /* new_value= NULL */ ++ /* new_value= NULL */ + entry_present_value_to_zapped_value(a, new_value); + new_value= NULL; + } + } +- else /* new value is after the current value */ ++ else /* new value is after the current value */ + { +- if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn)) ++ if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn)) + { +- /* attribute.current_value = new_value */ ++ /* attribute.current_value = new_value */ + entry_present_value_to_zapped_value(a, current_value); + current_value= new_value; + new_value= NULL; + current_value_vucsn= new_value_vucsn; + } +- else /* value is distinguished - check if we should replace the current pending value */ ++ else /* value is distinguished - check if we should replace the current pending value */ + { +- if(csn_compare(new_value_vucsn, pending_value_vucsn)>0) ++ if(csn_compare(new_value_vucsn, pending_value_vucsn)>0) + { +- /* attribute.pending_value = new_value */ ++ /* attribute.pending_value = new_value */ + entry_deleted_value_to_zapped_value(a,pending_value); + entry_present_value_to_deleted_value(a,new_value); + pending_value= new_value; + new_value= NULL; + pending_value_vucsn= new_value_vucsn; +- } +- } +- } +- } ++ } ++ } ++ } ++ } + +- /* +- * This call ensures that the attribute does not have a pending_value ++ /* ++ * This call ensures that the attribute does not have a pending_value + * or a deletion_csn that is earlier than the current_value. + */ + /* purge_attribute_state_single_valued */ +- if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) || +- (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0))) ++ if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) || ++ (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0))) + { + attr_set_deletion_csn(a,NULL); + adcsn= NULL; +- } ++ } + +- /* set attribute state */ +- if(current_value==NULL) ++ /* set attribute state */ ++ if(current_value==NULL) + { + if(attribute_state==ATTRIBUTE_PRESENT) + { + entry_present_attribute_to_deleted_attribute(e, a); + } + } +- else ++ else + { + if(attribute_state==ATTRIBUTE_DELETED) + { + entry_deleted_attribute_to_present_attribute(e, a); + } +- } ++ } + } + + static void +diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h +index ddeac62..1efbc8b 100644 +--- a/ldap/servers/slapd/slapi-private.h ++++ b/ldap/servers/slapd/slapi-private.h +@@ -196,6 +196,8 @@ PRUint16 csn_get_seqnum(const CSN *csn); + PRUint16 csn_get_subseqnum(const CSN *csn); + char *csn_as_string(const CSN *csn, PRBool replicaIdOrder, char *ss); /* WARNING: ss must be CSN_STRSIZE bytes, or NULL. */ + int csn_compare(const CSN *csn1, const CSN *csn2); ++int csn_compare_ext(const CSN *csn1, const CSN *csn2, unsigned int flags); ++#define CSN_COMPARE_SKIP_SUBSEQ 0x1 + time_t csn_time_difference(const CSN *csn1, const CSN *csn2); + size_t csn_string_size(); + char *csn_as_attr_option_string(CSNType t,const CSN *csn,char *ss); +-- +1.8.1.4 + diff --git a/0081-Ticket-47428-Memory-leak-in-389-ds-base-1.2.11.15.patch b/0081-Ticket-47428-Memory-leak-in-389-ds-base-1.2.11.15.patch new file mode 100644 index 0000000..c404b6b --- /dev/null +++ b/0081-Ticket-47428-Memory-leak-in-389-ds-base-1.2.11.15.patch @@ -0,0 +1,68 @@ +From ef6e05286dbd4df3bc20cee51b1769496612a7af Mon Sep 17 00:00:00 2001 +From: Matthew Via <​matthew.via@mailtrust.com> +Date: Wed, 10 Jul 2013 11:30:57 -0600 +Subject: [PATCH 81/99] Ticket #47428 - Memory leak in 389-ds-base 1.2.11.15 + +https://fedorahosted.org/389/ticket/47428 +Reviewed by: rmeggins +Branch: 389-ds-base-1.2.11 +Fix Description: Call ber_sockbuf_remove_io to remove our openldap io layer +from the connection c_sb and free the data associated with it. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit df93b03da12c22d18a4153105f687671e52efdd5) +(cherry picked from commit ed26da0722a23a50fb286e8bc57ec4fea8dde4a2) +(cherry picked from commit b18ee0b41fbcc901ed2a9b5c0431708e452a40c6) +(cherry picked from commit 6e0a8efb16a1651387623ce997c021f0460d2788) +--- + ldap/servers/slapd/connection.c | 1 + + ldap/servers/slapd/daemon.c | 7 +++++++ + ldap/servers/slapd/proto-slap.h | 1 + + 3 files changed, 9 insertions(+) + +diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c +index 1d1adac..914a2d3 100644 +--- a/ldap/servers/slapd/connection.c ++++ b/ldap/servers/slapd/connection.c +@@ -203,6 +203,7 @@ connection_cleanup(Connection *conn) + /* destroy any sasl context */ + sasl_dispose((sasl_conn_t**)&conn->c_sasl_conn); + /* PAGED_RESULTS */ ++ handle_closed_connection(conn); /* Clean up sockbufs */ + pagedresults_cleanup(conn, 0 /* do not need to lock inside */); + + /* free the connection socket buffer */ +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index c67067b..8f147f1 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -2590,6 +2590,13 @@ bail: + #endif /* ENABLE_AUTOBIND */ + #endif /* ENABLE_LDAPI */ + ++void ++handle_closed_connection(Connection *conn) ++{ ++ ber_sockbuf_remove_io(conn->c_sb, &openldap_sockbuf_io, ++ LBER_SBIOD_LEVEL_PROVIDER); ++} ++ + /* NOTE: this routine is not reentrant */ + static int + handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, int secure, int local) +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index a15c0cc..d4c9ab6 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -1379,6 +1379,7 @@ int sasl_io_setup(Connection *c); + /* + * daemon.c + */ ++void handle_closed_connection(Connection *); + #ifndef LINUX + void slapd_do_nothing(int); + #endif +-- +1.8.1.4 + diff --git a/0082-Ticket-47378-fix-recent-compiler-warnings.patch b/0082-Ticket-47378-fix-recent-compiler-warnings.patch new file mode 100644 index 0000000..e50868d --- /dev/null +++ b/0082-Ticket-47378-fix-recent-compiler-warnings.patch @@ -0,0 +1,713 @@ +From 45a86b895601644b624d27484933735d7e665a66 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 5 Jun 2013 11:30:13 -0600 +Subject: [PATCH 82/99] Ticket #47378 - fix recent compiler warnings + +https://fedorahosted.org/389/ticket/47378 +Reviewed by: nhosoi (Thanks!) +Branch: master +Fix Description: Fix the various compiler warnings as reported by +http://jenkins.cloud.fedoraproject.org/job/389-ds-base/ws/build-warns.1370449480.txt +In addition, fixed a bug in the slapi_re_subs_ext - if there was an +ampersand that did not need to be replaced, that is, if the ampersand +was part of an LDAP search filter, it was replaced with a '('. Also, an +ampersand preceeded by an open parenthesis and followed by a non-open +parenthesis is supposed to be replaced in the string, but this was not +working. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 0dc230b007dc3ad292961f378421b03736b68f9e) +(cherry picked from commit 79739bdfba251ed6445ae4a16e90a471ca3f7b94) +--- + .../plugins/acct_usability/acct_usability.c | 2 +- + ldap/servers/plugins/acl/acl_ext.c | 2 +- + ldap/servers/plugins/acl/aclutil.c | 3 ++- + ldap/servers/plugins/automember/automember.c | 3 ++- + ldap/servers/plugins/deref/deref.c | 2 +- + ldap/servers/plugins/http/http_impl.c | 4 ++-- + ldap/servers/plugins/pam_passthru/pam_ptimpl.c | 2 +- + ldap/servers/plugins/referint/referint.c | 2 +- + ldap/servers/plugins/replication/cl5_api.c | 20 +++++++++--------- + .../plugins/replication/windows_inc_protocol.c | 2 +- + ldap/servers/plugins/replication/windows_private.c | 9 ++++++-- + ldap/servers/plugins/usn/usn.c | 4 ++-- + ldap/servers/slapd/back-ldbm/import-threads.c | 2 +- + ldap/servers/slapd/back-ldbm/monitor.c | 18 ++++++++-------- + ldap/servers/slapd/log.c | 24 ++++++++++++++-------- + ldap/servers/slapd/mapping_tree.c | 6 +++++- + ldap/servers/slapd/regex.c | 10 ++++++--- + ldap/servers/slapd/slapi-plugin.h | 9 ++++++++ + ldap/servers/slapd/tools/ldclt/ldapfct.c | 5 ----- + ldap/servers/slapd/tools/rsearch/infadd.c | 7 +++---- + ldap/servers/snmp/main.c | 13 +++++++++++- + lib/libaccess/acltools.cpp | 2 +- + lib/libaccess/register.cpp | 10 +++++---- + 23 files changed, 100 insertions(+), 61 deletions(-) + +diff --git a/ldap/servers/plugins/acct_usability/acct_usability.c b/ldap/servers/plugins/acct_usability/acct_usability.c +index 19e55c3..f41f934 100644 +--- a/ldap/servers/plugins/acct_usability/acct_usability.c ++++ b/ldap/servers/plugins/acct_usability/acct_usability.c +@@ -312,7 +312,7 @@ auc_pre_search(Slapi_PBlock *pb) + int ldapcode = LDAP_SUCCESS; + const LDAPControl **reqctrls = NULL; + const LDAPControl *aucctrl = NULL; +- const char *ldaperrtext; ++ const char *ldaperrtext = "Unknown error"; + const char *incompatible = NULL; + int isroot = 0; + int ii; +diff --git a/ldap/servers/plugins/acl/acl_ext.c b/ldap/servers/plugins/acl/acl_ext.c +index f8699b4..e42a7e2 100644 +--- a/ldap/servers/plugins/acl/acl_ext.c ++++ b/ldap/servers/plugins/acl/acl_ext.c +@@ -128,7 +128,7 @@ acl_get_ext (ext_type type, void *object) + void + acl_set_ext (ext_type type, void *object, void *data) + { +- if ( type >= 0 && type < ACL_EXT_ALL ) ++ if ( type < ACL_EXT_ALL ) + { + struct acl_ext ext = acl_ext_list [type]; + slapi_set_object_extension ( ext.object_type, object, ext.handle, data ); +diff --git a/ldap/servers/plugins/acl/aclutil.c b/ldap/servers/plugins/acl/aclutil.c +index 77ec35f..2002276 100644 +--- a/ldap/servers/plugins/acl/aclutil.c ++++ b/ldap/servers/plugins/acl/aclutil.c +@@ -96,6 +96,7 @@ aclutil_str_append_ext(char **dest, size_t *dlen, const char *src, size_t slen) + char *ptr = NULL; + int rc = 0; + ++ PR_ASSERT(NULL != dlen); + if ( dest == NULL || src == NULL ) { + return rc; + } +@@ -103,7 +104,7 @@ aclutil_str_append_ext(char **dest, size_t *dlen, const char *src, size_t slen) + if (0 == slen) { + slen = strlen(src); + } +- if (*dest && dlen > 0) { ++ if (*dest && *dlen > 0) { + size_t dest_strlen = strlen(*dest); + size_t new_len = dest_strlen + slen + 1; + if (new_len > *dlen) { +diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c +index 424b507..49f47f7 100644 +--- a/ldap/servers/plugins/automember/automember.c ++++ b/ldap/servers/plugins/automember/automember.c +@@ -2522,10 +2522,11 @@ void automember_map_task_thread(void *arg){ + #if defined(USE_OPENLDAP) + int buflen = 0; + LDIFFP *ldif_fd_in = NULL; ++ ldif_record_lineno_t lineno = 0; + #else + PRFileDesc *ldif_fd_in = NULL; +-#endif + int lineno = 0; ++#endif + int rc = 0; + + td = (task_data *)slapi_task_get_data(task); +diff --git a/ldap/servers/plugins/deref/deref.c b/ldap/servers/plugins/deref/deref.c +index 51394c8..6e4d4ec 100644 +--- a/ldap/servers/plugins/deref/deref.c ++++ b/ldap/servers/plugins/deref/deref.c +@@ -440,7 +440,7 @@ deref_pre_search(Slapi_PBlock *pb) + int ldapcode = LDAP_SUCCESS; + const LDAPControl **reqctrls = NULL; + const LDAPControl *derefctrl = NULL; +- const char *ldaperrtext; ++ const char *ldaperrtext = "Unknown error"; + const char *incompatible = NULL; + DerefSpecList *speclist = NULL; + int ii; +diff --git a/ldap/servers/plugins/http/http_impl.c b/ldap/servers/plugins/http/http_impl.c +index f96d75a..db02b67 100644 +--- a/ldap/servers/plugins/http/http_impl.c ++++ b/ldap/servers/plugins/http/http_impl.c +@@ -260,7 +260,7 @@ static int doRequest(const char *url, httpheader **httpheaderArray, char *body, + PRInt32 port; + PRInt32 errcode = 0; + PRInt32 http_connection_time_out = 0; +- PRInt32 sslOn; ++ PRInt32 sslOn = 0; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "--> doRequest -- BEGIN\n",0,0,0); + +@@ -1178,7 +1178,7 @@ SECStatus + struct SECKEYPrivateKeyStr **pRetKey) + { + CERTCertificate * cert; +- SECKEYPrivateKey * privKey; ++ SECKEYPrivateKey * privKey = NULL; + char * chosenNickName = (char *)arg; + void * proto_win = NULL; + SECStatus secStatus = SECFailure; +diff --git a/ldap/servers/plugins/pam_passthru/pam_ptimpl.c b/ldap/servers/plugins/pam_passthru/pam_ptimpl.c +index 69c08e8..2558b9e 100644 +--- a/ldap/servers/plugins/pam_passthru/pam_ptimpl.c ++++ b/ldap/servers/plugins/pam_passthru/pam_ptimpl.c +@@ -263,7 +263,7 @@ do_one_pam_auth( + MyStrBuf pam_id; + const char *binddn = NULL; + Slapi_DN *bindsdn = NULL; +- int rc; ++ int rc = PAM_SUCCESS; + int retcode = LDAP_SUCCESS; + pam_handle_t *pam_handle; + struct my_pam_conv_str my_data; +diff --git a/ldap/servers/plugins/referint/referint.c b/ldap/servers/plugins/referint/referint.c +index 8f751da..4a722c1 100644 +--- a/ldap/servers/plugins/referint/referint.c ++++ b/ldap/servers/plugins/referint/referint.c +@@ -896,7 +896,7 @@ void + referint_thread_func(void *arg) + { + char **plugin_argv = (char **)arg; +- PRFileDesc *prfd; ++ PRFileDesc *prfd = NULL; + char *logfilename; + char thisline[MAX_LINE]; + int delay; +diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c +index e24cead..a06c43f 100644 +--- a/ldap/servers/plugins/replication/cl5_api.c ++++ b/ldap/servers/plugins/replication/cl5_api.c +@@ -271,8 +271,8 @@ static CL5Desc s_cl5Desc; + + /* changelog initialization and cleanup */ + static int _cl5Open (const char *dir, const CL5DBConfig *config, CL5OpenMode openMode); +-static int _cl5AppInit (PRBool *didRecovery); +-static int _cl5DBOpen (); ++static int _cl5AppInit (void); ++static int _cl5DBOpen (void); + static void _cl5SetDefaultDBConfig (); + static void _cl5SetDBConfig (const CL5DBConfig *config); + static int _cl5CheckDBVersion (); +@@ -876,12 +876,13 @@ cl5ImportLDIF (const char *clDir, const char *ldifFile, Object **replicas) + #if defined(USE_OPENLDAP) + LDIFFP *file = NULL; + int buflen; ++ ldif_record_lineno_t lineno = 0; + #else + FILE *file = NULL; ++ int lineno = 0; + #endif + int rc; + char *buff = NULL; +- int lineno = 0; + slapi_operation_parameters op; + Object *prim_replica_obj = NULL; + Object *replica_obj = NULL; +@@ -1850,7 +1851,6 @@ int cl5GetOperationCount (Object *replica) + static int _cl5Open (const char *dir, const CL5DBConfig *config, CL5OpenMode openMode) + { + int rc; +- PRBool didRecovery; + + PR_ASSERT (dir); + +@@ -1898,7 +1898,7 @@ static int _cl5Open (const char *dir, const CL5DBConfig *config, CL5OpenMode ope + s_cl5Desc.dbOpenMode = openMode; + + /* initialize db environment */ +- rc = _cl5AppInit (&didRecovery); ++ rc = _cl5AppInit (); + if (rc != CL5_SUCCESS) + { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, +@@ -1913,7 +1913,7 @@ static int _cl5Open (const char *dir, const CL5DBConfig *config, CL5OpenMode ope + } + + /* open database files */ +- rc = _cl5DBOpen (!didRecovery); ++ rc = _cl5DBOpen (); + if (rc != CL5_SUCCESS) + { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, +@@ -1989,7 +1989,7 @@ int cl5CreateDirIfNeeded (const char *dirName) + return CL5_SUCCESS; + } + +-static int _cl5AppInit (PRBool *didRecovery) ++static int _cl5AppInit (void) + { + int rc = -1; /* initialize to failure */ + DB_ENV *dbEnv = NULL; +@@ -2853,7 +2853,7 @@ static int _cl5Upgrade3_4(char *fromVersion, char *toVersion) + backup = s_cl5Desc.dbOpenMode; + s_cl5Desc.dbOpenMode = CL5_OPEN_CLEAN_RECOVER; + /* CL5_OPEN_CLEAN_RECOVER does 1 and 2 */ +- rc = _cl5AppInit (NULL); ++ rc = _cl5AppInit (); + if (rc != CL5_SUCCESS) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, +@@ -2943,7 +2943,7 @@ static int _cl5Upgrade4_4(char *fromVersion, char *toVersion) + backup = s_cl5Desc.dbOpenMode; + s_cl5Desc.dbOpenMode = CL5_OPEN_CLEAN_RECOVER; + /* CL5_OPEN_CLEAN_RECOVER does 1 and 2 */ +- rc = _cl5AppInit (NULL); ++ rc = _cl5AppInit (); + if (rc != CL5_SUCCESS) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, +@@ -4208,7 +4208,7 @@ static int _cl5Operation2LDIF (const slapi_operation_parameters *op, const char + int len = 2; + lenstr *l = NULL; + const char *strType; +- char *strDeleteOldRDN; ++ const char *strDeleteOldRDN = "false"; + char *buff, *start; + LDAPMod **add_mods; + char *rawDN = NULL; +diff --git a/ldap/servers/plugins/replication/windows_inc_protocol.c b/ldap/servers/plugins/replication/windows_inc_protocol.c +index b5fcadc..cb3b3d2 100644 +--- a/ldap/servers/plugins/replication/windows_inc_protocol.c ++++ b/ldap/servers/plugins/replication/windows_inc_protocol.c +@@ -1175,7 +1175,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu + { + CL5Entry entry; + slapi_operation_parameters op; +- int return_value; ++ int return_value = UPDATE_NO_MORE_UPDATES; + int rc; + int set_mincsn = 0; + CL5ReplayIterator *changelog_iterator = NULL; +diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c +index 20360a3..a103cad 100644 +--- a/ldap/servers/plugins/replication/windows_private.c ++++ b/ldap/servers/plugins/replication/windows_private.c +@@ -1344,11 +1344,16 @@ windows_plugin_init(Repl_Agmt *ra) + { + struct winsync_plugin_cookie *list = NULL; + void *cookie = NULL; +- PRStatus rv; + + LDAPDebug0Args( LDAP_DEBUG_PLUGIN, "--> windows_plugin_init_start -- begin\n"); + +- rv = PR_CallOnce(&winsync_callOnce, windows_plugin_callonce); ++ if (PR_CallOnce(&winsync_callOnce, windows_plugin_callonce)) { ++ PRErrorCode prerr = PR_GetError(); ++ slapi_log_error(SLAPI_LOG_FATAL, "windows_plugin_init", ++ "cannot initialize plugin: %d:%s\n", prerr, ++ slapi_pr_strerror(prerr)); ++ return; ++ } + + /* call each plugin init function in turn - store the returned cookie + indexed by the api */ +diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c +index 0273fd1..4473618 100644 +--- a/ldap/servers/plugins/usn/usn.c ++++ b/ldap/servers/plugins/usn/usn.c +@@ -673,7 +673,7 @@ usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, + if (be && be->be_usn_counter) { + /* get a next USN counter from be_usn_counter; + * then minus 1 from it */ +- PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRI64 "d", ++ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64, + slapi_counter_get_value(be->be_usn_counter)-1); + usn_berval.bv_len = strlen(usn_berval.bv_val); + slapi_entry_attr_replace(e, attr, vals); +@@ -692,7 +692,7 @@ usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, + } + /* get a next USN counter from be_usn_counter; + * then minus 1 from it */ +- PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRI64 "d", ++ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64, + slapi_counter_get_value(be->be_usn_counter)-1); + usn_berval.bv_len = strlen(usn_berval.bv_val); + +diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c +index b85f073..5667acb 100644 +--- a/ldap/servers/slapd/back-ldbm/import-threads.c ++++ b/ldap/servers/slapd/back-ldbm/import-threads.c +@@ -3622,7 +3622,7 @@ _get_import_entryusn(ImportJob *job, Slapi_Value **usn_value) + * Use the counter which stores the old DB's + * next entryusn. */ + PR_snprintf(counter_buf, USN_COUNTER_BUF_LEN, +- "%" NSPRI64 "d", ++ "%" NSPRIu64, + slapi_counter_get_value(be->be_usn_counter)); + } else { + /* import_init value is digit. +diff --git a/ldap/servers/slapd/back-ldbm/monitor.c b/ldap/servers/slapd/back-ldbm/monitor.c +index 075a48f..e3e1fb5 100644 +--- a/ldap/servers/slapd/back-ldbm/monitor.c ++++ b/ldap/servers/slapd/back-ldbm/monitor.c +@@ -214,13 +214,13 @@ int ldbm_back_monitor_instance_search(Slapi_PBlock *pb, Slapi_Entry *e, + #endif + MSETF("dbFilename-%d", i); + +- sprintf(buf, "%u", mpfstat[i]->st_cache_hit); ++ sprintf(buf, "%lu", (unsigned long)mpfstat[i]->st_cache_hit); + MSETF("dbFileCacheHit-%d", i); +- sprintf(buf, "%u", mpfstat[i]->st_cache_miss); ++ sprintf(buf, "%lu", (unsigned long)mpfstat[i]->st_cache_miss); + MSETF("dbFileCacheMiss-%d", i); +- sprintf(buf, "%u", mpfstat[i]->st_page_in); ++ sprintf(buf, "%lu", (unsigned long)mpfstat[i]->st_page_in); + MSETF("dbFilePageIn-%d", i); +- sprintf(buf, "%u", mpfstat[i]->st_page_out); ++ sprintf(buf, "%lu", (unsigned long)mpfstat[i]->st_page_out); + MSETF("dbFilePageOut-%d", i); + + slapi_ch_free_string(&absolute_pathname); +@@ -267,7 +267,7 @@ int ldbm_back_monitor_search(Slapi_PBlock *pb, Slapi_Entry *e, + } + + /* cache hits*/ +- sprintf(buf, "%u", mpstat->st_cache_hit); ++ sprintf(buf, "%lu", (unsigned long)mpstat->st_cache_hit); + MSET("dbCacheHits"); + + /* cache tries*/ +@@ -279,13 +279,13 @@ int ldbm_back_monitor_search(Slapi_PBlock *pb, Slapi_Entry *e, + sprintf(buf, "%lu", (unsigned long)(100.0 * (double)mpstat->st_cache_hit / (double)(cache_tries > 0 ? cache_tries : 1) )); + MSET("dbCacheHitRatio"); + +- sprintf(buf, "%u", mpstat->st_page_in); ++ sprintf(buf, "%lu", (unsigned long)mpstat->st_page_in); + MSET("dbCachePageIn"); +- sprintf(buf, "%u", mpstat->st_page_out); ++ sprintf(buf, "%lu", (unsigned long)mpstat->st_page_out); + MSET("dbCachePageOut"); +- sprintf(buf, "%u", mpstat->st_ro_evict); ++ sprintf(buf, "%lu", (unsigned long)mpstat->st_ro_evict); + MSET("dbCacheROEvict"); +- sprintf(buf, "%u", mpstat->st_rw_evict); ++ sprintf(buf, "%lu", (unsigned long)mpstat->st_rw_evict); + MSET("dbCacheRWEvict"); + + slapi_ch_free((void **)&mpstat); +diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c +index e65b247..a765001 100644 +--- a/ldap/servers/slapd/log.c ++++ b/ldap/servers/slapd/log.c +@@ -207,6 +207,15 @@ slapd_log_error_proc_internal( + /* Should be a flush in here ?? Yes because PR_SYNC doesn't work ! */ \ + PR_Sync(fd); \ + } while (0) ++#define LOG_WRITE_NOW_NO_ERR(fd, buffer, size, headersize) do {\ ++ if ( slapi_write_buffer((fd), (buffer), (size)) != (size) ) \ ++ { \ ++ PRErrorCode prerr = PR_GetError(); \ ++ syslog(LOG_ERR, "Failed to write log, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s): %s\n", prerr, slapd_pr_strerror(prerr), (buffer)+(headersize) ); \ ++ } \ ++ /* Should be a flush in here ?? Yes because PR_SYNC doesn't work ! */ \ ++ PR_Sync(fd); \ ++ } while (0) + #define LOG_CLOSE(fd) \ + PR_Close((fd)) + #endif +@@ -1279,7 +1288,7 @@ int + log_set_maxdiskspace(const char *attrname, char *maxdiskspace_str, int logtype, char *errorbuf, int apply) + { + int rv = 0; +- PRInt64 mlogsize; /* in bytes */ ++ PRInt64 mlogsize = 0; /* in bytes */ + PRInt64 maxdiskspace; /* in bytes */ + int s_maxdiskspace; /* in megabytes */ + +@@ -1520,7 +1529,7 @@ log_set_expirationtimeunit(const char *attrname, char *expunit, int logtype, cha + { + int value = 0; + int rv = 0; +- int exptime, rsecs; ++ int exptime = 0, rsecs = 0; + int *exptimeunitp = NULL; + slapdFrontendConfig_t *fe_cfg = getFrontendConfig(); + +@@ -1642,12 +1651,11 @@ log_write_title (LOGFD fp) + char *buildnum = config_get_buildnum(); + char buff[512]; + int bufflen = sizeof(buff); +- int err = 0; + + PR_snprintf(buff, bufflen, "\t%s B%s\n", + fe_cfg->versionstring ? fe_cfg->versionstring : CAPBRAND "-Directory/" DS_PACKAGE_VERSION, + buildnum ? buildnum : ""); +- LOG_WRITE_NOW(fp, buff, strlen(buff), 0, err); ++ LOG_WRITE_NOW_NO_ERR(fp, buff, strlen(buff), 0); + + if (fe_cfg->localhost) { + PR_snprintf(buff, bufflen, "\t%s:%d (%s)\n\n", +@@ -1662,7 +1670,7 @@ log_write_title (LOGFD fp) + PR_snprintf(buff, bufflen, "\t: (%s)\n\n", + fe_cfg->configdir ? fe_cfg->configdir : ""); + } +- LOG_WRITE_NOW(fp, buff, strlen(buff), 0, err); ++ LOG_WRITE_NOW_NO_ERR(fp, buff, strlen(buff), 0); + slapi_ch_free((void **)&buildnum); + } + +@@ -1768,7 +1776,7 @@ slapd_log_audit_proc ( + log_write_title( loginfo.log_audit_fdes); + loginfo.log_audit_state &= ~LOGGING_NEED_TITLE; + } +- LOG_WRITE_NOW(loginfo.log_audit_fdes, buffer, buf_len, 0, err); ++ LOG_WRITE_NOW_NO_ERR(loginfo.log_audit_fdes, buffer, buf_len, 0); + LOG_AUDIT_UNLOCK_WRITE(); + return 0; + } +@@ -4185,8 +4193,8 @@ static void log_flush_buffer(LogBufferInfo *lbi, int type, int sync_now) + if (!sync_now && slapdFrontendConfig->accesslogbuffering) { + LOG_WRITE(loginfo.log_access_fdes, lbi->top, lbi->current - lbi->top, 0); + } else { +- LOG_WRITE_NOW(loginfo.log_access_fdes, lbi->top, +- lbi->current - lbi->top, 0, err); ++ LOG_WRITE_NOW_NO_ERR(loginfo.log_access_fdes, lbi->top, ++ lbi->current - lbi->top, 0); + } + + lbi->current = lbi->top; +diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c +index da8e4f3..19c5708 100644 +--- a/ldap/servers/slapd/mapping_tree.c ++++ b/ldap/servers/slapd/mapping_tree.c +@@ -158,8 +158,10 @@ static mapping_tree_node * + static int _mtn_update_config_param(int op, char *type, char *strvalue); + + #ifdef DEBUG ++#ifdef USE_DUMP_MAPPING_TREE + static void dump_mapping_tree(mapping_tree_node *parent, int depth); + #endif ++#endif + + /* structure and static local variable used to store the + * list of plugins that have registered to a callback when backend state +@@ -3721,6 +3723,7 @@ void test_register() + #endif + + #ifdef DEBUG ++#ifdef USE_DUMP_MAPPING_TREE + static void dump_mapping_tree(mapping_tree_node *parent, int depth) + { + mapping_tree_node *current = NULL; +@@ -3751,7 +3754,8 @@ static void dump_mapping_tree(mapping_tree_node *parent, int depth) + } + return; + } +-#endif ++#endif /* USE_DUMP_MAPPING_TREE */ ++#endif /* DEBUG */ + + /* helper function to set/remove the config param in cn=config */ + static int +diff --git a/ldap/servers/slapd/regex.c b/ldap/servers/slapd/regex.c +index 3697fde..29edffe 100644 +--- a/ldap/servers/slapd/regex.c ++++ b/ldap/servers/slapd/regex.c +@@ -161,7 +161,7 @@ slapi_re_subs_ext( Slapi_Regex *re_handle, const char *subject, + int pin; + int *ovector; + char *mydst; +- const char *prev, *next; ++ const char *prev; + const char *substring_start; + const char *p; + +@@ -179,8 +179,7 @@ slapi_re_subs_ext( Slapi_Regex *re_handle, const char *subject, + for (p = src; *p != '\0'; p++) { + if ('&' == *p) { + /* Don't replace '&' if it's a filter AND: "(&(cn=a)(sn=b))" */ +- next = p; +- if(!filter || (*prev != '(' && *next++ != '(')){ ++ if(!filter || !(*prev == '(' && *(p+1) == '(')){ + if (re_handle->re_oveccount <= 1) { + memset(*dst, '\0', dstlen); + return -1; +@@ -188,6 +187,11 @@ slapi_re_subs_ext( Slapi_Regex *re_handle, const char *subject, + substring_start = subject + ovector[0]; + thislen = ovector[1] - ovector[0]; + len += thislen; ++ } else { /* is a filter AND clause */ ++ /* just copy it into the filter */ ++ substring_start = p; ++ thislen = 1; ++ len++; + } + } else if (('\\' == *p) && ('0' <= *(p+1) && *(p+1) <= '9')) { + pin = *(++p) - '0'; +diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h +index 5b3e1ab..0fdb206 100644 +--- a/ldap/servers/slapd/slapi-plugin.h ++++ b/ldap/servers/slapd/slapi-plugin.h +@@ -6870,6 +6870,15 @@ int slapi_ldap_get_lderrno(LDAP *ld, char **m, char **s); + #endif + void slapi_ldif_put_type_and_value_with_options( char **out, const char *t, const char *val, int vlen, unsigned long options ); + ++/* ldif_read_record lineno argument type depends on openldap version */ ++#if defined(USE_OPENLDAP) ++#if LDAP_VENDOR_VERSION >= 20434 /* changed in 2.4.34 */ ++typedef unsigned long int ldif_record_lineno_t; ++#else ++typedef int ldif_record_lineno_t; ++#endif ++#endif ++ + #if defined(USE_OPENLDAP) + /* + * UTF-8 routines (should these move into libnls?) +diff --git a/ldap/servers/slapd/tools/ldclt/ldapfct.c b/ldap/servers/slapd/tools/ldclt/ldapfct.c +index 3f74fd0..b177d7c 100644 +--- a/ldap/servers/slapd/tools/ldclt/ldapfct.c ++++ b/ldap/servers/slapd/tools/ldclt/ldapfct.c +@@ -732,10 +732,8 @@ LDAP * + connectToLDAP(thread_context *tttctx, const char *bufBindDN, const char *bufPasswd, unsigned int mode, unsigned int mod2) + { + LDAP *ld = NULL; +- const char *mech = LDAP_SASL_SIMPLE; + struct berval cred = {0, NULL}; + int v2v3 = LDAP_VERSION3; +- const char *binddn = NULL; + const char *passwd = NULL; + #if defined(USE_OPENLDAP) + char *ldapurl = NULL; +@@ -863,11 +861,8 @@ connectToLDAP(thread_context *tttctx, const char *bufBindDN, const char *bufPass + #endif /* !USE_OPENLDAP */ + + if (mode & CLTAUTH) { +- mech = "EXTERNAL"; +- binddn = ""; + passwd = NULL; + } else { +- binddn = bufBindDN?bufBindDN:mctx.bindDN; + passwd = bufPasswd?bufPasswd:mctx.passwd; + if (passwd) { + cred.bv_val = (char *)passwd; +diff --git a/ldap/servers/slapd/tools/rsearch/infadd.c b/ldap/servers/slapd/tools/rsearch/infadd.c +index 607381a..4a9f2e9 100644 +--- a/ldap/servers/slapd/tools/rsearch/infadd.c ++++ b/ldap/servers/slapd/tools/rsearch/infadd.c +@@ -127,11 +127,10 @@ char *randName(void) + return x; + } + +-int fill_table(NameTable *nt, PRUint32 size) ++void fill_table(NameTable *nt, PRUint32 size) + { + PRUint32 i; + char *x; +- int ret; + + fprintf(stdout, "Generating random names: 0 "); + for (i = 0; i < size; i++) { +@@ -141,13 +140,13 @@ int fill_table(NameTable *nt, PRUint32 size) + free(x); + x = randName(); + } +- ret = nt_push(nt, x); ++ (void)nt_push(nt, x); + if ((i % 100) == 0) { + fprintf(stdout, "\b\b\b\b\b\b\b%-7d", i); + } + } + fprintf(stdout, "\b\b\b\b\b\b\b%d. Done.\n", size); +- return ret; ++ return; + } + + int main(int argc, char **argv) +diff --git a/ldap/servers/snmp/main.c b/ldap/servers/snmp/main.c +index 53af972..0d1fb25 100644 +--- a/ldap/servers/snmp/main.c ++++ b/ldap/servers/snmp/main.c +@@ -236,6 +236,15 @@ main (int argc, char *argv[]) { + return 0; + } + ++/* ldif_read_record lineno argument type depends on openldap version */ ++#if defined(USE_OPENLDAP) ++#if LDAP_VENDOR_VERSION >= 20434 /* changed in 2.4.34 */ ++typedef unsigned long int ldif_record_lineno_t; ++#else ++typedef int ldif_record_lineno_t; ++#endif ++#endif ++ + /************************************************************************ + * load_config + * +@@ -249,8 +258,10 @@ load_config(char *conf_path) + #if defined(USE_OPENLDAP) + LDIFFP *dse_fp = NULL; + int buflen = 0; ++ ldif_record_lineno_t lineno = 0; + #else + FILE *dse_fp = NULL; ++ int lineno = 0; + #endif + char line[MAXLINE]; + char *p = NULL; +@@ -329,10 +340,10 @@ load_config(char *conf_path) + } else if ((p = strstr(line, "server")) != NULL) { + int got_port = 0; + int got_rundir = 0; +- int lineno = 0; + char *entry = NULL; + char *instancename = NULL; + ++ lineno = 0; + /* Allocate a server_instance */ + if ((serv_p = malloc(sizeof(server_instance))) == NULL) { + printf("ldap-agent: malloc error processing config file\n"); +diff --git a/lib/libaccess/acltools.cpp b/lib/libaccess/acltools.cpp +index df08658..4c1d28c 100644 +--- a/lib/libaccess/acltools.cpp ++++ b/lib/libaccess/acltools.cpp +@@ -1741,7 +1741,7 @@ static PList_t ACLAttr2IndexPList = NULL; + int + ACL_InitAttr2Index(void) + { +- int i; ++ intptr_t i; + + if (ACLAttr2IndexPList) return 0; + +diff --git a/lib/libaccess/register.cpp b/lib/libaccess/register.cpp +index 3f2acc5..595c1f2 100644 +--- a/lib/libaccess/register.cpp ++++ b/lib/libaccess/register.cpp +@@ -77,6 +77,8 @@ ACL_LasHashInit() + { + int i; + ++ (void)(link_ACLGlobal); /* get rid of defined but not used compiler warning */ ++ (void)(link_nsacl_table); /* get rid of defined but not used compiler warning */ + ACLLasEvalHash = PR_NewHashTable(0, + PR_HashString, + PR_CompareStrings, +@@ -268,11 +270,11 @@ ACL_MethodRegister(NSErr_t *errp, const char *name, ACLMethod_t *t) + } + + /* Put it in the hash table */ +- if (NULL == PR_HashTableAdd(ACLMethodHash, name, (void *)++cur_method)) { ++ if (NULL == PR_HashTableAdd(ACLMethodHash, name, (void *)(intptr_t)++cur_method)) { + ACL_CritExit(); + return -1; + } +- *t = (ACLMethod_t) cur_method; ++ *t = (ACLMethod_t) (intptr_t)cur_method; + + ACL_CritExit(); + return 0; +@@ -412,11 +414,11 @@ ACL_DbTypeRegister(NSErr_t *errp, const char *name, DbParseFn_t func, ACLDbType_ + } + + /* Put it in the hash table */ +- if (NULL == PR_HashTableAdd(ACLDbTypeHash, name, (void *)++cur_dbtype)) { ++ if (NULL == PR_HashTableAdd(ACLDbTypeHash, name, (void *)(intptr_t)++cur_dbtype)) { + ACL_CritExit(); + return -1; + } +- *t = (ACLDbType_t) cur_dbtype; ++ *t = (ACLDbType_t) (intptr_t)cur_dbtype; + ACLDbParseFnTable[cur_dbtype] = func; + + ACL_CritExit(); +-- +1.8.1.4 + diff --git a/0083-Ticket-47378-fix-recent-compiler-warnings.patch b/0083-Ticket-47378-fix-recent-compiler-warnings.patch new file mode 100644 index 0000000..e27bf0d --- /dev/null +++ b/0083-Ticket-47378-fix-recent-compiler-warnings.patch @@ -0,0 +1,182 @@ +From e10be9d331082ba331bc1f8f0fe161445cf41faa Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 29 Jul 2013 09:34:50 -0700 +Subject: [PATCH 83/99] Ticket #47378 - fix recent compiler warnings + +Description: This patch removes unused function compare_entries +in back-ldbm/sort.c. + +https://fedorahosted.org/389/ticket/47378 +(cherry picked from commit 9737076aa97622ac5f25d59e86b350050e700f60) +(cherry picked from commit e0dad88902a3c4bd625c149e0f6b10f976c57a7a) +--- + ldap/servers/slapd/back-ldbm/sort.c | 139 +----------------------------------- + 1 file changed, 2 insertions(+), 137 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/sort.c b/ldap/servers/slapd/back-ldbm/sort.c +index 6984467..7768737 100644 +--- a/ldap/servers/slapd/back-ldbm/sort.c ++++ b/ldap/servers/slapd/back-ldbm/sort.c +@@ -469,141 +469,6 @@ int sort_attr_compare(struct berval ** value_a, struct berval ** value_b, value_ + + } + +- +-#if 0 +-/* USE THE _SV VERSION NOW */ +- +-/* Comparison routine, called by qsort. +- * The job here is to return the correct value +- * for the operation a < b +- * Returns: +- * <0 when a < b +- * 0 when a == b +- * >0 when a > b +- */ +-static int compare_entries(ID *id_a, ID *id_b, sort_spec *s,baggage_carrier *bc, int *error) +-{ +- /* We get passed the IDs, but need to fetch the entries in order to +- * perform the comparison . +- */ +- struct backentry *a = NULL; +- struct backentry *b = NULL; +- int result = 0; +- sort_spec_thing *this_one = NULL; +- int return_value = -1; +- backend *be = bc->be; +- ldbm_instance *inst = (ldbm_instance *) be->be_instance_info; +- int err; +- +- *error = 1; +- a = id2entry(be,*id_a,NULL,&err); +- if (NULL == a) { +- if (0 != err ) { +- LDAPDebug(LDAP_DEBUG_ANY,"compare_entries db err %d\n",err,0,0); +- } +- /* Were up a creek without paddle here */ +- /* Best to log error and set some flag */ +- return 0; +- } +- b = id2entry(be,*id_b,NULL,&err); +- if (NULL == b) { +- if (0 != err ) { +- LDAPDebug(LDAP_DEBUG_ANY,"compare_entries db err %d\n",err,0,0); +- } +- return 0; +- } +- /* OK, now we have the entries, so we work our way down the attribute list comparing as we go */ +- for (this_one = (sort_spec_thing*)s; this_one ; this_one = this_one->next) { +- +- char *type = this_one->type; +- int order = this_one->order; +- Slapi_Attr *attr_a = NULL; +- Slapi_Attr *attr_b = NULL; +- struct berval **value_a = NULL; +- struct berval **value_b = NULL; +- +- /* Get the two attribute values from the entries */ +- return_value = slapi_entry_attr_find(a->ep_entry,type,&attr_a); +- return_value = slapi_entry_attr_find(b->ep_entry,type,&attr_b); +- /* What do we do if one or more of the entries lacks this attribute ? */ +- /* if one lacks the attribute */ +- if (NULL == attr_a) { +- /* then if the other does too, they're equal */ +- if (NULL == attr_b) { +- result = 0; +- continue; +- } else +- { +- /* If one has the attribute, and the other +- * doesn't, the missing attribute is the +- * LARGER one. (bug #108154) -robey +- */ +- result = 1; +- break; +- } +- } +- if (NULL == attr_b) { +- result = -1; +- break; +- } +- /* Somewhere in here, we need to go sideways for match rule case +- * we need to call the match rule plugin to get the attribute values +- * converted into ordering keys. Then we proceed as usual to use those, +- * but ensuring that we don't leak memory anywhere. This works as follows: +- * the code assumes that the attrs are references into the entry, so +- * doesn't try to free them. We need to note at the right place that +- * we're on the matchrule path, and accordingly free the keys---this turns out +- * to be when we free the indexer */ +- if (NULL == s->matchrule) { +- /* Non-match rule case */ +- /* xxxPINAKI +- needs modification +- +- value_a = attr_a->a_vals; +- value_b = attr_b->a_vals; +- */ +- } else { +- /* Match rule case */ +- struct berval **actual_value_b = NULL; +- struct berval **temp_value = NULL; +- +- /* xxxPINAKI +- needs modification +- struct berval **actual_value_a = NULL; +- +- actual_value_a = attr_a->a_vals; +- actual_value_b = attr_b->a_vals; +- matchrule_values_to_keys(s->mr_pb,actual_value_a,&temp_value); +- */ +- /* Now copy it, so the second call doesn't crap on it */ +- value_a = slapi_ch_bvecdup(temp_value); /* Really, we'd prefer to not call the chXXX variant...*/ +- matchrule_values_to_keys(s->mr_pb,actual_value_b,&value_b); +- } +- /* Compare them */ +- if (!order) { +- result = sort_attr_compare(value_a, value_b, s->compare_fn); +- } else { +- /* If reverse, invert the sense of the comparison */ +- result = sort_attr_compare(value_b, value_a, s->compare_fn); +- } +- /* Time to free up the attribute allocated above */ +- if (NULL != s->matchrule) { +- ber_bvecfree(value_a); +- } +- /* Are they equal ? */ +- if (0 != result) { +- /* If not, we're done */ +- break; +- } +- /* If so, proceed to the next attribute for comparison */ +- } +- CACHE_RETURN(&inst->inst_cache,&a); +- CACHE_RETURN(&inst->inst_cache,&b); +- *error = 0; +- return result; +-} +-#endif +- + /* Comparison routine, called by qsort. + * The job here is to return the correct value + * for the operation a < b +@@ -631,7 +496,7 @@ static int compare_entries_sv(ID *id_a, ID *id_b, sort_spec *s,baggage_carrier * + a = id2entry(be,*id_a,&txn,&err); + if (NULL == a) { + if (0 != err ) { +- LDAPDebug(LDAP_DEBUG_TRACE,"compare_entries db err %d\n",err,0,0); ++ LDAPDebug(LDAP_DEBUG_TRACE,"compare_entries_sv db err %d\n",err,0,0); + } + /* Were up a creek without paddle here */ + /* Best to log error and set some flag */ +@@ -640,7 +505,7 @@ static int compare_entries_sv(ID *id_a, ID *id_b, sort_spec *s,baggage_carrier * + b = id2entry(be,*id_b,&txn,&err); + if (NULL == b) { + if (0 != err ) { +- LDAPDebug(LDAP_DEBUG_TRACE,"compare_entries db err %d\n",err,0,0); ++ LDAPDebug(LDAP_DEBUG_TRACE,"compare_entries_sv db err %d\n",err,0,0); + } + CACHE_RETURN(&inst->inst_cache,&a); + return 0; +-- +1.8.1.4 + diff --git a/0084-Ticket-47435-Very-large-entryusn-values-after-enabli.patch b/0084-Ticket-47435-Very-large-entryusn-values-after-enabli.patch new file mode 100644 index 0000000..60025ad --- /dev/null +++ b/0084-Ticket-47435-Very-large-entryusn-values-after-enabli.patch @@ -0,0 +1,109 @@ +From 7d1e56dc90ebea1f14d06de5a6124d4ed186115f Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 19 Jul 2013 13:45:22 -0700 +Subject: [PATCH 84/99] Ticket #47435 - Very large entryusn values after + enabling the USN plugin and the lastusn value is negative. + +1. Bug description: The initial value of lastusn is -1, but since +the entryusn has the unsigned long long integer type, the server +returns 18446744073709551615 == 0XFFFFFFFFFFFFFFFF. + +Fix description: The initial value "-1" is returned as it is. + +2. Bug description: Entryusn syntax is defined as an integer in +the schema. If negative values are accidentally stored in the +entryusn value in the database, it was casted to the unsigned +integer in the entryusn initialization code (usn_get_last_usn). + +Fix description: When an entryusn value is retrieved from the +database, it's checked as a singed integer once and if it is +negative, it's replaced with the initial value "-1". + +https://fedorahosted.org/389/ticket/47435 + +Reviewed by Mark and Rich (Thank you!!) +(cherry picked from commit c94da991450da486b2032815b867bd2548a1614c) +(cherry picked from commit f54e44c138b0c56c2845d3614753d9ec5ebbdcba) +--- + ldap/servers/plugins/usn/usn.c | 20 ++++++++++++++------ + ldap/servers/slapd/back-ldbm/back-ldbm.h | 1 + + ldap/servers/slapd/back-ldbm/ldbm_usn.c | 6 +++++- + 3 files changed, 20 insertions(+), 7 deletions(-) + +diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c +index 4473618..4eb6528 100644 +--- a/ldap/servers/plugins/usn/usn.c ++++ b/ldap/servers/plugins/usn/usn.c +@@ -672,9 +672,13 @@ usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, + } + if (be && be->be_usn_counter) { + /* get a next USN counter from be_usn_counter; +- * then minus 1 from it */ +- PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64, +- slapi_counter_get_value(be->be_usn_counter)-1); ++ * then minus 1 from it (except if be_usn_counter has value 0) */ ++ if (slapi_counter_get_value(be->be_usn_counter)) { ++ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64, ++ slapi_counter_get_value(be->be_usn_counter)-1); ++ } else { ++ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "-1"); ++ } + usn_berval.bv_len = strlen(usn_berval.bv_val); + slapi_entry_attr_replace(e, attr, vals); + } +@@ -691,9 +695,13 @@ usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, + continue; + } + /* get a next USN counter from be_usn_counter; +- * then minus 1 from it */ +- PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64, +- slapi_counter_get_value(be->be_usn_counter)-1); ++ * then minus 1 from it (except if be_usn_counter has value 0) */ ++ if (slapi_counter_get_value(be->be_usn_counter)) { ++ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64, ++ slapi_counter_get_value(be->be_usn_counter)-1); ++ } else { ++ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "-1"); ++ } + usn_berval.bv_len = strlen(usn_berval.bv_val); + + if (USN_LAST_USN_ATTR_CORE_LEN+strlen(be->be_name)+2 > attr_len) { +diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h +index 3330449..61c7af9 100644 +--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h +@@ -868,6 +868,7 @@ typedef struct _back_search_result_set + #define LDBM_ERROR_FOUND_DUPDN 9999 + + /* Initial entryusn value */ ++#define SIGNEDINITIALUSN (-1) + #define INITIALUSN (PRUint64)(-1) + + /* changelog backup dir name +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_usn.c b/ldap/servers/slapd/back-ldbm/ldbm_usn.c +index 403e279..7c11a68 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_usn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_usn.c +@@ -124,6 +124,7 @@ usn_get_last_usn(Slapi_Backend *be, PRUint64 *last_usn) + DBC *dbc = NULL; + DBT key; /* For the last usn */ + DBT value; ++ PRInt64 signed_last_usn; + + if (NULL == last_usn) { + return rc; +@@ -167,7 +168,10 @@ usn_get_last_usn(Slapi_Backend *be, PRUint64 *last_usn) + p = (char *)key.data; + } + if (0 == rc) { +- *last_usn = strtoll(++p, (char **)NULL, 0); /* key.data: =num */ ++ signed_last_usn = strtoll(++p, (char **)NULL, 0); /* key.data: =num */ ++ if (signed_last_usn > SIGNEDINITIALUSN) { ++ *last_usn = signed_last_usn; ++ } + } + } else if (DB_NOTFOUND == rc) { + /* if empty, it's okay. This is just a beginning. */ +-- +1.8.1.4 + diff --git a/0085-Ticket-47421-memory-leaks-in-set_krb5_creds.patch b/0085-Ticket-47421-memory-leaks-in-set_krb5_creds.patch new file mode 100644 index 0000000..1ff1ef1 --- /dev/null +++ b/0085-Ticket-47421-memory-leaks-in-set_krb5_creds.patch @@ -0,0 +1,35 @@ +From 2a2a33eb0bb08d81924f0e0a81168486b78f43ce Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 18 Jul 2013 15:50:36 -0400 +Subject: [PATCH 85/99] Ticket 47421 - memory leaks in set_krb5_creds + +Bug Description: Valgrind shows memory leaks in set_krb5_creds() + +Fix description: krb5_unparse_name() allocates/returns the principle name. + But we can call this function twice without freeing the first + returned value. + +https://fedorahosted.org/389/ticket/47421 + +Reviewed by: richm(Thanks!) +(cherry picked from commit db124a2711576de2dd0009528d60b2860e815210) +(cherry picked from commit c1dcfc605b56a61199d827f213c490e109d8279e) +--- + ldap/servers/slapd/ldaputil.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c +index 3041f51..331dd71 100644 +--- a/ldap/servers/slapd/ldaputil.c ++++ b/ldap/servers/slapd/ldaputil.c +@@ -1901,6 +1901,7 @@ set_krb5_creds( + } + } + ++ slapi_ch_free_string(&princ_name); + if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) { + slapi_log_error(SLAPI_LOG_FATAL, logname, + "Unable to get name of principal: " +-- +1.8.1.4 + diff --git a/0086-Ticket-47449-deadlock-after-adding-and-deleting-entr.patch b/0086-Ticket-47449-deadlock-after-adding-and-deleting-entr.patch new file mode 100644 index 0000000..7730695 --- /dev/null +++ b/0086-Ticket-47449-deadlock-after-adding-and-deleting-entr.patch @@ -0,0 +1,49 @@ +From fb0a01cbb239b75681535e329782e2e6309fc41c Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 25 Jul 2013 16:41:01 -0400 +Subject: [PATCH 86/99] Ticket 47449 - deadlock after adding and deleting + entries + +Bug Description: If multiple clients are each doing their own add/delete of the same entries, + the server will deadlock very quickly. + +Fix Description: The server was not signaling an error when it failed to lock the parent + entry lock. I've checked add/mod/modrdn functions as well, and they do correctly + unlock the cache entry(this includes the old/new superior for modrdn). + +https://fedorahosted.org/389/ticket/47449 + +Reviewed by: richm(Thanks!) +(cherry picked from commit 66fbebc7d4c6552fcbbea7351dea5527d88195a1) +--- + ldap/servers/slapd/back-ldbm/ldbm_delete.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +index 3cf58f4..a3dc17b 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c +@@ -340,6 +340,7 @@ ldbm_back_delete( Slapi_PBlock *pb ) + if (parent && cache_lock_entry(&inst->inst_cache, parent)) { + /* Failed to obtain parent entry's entry lock */ + CACHE_RETURN(&(inst->inst_cache), &parent); ++ retval = -1; + goto error_return; + } + } +@@ -509,9 +510,9 @@ ldbm_back_delete( Slapi_PBlock *pb ) + "Delete Retrying Transaction\n"); + #ifndef LDBM_NO_BACKOFF_DELAY + { +- PRIntervalTime interval; +- interval = PR_MillisecondsToInterval(slapi_rand() % 100); +- DS_Sleep(interval); ++ PRIntervalTime interval; ++ interval = PR_MillisecondsToInterval(slapi_rand() % 100); ++ DS_Sleep(interval); + } + #endif + } +-- +1.8.1.4 + diff --git a/0087-Ticket-543-Sorting-with-attributes-in-ldapsearch-giv.patch b/0087-Ticket-543-Sorting-with-attributes-in-ldapsearch-giv.patch new file mode 100644 index 0000000..82db02e --- /dev/null +++ b/0087-Ticket-543-Sorting-with-attributes-in-ldapsearch-giv.patch @@ -0,0 +1,68 @@ +From 59d71e56a68c2fb6a52875767d0665dd76a78181 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 31 Jan 2013 16:45:28 -0800 +Subject: [PATCH 87/99] Ticket #543 - Sorting with attributes in ldapsearch + gives incorrect result + +Bug description: In the server side sorting compare function +compare_entries_sv, if multiple attribute types are specified, +the sort spec for each attribute is scanned one by one in the +for loop. In the for loop, instead of using the "current" +spec, the first spec is kept using. If the attribute types +have different syntaxes (e.g., cis, tel), then the first +syntax is unexpectedly selected for the second syntax. + +Fix description: This patch correctly uses the current spec +in the for loop. + +Reviewed by Nathan (Thank you!!) +(cherry picked from commit 95f425da43b380163c2ddae66fc77d2b863a00e5) +(cherry picked from commit 855d2890bc57482d7c22c6821a15b74f8053dc29) +--- + ldap/servers/slapd/back-ldbm/sort.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/sort.c b/ldap/servers/slapd/back-ldbm/sort.c +index 7768737..4164147 100644 +--- a/ldap/servers/slapd/back-ldbm/sort.c ++++ b/ldap/servers/slapd/back-ldbm/sort.c +@@ -552,7 +552,7 @@ static int compare_entries_sv(ID *id_a, ID *id_b, sort_spec *s,baggage_carrier * + * doesn't try to free them. We need to note at the right place that + * we're on the matchrule path, and accordingly free the keys---this turns out + * to be when we free the indexer */ +- if (NULL == s->matchrule) { ++ if (NULL == this_one->matchrule) { + /* Non-match rule case */ + valuearray_get_bervalarray(valueset_get_valuearray(&attr_a->a_present_values),&value_a); + valuearray_get_bervalarray(valueset_get_valuearray(&attr_b->a_present_values),&value_b); +@@ -564,22 +564,22 @@ static int compare_entries_sv(ID *id_a, ID *id_b, sort_spec *s,baggage_carrier * + + valuearray_get_bervalarray(valueset_get_valuearray(&attr_a->a_present_values),&actual_value_a); + valuearray_get_bervalarray(valueset_get_valuearray(&attr_b->a_present_values),&actual_value_b); +- matchrule_values_to_keys(s->mr_pb,actual_value_a,&temp_value); ++ matchrule_values_to_keys(this_one->mr_pb,actual_value_a,&temp_value); + /* Now copy it, so the second call doesn't crap on it */ + value_a = slapi_ch_bvecdup(temp_value); /* Really, we'd prefer to not call the chXXX variant...*/ +- matchrule_values_to_keys(s->mr_pb,actual_value_b,&value_b); ++ matchrule_values_to_keys(this_one->mr_pb,actual_value_b,&value_b); + if (actual_value_a) ber_bvecfree(actual_value_a); + if (actual_value_b) ber_bvecfree(actual_value_b); + } + /* Compare them */ + if (!order) { +- result = sort_attr_compare(value_a, value_b, s->compare_fn); ++ result = sort_attr_compare(value_a, value_b, this_one->compare_fn); + } else { + /* If reverse, invert the sense of the comparison */ +- result = sort_attr_compare(value_b, value_a, s->compare_fn); ++ result = sort_attr_compare(value_b, value_a, this_one->compare_fn); + } + /* Time to free up the attributes allocated above */ +- if (NULL != s->matchrule) { ++ if (NULL != this_one->matchrule) { + ber_bvecfree(value_a); + } else { + ber_bvecfree(value_a); +-- +1.8.1.4 + diff --git a/0088-Ticket-47441-Disk-Monitoring-not-checking-filesystem.patch b/0088-Ticket-47441-Disk-Monitoring-not-checking-filesystem.patch new file mode 100644 index 0000000..f8ed267 --- /dev/null +++ b/0088-Ticket-47441-Disk-Monitoring-not-checking-filesystem.patch @@ -0,0 +1,52 @@ +From 1d7b8e00c8798ecfdc378f4297e958b9400c9234 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 22 Jul 2013 15:36:49 -0400 +Subject: [PATCH 88/99] Ticket 47441 - Disk Monitoring not checking filesystem + with logs + +Bug Description: If logging is not set to critical, then the log directories + are not checked for available diskspace. + +Fix Description: Remove the "logging_critical" check, and always include the + log directories. + +https://fedorahosted.org/389/ticket/47441 + +Reviewed by: richm(Thanks!) +(cherry picked from commit 0ac4187eb5e1d4551a955196e649aca47aa3ea1a) +--- + ldap/servers/slapd/daemon.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index 8f147f1..221b156 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -600,14 +600,6 @@ disk_mon_get_dirs(char ***list, int logs_critical){ + char *cookie = NULL; + char *dir = NULL; + +- if(logs_critical){ +- slapi_rwlock_rdlock(config->cfg_rwlock); +- disk_mon_add_dir(list, config->accesslog); +- disk_mon_add_dir(list, config->errorlog); +- disk_mon_add_dir(list, config->auditlog); +- slapi_rwlock_unlock(config->cfg_rwlock); +- } +- + /* Add /var just to be safe */ + #ifdef LOCALSTATEDIR + disk_mon_add_dir(list, LOCALSTATEDIR); +@@ -618,6 +610,9 @@ disk_mon_get_dirs(char ***list, int logs_critical){ + /* config and backend directories */ + slapi_rwlock_rdlock(config->cfg_rwlock); + disk_mon_add_dir(list, config->configdir); ++ disk_mon_add_dir(list, config->accesslog); ++ disk_mon_add_dir(list, config->errorlog); ++ disk_mon_add_dir(list, config->auditlog); + slapi_rwlock_unlock(config->cfg_rwlock); + + be = slapi_get_first_backend (&cookie); +-- +1.8.1.4 + diff --git a/0089-Coverity-Fixes-part-1.patch b/0089-Coverity-Fixes-part-1.patch new file mode 100644 index 0000000..cfc0cbb --- /dev/null +++ b/0089-Coverity-Fixes-part-1.patch @@ -0,0 +1,350 @@ +From 8a5273d62a8785e6443aca11d6c06e5650884911 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 3 Jun 2013 17:17:24 -0400 +Subject: [PATCH 89/99] Coverity Fixes (part 1) + +11648 - string length miscalulation (ldclt.c) +11655 - unchecked return value (agtmmap.c) +11656 - unchecked return value (dblayer.c) +11657 - unchecked return value (daemon.c) +11658 - unchecked return value (daemon.c) +11660 - unchecked return value (log.c) +11661 - unchecked return value (main.c) +11662 - unchecked return value (ssl.c) +11668 - Same on both sides (repl5_protocol_util.c) +11669 - Same on both sides (ssl.c) +11670 - Same on both sides (util.c) +11673 - Copy-and-paste error (tools/rsearch/sdattable.c) + +https://bugzilla.redhat.com/show_bug.cgi?id=970221 + +Reviewed by: Noriko(Thanks!) +(cherry picked from commit 2b5aecb77784a9cf68fe29204f15bd4b61159d6d) +(cherry picked from commit f771f95f3f34442a9c238b687227d1d17a1015e7) +--- + .../plugins/replication/repl5_protocol_util.c | 2 +- + ldap/servers/slapd/agtmmap.c | 69 +++++++++++----------- + ldap/servers/slapd/back-ldbm/dblayer.c | 7 ++- + ldap/servers/slapd/daemon.c | 29 +++++---- + ldap/servers/slapd/log.c | 18 +++++- + ldap/servers/slapd/main.c | 5 +- + ldap/servers/slapd/ssl.c | 17 ++++-- + ldap/servers/slapd/tools/ldclt/ldclt.c | 4 +- + ldap/servers/slapd/tools/rsearch/sdattable.c | 2 +- + ldap/servers/slapd/util.c | 2 +- + 10 files changed, 98 insertions(+), 57 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl5_protocol_util.c b/ldap/servers/plugins/replication/repl5_protocol_util.c +index 30d211a..4449170 100644 +--- a/ldap/servers/plugins/replication/repl5_protocol_util.c ++++ b/ldap/servers/plugins/replication/repl5_protocol_util.c +@@ -603,7 +603,7 @@ release_replica(Private_Repl_Protocol *prp) + struct berval *data = NULL; + + /* Check the message id's match */ +- if (sent_message_id != sent_message_id) ++ if (sent_message_id != ret_message_id) + { + int operation, error; + conn_get_error(prp->conn, &operation, &error); +diff --git a/ldap/servers/slapd/agtmmap.c b/ldap/servers/slapd/agtmmap.c +index d82da5f..f18138a 100644 +--- a/ldap/servers/slapd/agtmmap.c ++++ b/ldap/servers/slapd/agtmmap.c +@@ -187,46 +187,49 @@ agt_mopen_stats (char * statsfile, int mode, int *hdl) + + if ( fd < 0 ) + { +- err = errno; ++ err = errno; + #if (0) +- fprintf (stderr, "returning errno =%d from %s(line: %d)\n", err, __FILE__, __LINE__); ++ fprintf (stderr, "returning errno =%d from %s(line: %d)\n", err, __FILE__, __LINE__); + #endif +- rc = err; +- goto bail; +- } ++ rc = err; ++ goto bail; ++ } + +- fstat (fd, &fileinfo); +- +- sz = sizeof (struct agt_stats_t); +- +- if (fileinfo.st_size < sz) +- { +- /* Without this we will get segv when we try to read/write later */ +- buf = calloc (1, sz); +- (void)write (fd, buf, sz); +- free (buf); +- } +- +- fp = mmap (NULL, sz, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0); +- +- if (fp == (caddr_t) -1) +- { +- err = errno; +- close (fd); ++ if(fstat (fd, &fileinfo) != 0){ ++ rc = errno; ++ goto bail; ++ } ++ ++ sz = sizeof (struct agt_stats_t); ++ ++ if (fileinfo.st_size < sz) ++ { ++ /* Without this we will get segv when we try to read/write later */ ++ buf = calloc (1, sz); ++ (void)write (fd, buf, sz); ++ free (buf); ++ } ++ ++ fp = mmap (NULL, sz, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0); ++ ++ if (fp == (caddr_t) -1) ++ { ++ err = errno; ++ close (fd); + #if (0) +- fprintf (stderr, "returning errno =%d from %s(line: %d)\n", err, __FILE__, __LINE__); ++ fprintf (stderr, "returning errno =%d from %s(line: %d)\n", err, __FILE__, __LINE__); + #endif +- rc = err; +- goto bail; +- } ++ rc = err; ++ goto bail; ++ } + +- mmap_tbl [1].maptype = AGT_MAP_RDWR; +- mmap_tbl [1].fd = fd; +- mmap_tbl [1].fp = fp; +- *hdl = 1; ++ mmap_tbl [1].maptype = AGT_MAP_RDWR; ++ mmap_tbl [1].fd = fd; ++ mmap_tbl [1].fp = fp; ++ *hdl = 1; + +- rc = 0; +- break; ++ rc = 0; ++ break; + } /* end switch */ + #else + /* _WIN32 */ +diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c +index 8696834..960d99e 100644 +--- a/ldap/servers/slapd/back-ldbm/dblayer.c ++++ b/ldap/servers/slapd/back-ldbm/dblayer.c +@@ -4478,7 +4478,12 @@ static int checkpoint_threadmain(void *param) + "%s.old", *listp); + checkpoint_debug_message(debug_checkpointing, + "Renaming %s -> %s\n",*listp, new_filename, 0); +- rename(*listp, new_filename); ++ if(rename(*listp, new_filename) != 0){ ++ LDAPDebug(LDAP_DEBUG_ANY, "checkpoint_threadmain: failed to rename log (%s) to (%s)\n", ++ *listp, new_filename, 0); ++ rval = -1; ++ goto error_return; ++ } + } + } + slapi_ch_free((void**)&list); +diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c +index 221b156..524a6aa 100644 +--- a/ldap/servers/slapd/daemon.c ++++ b/ldap/servers/slapd/daemon.c +@@ -3384,8 +3384,14 @@ createsignalpipe( void ) + } + writesignalpipe = PR_FileDesc2NativeHandle(signalpipe[1]); + readsignalpipe = PR_FileDesc2NativeHandle(signalpipe[0]); +- fcntl(writesignalpipe, F_SETFD, O_NONBLOCK); +- fcntl(readsignalpipe, F_SETFD, O_NONBLOCK); ++ if(fcntl(writesignalpipe, F_SETFD, O_NONBLOCK) == -1){ ++ LDAPDebug( LDAP_DEBUG_ANY,"createsignalpipe: failed to set FD for write pipe (%d).\n", ++ errno, 0, 0 ); ++ } ++ if(fcntl(readsignalpipe, F_SETFD, O_NONBLOCK) == -1){ ++ LDAPDebug( LDAP_DEBUG_ANY,"createsignalpipe: failed to set FD for read pipe (%d).\n", ++ errno, 0, 0); ++ } + #endif + + return( 0 ); +@@ -3605,7 +3611,7 @@ void configure_ns_socket( int * ns ) + { + + int enable_nagle = config_get_nagle(); +- int on; ++ int on, rc; + + #if defined(LINUX) + /* On Linux we use TCP_CORK so we must enable nagle */ +@@ -3615,19 +3621,18 @@ void configure_ns_socket( int * ns ) + if ( have_send_timeouts ) { + daemon_configure_send_timeout( *ns, config_get_ioblocktimeout() ); + } +- +- ++ /* set the nagle */ + if ( !enable_nagle ) { +- on = 1; +- setsockopt( *ns, IPPROTO_TCP, TCP_NODELAY, (char * ) &on, sizeof(on) ); ++ on = 1; + } else { +- on = 0; +- setsockopt( *ns, IPPROTO_TCP, TCP_NODELAY, (char * ) &on, sizeof(on) ); +- } /* else (!enable_nagle) */ +- ++ on = 0; ++ } ++ /* check for errors */ ++ if((rc = setsockopt( *ns, IPPROTO_TCP, TCP_NODELAY, (char * ) &on, sizeof(on) ) != 0)){ ++ LDAPDebug( LDAP_DEBUG_ANY,"configure_ns_socket: Failed to configure socket (%d).\n", rc, 0, 0); ++ } + + return; +- + } + + +diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c +index a765001..9b3f640 100644 +--- a/ldap/servers/slapd/log.c ++++ b/ldap/servers/slapd/log.c +@@ -3789,6 +3789,9 @@ log__open_errorlogfile(int logfile_state, int locked) + struct logfileinfo *logp; + char buffer[BUFSIZ]; + struct passwd *pw = NULL; ++#ifndef _WIN32 ++ int rc = 0; ++#endif + + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + +@@ -3886,7 +3889,20 @@ log__open_errorlogfile(int logfile_state, int locked) + * alternate ns-slapd modes, such as db2bak, tries to log an error + * at startup, it will create the logfile as root! + */ +- slapd_chown_if_not_owner(loginfo.log_error_file, pw->pw_uid, -1); ++ if((rc = slapd_chown_if_not_owner(loginfo.log_error_file, pw->pw_uid, -1)) != 0){ ++ PR_snprintf(buffer, sizeof(buffer), ++ "Failed to chown log file %s: error %d (%s); Exiting...", ++ loginfo.log_error_file, errno, slapd_system_strerror(errno)); ++ log__error_emergency(buffer, 1, locked); ++ if (!locked) LOG_ERROR_UNLOCK_WRITE(); ++ /* failed to write to the errors log. should not continue. */ ++ g_set_shutdown( SLAPI_SHUTDOWN_EXIT ); ++ /*if I have an old log file -- I should log a message ++ ** that I can't open the new file. Let the caller worry ++ ** about logging message. ++ */ ++ return LOG_UNABLE_TO_OPENFILE; ++ } + #endif + + loginfo.log_error_fdes = fp; +diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c +index 84ce01d..9938c01 100644 +--- a/ldap/servers/slapd/main.c ++++ b/ldap/servers/slapd/main.c +@@ -247,7 +247,10 @@ chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn, PRBool both) + while( (entry = PR_ReadDir(dir , PR_SKIP_BOTH )) !=NULL ) + { + PR_snprintf(file,MAXPATHLEN+1,"%s/%s",log,entry->name); +- slapd_chown_if_not_owner( file, pw->pw_uid, both?pw->pw_gid:-1 ); ++ if((rc = slapd_chown_if_not_owner( file, pw->pw_uid, both?pw->pw_gid:-1 )) != 0){ ++ LDAPDebug(LDAP_DEBUG_ANY, "chown_dir_files: file (%s) chown failed (%d) %s.\n", ++ file, errno, slapd_system_strerror(errno)); ++ } + } + PR_CloseDir( dir ); + } +diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c +index 0aab53d..f515b8e 100644 +--- a/ldap/servers/slapd/ssl.c ++++ b/ldap/servers/slapd/ssl.c +@@ -360,7 +360,7 @@ _conf_setciphers(char *ciphers) + if(t) + ciphers = t; + } +- if (unsuplist && unsuplist) { ++ if (unsuplist && *unsuplist) { + char *strsup = charray2str(suplist, ","); + char *strunsup = charray2str(unsuplist, ","); + slapd_SSL_warn("Security Initialization: FIPS mode is enabled - only the following " +@@ -614,9 +614,18 @@ slapd_nss_init(int init_ssl, int config_available) + certdb_file_name = slapi_ch_smprintf("%s/cert8.db", certdir); + keydb_file_name = slapi_ch_smprintf("%s/key3.db", certdir); + secmoddb_file_name = slapi_ch_smprintf("%s/secmod.db", certdir); +- chmod(certdb_file_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); +- chmod(keydb_file_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); +- chmod(secmoddb_file_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); ++ if(chmod(certdb_file_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP )){ ++ LDAPDebug(LDAP_DEBUG_ANY, "slapd_nss_init: chmod failed for file %s error (%d) %s.\n", ++ certdb_file_name, errno, slapd_system_strerror(errno)); ++ } ++ if(chmod(keydb_file_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP )){ ++ LDAPDebug(LDAP_DEBUG_ANY, "slapd_nss_init: chmod failed for file %s error (%d) %s.\n", ++ keydb_file_name, errno, slapd_system_strerror(errno)); ++ } ++ if(chmod(secmoddb_file_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP )){ ++ LDAPDebug(LDAP_DEBUG_ANY, "slapd_nss_init: chmod failed for file %s error (%d) %s.\n", ++ secmoddb_file_name, errno, slapd_system_strerror(errno)); ++ } + } + + /****** end of NSS Initialization ******/ +diff --git a/ldap/servers/slapd/tools/ldclt/ldclt.c b/ldap/servers/slapd/tools/ldclt/ldclt.c +index 27a2412..2a45c76 100644 +--- a/ldap/servers/slapd/tools/ldclt/ldclt.c ++++ b/ldap/servers/slapd/tools/ldclt/ldclt.c +@@ -1497,7 +1497,7 @@ basicInit (void) + /* + * Parse the deference attribute value + */ +- mctx.attRefDef= (char *)malloc(strlen(mctx.attrpl+i+1) + 1); ++ mctx.attRefDef= (char *)malloc(strlen(mctx.attrpl + i) + 2); + if (mctx.attRefDef== NULL) { + printf ("Error: unable to allocate memory for attRefDef\n"); + return (-1); +@@ -1525,7 +1525,7 @@ basicInit (void) + /* + * Parse the attribute value + */ +- mctx.attrplFile = (char *)malloc(strlen(mctx.attrpl+i+1) + 1); ++ mctx.attrplFile = (char *)malloc(strlen(mctx.attrpl+i) + 2); + if (mctx.attrplFile == NULL) { + printf ("Error: unable to allocate memory for attreplfile\n"); + return (-1); +diff --git a/ldap/servers/slapd/tools/rsearch/sdattable.c b/ldap/servers/slapd/tools/rsearch/sdattable.c +index df1c152..c0274d0 100644 +--- a/ldap/servers/slapd/tools/rsearch/sdattable.c ++++ b/ldap/servers/slapd/tools/rsearch/sdattable.c +@@ -183,7 +183,7 @@ int sdt_save(SDatTable *sdt, const char *filename) + PR_Write(fd, sdt->dns[i], strlen(sdt->dns[i])); + PR_Write(fd, "\n", 1); + } +- if (sdt->dns[i]) { ++ if (sdt->uids[i]) { + PR_Write(fd, "uid: ", 5); + PR_Write(fd, sdt->uids[i], strlen(sdt->uids[i])); + PR_Write(fd, "\n", 1); +diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c +index 649b3a9..0a9d23d 100644 +--- a/ldap/servers/slapd/util.c ++++ b/ldap/servers/slapd/util.c +@@ -417,7 +417,7 @@ normalize_mods2bvals(const LDAPMod **mods) + num_values++; + } + } else { +- for (x = 0; mods[w]->mod_values[x] != NULL && ++ for (x = 0; mods[w]->mod_values != NULL && + mods[w]->mod_values[x] != NULL; x++) + { + num_values++; +-- +1.8.1.4 + diff --git a/0090-Coverity-Fixes-Part-2.patch b/0090-Coverity-Fixes-Part-2.patch new file mode 100644 index 0000000..945f7f8 --- /dev/null +++ b/0090-Coverity-Fixes-Part-2.patch @@ -0,0 +1,394 @@ +From e767924756756993ea08c1636ee6d1af3e2775b0 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 4 Jun 2013 13:25:22 -0400 +Subject: [PATCH 90/99] Coverity Fixes (Part 2) + +11674 - logically dead code (collate.c) +11675 - logically dead code (windows_protocol_util.c) +11676 - logically dead code (index.c) +11677 - logically dead code (ldbm_entryrdn.c) +11678 - logically dead code (ldbm_entryrdn.c) +11680 - logically dead code (ldbm_search.c) +11681 - Dead default in switch (seq.c) +11683 - logically dead code (bind.c) +11684 - logically dead code (connection.c) +11686 - Dead default in switch (log.c) +11687 - Dead default in switch (log.c) +11688 - Dead default in switch (log.c) +11689 - Dead default in switch (log.c) +11690 - Dead default in switch (log.c) +11691 - Dead default in switch (log.c) + +https://bugzilla.redhat.com/show_bug.cgi?id=970221 + +Reviewed by: nhosoi(Thanks!) +(cherry picked from commit db673270e9a01e48adb22d94e676f25a223f407b) +(cherry picked from commit 41a882743c7c21575ed5365fe0484bc8d96edc6f) +--- + ldap/servers/plugins/collation/collate.c | 24 +++++------ + .../plugins/replication/windows_protocol_util.c | 9 ++--- + ldap/servers/slapd/back-ldbm/index.c | 17 ++++---- + ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 24 +++-------- + ldap/servers/slapd/back-ldbm/ldbm_search.c | 2 +- + ldap/servers/slapd/back-ldbm/seq.c | 2 - + ldap/servers/slapd/bind.c | 2 +- + ldap/servers/slapd/log.c | 46 +++++----------------- + 8 files changed, 40 insertions(+), 86 deletions(-) + +diff --git a/ldap/servers/plugins/collation/collate.c b/ldap/servers/plugins/collation/collate.c +index 240da70..2a73ee1 100644 +--- a/ldap/servers/plugins/collation/collate.c ++++ b/ldap/servers/plugins/collation/collate.c +@@ -437,11 +437,7 @@ collation_indexer_create (const char* oid) + profile->variant == NULL); + UErrorCode err = U_ZERO_ERROR; + if ( ! is_default) { +- if (locale) { +- PR_smprintf_free(locale); +- locale = NULL; +- } +- err = s_newNamedLocaleFromComponents(&locale, ++ err = s_newNamedLocaleFromComponents(&locale, + profile->language, + profile->country, + profile->variant); +@@ -460,27 +456,27 @@ collation_indexer_create (const char* oid) + ucol_setAttribute (coll, UCOL_STRENGTH, profile->strength, &err); + if (err != U_ZERO_ERROR && err != U_USING_FALLBACK_WARNING + && (err != U_USING_DEFAULT_WARNING || !is_default)) { +- LDAPDebug (LDAP_DEBUG_ANY, "collation_indexer_create: could not " ++ LDAPDebug (LDAP_DEBUG_ANY, "collation_indexer_create: could not " + "set the collator strength for oid %s to %d: err %d\n", + oid, profile->strength, err); + } + ucol_setAttribute (coll, UCOL_DECOMPOSITION_MODE, profile->decomposition, &err); + if (err != U_ZERO_ERROR && err != U_USING_FALLBACK_WARNING + && (err != U_USING_DEFAULT_WARNING || !is_default)) { +- LDAPDebug (LDAP_DEBUG_ANY, "collation_indexer_create: could not " ++ LDAPDebug (LDAP_DEBUG_ANY, "collation_indexer_create: could not " + "set the collator decomposition mode for oid %s to %d: err %d\n", + oid, profile->decomposition, err); + } + etc->collator = coll; + for (id = collation_id; *id; ++id) { +- if ((*id)->profile == profile) { +- break; /* found the 'official' id */ +- } ++ if ((*id)->profile == profile) { ++ break; /* found the 'official' id */ ++ } + } +- if (!*id) { +- LDAPDebug (LDAP_DEBUG_ANY, "collation_indexer_create: id not found\n", 0, 0, 0); +- goto error; +- } ++ if (!*id) { ++ LDAPDebug (LDAP_DEBUG_ANY, "collation_indexer_create: id not found\n", 0, 0, 0); ++ goto error; ++ } + + ix->ix_etc = etc; + ix->ix_oid = (*id)->oid; +diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c +index 1bafa9a..0b3c575 100644 +--- a/ldap/servers/plugins/replication/windows_protocol_util.c ++++ b/ldap/servers/plugins/replication/windows_protocol_util.c +@@ -4190,7 +4190,7 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr + windows_is_remote_entry_user_or_group(remote_entry,&is_user,&is_group); + } + +- for (rc = slapi_entry_first_attr(remote_entry, &attr); rc == 0; ++ for (rc = slapi_entry_first_attr(remote_entry, &attr); rc == 0; + rc = slapi_entry_next_attr(remote_entry, attr, &attr)) + { + int is_present_local = 0; +@@ -4201,7 +4201,6 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr + int is_guid = 0; + int mapdn = 0; + +- + slapi_attr_get_type( attr, &type ); + slapi_attr_get_valueset(attr,&vs); + +@@ -4360,7 +4359,7 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr + "windows_generate_update_mods: no restricted local values found for " + "local attribute %s in local entry %s for remote attribute " + "%s in remote entry %s\n", +- local_type ? local_type : "NULL", ++ local_type, + slapi_entry_get_dn(local_entry), + type ? type : "NULL", + slapi_entry_get_dn(remote_entry)); +@@ -4372,7 +4371,7 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr + "windows_generate_update_mods: no local values found for " + "local attribute %s in local entry %s for remote attribute " + "%s in remote entry %s\n", +- local_type ? local_type : "NULL", ++ local_type, + slapi_entry_get_dn(local_entry), + type ? type : "NULL", + slapi_entry_get_dn(remote_entry)); +@@ -4384,7 +4383,7 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr + "windows_generate_update_mods: could not map the values in " + "local attribute %s in local entry %s for remote attribute " + "%s in remote entry %s\n", +- local_type ? local_type : "NULL", ++ local_type, + slapi_entry_get_dn(local_entry), + type ? type : "NULL", + slapi_entry_get_dn(remote_entry)); +diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c +index 62a58a7..7769791 100644 +--- a/ldap/servers/slapd/back-ldbm/index.c ++++ b/ldap/servers/slapd/back-ldbm/index.c +@@ -649,18 +649,17 @@ index_add_mods( + mods[i]->mod_op |= LDAP_MOD_IGNORE; + } + } +- if (mods_valueArray) { +- rc = index_addordel_values_sv( be, +- mods[i]->mod_type, +- mods_valueArray, NULL, +- id, BE_INDEX_ADD, txn ); +- if (rc) { +- ldbm_nasty(errmsg, 1042, rc); +- goto error; +- } ++ if(mods_valueArray[0]){ ++ rc = index_addordel_values_sv( be, mods[i]->mod_type, ++ mods_valueArray, NULL, ++ id, BE_INDEX_ADD, txn ); + } else { + rc = 0; + } ++ if (rc) { ++ ldbm_nasty(errmsg, 1042, rc); ++ goto error; ++ } + } + } + break; +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +index 4329b16..156461b 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +@@ -809,14 +809,8 @@ entryrdn_rename_subtree(backend *be, + renamedata.data = (void *)oldsupelem; + } + } else { +- if (mynewsupsdn) { +- renamedata.ulen = renamedata.size = newsupelemlen; +- renamedata.data = (void *)newsupelem; +- } else { +- /* never comes here */ +- rc = -1; +- goto bail; +- } ++ renamedata.ulen = renamedata.size = newsupelemlen; ++ renamedata.data = (void *)newsupelem; + } + rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT, db_txn); + if (rc) { +@@ -901,16 +895,10 @@ entryrdn_rename_subtree(backend *be, + renamedata.data = (void *)targetelem; + } + } else { +- if (mynewsrdn) { +- memset(&renamedata, 0, sizeof(renamedata)); +- renamedata.ulen = renamedata.size = newelemlen; +- renamedata.data = (void *)newelem; +- renamedata.flags = DB_DBT_USERMEM; +- } else { +- /* never comes here */ +- rc = -1; +- goto bail; +- } ++ memset(&renamedata, 0, sizeof(renamedata)); ++ renamedata.ulen = renamedata.size = newelemlen; ++ renamedata.data = (void *)newelem; ++ renamedata.flags = DB_DBT_USERMEM; + } + rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD, db_txn); + if (rc) { +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c +index 670f627..e68b897 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c +@@ -573,7 +573,7 @@ ldbm_back_search( Slapi_PBlock *pb ) + /* This candidate list is for vlv, no need for sort only. */ + switch (vlv_search_build_candidate_list(pb, basesdn, &vlv_rc, + sort_control, +- (vlv ? &vlv_request_control : NULL), ++ &vlv_request_control, + &candidates, &vlv_response_control)) { + case VLV_ACCESS_DENIED: + return ldbm_back_search_cleanup(pb, li, sort_control, +diff --git a/ldap/servers/slapd/back-ldbm/seq.c b/ldap/servers/slapd/back-ldbm/seq.c +index 1435ba2..ab473bd 100644 +--- a/ldap/servers/slapd/back-ldbm/seq.c ++++ b/ldap/servers/slapd/back-ldbm/seq.c +@@ -221,8 +221,6 @@ ldbm_back_seq( Slapi_PBlock *pb ) + } + } + break; +- default: +- PR_ASSERT(0); + } + + dbc->c_close(dbc); +diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c +index e92add5..ec874cc 100644 +--- a/ldap/servers/slapd/bind.c ++++ b/ldap/servers/slapd/bind.c +@@ -178,7 +178,7 @@ do_bind( Slapi_PBlock *pb ) + /* check that the dn is formatted correctly */ + rc = slapi_dn_syntax_check(pb, rawdn, 1); + if (rc) { /* syntax check failed */ +- op_shared_log_error_access(pb, "BIND", rawdn?rawdn:"", ++ op_shared_log_error_access(pb, "BIND", rawdn, + "strict: invalid bind dn"); + send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, + NULL, "invalid bind dn", 0, NULL); +diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c +index 9b3f640..72a918b 100644 +--- a/ldap/servers/slapd/log.c ++++ b/ldap/servers/slapd/log.c +@@ -1011,8 +1011,6 @@ log_set_rotationsynchour(const char *attrname, char *rhour_str, int logtype, cha + fe_cfg->auditlog_rotationsynchour = rhour; + LOG_AUDIT_UNLOCK_WRITE(); + break; +- default: +- rv = 1; + } + + return rv; +@@ -1065,8 +1063,6 @@ log_set_rotationsyncmin(const char *attrname, char *rmin_str, int logtype, char + loginfo.log_audit_rotationsyncclock = log_get_rotationsyncclock( loginfo.log_audit_rotationsynchour, rmin ); + LOG_AUDIT_UNLOCK_WRITE(); + break; +- default: +- rv = 1; + } + + return rv; +@@ -1122,8 +1118,6 @@ log_set_rotationtime(const char *attrname, char *rtime_str, int logtype, char *r + loginfo.log_audit_rotationtime = rtime; + runit = loginfo.log_audit_rotationunit; + break; +- default: +- rv = 1; + } + + /* find out the rotation unit we have se right now */ +@@ -1151,19 +1145,17 @@ log_set_rotationtime(const char *attrname, char *rtime_str, int logtype, char *r + fe_cfg->accesslog_rotationtime = rtime; + loginfo.log_access_rotationtime_secs = value; + LOG_ACCESS_UNLOCK_WRITE(); +- break; ++ break; + case SLAPD_ERROR_LOG: + fe_cfg->errorlog_rotationtime = rtime; +- loginfo.log_error_rotationtime_secs = value; +- LOG_ERROR_UNLOCK_WRITE(); +- break; ++ loginfo.log_error_rotationtime_secs = value; ++ LOG_ERROR_UNLOCK_WRITE(); ++ break; + case SLAPD_AUDIT_LOG: + fe_cfg->auditlog_rotationtime = rtime; +- loginfo.log_audit_rotationtime_secs = value; +- LOG_AUDIT_UNLOCK_WRITE(); +- break; +- default: +- rv = 1; ++ loginfo.log_audit_rotationtime_secs = value; ++ LOG_AUDIT_UNLOCK_WRITE(); ++ break; + } + return rv; + } +@@ -1219,8 +1211,6 @@ int log_set_rotationtimeunit(const char *attrname, char *runit, int logtype, cha + LOG_AUDIT_LOCK_WRITE( ); + origvalue = loginfo.log_audit_rotationtime; + break; +- default: +- rv = 1; + } + + if (strcasecmp(runit, "month") == 0) { +@@ -1270,8 +1260,6 @@ int log_set_rotationtimeunit(const char *attrname, char *runit, int logtype, cha + fe_cfg->auditlog_rotationunit = slapi_ch_strdup ( runit ); + LOG_AUDIT_UNLOCK_WRITE(); + break; +- default: +- rv = 1; + } + return rv; + } +@@ -1321,9 +1309,6 @@ log_set_maxdiskspace(const char *attrname, char *maxdiskspace_str, int logtype, + LOG_AUDIT_LOCK_WRITE( ); + mlogsize = loginfo.log_audit_maxlogsize; + break; +- default: +- rv = 1; +- mlogsize = -1; + } + maxdiskspace = (PRInt64)s_maxdiskspace * LOG_MB_IN_BYTES; + if (maxdiskspace < 0) { +@@ -1357,11 +1342,6 @@ log_set_maxdiskspace(const char *attrname, char *maxdiskspace_str, int logtype, + } + LOG_AUDIT_UNLOCK_WRITE(); + break; +- default: +- PR_snprintf( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, +- "%s: invalid log type (%d) for setting maximum disk space: %d MB\n", +- attrname, logtype, s_maxdiskspace); +- rv = LDAP_OPERATIONS_ERROR; + } + return rv; + +@@ -1581,10 +1561,6 @@ log_set_expirationtimeunit(const char *attrname, char *expunit, int logtype, cha + rsecs = loginfo.log_audit_rotationtime_secs; + exptimeunitp = &(loginfo.log_audit_exptimeunit); + break; +- default: +- rv = 1; +- exptime = -1; +- rsecs = -1; + } + + value = -1; +@@ -1634,8 +1610,6 @@ log_set_expirationtimeunit(const char *attrname, char *expunit, int logtype, cha + fe_cfg->auditlog_exptimeunit = slapi_ch_strdup ( expunit ); + LOG_AUDIT_UNLOCK_WRITE(); + break; +- default: +- rv = 1; + } + + return rv; +@@ -1756,8 +1730,8 @@ slapd_log_audit_proc ( + char *buffer, + int buf_len) + { +- int err; + if ( (loginfo.log_audit_state & LOGGING_ENABLED) && (loginfo.log_audit_file != NULL) ){ ++ int err; + LOG_AUDIT_LOCK_WRITE( ); + if (log__needrotation(loginfo.log_audit_fdes, + SLAPD_AUDIT_LOG) == LOG_ROTATE) { +@@ -4176,9 +4150,9 @@ static void log_append_buffer2(time_t tnl, LogBufferInfo *lbi, char *msg1, size_ + static void log_flush_buffer(LogBufferInfo *lbi, int type, int sync_now) + { + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); +- int err = 0; +- ++ + if (type == SLAPD_ACCESS_LOG) { ++ int err = 0; + + /* It is only safe to flush once any other threads which are copying are finished */ + while (lbi->refcount > 0) { +-- +1.8.1.4 + diff --git a/0091-Coverity-Fixes-Part-3.patch b/0091-Coverity-Fixes-Part-3.patch new file mode 100644 index 0000000..eba1408 --- /dev/null +++ b/0091-Coverity-Fixes-Part-3.patch @@ -0,0 +1,484 @@ +From 1f463f1401b0adfd12cca7851d57a72fa6c58ce0 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 5 Jun 2013 12:15:05 -0400 +Subject: [PATCH 91/99] Coverity Fixes (Part 3) + +11692 - Explicit null dereferenced (libavl/avl.c) +11695 - Explicit null dereferenced (cb_conn_stateless.c) +11696 - Explicit null dereferenced (memberof_config.c) +11697 - Explicit null dereferenced (memberof.c) +11698 - Explicit null dereferenced (memberof.c) +11699 - Explicit null dereferenced (memberof.c) +11700 - Explicit null dereferenced (memberof.c) +11701 - Explicit null dereferenced (cl5_api.c) +11702 - Explicit null dereferenced (cl5_api.c) +11703 - Dereference after null check (cl5_clcache.c) +11704 - Dereference after null check (repl5_replica_config.c) +11705 - Explicit null dereferenced (syntaxes/string.c) +11706 - Dereference after null check (plugin.c) +11707 - Dereference after null check (plugin.c) +11711 - Dereference after null check (ldif2ldbm.c) +11726 - Dereference after null check (valueset.c) +11729 - Explicit null dereferenced (libaccess/oneeval.cpp) +11744 - Explicit null dereferenced (dbverify.c) +11745 - Out-of-bounds read (linked_attrs.c) +11745 - Out-of-bounds read (memberof.c) + +https://bugzilla.redhat.com/show_bug.cgi?id=970221 + +Reviewed by: richm(Thanks!) +(cherry picked from commit 36f25726b9723f743bc240cb44b88f74ad478ef2) +--- + ldap/libraries/libavl/avl.c | 7 +++++-- + ldap/servers/plugins/chainingdb/cb_conn_stateless.c | 2 +- + ldap/servers/plugins/linkedattrs/linked_attrs.c | 17 ++++++++++++++--- + ldap/servers/plugins/memberof/memberof.c | 18 ++++++++++++++---- + ldap/servers/plugins/memberof/memberof_config.c | 2 +- + ldap/servers/plugins/replication/cl5_api.c | 17 ++++++++++++++++- + ldap/servers/plugins/replication/cl5_clcache.c | 11 ++++++++--- + .../plugins/replication/repl5_replica_config.c | 5 +++++ + ldap/servers/plugins/syntaxes/string.c | 14 +++++++++----- + ldap/servers/slapd/back-ldbm/dbverify.c | 6 ++++-- + ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 16 ++++++++++++---- + ldap/servers/slapd/dn.c | 1 + + ldap/servers/slapd/plugin.c | 21 +++++++++++++++------ + ldap/servers/slapd/valueset.c | 17 ++++++++++------- + lib/libaccess/oneeval.cpp | 12 ++++++------ + 15 files changed, 121 insertions(+), 45 deletions(-) + +diff --git a/ldap/libraries/libavl/avl.c b/ldap/libraries/libavl/avl.c +index 7577891..18c43e0 100644 +--- a/ldap/libraries/libavl/avl.c ++++ b/ldap/libraries/libavl/avl.c +@@ -780,8 +780,11 @@ avl_getfirst( Avlnode *root ) + return( 0 ); + + (void) avl_apply( root, avl_buildlist, (caddr_t) 0, -1, AVL_INORDER ); +- +- return( avl_list[ avl_nextlist++ ] ); ++ if(avl_list && avl_list[avl_nextlist++]){ ++ return avl_list[avl_nextlist]; ++ } else { ++ return( NULL ); ++ } + } + + caddr_t +diff --git a/ldap/servers/plugins/chainingdb/cb_conn_stateless.c b/ldap/servers/plugins/chainingdb/cb_conn_stateless.c +index a9abc31..a85b392 100644 +--- a/ldap/servers/plugins/chainingdb/cb_conn_stateless.c ++++ b/ldap/servers/plugins/chainingdb/cb_conn_stateless.c +@@ -856,7 +856,7 @@ void cb_stale_all_connections( cb_backend_instance * cb) + else { + if (conn==pools[i]->conn.conn_list) { + pools[i]->conn.conn_list=next_conn; +- } else { ++ } else if(prev_conn){ + prev_conn->next=next_conn; + } + cb_close_and_dispose_connection(conn); +diff --git a/ldap/servers/plugins/linkedattrs/linked_attrs.c b/ldap/servers/plugins/linkedattrs/linked_attrs.c +index ff3dc3a..4bea10f 100644 +--- a/ldap/servers/plugins/linkedattrs/linked_attrs.c ++++ b/ldap/servers/plugins/linkedattrs/linked_attrs.c +@@ -1231,10 +1231,21 @@ linked_attrs_load_array(Slapi_Value **array, Slapi_Attr *attr) + int + linked_attrs_compare(const void *a, const void *b) + { ++ Slapi_Value *val1; ++ Slapi_Value *val2; ++ Slapi_Attr *linkattr; + int rc = 0; +- Slapi_Value *val1 = *((Slapi_Value **)a); +- Slapi_Value *val2 = *((Slapi_Value **)b); +- Slapi_Attr *linkattr = slapi_attr_new(); ++ ++ if(a == NULL && b != NULL){ ++ return 1; ++ } else if(a != NULL && b == NULL){ ++ return -1; ++ } else if(a == NULL && b == NULL){ ++ return 0; ++ } ++ val1 = *((Slapi_Value **)a); ++ val2 = *((Slapi_Value **)b); ++ linkattr = slapi_attr_new(); + + slapi_attr_init(linkattr, "distinguishedName"); + +diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c +index a3f875d..d11983b 100644 +--- a/ldap/servers/plugins/memberof/memberof.c ++++ b/ldap/servers/plugins/memberof/memberof.c +@@ -460,7 +460,7 @@ memberof_del_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, Slapi_DN * + /* Loop through each grouping attribute to find groups that have + * dn as a member. For any matches, delete the dn value from the + * same grouping attribute. */ +- for (i = 0; config->groupattrs[i]; i++) ++ for (i = 0; config->groupattrs && config->groupattrs[i]; i++) + { + memberof_del_dn_data data = {(char *)slapi_sdn_get_dn(sdn), + config->groupattrs[i]}; +@@ -712,7 +712,7 @@ memberof_replace_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, + /* Loop through each grouping attribute to find groups that have + * pre_dn as a member. For any matches, replace pre_dn with post_dn + * using the same grouping attribute. */ +- for (i = 0; config->groupattrs[i]; i++) ++ for (i = 0; config->groupattrs && config->groupattrs[i]; i++) + { + replace_dn_data data = {(char *)slapi_sdn_get_ndn(pre_sdn), + (char *)slapi_sdn_get_ndn(post_sdn), +@@ -2203,8 +2203,18 @@ void memberof_load_array(Slapi_Value **array, Slapi_Attr *attr) + */ + int memberof_compare(MemberOfConfig *config, const void *a, const void *b) + { +- Slapi_Value *val1 = *((Slapi_Value **)a); +- Slapi_Value *val2 = *((Slapi_Value **)b); ++ Slapi_Value *val1; ++ Slapi_Value *val2; ++ ++ if(a == NULL && b != NULL){ ++ return 1; ++ } else if(a != NULL && b == NULL){ ++ return -1; ++ } else if(a == NULL && b == NULL){ ++ return 0; ++ } ++ val1 = *((Slapi_Value **)a); ++ val2 = *((Slapi_Value **)b); + + /* We only need to provide a Slapi_Attr here for it's syntax. We + * already validated all grouping attributes to use the Distinguished +diff --git a/ldap/servers/plugins/memberof/memberof_config.c b/ldap/servers/plugins/memberof/memberof_config.c +index b4d557a..3fd63a9 100644 +--- a/ldap/servers/plugins/memberof/memberof_config.c ++++ b/ldap/servers/plugins/memberof/memberof_config.c +@@ -486,7 +486,7 @@ memberof_free_config(MemberOfConfig *config) + slapi_ch_array_free(config->groupattrs); + slapi_filter_free(config->group_filter, 1); + +- for (i = 0; config->group_slapiattrs[i]; i++) ++ for (i = 0; config->group_slapiattrs && config->group_slapiattrs[i]; i++) + { + slapi_attr_free(&config->group_slapiattrs[i]); + } +diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c +index a06c43f..f17650d 100644 +--- a/ldap/servers/plugins/replication/cl5_api.c ++++ b/ldap/servers/plugins/replication/cl5_api.c +@@ -3506,6 +3506,13 @@ static void _cl5TrimFile (Object *obj, long *numToTrim, ReplicaId cleaned_rid) + * This change can be trimmed if it exceeds purge + * parameters and has been seen by all consumers. + */ ++ if(op.csn == NULL){ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "_cl5TrimFile: " ++ "Operation missing csn, moving on to next entry.\n"); ++ cl5_operation_parameters_done (&op); ++ finished =_cl5GetNextEntry (&entry, it); ++ continue; ++ } + csn_rid = csn_get_replicaid (op.csn); + if ( (*numToTrim > 0 || _cl5CanTrim (entry.time, numToTrim)) && + ruv_covers_csn_strict (ruv, op.csn) ) +@@ -3835,7 +3842,15 @@ static int _cl5ConstructRUV (const char *replGen, Object *obj, PRBool purge) + rc = _cl5GetFirstEntry (obj, &entry, &iterator, NULL); + while (rc == CL5_SUCCESS) + { +- rid = csn_get_replicaid (op.csn); ++ if(op.csn){ ++ rid = csn_get_replicaid (op.csn); ++ } else { ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "_cl5ConstructRUV: " ++ "Operation missing csn, moving on to next entry.\n"); ++ cl5_operation_parameters_done (&op); ++ rc = _cl5GetNextEntry (&entry, iterator); ++ continue; ++ } + if(is_cleaned_rid(rid)){ + /* skip this entry as the rid is invalid */ + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5ConstructRUV: " +diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c +index 5329b4b..67e64f5 100644 +--- a/ldap/servers/plugins/replication/cl5_clcache.c ++++ b/ldap/servers/plugins/replication/cl5_clcache.c +@@ -750,9 +750,14 @@ clcache_skip_change ( CLC_Buffer *buf ) + */ + if ( csn_time_difference(buf->buf_current_csn, cscb->local_maxcsn) == 0 && + (csn_get_seqnum(buf->buf_current_csn) == +- csn_get_seqnum(cscb->local_maxcsn) + 1) ) { +- csn_init_by_csn ( cscb->local_maxcsn, buf->buf_current_csn ); +- csn_init_by_csn ( cscb->consumer_maxcsn, buf->buf_current_csn ); ++ csn_get_seqnum(cscb->local_maxcsn) + 1) ) ++ { ++ if(cscb->local_maxcsn){ ++ csn_init_by_csn ( cscb->local_maxcsn, buf->buf_current_csn ); ++ } ++ if(cscb->consumer_maxcsn){ ++ csn_init_by_csn ( cscb->consumer_maxcsn, buf->buf_current_csn ); ++ } + skip = 0; + break; + } +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 7c625eb..7b684e9 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -2366,6 +2366,11 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + int found = 0, i; + int rc, ret, rid; + ++ if(clean_data == NULL){ ++ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "delete_cleaned_rid_config: cleanruv data is NULL, " ++ "failed to clean the config.\n"); ++ return; ++ } + /* + * If there is no maxcsn, set the proper csnstr + */ +diff --git a/ldap/servers/plugins/syntaxes/string.c b/ldap/servers/plugins/syntaxes/string.c +index 54cd7c8..6c0da94 100644 +--- a/ldap/servers/plugins/syntaxes/string.c ++++ b/ldap/servers/plugins/syntaxes/string.c +@@ -84,7 +84,11 @@ string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax, + bvfilter_norm.bv_val = alt; + alt = NULL; + } +- bvfilter_norm.bv_len = strlen(bvfilter_norm.bv_val); ++ if(bvfilter_norm.bv_val){ ++ bvfilter_norm.bv_len = strlen(bvfilter_norm.bv_val); ++ } else { ++ bvfilter_norm.bv_len = 0; ++ } + } + + for ( i = 0; (bvals != NULL) && (bvals[i] != NULL); i++ ) { +@@ -103,7 +107,7 @@ string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax, + if(retVal) { + *retVal = bvals[i]; + } +- slapi_ch_free ((void**)&bvfilter_norm.bv_val); ++ slapi_ch_free_string(&bvfilter_norm.bv_val); + return( 0 ); + } + break; +@@ -112,7 +116,7 @@ string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax, + if(retVal) { + *retVal = bvals[i]; + } +- slapi_ch_free ((void**)&bvfilter_norm.bv_val); ++ slapi_ch_free_string(&bvfilter_norm.bv_val); + return( 0 ); + } + break; +@@ -121,14 +125,14 @@ string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax, + if(retVal) { + *retVal = bvals[i]; + } +- slapi_ch_free ((void**)&bvfilter_norm.bv_val); ++ slapi_ch_free_string(&bvfilter_norm.bv_val); + return( 0 ); + } + break; + } + } + +- slapi_ch_free ((void**)&bvfilter_norm.bv_val); ++ slapi_ch_free_string(&bvfilter_norm.bv_val); + return( -1 ); + } + +diff --git a/ldap/servers/slapd/back-ldbm/dbverify.c b/ldap/servers/slapd/back-ldbm/dbverify.c +index 43fc9d5..ffd5900 100644 +--- a/ldap/servers/slapd/back-ldbm/dbverify.c ++++ b/ldap/servers/slapd/back-ldbm/dbverify.c +@@ -119,9 +119,11 @@ dbverify_ext( ldbm_instance *inst, int verbose ) + char *p = NULL; + p = strstr(filep, LDBM_FILENAME_SUFFIX); /* since already checked, + it must have it */ +- *p = '\0'; ++ if(p) ++ *p = '\0'; + ainfo_get( inst->inst_be, filep+1, &ai ); +- *p = '.'; ++ if(p) ++ *p = '.'; + if (ai->ai_key_cmp_fn) { + dbp->app_private = (void *)ai->ai_key_cmp_fn; + dbp->set_bt_compare(dbp, dblayer_bt_compare); +diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c +index c802ff2..47e0269 100644 +--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c ++++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c +@@ -2246,15 +2246,23 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) + * Update the Virtual List View indexes + */ + for ( vlvidx = 0; vlvidx < numvlv; vlvidx++ ) { ++ char *ai = "Unknown index"; ++ + if ( g_get_shutdown() || c_get_shutdown() ) { + goto err_out; + } ++ if(indexAttrs){ ++ if(indexAttrs[vlvidx]){ ++ ai = indexAttrs[vlvidx]; ++ } ++ } + if (!run_from_cmdline) { + rc = dblayer_txn_begin(li, NULL, &txn); + if (0 != rc) { ++ + LDAPDebug(LDAP_DEBUG_ANY, + "%s: ERROR: failed to begin txn for update index '%s'\n", +- inst->inst_name, indexAttrs[vlvidx], 0); ++ inst->inst_name, ai, 0); + LDAPDebug(LDAP_DEBUG_ANY, + "%s: Error %d: %s\n", inst->inst_name, rc, + dblayer_strerror(rc)); +@@ -2262,7 +2270,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) + slapi_task_log_notice(task, + "%s: ERROR: failed to begin txn for update index '%s' " + "(err %d: %s)", inst->inst_name, +- indexAttrs[vlvidx], rc, dblayer_strerror(rc)); ++ ai, rc, dblayer_strerror(rc)); + } + return_value = -2; + goto err_out; +@@ -2281,7 +2289,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) + if (0 != rc) { + LDAPDebug(LDAP_DEBUG_ANY, + "%s: ERROR: failed to commit txn for update index '%s'\n", +- inst->inst_name, indexAttrs[vlvidx], 0); ++ inst->inst_name, ai, 0); + LDAPDebug(LDAP_DEBUG_ANY, + "%s: Error %d: %s\n", inst->inst_name, rc, + dblayer_strerror(rc)); +@@ -2289,7 +2297,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) + slapi_task_log_notice(task, + "%s: ERROR: failed to commit txn for update index '%s' " + "(err %d: %s)", inst->inst_name, +- indexAttrs[vlvidx], rc, dblayer_strerror(rc)); ++ ai, rc, dblayer_strerror(rc)); + } + return_value = -2; + goto err_out; +diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c +index 2f50e97..dda439b 100644 +--- a/ldap/servers/slapd/dn.c ++++ b/ldap/servers/slapd/dn.c +@@ -2614,3 +2614,4 @@ slapi_sdn_get_size(const Slapi_DN *sdn) + } + return sz; + } ++ +diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c +index 436cc02..0a4f4e0 100644 +--- a/ldap/servers/slapd/plugin.c ++++ b/ldap/servers/slapd/plugin.c +@@ -1493,15 +1493,24 @@ int + slapi_berval_cmp (const struct berval* L, const struct berval* R) /* JCM - This does not belong here. But, where should it go? */ + { + int result = 0; ++ ++ if(L == NULL && R != NULL){ ++ return 1; ++ } else if(L != NULL && R == NULL){ ++ return -1; ++ } else if(L == NULL && R == NULL){ ++ return 0; ++ } + if (L->bv_len < R->bv_len) { +- result = memcmp (L->bv_val, R->bv_val, L->bv_len); +- if (result == 0) +- result = -1; ++ result = memcmp (L->bv_val, R->bv_val, L->bv_len); ++ if (result == 0) ++ result = -1; + } else { +- result = memcmp (L->bv_val, R->bv_val, R->bv_len); +- if (result == 0 && (L->bv_len > R->bv_len)) +- result = 1; ++ result = memcmp (L->bv_val, R->bv_val, R->bv_len); ++ if (result == 0 && (L->bv_len > R->bv_len)) ++ result = 1; + } ++ + return result; + } + +diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c +index a91256c..f04acc3 100644 +--- a/ldap/servers/slapd/valueset.c ++++ b/ldap/servers/slapd/valueset.c +@@ -190,20 +190,23 @@ valuearray_add_valuearray(Slapi_Value ***vals, Slapi_Value **addvals, PRUint32 f + { + int valslen; + int addvalslen; +- int maxvals; ++ int maxvals; + +- addvalslen= valuearray_count(addvals); ++ if(vals == NULL){ ++ return; ++ } ++ addvalslen= valuearray_count(addvals); + if(*vals == NULL) + { +- valslen= 0; +- maxvals= 0; ++ valslen= 0; ++ maxvals= 0; + } + else + { +- valslen= valuearray_count(*vals); +- maxvals= valslen+1; ++ valslen= valuearray_count(*vals); ++ maxvals= valslen+1; + } +- valuearray_add_valuearray_fast(vals,addvals,valslen,addvalslen,&maxvals,1/*Exact*/,flags & SLAPI_VALUE_FLAG_PASSIN); ++ valuearray_add_valuearray_fast(vals,addvals,valslen,addvalslen,&maxvals,1/*Exact*/,flags & SLAPI_VALUE_FLAG_PASSIN); + } + + int +diff --git a/lib/libaccess/oneeval.cpp b/lib/libaccess/oneeval.cpp +index eff4e10..a6d3bbd 100644 +--- a/lib/libaccess/oneeval.cpp ++++ b/lib/libaccess/oneeval.cpp +@@ -381,20 +381,19 @@ ACLEvalBuildContext( + /* Loop through all the ACLs in the list */ + while (wrapper) + { +- acl = wrapper->acl; ++ acl = wrapper->acl; + ace = acl->expr_list_head; + + while (ace) /* Loop through all the ACEs in this ACL */ + { +- + /* allocate a new ace list entry and link it in to the ordered + * list. + */ + new_ace = (ACLAceEntry_t *)PERM_CALLOC(sizeof(ACLAceEntry_t)); + if (new_ace == (ACLAceEntry_t *)NULL) { +- nserrGenerate(errp, ACLERRNOMEM, ACLERR4020, ACL_Program, 1, +- XP_GetAdminStr(DBT_EvalBuildContextUnableToAllocAceEntry)); +- goto error; ++ nserrGenerate(errp, ACLERRNOMEM, ACLERR4020, ACL_Program, 1, ++ XP_GetAdminStr(DBT_EvalBuildContextUnableToAllocAceEntry)); ++ goto error; + } + new_ace->acep = ace; + ace_cnt++; +@@ -402,7 +401,8 @@ ACLEvalBuildContext( + if (cache->acelist == NULL) + cache->acelist = acelast = new_ace; + else { +- acelast->next = new_ace; ++ if(acelast) ++ acelast->next = new_ace; + acelast = new_ace; + new_ace->acep = ace; + } +-- +1.8.1.4 + diff --git a/0092-Coverity-Fixes-Part-4.patch b/0092-Coverity-Fixes-Part-4.patch new file mode 100644 index 0000000..53b30f7 --- /dev/null +++ b/0092-Coverity-Fixes-Part-4.patch @@ -0,0 +1,663 @@ +From 12552b47385b98ad294fdb1f229861998c83ec2f Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 5 Jun 2013 16:19:57 -0400 +Subject: [PATCH 92/99] Coverity Fixes (Part 4) + +11753 - Resource leak (aclparse.c) +11754 - Resource leak (dna.c) +11755 - Resource leak (dna.c) +11756 - Resource leak (linked_attrs.c) +11757 - Resource leak (pam_ptconfig.c) +11758 - Resource leak (repl5_replica_config.c) +11759 - Resource leak (windows_inc_protocol.c) +11760 - Resource leak (syntaxes/value.c) +11761 - Resource leak (dblayer.c) +11764 - Resource leak (dblayer.c) +11766 - Resource leak (dblayer.c) +11769 - Resource leak (entry.c) +11770 - Resource leak (entry.c) +11773 - Resource leak (schema.c) +11774 - Resource leak (snmp_collator.c) +11775 - Resource leak (ldclt/data.c) +11776 - Resource leak (tools/mmldif.c) +11777 - Resource leak (snmp/main.c) +11778 - Resource leak (lib/libutil/dbconf.c) +11779 - Resource leak (lib/libaccess/register.cpp) +11781 - Resource leak (lib/libadmin/error.c) +11872 - Resource leak (agtmmap.c) + +https://bugzilla.redhat.com/show_bug.cgi?id=970221 + +Reviewed by: nhosoi(Thanks!) +(cherry picked from commit 26127d5f7a96c33dfc46f3c8fc21de07455ea667) +(cherry picked from commit 3ab5aba6252798b895953a6f2af50916d3525ceb) +--- + ldap/servers/plugins/acl/acl.h | 1 + + ldap/servers/plugins/acl/acllist.c | 7 +++--- + ldap/servers/plugins/acl/aclparse.c | 29 +++++++++++----------- + ldap/servers/plugins/dna/dna.c | 7 ++++++ + ldap/servers/plugins/linkedattrs/linked_attrs.c | 7 ++++++ + ldap/servers/plugins/pam_passthru/pam_ptconfig.c | 6 +++++ + .../plugins/replication/repl5_replica_config.c | 3 +-- + .../plugins/replication/windows_inc_protocol.c | 1 + + ldap/servers/plugins/syntaxes/value.c | 14 +++++++++++ + ldap/servers/slapd/agtmmap.c | 1 + + ldap/servers/slapd/back-ldbm/dblayer.c | 14 +++++++---- + ldap/servers/slapd/entry.c | 7 +++++- + ldap/servers/slapd/schema.c | 6 +++-- + ldap/servers/slapd/snmp_collator.c | 4 ++- + ldap/servers/slapd/tools/ldclt/data.c | 2 ++ + ldap/servers/slapd/tools/mmldif.c | 6 +++++ + ldap/servers/snmp/main.c | 3 +++ + lib/ldaputil/dbconf.c | 7 ++++-- + lib/libaccess/register.cpp | 1 + + lib/libadmin/error.c | 7 ++++-- + 20 files changed, 99 insertions(+), 34 deletions(-) + +diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h +index e2b04c3..c61ee70 100644 +--- a/ldap/servers/plugins/acl/acl.h ++++ b/ldap/servers/plugins/acl/acl.h +@@ -866,6 +866,7 @@ int acllist_moddn_aci_needsLock ( Slapi_DN *oldsdn, char *newdn ); + void acllist_print_tree ( Avlnode *root, int *depth, char *start, char *side); + AciContainer *acllist_get_aciContainer_new ( ); + void acllist_done_aciContainer ( AciContainer *); ++void free_targetattrfilters( Targetattrfilter ***attrFilterArray); + + aclUserGroup* aclg_find_userGroup (const char *n_dn); + void aclg_regen_ugroup_signature( aclUserGroup *ugroup); +diff --git a/ldap/servers/plugins/acl/acllist.c b/ldap/servers/plugins/acl/acllist.c +index e8198af..623a739 100644 +--- a/ldap/servers/plugins/acl/acllist.c ++++ b/ldap/servers/plugins/acl/acllist.c +@@ -94,7 +94,6 @@ static int __acllist_add_aci ( aci_t *aci ); + static int __acllist_aciContainer_node_cmp ( caddr_t d1, caddr_t d2 ); + static int __acllist_aciContainer_node_dup ( caddr_t d1, caddr_t d2 ); + static void __acllist_free_aciContainer ( AciContainer **container); +-static void free_targetattrfilters( Targetattrfilter ***input_attrFilterArray); + + void my_print( Avlnode *root ); + +@@ -565,8 +564,9 @@ acllist_free_aci(aci_t *item) + slapi_ch_free ( (void **) &item ); + } + +-static void free_targetattrfilters( Targetattrfilter ***attrFilterArray) { +- ++void ++free_targetattrfilters( Targetattrfilter ***attrFilterArray) ++{ + if (*attrFilterArray) { + int i = 0; + Targetattrfilter *attrfilter; +@@ -592,7 +592,6 @@ static void free_targetattrfilters( Targetattrfilter ***attrFilterArray) { + /* Now free the array */ + slapi_ch_free ( (void **) attrFilterArray ); + } +- + } + + /* SEARCH */ +diff --git a/ldap/servers/plugins/acl/aclparse.c b/ldap/servers/plugins/acl/aclparse.c +index 39d9f6c..8b11471 100644 +--- a/ldap/servers/plugins/acl/aclparse.c ++++ b/ldap/servers/plugins/acl/aclparse.c +@@ -1935,14 +1935,13 @@ static int __acl__init_targetattrfilters( aci_t *aci, char *input_str) { + * We need to put each component into a targetattrfilter component of + * the array. + * +-*/ +- ++ */ + static int process_filter_list( Targetattrfilter ***input_attrFilterArray, + char * input_str) { + + char *str, *end_attr; + Targetattrfilter *attrfilter = NULL; +- int numattr=0; ++ int numattr=0, rc = 0; + Targetattrfilter **attrFilterArray = NULL; + + str = input_str; +@@ -1974,22 +1973,20 @@ static int process_filter_list( Targetattrfilter ***input_attrFilterArray, + memset (attrfilter, 0, sizeof(Targetattrfilter)); + + if (strstr( str,":") != NULL) { +- + if ( __acl_init_targetattrfilter( attrfilter, str ) != 0 ) { + slapi_ch_free((void**)&attrfilter); +- return(ACL_SYNTAX_ERR); ++ rc = ACL_SYNTAX_ERR; ++ break; + } + } else { + slapi_ch_free((void**)&attrfilter); +- return(ACL_SYNTAX_ERR); ++ rc = ACL_SYNTAX_ERR; ++ break; + } + +- + /* +- * Add the attrfilte to the targetAttrFilter list +- */ +- +- ++ * Add the attrfilter to the targetAttrFilter list ++ */ + attrFilterArray = (Targetattrfilter **) slapi_ch_realloc ( + (void *) attrFilterArray, + ((numattr+1)*sizeof(Targetattrfilter *)) ); +@@ -1998,7 +1995,6 @@ static int process_filter_list( Targetattrfilter ***input_attrFilterArray, + + /* Move on to the next attribute in the list */ + str = end_attr; +- + }/* while */ + + /* NULL terminate the list */ +@@ -2007,10 +2003,13 @@ static int process_filter_list( Targetattrfilter ***input_attrFilterArray, + (void *) attrFilterArray, + ((numattr+1)*sizeof(Targetattrfilter *)) ); + attrFilterArray[numattr] = NULL; ++ if(rc){ ++ free_targetattrfilters(&attrFilterArray); ++ } else { ++ *input_attrFilterArray = attrFilterArray; ++ } + +- *input_attrFilterArray = attrFilterArray; +- return 0; +- ++ return rc; + } + + /* +diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c +index d3dfa52..958a4a7 100644 +--- a/ldap/servers/plugins/dna/dna.c ++++ b/ldap/servers/plugins/dna/dna.c +@@ -1515,11 +1515,13 @@ dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers) + * to lowest. */ + struct dnaServer *sitem; + PRCList* item = PR_LIST_HEAD(*servers); ++ int inserted = 0; + + while (item != *servers) { + sitem = (struct dnaServer *)item; + if (server->remaining > sitem->remaining) { + PR_INSERT_BEFORE(&(server->list), item); ++ inserted = 1; + break; + } + +@@ -1528,9 +1530,13 @@ dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers) + if (*servers == item) { + /* add to tail */ + PR_INSERT_BEFORE(&(server->list), item); ++ inserted = 1; + break; + } + } ++ if(!inserted){ ++ dna_free_shared_server(&server); ++ } + } + } + } +@@ -3340,6 +3346,7 @@ dna_pre_op(Slapi_PBlock * pb, int modtype) + bail: + if (resulting_e) + slapi_entry_free(resulting_e); ++ slapi_mods_free(&smods); + + if (ret) { + slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM, +diff --git a/ldap/servers/plugins/linkedattrs/linked_attrs.c b/ldap/servers/plugins/linkedattrs/linked_attrs.c +index 4bea10f..7d8370d 100644 +--- a/ldap/servers/plugins/linkedattrs/linked_attrs.c ++++ b/ldap/servers/plugins/linkedattrs/linked_attrs.c +@@ -755,6 +755,7 @@ linked_attrs_insert_config_index(struct configEntry *entry) + struct configEntry *config_entry = NULL; + struct configIndex *index_entry = NULL; + PRCList *list = PR_LIST_HEAD(g_managed_config_index); ++ int inserted = 0; + + index_entry = (struct configIndex *)slapi_ch_calloc(1, sizeof(struct configIndex)); + index_entry->config = entry; +@@ -769,6 +770,7 @@ linked_attrs_insert_config_index(struct configEntry *entry) + slapi_log_error(SLAPI_LOG_CONFIG, LINK_PLUGIN_SUBSYSTEM, + "store [%s] before [%s] \n", entry->dn, + config_entry->dn); ++ inserted = 1; + break; + } + +@@ -779,6 +781,7 @@ linked_attrs_insert_config_index(struct configEntry *entry) + PR_INSERT_BEFORE(&(index_entry->list), list); + slapi_log_error(SLAPI_LOG_CONFIG, LINK_PLUGIN_SUBSYSTEM, + "store [%s] at tail\n", entry->dn); ++ inserted = 1; + break; + } + } +@@ -787,6 +790,10 @@ linked_attrs_insert_config_index(struct configEntry *entry) + slapi_log_error(SLAPI_LOG_CONFIG, LINK_PLUGIN_SUBSYSTEM, + "store [%s] at head \n", entry->dn); + PR_INSERT_LINK(&(index_entry->list), g_managed_config_index); ++ inserted = 1; ++ } ++ if(!inserted){ ++ slapi_ch_free((void **)&index_entry); + } + } + +diff --git a/ldap/servers/plugins/pam_passthru/pam_ptconfig.c b/ldap/servers/plugins/pam_passthru/pam_ptconfig.c +index fce8000..9391891 100644 +--- a/ldap/servers/plugins/pam_passthru/pam_ptconfig.c ++++ b/ldap/servers/plugins/pam_passthru/pam_ptconfig.c +@@ -603,6 +603,7 @@ pam_passthru_apply_config (Slapi_Entry* e) + PRCList *list; + Slapi_Attr *a = NULL; + char *filter_str = NULL; ++ int inserted = 0; + + pam_ident_attr = slapi_entry_attr_get_charptr(e, PAMPT_PAM_IDENT_ATTR); + map_method = slapi_entry_attr_get_charptr(e, PAMPT_MAP_METHOD_ATTR); +@@ -689,6 +690,7 @@ pam_passthru_apply_config (Slapi_Entry* e) + PR_INSERT_BEFORE(&(entry->list), list); + slapi_log_error(SLAPI_LOG_CONFIG, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, + "store [%s] at tail\n", entry->dn); ++ inserted = 1; + break; + } + } +@@ -697,9 +699,13 @@ pam_passthru_apply_config (Slapi_Entry* e) + PR_INSERT_LINK(&(entry->list), pam_passthru_global_config); + slapi_log_error(SLAPI_LOG_CONFIG, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, + "store [%s] at head \n", entry->dn); ++ inserted = 1; + } + + bail: ++ if(!inserted){ ++ pam_passthru_free_config_entry(&entry); ++ } + slapi_ch_free_string(&new_service); + slapi_ch_free_string(&map_method); + slapi_ch_free_string(&pam_ident_attr); +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 7b684e9..5ca7706 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -1745,7 +1745,7 @@ check_replicas_are_done_cleaning(cleanruv_data *data ) + { + Object *agmt_obj; + Repl_Agmt *agmt; +- char *csnstr = NULL; ++ char csnstr[CSN_STRSIZE]; + char *filter = NULL; + int not_all_cleaned = 1; + int interval = 10; +@@ -1788,7 +1788,6 @@ check_replicas_are_done_cleaning(cleanruv_data *data ) + interval = 14400; + } + } +- slapi_ch_free_string(&csnstr); + slapi_ch_free_string(&filter); + } + +diff --git a/ldap/servers/plugins/replication/windows_inc_protocol.c b/ldap/servers/plugins/replication/windows_inc_protocol.c +index cb3b3d2..15d69a3 100644 +--- a/ldap/servers/plugins/replication/windows_inc_protocol.c ++++ b/ldap/servers/plugins/replication/windows_inc_protocol.c +@@ -1026,6 +1026,7 @@ windows_inc_run(Private_Repl_Protocol *prp) + windows_conn_cancel_linger(prp->conn); + /* ... and disconnect, if currently connected */ + windows_conn_disconnect(prp->conn); ++ ruv_destroy ( &ruv ); + LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_inc_run\n" ); + } + +diff --git a/ldap/servers/plugins/syntaxes/value.c b/ldap/servers/plugins/syntaxes/value.c +index efef9a8..0335a89 100644 +--- a/ldap/servers/plugins/syntaxes/value.c ++++ b/ldap/servers/plugins/syntaxes/value.c +@@ -282,10 +282,13 @@ value_cmp( + value_normalize_ext( v1->bv_val, syntax, + 1 /* trim leading blanks */, &alt ); + if (alt) { ++ int inserted = 0; ++ + if (free_v1) { + slapi_ch_free_string(&v1->bv_val); + v1->bv_val = alt; + v1->bv_len = strlen(alt); ++ inserted = 1; + } else { + if (strlen(alt) < buffer_space) { + v1->bv_len = strlen(alt); +@@ -297,8 +300,12 @@ value_cmp( + v1 = (struct berval *)slapi_ch_malloc(sizeof(struct berval)); + v1->bv_val = alt; + v1->bv_len = strlen(alt); ++ inserted = 1; + } + } ++ if(!inserted){ ++ slapi_ch_free_string(&alt); ++ } + } + if (!free_v1) { + buffer_space -= v1->bv_len + 1; +@@ -320,10 +327,13 @@ value_cmp( + value_normalize_ext( v2->bv_val, syntax, + 1 /* trim leading blanks */, &alt ); + if (alt) { ++ int inserted = 0; ++ + if (free_v2) { + slapi_ch_free_string(&v2->bv_val); + v2->bv_val = alt; + v2->bv_len = strlen(alt); ++ inserted = 1; + } else { + if (strlen(alt) < buffer_space) { + v2->bv_len = strlen(alt); +@@ -335,8 +345,12 @@ value_cmp( + v2 = (struct berval *)slapi_ch_malloc(sizeof(struct berval)); + v2->bv_val = alt; + v2->bv_len = strlen(alt); ++ inserted = 1; + } + } ++ if(!inserted){ ++ slapi_ch_free_string(&alt); ++ } + } + if (!free_v2) { + buffer_space -= v2->bv_len + 1; +diff --git a/ldap/servers/slapd/agtmmap.c b/ldap/servers/slapd/agtmmap.c +index f18138a..3922547 100644 +--- a/ldap/servers/slapd/agtmmap.c ++++ b/ldap/servers/slapd/agtmmap.c +@@ -196,6 +196,7 @@ agt_mopen_stats (char * statsfile, int mode, int *hdl) + } + + if(fstat (fd, &fileinfo) != 0){ ++ close(fd); + rc = errno; + goto bail; + } +diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c +index 960d99e..cb8ef68 100644 +--- a/ldap/servers/slapd/back-ldbm/dblayer.c ++++ b/ldap/servers/slapd/back-ldbm/dblayer.c +@@ -1897,9 +1897,9 @@ dblayer_get_id2entry_size(ldbm_instance *inst) + { + struct ldbminfo *li = NULL; + char *id2entry_file = NULL; +- PRFileInfo info; ++ PRFileInfo64 info; + int rc; +- char inst_dir[MAXPATHLEN], *inst_dirp; ++ char inst_dir[MAXPATHLEN], *inst_dirp = NULL; + + if (NULL == inst) { + return 0; +@@ -1908,7 +1908,10 @@ dblayer_get_id2entry_size(ldbm_instance *inst) + inst_dirp = dblayer_get_full_inst_dir(li, inst, inst_dir, MAXPATHLEN); + id2entry_file = slapi_ch_smprintf("%s/%s", inst_dirp, + ID2ENTRY LDBM_FILENAME_SUFFIX); +- rc = PR_GetFileInfo(id2entry_file, &info); ++ if(inst_dirp != inst_dir){ ++ slapi_ch_free_string(&inst_dirp); ++ } ++ rc = PR_GetFileInfo64(id2entry_file, &info); + slapi_ch_free_string(&id2entry_file); + if (inst_dirp != inst_dir) + slapi_ch_free_string(&inst_dirp); +@@ -3069,6 +3072,9 @@ dblayer_open_file(backend *be, char* indexname, int open_flag, + } + abs_file_name = slapi_ch_smprintf("%s%c%s", + inst_dirp, get_sep(inst_dirp), file_name); ++ if (inst_dirp != inst_dir){ ++ slapi_ch_free_string(&inst_dirp); ++ } + DB_OPEN(pENV->dblayer_openflags, + dbp, NULL/* txnid */, abs_file_name, subname, DB_BTREE, + open_flags, priv->dblayer_file_mode, return_value); +@@ -3084,8 +3090,6 @@ dblayer_open_file(backend *be, char* indexname, int open_flag, + goto out; + + slapi_ch_free_string(&abs_file_name); +- if (inst_dirp != inst_dir) +- slapi_ch_free_string(&inst_dirp); + } + DB_OPEN(pENV->dblayer_openflags, + dbp, NULL, /* txnid */ rel_path, subname, DB_BTREE, +diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c +index f38c39e..a43dc21 100644 +--- a/ldap/servers/slapd/entry.c ++++ b/ldap/servers/slapd/entry.c +@@ -552,6 +552,7 @@ str2entry_fast( const char *rawdn, char *s, int flags, int read_stateinfo ) + } + + done: ++ csnset_free(&valuecsnset); + csn_free(&attributedeletioncsn); + csn_free(&maxcsn); + LDAPDebug( LDAP_DEBUG_TRACE, "<= str2entry_fast 0x%x\n", +@@ -744,6 +745,7 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo ) + ( 0 != ( flags & SLAPI_STR2ENTRY_REMOVEDUPVALS )); + Slapi_Value *value = 0; + CSN *attributedeletioncsn= NULL; ++ CSNSet *valuecsnset= NULL; + CSN *maxcsn= NULL; + char *normdn = NULL; + int strict = 0; +@@ -764,7 +766,6 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo ) + } + while ( (s = ldif_getline( &next )) != NULL ) + { +- CSNSet *valuecsnset= NULL; + int value_state= VALUE_NOTFOUND; + int attr_state= VALUE_NOTFOUND; + int freeval = 0; +@@ -819,6 +820,7 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo ) + "str2entry_dupcheck: Invalid DN: %s\n", rawdn); + slapi_entry_free( e ); + if (freeval) slapi_ch_free_string(&bvvalue.bv_val); ++ csnset_free(&valuecsnset); + csn_free(&attributedeletioncsn); + csn_free(&maxcsn); + return NULL; +@@ -841,6 +843,7 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo ) + "str2entry_dupcheck: Invalid DN: %s\n", rawdn); + slapi_entry_free( e ); + if (freeval) slapi_ch_free_string(&bvvalue.bv_val); ++ csnset_free(&valuecsnset); + csn_free(&attributedeletioncsn); + csn_free(&maxcsn); + return NULL; +@@ -954,6 +957,7 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo ) + if (freeval) slapi_ch_free_string(&bvvalue.bv_val); + csn_free(&attributedeletioncsn); + csn_free(&maxcsn); ++ csnset_free(&valuecsnset); + return NULL; + } + for ( i = 0; i < nattrs; i++ ) +@@ -1285,6 +1289,7 @@ free_and_return: + } + slapi_ch_free((void **) &dyn_attrs ); + if (value) slapi_value_free(&value); ++ csnset_free(&valuecsnset); + csn_free(&attributedeletioncsn); + csn_free(&maxcsn); + +diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c +index 1768c7e..258f6eb 100644 +--- a/ldap/servers/slapd/schema.c ++++ b/ldap/servers/slapd/schema.c +@@ -3083,11 +3083,11 @@ read_oc_ldif ( const char *input, struct objclass **oc, char *errorbuf, + pnew_oc->oc_kind = kind; + + *oc = pnew_oc; ++ + return read_oc_ldif_return( LDAP_SUCCESS, pOcOid, psbOcName, pOcSup, + oc_origins, num_origins, pOcDesc ); + } + +- + static void + oc_free( struct objclass **ocp ) + { +@@ -3969,7 +3969,9 @@ load_schema_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *ignored, + if ( LDAP_SUCCESS != (*returncode = read_oc_ldif(s, &oc, returntext, + SLAPI_DSE_RETURNTEXT_SIZE, flags, + primary_file /* force user defined? */, +- schema_ds4x_compat))) { ++ schema_ds4x_compat))) ++ { ++ oc_free( &oc ); + break; + } + if (flags & DSE_SCHEMA_NO_LOAD) +diff --git a/ldap/servers/slapd/snmp_collator.c b/ldap/servers/slapd/snmp_collator.c +index aeac7ae..b3d072a 100644 +--- a/ldap/servers/slapd/snmp_collator.c ++++ b/ldap/servers/slapd/snmp_collator.c +@@ -738,8 +738,10 @@ snmp_update_cache_stats() + + /* set the cache hits/cache entries info */ + be = slapi_get_first_backend(&cookie); +- if (!be) ++ if (!be){ ++ slapi_ch_free ((void **) &cookie); + return; ++ } + + be_next = slapi_get_next_backend(cookie); + +diff --git a/ldap/servers/slapd/tools/ldclt/data.c b/ldap/servers/slapd/tools/ldclt/data.c +index e0eac55..f6dd4ef 100644 +--- a/ldap/servers/slapd/tools/ldclt/data.c ++++ b/ldap/servers/slapd/tools/ldclt/data.c +@@ -335,6 +335,8 @@ exit: + #ifdef _WIN32 + if (findPath) free (findPath); + #endif ++ close(fd); ++ + return rc; + } + +diff --git a/ldap/servers/slapd/tools/mmldif.c b/ldap/servers/slapd/tools/mmldif.c +index 6d62338..fb97129 100644 +--- a/ldap/servers/slapd/tools/mmldif.c ++++ b/ldap/servers/slapd/tools/mmldif.c +@@ -735,6 +735,7 @@ readrec(edfFILE * edf1, attrib1_t ** attrib) + attrib1_t * newlist = NULL; + attrib1_t * a; + int ignore_rec = FALSE; ++ int free_it = 0; + + *attrib = NULL; + if (edf1->end) { +@@ -759,6 +760,9 @@ readrec(edfFILE * edf1, attrib1_t ** attrib) + /* that's for the case where the file */ + /* has a trailing blank line */ + freefreelist(freelist); ++ if(free_it){ ++ freefreelist(att); ++ } + return IDDS_MM_EOF; + } + break; /* return */ +@@ -790,9 +794,11 @@ readrec(edfFILE * edf1, attrib1_t ** attrib) + continue; + if (!freelist) { + att = (attrib1_t *)malloc(sizeof(attrib1_t)); ++ free_it = 1; + } else { + att = freelist; + freelist = freelist->next; ++ free_it = 0; + } + att->namelen = vptr-line; + +diff --git a/ldap/servers/snmp/main.c b/ldap/servers/snmp/main.c +index 0d1fb25..78d4814 100644 +--- a/ldap/servers/snmp/main.c ++++ b/ldap/servers/snmp/main.c +@@ -322,6 +322,9 @@ load_config(char *conf_path) + /* load agentx-master setting */ + p = p + 13; + if ((p = strtok(p, " \t\n")) != NULL) { ++ if (agentx_master){ ++ free(agentx_master); ++ } + if ((agentx_master = (char *) malloc(strlen(p) + 1)) != NULL) + strcpy(agentx_master, p); + } +diff --git a/lib/ldaputil/dbconf.c b/lib/ldaputil/dbconf.c +index 746afc9..e6de3b7 100644 +--- a/lib/ldaputil/dbconf.c ++++ b/lib/ldaputil/dbconf.c +@@ -263,7 +263,10 @@ static int dbconf_parse_propval (char *buf, char *ptr, + /* Success - we have prop & val */ + propval = (DBPropVal_t *)malloc(sizeof(DBPropVal_t)); + +- if (!propval) return LDAPU_ERR_OUT_OF_MEMORY; ++ if (!propval){ ++ if (encval) free(val); ++ return LDAPU_ERR_OUT_OF_MEMORY; ++ } + memset((void *)propval, 0, sizeof(DBPropVal_t)); + propval->prop = strdup(prop); + propval->val = val ? strdup(val) : 0; +@@ -273,7 +276,7 @@ static int dbconf_parse_propval (char *buf, char *ptr, + return LDAPU_ERR_OUT_OF_MEMORY; + } + +- if (encval) free(val); /* val was allocated by dbconf_decodeval */ ++ if(encval) free(val); /* val was allocated by dbconf_decodeval */ + + insert_dbinfo_propval(db_info, propval); + return LDAPU_SUCCESS; +diff --git a/lib/libaccess/register.cpp b/lib/libaccess/register.cpp +index 595c1f2..798a926 100644 +--- a/lib/libaccess/register.cpp ++++ b/lib/libaccess/register.cpp +@@ -793,6 +793,7 @@ ACL_AttrGetterRegister(NSErr_t *errp, const char *attr, ACLAttrGetterFn_t fn, + if (*hep == 0) { /* New entry */ + PR_INIT_CLIST(&getter->list); + if (NULL == PR_HashTableAdd(ACLAttrGetterHash, attr, (void *)getter)) { ++ FREE(getter); + ACL_CritExit(); + return -1; + } +diff --git a/lib/libadmin/error.c b/lib/libadmin/error.c +index c0a1f80..4ba9803 100644 +--- a/lib/libadmin/error.c ++++ b/lib/libadmin/error.c +@@ -126,10 +126,13 @@ NSAPI_PUBLIC void output_alert(int type, char *info, char *details, int wait) + fprintf(stdout, "%s:%s\\n%s", error_headers[type], info, wrapped); + if(type==FILE_ERROR || type==SYSTEM_ERROR) { + err = get_error(); +- if(err != 0) ++ if(err != 0){ ++ char *err_str = verbose_error(); + fprintf(stdout, + "\\n\\nThe system returned error number %d, " +- "which is %s.", err, verbose_error()); ++ "which is %s.", err, err_str); ++ FREE(err_str); ++ } + } + fprintf(stdout, "\");"); + +-- +1.8.1.4 + diff --git a/0093-Coverity-Fixes-Part-5.patch b/0093-Coverity-Fixes-Part-5.patch new file mode 100644 index 0000000..0dfc27e --- /dev/null +++ b/0093-Coverity-Fixes-Part-5.patch @@ -0,0 +1,282 @@ +From dd6f95cfdb5d95d6a2abba57082ef94206abab37 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Thu, 6 Jun 2013 11:28:07 -0400 +Subject: [PATCH 93/99] Coverity Fixes (Part 5) + +11784 - Deference before null check (uiduniq/uid.c) +11785 - Deference before null check (conntable.c) +11786 - Deference before null check (opshared.c) +11787 - Deference before null check (tools/dbscan.c) +11788 - Deference before null check (tools/dbscan.c) +11789 - Deference before null check (tools/dbscan.c) +11790 - Allocation size mismatch (idl.c) +11791 - Allocation size mismatch (idl.c) +11792 - Wrong sizeof argument (dna.c) +11793 - Stray semicolon (lib/base/util.c) +11794 - Stray semicolon (lib/base/util.c) +11795 - Destination buffer too small (log.c) +11809 - Use after free (repl5_mtnode_ext.c) +11849 - Unitialized sclara variable (dblayer.c) + +https://bugzilla.redhat.com/show_bug.cgi?id=970221 + +Reviewed by: richm(Thanks!!) +(cherry picked from commit 6d23891a44fd41aa0580cdc223667f0ca2b9e1cc) +(cherry picked from commit 9ac276a838636326811284a28695c0fdea4a8d03) +--- + ldap/servers/plugins/dna/dna.c | 2 +- + .../servers/plugins/replication/repl5_mtnode_ext.c | 6 ++- + ldap/servers/plugins/uiduniq/uid.c | 2 +- + ldap/servers/slapd/back-ldbm/idl.c | 4 +- + ldap/servers/slapd/conntable.c | 4 +- + ldap/servers/slapd/log.c | 54 +++++++++++----------- + ldap/servers/slapd/opshared.c | 4 +- + ldap/servers/slapd/tools/dbscan.c | 15 +++--- + lib/base/util.cpp | 2 +- + 9 files changed, 44 insertions(+), 49 deletions(-) + +diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c +index 958a4a7..f7e1004 100644 +--- a/ldap/servers/plugins/dna/dna.c ++++ b/ldap/servers/plugins/dna/dna.c +@@ -1865,7 +1865,7 @@ dna_first_free_value(struct configEntry *config_entry, + } else { + /* This is a single-type range, so just use the first (only) + * type from the list. */ +- ctrls = (LDAPControl **)slapi_ch_calloc(2, sizeof(LDAPControl)); ++ ctrls = (LDAPControl **)slapi_ch_calloc(2, sizeof(LDAPControl *)); + if (NULL == ctrls) + return LDAP_OPERATIONS_ERROR; + +diff --git a/ldap/servers/plugins/replication/repl5_mtnode_ext.c b/ldap/servers/plugins/replication/repl5_mtnode_ext.c +index dd0d261..9b61920 100644 +--- a/ldap/servers/plugins/replication/repl5_mtnode_ext.c ++++ b/ldap/servers/plugins/replication/repl5_mtnode_ext.c +@@ -110,8 +110,10 @@ multimaster_mtnode_construct_replicas () + ext->replica = object_new(r, replica_destroy); + if (replica_add_by_name (replica_get_name (r), ext->replica) != 0) + { +- object_release (ext->replica); +- ext->replica = NULL; ++ if(ext->replica){ ++ object_release (ext->replica); ++ ext->replica = NULL; ++ } + } + } + } +diff --git a/ldap/servers/plugins/uiduniq/uid.c b/ldap/servers/plugins/uiduniq/uid.c +index d9e6ba4..984b93e 100644 +--- a/ldap/servers/plugins/uiduniq/uid.c ++++ b/ldap/servers/plugins/uiduniq/uid.c +@@ -509,7 +509,7 @@ findSubtreeAndSearch(Slapi_DN *parentDN, const char *attrName, Slapi_Attr *attr, + Slapi_DN *newpar = NULL; + + slapi_sdn_get_parent(parentDN, curpar); +- while ((curpar != NULL) && (slapi_sdn_get_dn(curpar) != NULL)) ++ while (slapi_sdn_get_dn(curpar) != NULL) + { + if ((spb = dnHasObjectClass(curpar, markerObjectClass))) + { +diff --git a/ldap/servers/slapd/back-ldbm/idl.c b/ldap/servers/slapd/back-ldbm/idl.c +index 58736f8..76ee252 100644 +--- a/ldap/servers/slapd/back-ldbm/idl.c ++++ b/ldap/servers/slapd/back-ldbm/idl.c +@@ -1247,7 +1247,7 @@ void idl_insert(IDList **idl, ID id) + (*idl)->b_nmax *= 2; + + (*idl) = (IDList *) slapi_ch_realloc( (char *) (*idl), +- ((*idl)->b_nmax + 2) * sizeof(ID) ); ++ ((*idl)->b_nmax + 2) * sizeof(ID) + sizeof(IDList) ); + } + + /* make a slot for the new id */ +@@ -1345,7 +1345,7 @@ idl_insert_maxids( IDList **idl, ID id, int maxids ) + (*idl)->b_nmax = maxids; + } + *idl = (IDList *) slapi_ch_realloc( (char *) *idl, +- ((*idl)->b_nmax + 2) * sizeof(ID) ); ++ ((*idl)->b_nmax + 2) * sizeof(ID) + sizeof(IDList)); + } + + /* make a slot for the new id */ +diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c +index df4f2f8..7cf9f31 100644 +--- a/ldap/servers/slapd/conntable.c ++++ b/ldap/servers/slapd/conntable.c +@@ -444,9 +444,7 @@ connection_table_as_entry(Connection_Table *ct, Slapi_Entry *e) + val.bv_val = bufptr; + val.bv_len = strlen( bufptr ); + attrlist_merge( &e->e_attrs, "connection", vals ); +- if (newbuf) { +- slapi_ch_free_string(&newbuf); +- } ++ slapi_ch_free_string(&newbuf); + } + PR_Unlock( ct->c[i].c_mutex ); + } +diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c +index 72a918b..c6131fb 100644 +--- a/ldap/servers/slapd/log.c ++++ b/ldap/servers/slapd/log.c +@@ -2058,7 +2058,7 @@ static int vslapd_log_access(char *fmt, va_list ap) + int blen, vlen; + /* info needed to keep us from calling localtime/strftime so often: */ + static time_t old_time = 0; +- static char old_tbuf[TBUFSIZE]; ++ static char old_tbuf[SLAPI_LOG_BUFSIZ]; + static int old_blen = 0; + + tnl = current_time(); +@@ -2066,11 +2066,11 @@ static int vslapd_log_access(char *fmt, va_list ap) + /* check if we can use the old strftime buffer */ + PR_Lock(ts_time_lock); + if (tnl == old_time) { +- strcpy(buffer, old_tbuf); +- blen = old_blen; +- PR_Unlock(ts_time_lock); ++ strcpy(buffer, old_tbuf); ++ blen = old_blen; ++ PR_Unlock(ts_time_lock); + } else { +- /* nope... painstakingly create the new strftime buffer */ ++ /* nope... painstakingly create the new strftime buffer */ + #ifdef _WIN32 + { + struct tm *pt = localtime( &tnl ); +@@ -2078,39 +2078,39 @@ static int vslapd_log_access(char *fmt, va_list ap) + memcpy(&tms, pt, sizeof(struct tm) ); + } + #else +- (void)localtime_r( &tnl, &tms ); +- tmsp = &tms; ++ (void)localtime_r( &tnl, &tms ); ++ tmsp = &tms; + #endif + + #ifdef BSD_TIME +- tz = tmsp->tm_gmtoff; ++ tz = tmsp->tm_gmtoff; + #else /* BSD_TIME */ +- tz = - timezone; +- if ( tmsp->tm_isdst ) { +- tz += 3600; +- } ++ tz = - timezone; ++ if ( tmsp->tm_isdst ) { ++ tz += 3600; ++ } + #endif /* BSD_TIME */ +- sign = ( tz >= 0 ? '+' : '-' ); +- if ( tz < 0 ) { +- tz = -tz; +- } +- (void)strftime( tbuf, (size_t)TBUFSIZE, "%d/%b/%Y:%H:%M:%S", tmsp); +- sprintf( buffer, "[%s %c%02d%02d] ", tbuf, sign, +- (int)( tz / 3600 ), (int)( tz % 3600)); +- old_time = tnl; +- strcpy(old_tbuf, buffer); +- blen = strlen(buffer); +- old_blen = blen; +- PR_Unlock(ts_time_lock); ++ sign = ( tz >= 0 ? '+' : '-' ); ++ if ( tz < 0 ) { ++ tz = -tz; ++ } ++ (void)strftime( tbuf, (size_t)TBUFSIZE, "%d/%b/%Y:%H:%M:%S", tmsp); ++ sprintf( buffer, "[%s %c%02d%02d] ", tbuf, sign, ++ (int)( tz / 3600 ), (int)( tz % 3600)); ++ old_time = tnl; ++ strcpy(old_tbuf, buffer); ++ blen = strlen(buffer); ++ old_blen = blen; ++ PR_Unlock(ts_time_lock); + } + +- vlen = PR_vsnprintf(vbuf, SLAPI_LOG_BUFSIZ, fmt, ap); ++ vlen = PR_vsnprintf(vbuf, SLAPI_LOG_BUFSIZ, fmt, ap); + if (! vlen) { +- return -1; ++ return -1; + } + + if (SLAPI_LOG_BUFSIZ - blen < vlen) { +- return -1; ++ return -1; + } + + log_append_buffer2(tnl, loginfo.log_access_buffer, buffer, blen, vbuf, vlen); +diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c +index a96b950..1689283 100644 +--- a/ldap/servers/slapd/opshared.c ++++ b/ldap/servers/slapd/opshared.c +@@ -1090,9 +1090,7 @@ process_entry(Slapi_PBlock *pb, Slapi_Entry *e, int send_result) + ber_bvecfree(refscopy); + refscopy = NULL; + } +- if( NULL != tmpUrls) { +- slapi_ch_free( (void **)&tmpUrls ); +- } ++ slapi_ch_free( (void **)&tmpUrls ); + } + + return 1; /* done with this entry */ +diff --git a/ldap/servers/slapd/tools/dbscan.c b/ldap/servers/slapd/tools/dbscan.c +index 6b0f525..d84f138 100644 +--- a/ldap/servers/slapd/tools/dbscan.c ++++ b/ldap/servers/slapd/tools/dbscan.c +@@ -825,10 +825,9 @@ display_entryrdn_self(DB *db, ID id, const char *nrdn, int indent) + display_entryrdn_children(db, id_stored_to_internal(elem->rdn_elem_id), + elem->rdn_elem_nrdn_rdn, indent); + bail: +- if (keybuf) { +- free(keybuf); +- } ++ free(keybuf); + cursor->c_close(cursor); ++ + return; + } + +@@ -866,10 +865,9 @@ display_entryrdn_parent(DB *db, ID id, const char *nrdn, int indent) + elem = (rdn_elem *)data.data; + _entryrdn_dump_rdn_elem(keybuf, elem, indent); + bail: +- if (keybuf) { +- free(keybuf); +- } ++ free(keybuf); + cursor->c_close(cursor); ++ + return; + } + +@@ -939,10 +937,9 @@ display_entryrdn_children(DB *db, ID id, const char *nrdn, int indent) + } + } + bail: +- if (keybuf) { +- free(keybuf); +- } ++ free(keybuf); + cursor->c_close(cursor); ++ + return; + } + +diff --git a/lib/base/util.cpp b/lib/base/util.cpp +index b198154..01f916d 100644 +--- a/lib/base/util.cpp ++++ b/lib/base/util.cpp +@@ -253,7 +253,7 @@ static char *Bfmt[] = { + + static void _util_strftime_conv(char *, int, int, char); + +-#define _util_strftime_add(str) for (;(*pt = *str++); pt++); ++#define _util_strftime_add(str) for (;(*pt = *str++); pt++) + #define _util_strftime_copy(str, len) memcpy(pt, str, len); pt += len; + #define _util_strftime_fmt util_strftime + +-- +1.8.1.4 + diff --git a/0094-Fri-Jun-7-10-41-00-2013-0400.patch b/0094-Fri-Jun-7-10-41-00-2013-0400.patch new file mode 100644 index 0000000..cacfd0a --- /dev/null +++ b/0094-Fri-Jun-7-10-41-00-2013-0400.patch @@ -0,0 +1,204 @@ +From f167a9e8a462c1b5deb7e5a3c36b989672e0fd0b Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 7 Jun 2013 11:15:27 -0400 +Subject: [PATCH 94/99] Fri Jun 7 10:41:00 2013 -0400 + + Coverity Fixes (Part 6) + + 11611 - Unchecked value (main.c) + 11671 - Copy-paste error (cb_instance.c) + 11704 - Dereference after null check (repl5_replica_config.c) + 11766 - Resource leak (dblayer.c) + 11873 - Argument can not be negative (ldclt/data.c) + Jenkins error: mmldif.c + 11876 - Deference before null check (cl5_clcache.c) + + https://bugzilla.redhat.com/show_bug.cgi?id=970221 + + Reviewed by: Rich(Thanks!) +(cherry picked from commit 4a0199b3c3a73b094a7bff64404a632c3bfe7072) +(cherry picked from commit 8212d48b57adf223c7022dba4fbdb70e7aa2080e) +--- + ldap/servers/plugins/chainingdb/cb_instance.c | 2 +- + ldap/servers/plugins/replication/cl5_clcache.c | 4 +--- + ldap/servers/plugins/replication/repl5_replica_config.c | 3 ++- + ldap/servers/slapd/back-ldbm/dblayer.c | 10 +++++----- + ldap/servers/slapd/main.c | 7 +++++-- + ldap/servers/slapd/tools/ldclt/data.c | 17 ++++++++++------- + ldap/servers/slapd/tools/mmldif.c | 2 +- + 7 files changed, 25 insertions(+), 20 deletions(-) + +diff --git a/ldap/servers/plugins/chainingdb/cb_instance.c b/ldap/servers/plugins/chainingdb/cb_instance.c +index 8fb694a..95781b5 100644 +--- a/ldap/servers/plugins/chainingdb/cb_instance.c ++++ b/ldap/servers/plugins/chainingdb/cb_instance.c +@@ -1437,7 +1437,7 @@ static int cb_instance_bindmech_set(void *arg, void *value, char *errorbuf, int + charray_add(&inst->pool->waste_basket,inst->pool->mech); + } + if (inst->bind_pool->mech) { +- charray_add(&inst->pool->waste_basket,inst->bind_pool->mech); ++ charray_add(&inst->bind_pool->waste_basket,inst->bind_pool->mech); + } + rc=CB_REOPEN_CONN; + } +diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c +index 67e64f5..7a6a446 100644 +--- a/ldap/servers/plugins/replication/cl5_clcache.c ++++ b/ldap/servers/plugins/replication/cl5_clcache.c +@@ -752,9 +752,7 @@ clcache_skip_change ( CLC_Buffer *buf ) + (csn_get_seqnum(buf->buf_current_csn) == + csn_get_seqnum(cscb->local_maxcsn) + 1) ) + { +- if(cscb->local_maxcsn){ +- csn_init_by_csn ( cscb->local_maxcsn, buf->buf_current_csn ); +- } ++ csn_init_by_csn ( cscb->local_maxcsn, buf->buf_current_csn ); + if(cscb->consumer_maxcsn){ + csn_init_by_csn ( cscb->consumer_maxcsn, buf->buf_current_csn ); + } +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 5ca7706..0b72bec 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -2352,7 +2352,7 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){ + static void + delete_cleaned_rid_config(cleanruv_data *clean_data) + { +- Slapi_PBlock *pb = slapi_pblock_new(); ++ Slapi_PBlock *pb; + Slapi_Entry **entries = NULL; + LDAPMod *mods[2]; + LDAPMod mod; +@@ -2381,6 +2381,7 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + /* + * Search the config for the exact attribute value to delete + */ ++ pb = slapi_pblock_new(); + dn = replica_get_dn(clean_data->replica); + slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_SUBTREE, "nsds5ReplicaCleanRUV=*", NULL, 0, NULL, NULL, + (void *)plugin_get_default_component_id(), 0); +diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c +index cb8ef68..fab61f3 100644 +--- a/ldap/servers/slapd/back-ldbm/dblayer.c ++++ b/ldap/servers/slapd/back-ldbm/dblayer.c +@@ -2996,6 +2996,8 @@ dblayer_open_file(backend *be, char* indexname, int open_flag, + int return_value = 0; + DB *dbp = NULL; + char *subname = NULL; ++ char inst_dir[MAXPATHLEN]; ++ char *inst_dirp = NULL; + + PR_ASSERT(NULL != li); + priv = (dblayer_private*)li->li_dblayer_private; +@@ -3059,8 +3061,6 @@ dblayer_open_file(backend *be, char* indexname, int open_flag, + inst->inst_parent_dir_name) > 0) && + !dblayer_inst_exists(inst, file_name)) + { +- char inst_dir[MAXPATHLEN]; +- char *inst_dirp = NULL; + char *abs_file_name = NULL; + /* create a file with abs path, then try again */ + +@@ -3072,9 +3072,6 @@ dblayer_open_file(backend *be, char* indexname, int open_flag, + } + abs_file_name = slapi_ch_smprintf("%s%c%s", + inst_dirp, get_sep(inst_dirp), file_name); +- if (inst_dirp != inst_dir){ +- slapi_ch_free_string(&inst_dirp); +- } + DB_OPEN(pENV->dblayer_openflags, + dbp, NULL/* txnid */, abs_file_name, subname, DB_BTREE, + open_flags, priv->dblayer_file_mode, return_value); +@@ -3107,6 +3104,9 @@ dblayer_open_file(backend *be, char* indexname, int open_flag, + out: + slapi_ch_free((void**)&file_name); + slapi_ch_free((void**)&rel_path); ++ if (inst_dirp != inst_dir){ ++ slapi_ch_free_string(&inst_dirp); ++ } + /* close the database handle to avoid handle leak */ + if (dbp && (return_value != 0)) { + dblayer_close_file(dbp); +diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c +index 9938c01..53cb5c8 100644 +--- a/ldap/servers/slapd/main.c ++++ b/ldap/servers/slapd/main.c +@@ -232,7 +232,10 @@ chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn, PRBool both) + if((ptr=strrchr(log,'/'))==NULL) + { + LDAPDebug(LDAP_DEBUG_ANY, "Caution changing ownership of ./%s \n",name,0,0); +- slapd_chown_if_not_owner(log, pw->pw_uid, -1 ); ++ if(slapd_chown_if_not_owner(log, pw->pw_uid, -1 )){ ++ LDAPDebug(LDAP_DEBUG_ANY, "chown_dir_files: file (%s) chown failed (%d) %s.\n", ++ log, errno, slapd_system_strerror(errno)); ++ } + rc=1; + } else if(log==ptr) { + LDAPDebug(LDAP_DEBUG_ANY, "Caution changing ownership of / directory and its contents to %s\n",pw->pw_name,0,0); +@@ -247,7 +250,7 @@ chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn, PRBool both) + while( (entry = PR_ReadDir(dir , PR_SKIP_BOTH )) !=NULL ) + { + PR_snprintf(file,MAXPATHLEN+1,"%s/%s",log,entry->name); +- if((rc = slapd_chown_if_not_owner( file, pw->pw_uid, both?pw->pw_gid:-1 )) != 0){ ++ if(slapd_chown_if_not_owner( file, pw->pw_uid, both?pw->pw_gid:-1 )){ + LDAPDebug(LDAP_DEBUG_ANY, "chown_dir_files: file (%s) chown failed (%d) %s.\n", + file, errno, slapd_system_strerror(errno)); + } +diff --git a/ldap/servers/slapd/tools/ldclt/data.c b/ldap/servers/slapd/tools/ldclt/data.c +index f6dd4ef..45016d8 100644 +--- a/ldap/servers/slapd/tools/ldclt/data.c ++++ b/ldap/servers/slapd/tools/ldclt/data.c +@@ -143,7 +143,7 @@ int loadImages ( + char *fileName; /* As read from the system */ + char name [1024]; /* To build the full path */ + struct stat stat_buf; /* To read the image size */ +- int fd; /* To open the image */ ++ int fd = -1; /* To open the image */ + int ret; /* Return value */ + int rc = 0; + +@@ -303,11 +303,13 @@ int loadImages ( + */ + if (close (fd) < 0) + { +- perror (name); +- fprintf (stderr, "Cannot close(%s)\n", name); +- fflush (stderr); +- rc = -1; +- goto exit; ++ perror (name); ++ fprintf (stderr, "Cannot close(%s)\n", name); ++ fflush (stderr); ++ rc = -1; ++ goto exit; ++ } else { ++ fd = -1; + } + } + #ifdef _WIN32 +@@ -335,7 +337,8 @@ exit: + #ifdef _WIN32 + if (findPath) free (findPath); + #endif +- close(fd); ++ if(fd != -1) ++ close(fd); + + return rc; + } +diff --git a/ldap/servers/slapd/tools/mmldif.c b/ldap/servers/slapd/tools/mmldif.c +index fb97129..1f01976 100644 +--- a/ldap/servers/slapd/tools/mmldif.c ++++ b/ldap/servers/slapd/tools/mmldif.c +@@ -729,7 +729,7 @@ readrec(edfFILE * edf1, attrib1_t ** attrib) + int toolong = FALSE; + int rc; + int cmp; +- attrib1_t * att; ++ attrib1_t * att = NULL; + attrib1_t ** prev; + attrib1_t * freelist = *attrib; + attrib1_t * newlist = NULL; +-- +1.8.1.4 + diff --git a/0095-Coverity-Fixes-Part-7.patch b/0095-Coverity-Fixes-Part-7.patch new file mode 100644 index 0000000..b01b744 --- /dev/null +++ b/0095-Coverity-Fixes-Part-7.patch @@ -0,0 +1,46 @@ +From 470ff92cb147334a4a59822eb2f15c67e34af3a7 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Fri, 14 Jun 2013 15:28:57 -0400 +Subject: [PATCH 95/99] Coverity Fixes (Part 7) + +11704 - Dereference after null check: repl5_replica_config.c + +https://bugzilla.redhat.com/show_bug.cgi?id=970221 + +Reviewed by: richm(Thanks!) +(cherry picked from commit a2cfcf7ff93bf2ef7a3cf4ad2ba2c4e0bd098a3a) +(cherry picked from commit e3b8e2f82b3d5b6223c65db8649e7ddcb46ee916) +--- + ldap/servers/plugins/replication/repl5_replica_config.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 0b72bec..c2ad504 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -2382,6 +2382,13 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + * Search the config for the exact attribute value to delete + */ + pb = slapi_pblock_new(); ++ if(clean_data->replica){ ++ dn = replica_get_dn(clean_data->replica); ++ } else { ++ rc = -1; ++ goto bail; ++ } ++ + dn = replica_get_dn(clean_data->replica); + slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_SUBTREE, "nsds5ReplicaCleanRUV=*", NULL, 0, NULL, NULL, + (void *)plugin_get_default_component_id(), 0); +@@ -2445,6 +2452,8 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); + slapi_modify_internal_pb (pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); ++ ++bail: + if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config " + "(%d), rid (%d)\n", rc, clean_data->rid); +-- +1.8.1.4 + diff --git a/0096-fix-compiler-warning.patch b/0096-fix-compiler-warning.patch new file mode 100644 index 0000000..108f5bd --- /dev/null +++ b/0096-fix-compiler-warning.patch @@ -0,0 +1,28 @@ +From 344d755e78e7600bfd3bea39b83c7d3584aa325f Mon Sep 17 00:00:00 2001 +From: Ludwig Krispenz +Date: Tue, 30 Jul 2013 11:29:47 +0200 +Subject: [PATCH 96/99] fix compiler warning (cherry picked from commit + 904416f4631d842a105851b4a9931ae17822a107) (cherry picked from commit + 3a5f8de21fba3656670b8ee35e020f159d4110db) (cherry picked from commit + efcb1af30b63f91d3235914962bd4aa399bc08ba) (cherry picked from commit + d9a1c7b527d7252195fac15636c22101ceb775bf) + +--- + ldap/servers/plugins/acl/aclutil.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ldap/servers/plugins/acl/aclutil.c b/ldap/servers/plugins/acl/aclutil.c +index 2002276..4f81bc0 100644 +--- a/ldap/servers/plugins/acl/aclutil.c ++++ b/ldap/servers/plugins/acl/aclutil.c +@@ -1400,7 +1400,6 @@ void acl_ht_add_and_freeOld(acl_ht_t * acl_ht, + void acl_ht_remove_and_free(acl_ht_t * acl_ht, + PLHashNumber key){ + char *old_value = NULL; +- uintptr_t pkey = (uintptr_t)key; + + if ( (old_value = (char *)acl_ht_lookup( acl_ht, key)) != NULL ) { + acl_ht_remove( acl_ht, key); +-- +1.8.1.4 + diff --git a/0097-fix-compiler-warning-in-posix-winsync-code-for-posix.patch b/0097-fix-compiler-warning-in-posix-winsync-code-for-posix.patch new file mode 100644 index 0000000..ce2c383 --- /dev/null +++ b/0097-fix-compiler-warning-in-posix-winsync-code-for-posix.patch @@ -0,0 +1,36 @@ +From 81d3e71027c8e702eba9961afa0220ae5e28066e Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 31 Jul 2013 09:53:52 -0600 +Subject: [PATCH 97/99] fix compiler warning in posix winsync code for + posix_group_del_memberuid_callback (cherry picked from commit + f440e039a5f2a7b2ea0dd087d8e91c554abc1be0) (cherry picked from commit + 761d9d550ca1025293dc1607760adea38ddc5452) (cherry picked from commit + 9750ea73014b36349040e166a469ed09236c2549) + +--- + ldap/servers/plugins/posix-winsync/posix-group-task.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ldap/servers/plugins/posix-winsync/posix-group-task.c b/ldap/servers/plugins/posix-winsync/posix-group-task.c +index 1d9135d..05c43af 100644 +--- a/ldap/servers/plugins/posix-winsync/posix-group-task.c ++++ b/ldap/servers/plugins/posix-winsync/posix-group-task.c +@@ -174,6 +174,7 @@ posix_group_task_destructor(Slapi_Task *task) + } + } + ++#ifdef USE_POSIX_GROUP_DEL_MEMBERUID + static int + posix_group_del_memberuid_callback(Slapi_Entry *e, void *callback_data) + { +@@ -208,6 +209,7 @@ posix_group_del_memberuid_callback(Slapi_Entry *e, void *callback_data) + + return rc; + } ++#endif + + static int + posix_group_fix_memberuid(char *dn, char *filter_str, void *txn) +-- +1.8.1.4 + diff --git a/0098-fix-coverity-11915-dead-code-introduced-with-fix-for.patch b/0098-fix-coverity-11915-dead-code-introduced-with-fix-for.patch new file mode 100644 index 0000000..db77259 --- /dev/null +++ b/0098-fix-coverity-11915-dead-code-introduced-with-fix-for.patch @@ -0,0 +1,40 @@ +From a56e266c80ed587d4b622b1c7247b4f8fb081eb1 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 31 Jul 2013 10:52:21 -0600 +Subject: [PATCH 98/99] fix coverity 11915 - dead code - introduced with fix + for ticket 346 + +just get rid of unused variable was_present_null +reviewed by: nhosoi (Thanks!) +(cherry picked from commit ba70aac1991a04455ba83362e22c33f7f6ab227a) +(cherry picked from commit fcf4154b73681752a5ac32954a1d25771a75478e) +(cherry picked from commit 67694e7a95f72067bba84e0f6af4ff1c4af89a9e) +(cherry picked from commit dc9192efc1c502e53e54291a8afda33f56a97d03) +--- + ldap/servers/slapd/attr.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c +index 87dfe1e..ed6d8de 100644 +--- a/ldap/servers/slapd/attr.c ++++ b/ldap/servers/slapd/attr.c +@@ -767,7 +767,6 @@ attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn) + int i = 0; + int numofvals = 0; + int duplicate_index = -1; +- int was_present_null = 0; + int rc = LDAP_SUCCESS; + + if (valuearray_isempty(vals)) { +@@ -866,7 +865,7 @@ attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn) + duplicate_string, + a->a_type, + dn ? dn : "", +- (was_present_null ? "duplicate new value" : "value exists")); ++ "value exists"); + } + return( rc ); + } +-- +1.8.1.4 + diff --git a/0099-Revert-fix-coverity-11915-dead-code-introduced-with-.patch b/0099-Revert-fix-coverity-11915-dead-code-introduced-with-.patch new file mode 100644 index 0000000..4241073 --- /dev/null +++ b/0099-Revert-fix-coverity-11915-dead-code-introduced-with-.patch @@ -0,0 +1,36 @@ +From eedc572f10eb41550ef2097dfee6cab3f9afaec8 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 31 Jul 2013 13:25:00 -0600 +Subject: [PATCH 99/99] Revert "fix coverity 11915 - dead code - introduced + with fix for ticket 346" + +This reverts commit dc9192efc1c502e53e54291a8afda33f56a97d03. +(cherry picked from commit 6b1cdd506eecfe575fe248e25d498fd07d512736) +--- + ldap/servers/slapd/attr.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c +index ed6d8de..87dfe1e 100644 +--- a/ldap/servers/slapd/attr.c ++++ b/ldap/servers/slapd/attr.c +@@ -767,6 +767,7 @@ attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn) + int i = 0; + int numofvals = 0; + int duplicate_index = -1; ++ int was_present_null = 0; + int rc = LDAP_SUCCESS; + + if (valuearray_isempty(vals)) { +@@ -865,7 +866,7 @@ attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn) + duplicate_string, + a->a_type, + dn ? dn : "", +- "value exists"); ++ (was_present_null ? "duplicate new value" : "value exists")); + } + return( rc ); + } +-- +1.8.1.4 + diff --git a/0100-Ticket-47318-server-fails-to-start-after-upgrade-sch.patch b/0100-Ticket-47318-server-fails-to-start-after-upgrade-sch.patch new file mode 100644 index 0000000..fd0e295 --- /dev/null +++ b/0100-Ticket-47318-server-fails-to-start-after-upgrade-sch.patch @@ -0,0 +1,37 @@ +From a8d0400ecca1acc279328fec4cc1b0d056ac7b80 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 8 Apr 2013 20:13:01 -0400 +Subject: [PATCH 100/101] Ticket 47318 - server fails to start after + upgrade(schema error) + +Bug Description: After upgrading the server fails to start because the Root DN + access control plugin's entry changed to include nsslapd-Plugin + objectclass. + +Fix Description: Update the schema to allow nsslapd-plugin-depends-on-type in + the nsslapdPlugin objectclass. + +https://fedorahosted.org/389/ticket/47318 + +Reviewed by: nhosoi(Thanks!) +(cherry picked from commit b139ff8e404bccacf88c34c03637da0e9c4c2a0d) +--- + ldap/schema/01core389.ldif | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif +index c99c34c..4f859d2 100644 +--- a/ldap/schema/01core389.ldif ++++ b/ldap/schema/01core389.ldif +@@ -156,7 +156,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2156 NAME 'nsslapd-sasl-max-buffer-size' + # objectclasses + # + objectClasses: ( 2.16.840.1.113730.3.2.40 NAME 'directoryServerFeature' DESC 'Netscape defined objectclass' SUP top MAY ( oid $ cn $ multiLineDescription ) X-ORIGIN 'Netscape Directory Server' ) +-objectClasses: ( 2.16.840.1.113730.3.2.41 NAME 'nsslapdPlugin' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsslapd-pluginPath $ nsslapd-pluginInitFunc $ nsslapd-pluginType $ nsslapd-pluginId $ nsslapd-pluginVersion $ nsslapd-pluginVendor $ nsslapd-pluginDescription $ nsslapd-pluginEnabled ) MAY ( nsslapd-pluginConfigArea ) X-ORIGIN 'Netscape Directory Server' ) ++objectClasses: ( 2.16.840.1.113730.3.2.41 NAME 'nsslapdPlugin' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsslapd-pluginPath $ nsslapd-pluginInitFunc $ nsslapd-pluginType $ nsslapd-pluginId $ nsslapd-pluginVersion $ nsslapd-pluginVendor $ nsslapd-pluginDescription $ nsslapd-pluginEnabled ) MAY ( nsslapd-pluginConfigArea $ nsslapd-plugin-depends-on-type ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.44 NAME 'nsIndex' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSystemIndex ) MAY ( description $ nsIndexType $ nsMatchingRule ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.109 NAME 'nsBackendInstance' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.110 NAME 'nsMappingTree' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' ) +-- +1.8.1.4 + diff --git a/0101-Bug-999634-ns-slapd-crash-due-to-bogus-DN.patch b/0101-Bug-999634-ns-slapd-crash-due-to-bogus-DN.patch new file mode 100644 index 0000000..6eb62d6 --- /dev/null +++ b/0101-Bug-999634-ns-slapd-crash-due-to-bogus-DN.patch @@ -0,0 +1,58 @@ +From deb4426cae8be62cc7531862b0232fb818bb807b Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Fri, 23 Aug 2013 14:16:29 -0600 +Subject: [PATCH 101/101] Bug 999634 - ns-slapd crash due to bogus DN + +https://bugzilla.redhat.com/show_bug.cgi?id=999634 +Reviewed by: ??? +Branch: rhel-6.5 +Fix Description: When the target DN is not a valid DN, the code will bypass +the initialization of unhashed_pw_smod, and attempt to call slapi_smods_done. +Depending on what memory is in the unhashed_pw_smod, if both mods and +free_mods are true, an attempt will be made to free mods or *mods and the +server will crash. It is tricky to find the right sequence of operations +that will write the stack in such a way that both unhashed_pw_smod.mods +and unhashed_pw_smod.free_mods are set. +The fix is to just get rid of unhashed_pw_smod which is not used. +I also check this code and other operation code for similar cases, but the +rest of the code is clean. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit a3d65ac00df871675896f587b0da2c24eab961bb) +--- + ldap/servers/slapd/modify.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c +index da742da..5e52f26 100644 +--- a/ldap/servers/slapd/modify.c ++++ b/ldap/servers/slapd/modify.c +@@ -642,7 +642,6 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw) + int passin_sdn = 0; + LDAPMod **mods, *pw_mod, **tmpmods = NULL; + Slapi_Mods smods; +- Slapi_Mods unhashed_pw_smod; + int repl_op, internal_op, lastmod, skip_modified_attrs; + char *unhashed_pw_attr = NULL; + Slapi_Operation *operation; +@@ -681,8 +680,6 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw) + + slapi_mods_init_passin (&smods, mods); + +- slapi_mods_init(&unhashed_pw_smod, 0); +- + /* target spec is used to decide which plugins are applicable for the operation */ + operation_set_target_spec (pb->pb_op, sdn); + +@@ -1008,7 +1005,6 @@ free_and_return: + if (be) + slapi_be_Unlock(be); + +- slapi_mods_done(&unhashed_pw_smod); /* can finalize now */ + if (unhashed_pw_attr) + slapi_ch_free ((void**)&unhashed_pw_attr); + +-- +1.8.1.4 + diff --git a/0102-Ticket-47427-Overflow-in-nsslapd-disk-monitoring-thr.patch b/0102-Ticket-47427-Overflow-in-nsslapd-disk-monitoring-thr.patch new file mode 100644 index 0000000..f445010 --- /dev/null +++ b/0102-Ticket-47427-Overflow-in-nsslapd-disk-monitoring-thr.patch @@ -0,0 +1,37 @@ +From 14655088af87f0f7244cb49351726fe89f8a9ef8 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 17 Sep 2013 14:04:46 -0700 +Subject: [PATCH] Ticket 47427 - Overflow in nsslapd-disk-monitoring-threshold + +Bug Description: Using ldapsearch shows threshold value as a negative number, even + though the feature is working correctly. + +Fix Description: When readingthe dse, the server was trying to cast the value as a "int". + Changed CONFIG_INT to CONFIG_LONG for nsslapd-disk-monioring-threshold. + +https://fedorahosted.org/389/ticket/47427 + +Manually cherry picked: + commit 5a0d74ab8030233bcde9aa787ba7a2929a75e267 + commit 23a6383357990ea8f17fec9af155313d0a186af6 +from 389-ds-base-1.2.11 branch. +--- + ldap/servers/slapd/libglobs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c +index f7d4ec3..aaee33a 100644 +--- a/ldap/servers/slapd/libglobs.c ++++ b/ldap/servers/slapd/libglobs.c +@@ -679,7 +679,7 @@ static struct config_get_and_set { + (ConfigGetFunc)config_get_disk_monitoring}, + {CONFIG_DISK_THRESHOLD, config_set_disk_threshold, + NULL, 0, +- (void**)&global_slapdFrontendConfig.disk_threshold, CONFIG_INT, ++ (void**)&global_slapdFrontendConfig.disk_threshold, CONFIG_LONG, + (ConfigGetFunc)config_get_disk_threshold}, + {CONFIG_DISK_GRACE_PERIOD, config_set_disk_grace_period, + NULL, 0, +-- +1.8.1.4 + diff --git a/0103-Ticket-47523-Set-up-replcation-agreement-before-init.patch b/0103-Ticket-47523-Set-up-replcation-agreement-before-init.patch new file mode 100644 index 0000000..8d54612 --- /dev/null +++ b/0103-Ticket-47523-Set-up-replcation-agreement-before-init.patch @@ -0,0 +1,195 @@ +From 3088c7e0776754c2d750d2871c77338eb9590fb7 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Thu, 26 Sep 2013 09:18:11 -0700 +Subject: [PATCH 103/104] Ticket #47523 - Set up replcation/agreement before + initializing the sub suffix, the sub suffix is not found by ldapsearch + +Bug description: If a replication is configured against a backend +before initializing the backend with a suffix entry, an RUV entry +is inserted first with the entryid 1. The RUV entry's entryrdn is +added to the entryrdn index with a suffix entry which is a parent +entry of the RUV entry having a temporary entryid 0, which was to +be replaced with the real entryid when the real suffix entry is +added. But the replacement code was not executed. + +Fix description: When a real suffix is added to the entryrdn index, +it returns DB_KEYEXIST, which used to be ignored by resetting 0 +(== SUCCESS). This patch returns DB_KEYEXIST to the caller and let +_entryrdn_insert_key use the info to replace the temporary entryid +with the real one. The error code is ignored by the other callers. + +https://fedorahosted.org/389/ticket/47523 + +Reviewed by nkinder (Thanks!). +(cherry picked from commit e6eab21920a0374eb356da3d1f041312c6857ecd) +(cherry picked from commit 6b35dc7b04da023cc14045cc6dd1f5e304cf265f) +(cherry picked from commit df1f0ed301db6404a8df479a051416da6c8b2738) +--- + ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 39 +++++++++++++++------------- + 1 file changed, 21 insertions(+), 18 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +index 156461b..887f74b 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c +@@ -747,7 +747,7 @@ entryrdn_rename_subtree(backend *be, + renamedata.data = (void *)newelem; + renamedata.flags = DB_DBT_USERMEM; + rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn); +- if (rc) { ++ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */ + slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG, + "entryrdn_rename_subtree: Adding %s failed; " + "%s(%d)\n", keybuf, dblayer_strerror(rc), rc); +@@ -768,7 +768,7 @@ entryrdn_rename_subtree(backend *be, + renamedata.flags = DB_DBT_USERMEM; + rc = _entryrdn_put_data(cursor, &key, + &renamedata, RDN_INDEX_CHILD, db_txn); +- if (rc) { ++ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */ + goto bail; + } + } +@@ -813,7 +813,7 @@ entryrdn_rename_subtree(backend *be, + renamedata.data = (void *)newsupelem; + } + rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_PARENT, db_txn); +- if (rc) { ++ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */ + slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG, + "entryrdn_rename_subtree: Adding " + "%s failed; %s(%d)\n", +@@ -848,7 +848,7 @@ entryrdn_rename_subtree(backend *be, + renamedata.data = (void *)newelem; + renamedata.flags = DB_DBT_USERMEM; + rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_SELF, db_txn); +- if (rc) { ++ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */ + slapi_log_error(ENTRYRDN_LOGLEVEL(rc), ENTRYRDN_TAG, + "entryrdn_rename_subtree: Adding %s failed; " + "%s(%d)\n", keybuf, dblayer_strerror(rc), rc); +@@ -901,7 +901,7 @@ entryrdn_rename_subtree(backend *be, + renamedata.flags = DB_DBT_USERMEM; + } + rc = _entryrdn_put_data(cursor, &key, &renamedata, RDN_INDEX_CHILD, db_txn); +- if (rc) { ++ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */ + goto bail; + } + } +@@ -1948,12 +1948,11 @@ _entryrdn_put_data(DBC *cursor, DBT *key, DBT *data, char type, DB_TXN *db_txn) + rc = cursor->c_put(cursor, key, data, DB_NODUPDATA); + if (rc) { + if (DB_KEYEXIST == rc) { +- /* this is okay */ ++ /* this is okay, but need to return DB_KEYEXIST to caller */ + slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG, + "_entryrdn_put_data: The same key (%s) and the " + "data exists in index\n", + (char *)key->data); +- rc = 0; + break; + } else { + char *keyword = NULL; +@@ -2102,7 +2101,7 @@ _entryrdn_insert_key_elems(backend *be, + /* adding RDN to the child key */ + rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_CHILD, db_txn); + keybuf = key->data; +- if (rc) { /* failed */ ++ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */ + goto bail; + } + +@@ -2118,7 +2117,7 @@ _entryrdn_insert_key_elems(backend *be, + key->flags = DB_DBT_USERMEM; + + rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_SELF, db_txn); +- if (rc) { /* failed */ ++ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */ + goto bail; + } + +@@ -2138,6 +2137,9 @@ _entryrdn_insert_key_elems(backend *be, + adddata.flags = DB_DBT_USERMEM; + /* adding RDN to the self key */ + rc = _entryrdn_put_data(cursor, key, &adddata, RDN_INDEX_PARENT, db_txn); ++ if (DB_KEYEXIST == rc) { /* failed && ignore already exists */ ++ rc = 0; ++ } + /* Succeeded or failed, it's done. */ + bail: + slapi_ch_free_string(&keybuf); +@@ -2261,7 +2263,7 @@ _entryrdn_replace_suffix_id(DBC *cursor, DBT *key, DBT *adddata, + /* Add it back */ + rc = _entryrdn_put_data(cursor, &realkey, &moddata, + RDN_INDEX_CHILD, db_txn); +- if (rc) { ++ if (rc && (DB_KEYEXIST != rc)) { /* failed && ignore already exists */ + goto bail0; + } + if (curr_childnum + 1 == childnum) { +@@ -2524,7 +2526,7 @@ _entryrdn_insert_key(backend *be, + slapi_ch_free_string(&dn); + goto bail; + } +- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len); ++ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len); + if (NULL == elem) { + char *dn = NULL; + slapi_rdn_get_dn(tmpsrdn, &dn); +@@ -2544,12 +2546,13 @@ _entryrdn_insert_key(backend *be, + rc = _entryrdn_get_elem(cursor, &key, &data, nrdn, &elem); + if (rc) { + const char *myrdn = slapi_rdn_get_nrdn(srdn); +- const char *ep = NULL; ++ const char **ep = NULL; + int isexception = 0; + /* Check the RDN is in the exception list */ +- for (ep = *rdn_exceptions; ep && *ep; ep++) { +- if (!strcmp(ep, myrdn)) { ++ for (ep = rdn_exceptions; ep && *ep; ep++) { ++ if (!strcmp(*ep, myrdn)) { + isexception = 1; ++ break; + } + } + +@@ -2629,7 +2632,7 @@ _entryrdn_insert_key(backend *be, + goto bail; + } + } +- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len); ++ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len); + if (NULL == elem) { + char *dn = NULL; + slapi_rdn_get_dn(tmpsrdn, &dn); +@@ -2884,7 +2887,7 @@ _entryrdn_delete_key(backend *be, + slapi_ch_free_string(&dn); + goto bail; + } +- elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len); ++ elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len); + if (NULL == elem) { + char *dn = NULL; + slapi_rdn_get_dn(tmpsrdn, &dn); +@@ -3127,7 +3130,7 @@ _entryrdn_index_read(backend *be, + slapi_ch_free_string(&dn); + goto bail; + } +- *elem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len); ++ *elem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len); + if (NULL == *elem) { + char *dn = NULL; + slapi_rdn_get_dn(tmpsrdn, &dn); +@@ -3205,7 +3208,7 @@ _entryrdn_index_read(backend *be, + goto bail; + } + } +- tmpelem = _entryrdn_new_rdn_elem(be, 0 /*fake id*/, tmpsrdn, &len); ++ tmpelem = _entryrdn_new_rdn_elem(be, TMPID, tmpsrdn, &len); + if (NULL == tmpelem) { + char *dn = NULL; + slapi_rdn_get_dn(tmpsrdn, &dn); +-- +1.8.1.4 + diff --git a/0104-Ticket-47489-Under-specific-values-of-nsDS5ReplicaNa.patch b/0104-Ticket-47489-Under-specific-values-of-nsDS5ReplicaNa.patch new file mode 100644 index 0000000..e9aa929 --- /dev/null +++ b/0104-Ticket-47489-Under-specific-values-of-nsDS5ReplicaNa.patch @@ -0,0 +1,49 @@ +From 0f77337669cfe94508e7a443d73e25532f770140 Mon Sep 17 00:00:00 2001 +From: "Thierry bordaz (tbordaz)" +Date: Wed, 11 Sep 2013 11:08:58 +0200 +Subject: [PATCH 104/104] Ticket 47489 - Under specific values of + nsDS5ReplicaName, replication may get broken or updates missing + +Bug Description: + If the 'nsDS5ReplicaName' (of a replica), contains the database suffix (e.g. 'db', 'db3' or 'db4). + Then replication plugin fails to open the changelog. It could conduct to changelog being recreated or some + last updates to be corrupted. + A consequence that I can reproduce, is that some updates may be removed from the changelog and missing + updates on consumers. + This could conduct to replication break, if for example an entry created is not replicated and then later updated. + +Fix Description: + The fix consist to use 'PL_strrstr' rather than 'strstr' to check the database suffix is valid + +https://fedorahosted.org/389/ticket/47489 + +Reviewed by: Rich Megginson (thanks Rich !) + +Platforms tested: Fedora 17 + +Flag Day: no + +Doc impact: no +(cherry picked from commit 7a7609d88caf9c0971e694d7eeb78f30aea7fec9) +(cherry picked from commit ac8aad8260d3e5ed403e2d4a9967447a97925ba7) +(cherry picked from commit f944cd093d05d4bd0784b0c46b91335b6bcebcf2) +--- + ldap/servers/plugins/replication/cl5_api.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c +index f17650d..f2e038e 100644 +--- a/ldap/servers/plugins/replication/cl5_api.c ++++ b/ldap/servers/plugins/replication/cl5_api.c +@@ -6117,7 +6117,7 @@ static int _cl5FileEndsWith(const char *filename, const char *ext) + { + return 0; + } +- p = strstr(filename, ext); ++ p = PL_strrstr(filename, ext); + if (NULL == p) + { + return 0; +-- +1.8.1.4 + diff --git a/0105-Ticket-47534-RUV-tombstone-search-with-scope-one-doe.patch b/0105-Ticket-47534-RUV-tombstone-search-with-scope-one-doe.patch new file mode 100644 index 0000000..cc4e84b --- /dev/null +++ b/0105-Ticket-47534-RUV-tombstone-search-with-scope-one-doe.patch @@ -0,0 +1,41 @@ +From 59bbc2f6c8fe8895bb1ccb90da9b5c25806c9320 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Fri, 27 Sep 2013 11:23:42 -0700 +Subject: [PATCH] Ticket #47534 - RUV tombstone search with scope "one" doesn`t + work + +Bug description: slapi_sdn_scope_test_ext examines the given dn +satisfies the scope against the base dn. Onelevel case for the +tombstone DN ignores the nsuniqueid leaf rdn before checking the +scope which should not be done for the RUV tombstone. + +Fix description: This patch correctly handles the RUV tombstone +as an exception. + +https://fedorahosted.org/389/ticket/47534 + +Reviewed by rmeggins (Thanks, Rich!) +(cherry picked from commit fbece32d94515bc1ca3889c3d7c0691bbeec3ab0) +--- + ldap/servers/slapd/dn.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c +index dda439b..0f20d16 100644 +--- a/ldap/servers/slapd/dn.c ++++ b/ldap/servers/slapd/dn.c +@@ -2537,7 +2537,10 @@ slapi_sdn_scope_test_ext( const Slapi_DN *dn, const Slapi_DN *base, int scope, i + } + break; + case LDAP_SCOPE_ONELEVEL: +- if (flags & SLAPI_ENTRY_FLAG_TOMBSTONE) { ++#define RUVRDN SLAPI_ATTR_UNIQUEID "=" RUV_STORAGE_ENTRY_UNIQUEID "," ++ if ((flags & SLAPI_ENTRY_FLAG_TOMBSTONE) && ++ (strncmp(slapi_sdn_get_ndn(dn), RUVRDN, sizeof(RUVRDN) - 1))) { ++ /* tombstones except RUV tombstone */ + Slapi_DN parent; + slapi_sdn_init(&parent); + slapi_sdn_get_parent(dn, &parent); +-- +1.8.1.4 + diff --git a/0106-Ticket-47509-CLEANALLRUV-doesnt-run-across-all-repli.patch b/0106-Ticket-47509-CLEANALLRUV-doesnt-run-across-all-repli.patch new file mode 100644 index 0000000..d260da2 --- /dev/null +++ b/0106-Ticket-47509-CLEANALLRUV-doesnt-run-across-all-repli.patch @@ -0,0 +1,608 @@ +From 80e169274a893207e20765c38ad44767b22c7b9f Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 17 Sep 2013 10:53:12 -0400 +Subject: [PATCH 106/107] Ticket 47509 - CLEANALLRUV doesnt run across all + replicas + +Bug Description: If one of the replicas in the environment is older and does not support + cleanallruv, then this would cause the cleanallruv task to never complete. + +Fix Description: Several issues are addressed with this fix: + + - Corrected error handling of replicas that do not support cleanallruv(prevent task hanging) + + - Created helper function to get local maxcsn: replica_cleanallruv_get_local_maxcsn(). + This code was taken from the extended op "multimaster_extop_cleanruv_get_maxcsn". + + - Improved replica_cleanallruv_find_maxcsn() to also include the local maxcsn, and not just the remote replicas. + + - Improved abort task processing. Abort task now waits for the cleanallruv task to be aborted before continuing. + + - Improved task configuration cleanup. Removed places where the config attribute value was manually created. + Now we search for the exact value to delete. + +https://fedorahosted.org/389/ticket/47509 + +Reviewed by: richm(Thanks!!) +(cherry picked from commit 26253234c7b1c69286d8cde8f5e000bae946b6a5) +(cherry picked from commit b80706245e0a04e34d2c532ea4acf758886e3037) +(cherry picked from commit f45116f7181e89a5294a3e72b4100b66c5b60bf5) +--- + ldap/servers/plugins/replication/repl5.h | 1 + + .../plugins/replication/repl5_replica_config.c | 314 ++++++++++++--------- + ldap/servers/plugins/replication/repl_extop.c | 53 +--- + 3 files changed, 188 insertions(+), 180 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h +index 780b198..8219103 100644 +--- a/ldap/servers/plugins/replication/repl5.h ++++ b/ldap/servers/plugins/replication/repl5.h +@@ -633,6 +633,7 @@ void delete_aborted_rid(Replica *replica, ReplicaId rid, char *repl_root, int sk + int is_pre_cleaned_rid(ReplicaId rid); + void set_cleaned_rid(ReplicaId rid); + void cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...); ++char * replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn); + + #define CLEANRIDSIZ 4 /* maximum number for concurrent CLEANALLRUV tasks */ + +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index c2ad504..0cca34e 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -1805,7 +1805,7 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task) + int rc = -1; + + if((conn = conn_new(agmt)) == NULL){ +- return -1; ++ return rc; + } + if(conn_connect(conn) == CONN_OPERATION_SUCCESS){ + payload = create_cleanruv_payload(filter); +@@ -1819,7 +1819,10 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task) + char *response = NULL; + + decode_cleanruv_payload(retsdata, &response); +- if(response && strcmp(response,CLEANRUV_FINISHED) == 0){ ++ if(response == NULL){ ++ /* this replica does not support cleanallruv */ ++ rc = 0; ++ } else if(strcmp(response,CLEANRUV_FINISHED) == 0){ + /* finished cleaning */ + rc = 0; + } +@@ -1829,8 +1832,6 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task) + slapi_ch_free_string(&retoid); + } + } +- } else { +- rc = -1; + } + conn_delete_internal_ext(conn); + if(payload) +@@ -2085,16 +2086,16 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data) + val.bv_val = data; + mods[0] = &mod; + mods[1] = NULL; +- repl_dn = slapi_create_dn_string("cn=replica,cn=%s,cn=mapping tree,cn=config", slapi_sdn_get_dn(sdn)); ++ repl_dn = slapi_create_dn_string("cn=replica,cn=\"%s\",cn=mapping tree,cn=config", slapi_sdn_get_dn(sdn)); + /* + * Add task to remote replica + */ + rc = ldap_modify_ext_s( ld, repl_dn, mods, NULL, NULL); + + if(rc != LDAP_SUCCESS){ +- cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task replica " ++ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task (%s) to replica " + "(%s). You will need to manually run the CLEANRUV task on this replica (%s) error (%d)", +- agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc); ++ repl_dn, agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc); + } + slapi_ch_free_string(&repl_dn); + slapi_sdn_free(&sdn); +@@ -2320,7 +2321,6 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){ + } else { + /* only remove the config, leave the in-memory rid */ + dn = replica_get_dn(r); +- pb = slapi_pblock_new(); + data = PR_smprintf("%d:%s", (int)rid, repl_root); + + mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; +@@ -2333,6 +2333,7 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){ + mods[0] = &mod; + mods[1] = NULL; + ++ pb = slapi_pblock_new(); + slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); + slapi_modify_internal_pb (pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); +@@ -2352,40 +2353,29 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){ + static void + delete_cleaned_rid_config(cleanruv_data *clean_data) + { +- Slapi_PBlock *pb; ++ Slapi_PBlock *pb, *modpb; + Slapi_Entry **entries = NULL; + LDAPMod *mods[2]; + LDAPMod mod; +- struct berval *vals[2]; +- struct berval val; +- char data[CSN_STRSIZE + 15]; +- char *csnstr = NULL; ++ struct berval *vals[5]= {0, 0, 0, 0, 0}; /* maximum of 4 tasks */ ++ struct berval val[5]; + char *iter = NULL; +- char *dn; +- int found = 0, i; +- int rc, ret, rid; ++ char *dn = NULL; ++ int i, ii; ++ int rc = -1, ret, rid; + + if(clean_data == NULL){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "delete_cleaned_rid_config: cleanruv data is NULL, " +- "failed to clean the config.\n"); ++ cleanruv_log(NULL, CLEANALLRUV_ID, "delete_cleaned_rid_config: cleanruv data is NULL, " ++ "failed to clean the config."); + return; + } + /* +- * If there is no maxcsn, set the proper csnstr +- */ +- csnstr = csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr); +- if ((csnstr == NULL) || (csn_get_replicaid(clean_data->maxcsn) == 0)) { +- slapi_ch_free_string(&csnstr); /* no problem to pass NULL */ +- csnstr = slapi_ch_strdup("00000000000000000000"); +- } +- /* + * Search the config for the exact attribute value to delete + */ + pb = slapi_pblock_new(); + if(clean_data->replica){ + dn = replica_get_dn(clean_data->replica); + } else { +- rc = -1; + goto bail; + } + +@@ -2395,72 +2385,81 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + slapi_search_internal_pb(pb); + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret); + if (ret != LDAP_SUCCESS){ +- /* +- * Search failed, manually build the attr value +- */ +- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", +- (int)clean_data->rid, csnstr, clean_data->force); +- slapi_pblock_destroy(pb); ++ cleanruv_log(clean_data->task, CLEANALLRUV_ID,"delete_cleaned_rid_config: internal search failed(%d).",ret); ++ goto bail; + } else { + slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); + if (entries == NULL || entries[0] == NULL){ + /* +- * Entry not found, manually build the attr value ++ * No matching entries! + */ +- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", +- (int)clean_data->rid, csnstr, clean_data->force); ++ cleanruv_log(clean_data->task, CLEANALLRUV_ID,"delete_cleaned_rid_config: failed to find any " ++ "entries with nsds5ReplicaCleanRUV under (%s)", dn); ++ goto bail; + } else { +- char **attr_val = slapi_entry_attr_get_charray(entries[0], "nsds5ReplicaCleanRUV"); +- +- for (i = 0; attr_val && attr_val[i] && !found; i++){ +- /* make a copy to retain the full value after toking */ +- char *aval = slapi_ch_strdup(attr_val[i]); +- +- rid = atoi(ldap_utf8strtok_r(attr_val[i], ":", &iter)); +- if(rid == clean_data->rid){ +- /* found it */ +- found = 1; +- val.bv_len = PR_snprintf(data, sizeof(data), "%s", aval); ++ /* ++ * Clean all the matching entries ++ */ ++ for(i = 0; entries[i] != NULL;i++){ ++ char **attr_val = slapi_entry_attr_get_charray(entries[i], type_replicaCleanRUV); ++ char *edn = slapi_entry_get_dn(entries[i]); ++ int count = 0; ++ ++ for (ii = 0; attr_val && attr_val[ii] && i < 5; ii++){ ++ /* make a copy to retain the full value after toking */ ++ char *aval = slapi_ch_strdup(attr_val[ii]); ++ ++ rid = atoi(ldap_utf8strtok_r(attr_val[ii], ":", &iter)); ++ if(rid == clean_data->rid){ ++ val[count].bv_len = strlen(aval); ++ val[count].bv_val = aval; ++ vals[count] = &val[count]; ++ count++; ++ } else { ++ slapi_ch_free_string(&aval); ++ } + } +- slapi_ch_free_string(&aval); +- } +- if(!found){ ++ slapi_ch_array_free(attr_val); ++ + /* +- * No match, manually build the attr value ++ * Now delete the attribute + */ +- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s", +- (int)clean_data->rid, csnstr, clean_data->force); ++ vals[5] = NULL; ++ mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; ++ mod.mod_type = (char *)type_replicaCleanRUV; ++ mod.mod_bvalues = vals; ++ mods[0] = &mod; ++ mods[1] = NULL; ++ ++ modpb = slapi_pblock_new(); ++ slapi_modify_internal_set_pb(modpb, edn, mods, NULL, NULL, ++ repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); ++ slapi_modify_internal_pb (modpb); ++ slapi_pblock_get(modpb, SLAPI_PLUGIN_INTOP_RESULT, &rc); ++ slapi_pblock_destroy(modpb); ++ ++ /* free the attr vals */ ++ for (ii = 0; ii < count; ii++){ ++ slapi_ch_free_string(&val[ii].bv_val); ++ } ++ ++ if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){ ++ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "delete_cleaned_rid_config: failed to remove task data " ++ "from (%s) error (%d), rid (%d)", edn, rc, clean_data->rid); ++ goto bail; ++ } + } +- slapi_ch_array_free(attr_val); + } +- slapi_free_search_results_internal(pb); +- slapi_pblock_destroy(pb); + } + +- /* +- * Now delete the attribute +- */ +- mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; +- mod.mod_type = (char *)type_replicaCleanRUV; +- mod.mod_bvalues = vals; +- vals [0] = &val; +- vals [1] = NULL; +- val.bv_val = data; +- mods[0] = &mod; +- mods[1] = NULL; +- pb = slapi_pblock_new(); +- slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); +- slapi_modify_internal_pb (pb); +- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); +- + bail: + if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config " +- "(%d), rid (%d)\n", rc, clean_data->rid); ++ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "delete_cleaned_rid_config: failed to remove replica config " ++ "(%d), rid (%d)", rc, clean_data->rid); + } ++ slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + slapi_ch_free_string(&dn); +- slapi_ch_free_string(&csnstr); + } + + /* +@@ -2665,6 +2664,7 @@ replica_abort_task_thread(void *arg) + int agmt_not_notified = 1; + int interval = 10; + int release_it = 0; ++ int count = 0, rc = 0; + + cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Aborting task for rid(%d)...",data->rid); + +@@ -2743,6 +2743,20 @@ done: + cleanruv_log(data->task, ABORT_CLEANALLRUV_ID,"Abort task failed, will resume the task at the next server startup."); + } else { + /* ++ * Wait for this server to stop its cleanallruv task(which removes the rid from the cleaned list) ++ */ ++ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Waiting for CleanAllRUV task to abort..."); ++ while(is_cleaned_rid(data->rid)){ ++ DS_Sleep(PR_SecondsToInterval(1)); ++ count++; ++ if(count == 60){ /* it should not take this long */ ++ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "CleanAllRUV task failed to abort. You might need to " ++ "rerun the task."); ++ rc = -1; ++ break; ++ } ++ } ++ /* + * Clean up the config + */ + delete_aborted_rid(data->replica, data->rid, data->repl_root, 1); /* delete just the config, leave rid in memory */ +@@ -2750,8 +2764,13 @@ done: + check_replicas_are_done_aborting(data); + } + delete_aborted_rid(data->replica, data->rid, data->repl_root, 0); /* remove the in-memory aborted rid */ +- cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid); ++ if(rc == 0){ ++ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid); ++ } else { ++ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Failed to abort task for rid(%d)",data->rid); ++ } + } ++ + if(data->task){ + slapi_task_finish(data->task, agmt_not_notified); + } +@@ -2829,6 +2848,7 @@ replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int che + * add the CLEANRUV task to the replica. + */ + replica_send_cleanruv_task(ra, clean_data); ++ rc = 0; + } + if (NULL != retsdata) + ber_bvfree(retsdata); +@@ -2852,72 +2872,49 @@ replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn) + { + Object *agmt_obj; + Repl_Agmt *agmt; +- char *rid_text; + CSN *maxcsn = NULL, *topcsn = NULL; +- int done = 1, found = 0; +- int interval = 10; ++ char *rid_text = slapi_ch_smprintf("%d", rid); ++ char *csnstr = NULL; + +- rid_text = slapi_ch_smprintf("%d", rid); ++ /* start with the local maxcsn */ ++ csnstr = replica_cleanallruv_get_local_maxcsn(rid, basedn); ++ if(csnstr){ ++ topcsn = csn_new(); ++ csn_init_by_string(topcsn, csnstr); ++ slapi_ch_free_string(&csnstr); ++ } + +- while(done && !is_task_aborted(rid) && !slapi_is_shutting_down()){ +- agmt_obj = agmtlist_get_first_agreement_for_replica (replica); +- if(agmt_obj == NULL){ +- break; ++ agmt_obj = agmtlist_get_first_agreement_for_replica (replica); ++ if(agmt_obj == NULL){ /* no agreements */ ++ goto done; ++ } ++ while (agmt_obj && !slapi_is_shutting_down()){ ++ agmt = (Repl_Agmt*)object_get_data (agmt_obj); ++ if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){ ++ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); ++ continue; + } +- while (agmt_obj && !slapi_is_shutting_down()){ +- agmt = (Repl_Agmt*)object_get_data (agmt_obj); +- if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){ ++ if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){ ++ if(maxcsn == NULL){ + agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); +- done = 0; + continue; + } +- if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){ +- if(maxcsn == NULL){ +- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); +- continue; +- } +- found = 1; +- if(topcsn == NULL){ ++ if(topcsn == NULL){ ++ topcsn = maxcsn; ++ } else { ++ if(csn_compare(topcsn, maxcsn) < 0){ ++ csn_free(&topcsn); + topcsn = maxcsn; + } else { +- if(csn_compare(topcsn, maxcsn) < 0){ +- csn_free(&topcsn); +- topcsn = maxcsn; +- } else { +- csn_free(&maxcsn); +- } ++ csn_free(&maxcsn); + } +- done = 0; +- } else { +- done = 1; +- break; + } +- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); +- } /* agmt while */ +- if(done == 0 || is_task_aborted(rid) ){ +- break; +- } +- if(!found){ +- /* we could not find any maxcsn's - already cleaned? */ +- return NULL; +- } +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: " +- "Not all replicas online, retrying in %d seconds\n", interval); +- PR_Lock( notify_lock ); +- PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) ); +- PR_Unlock( notify_lock ); +- +- if(interval < 14400){ /* 4 hour max */ +- interval = interval * 2; +- } else { +- interval = 14400; + } ++ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj); + } +- slapi_ch_free_string(&rid_text); + +- if(is_task_aborted(rid)){ +- return NULL; +- } ++done: ++ slapi_ch_free_string(&rid_text); + + return topcsn; + } +@@ -3200,3 +3197,64 @@ cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...) + va_end(ap4); + } + ++char * ++replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn) ++{ ++ Slapi_PBlock *search_pb = NULL; ++ Slapi_Entry **entries = NULL; ++ char **ruv_elements = NULL; ++ char *maxcsn = NULL; ++ char *filter = NULL; ++ char *ridstr = NULL; ++ char *iter = NULL; ++ char *attrs[2]; ++ char *ruv_part = NULL; ++ int part_count = 0; ++ int res, i; ++ ++ /* ++ * Get the maxruv from the database tombstone entry ++ */ ++ filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))"; ++ attrs[0] = "nsds50ruv"; ++ attrs[1] = NULL; ++ ridstr = slapi_ch_smprintf("{replica %d ldap", rid); ++ ++ search_pb = slapi_pblock_new(); ++ slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0); ++ slapi_search_internal_pb (search_pb); ++ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res); ++ ++ if ( LDAP_SUCCESS == res ) { ++ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); ++ if (NULL == entries || entries[0] == NULL) { ++ /* Hmmm, no tombstone! Error out */ ++ } else { ++ /* find the right ruv element, and find the maxcsn */ ++ ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]); ++ for(i = 0; ruv_elements && ruv_elements[i] ; i++){ ++ if(strstr(ruv_elements[i], ridstr)){ ++ /* get the max csn */ ++ ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter); ++ for(part_count = 1; ruv_part && part_count < 5; part_count++){ ++ ruv_part = ldap_utf8strtok_r(iter, " ", &iter); ++ } ++ if(part_count == 5 && ruv_part){/* we have the maxcsn */ ++ maxcsn = slapi_ch_strdup(ruv_part); ++ break; ++ } ++ } ++ } ++ slapi_ch_array_free(ruv_elements); ++ } ++ } else { ++ /* internal search failed */ ++ cleanruv_log(NULL, CLEANALLRUV_ID, "replica_cleanallruv_get_local_maxcsn: internal search failed (%d)\n", res); ++ } ++ ++ slapi_free_search_results_internal(search_pb); ++ slapi_pblock_destroy(search_pb); ++ slapi_ch_free_string(&ridstr); ++ ++ return maxcsn; ++} +diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c +index 68aed62..37ee1ff 100644 +--- a/ldap/servers/plugins/replication/repl_extop.c ++++ b/ldap/servers/plugins/replication/repl_extop.c +@@ -1775,26 +1775,16 @@ free_and_return: + int + multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb) + { +- Slapi_PBlock *search_pb = NULL; +- Slapi_Entry **entries = NULL; + struct berval *resp_bval = NULL; + struct berval *extop_payload; + BerElement *resp_bere = NULL; +- char **ruv_elements = NULL; + char *extop_oid = NULL; +- char *ruv_part = NULL; + char *base_dn = NULL; + char *payload = NULL; + char *maxcsn = NULL; +- char *filter = NULL; +- char *ridstr = NULL; + char *iter = NULL; +- char *attrs[2]; +- int part_count = 0; + int rid = 0; +- int res = 0; + int rc = LDAP_OPERATIONS_ERROR; +- int i = 0; + + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid); + slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload); +@@ -1813,45 +1803,7 @@ multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb) + } + rid = atoi(ldap_utf8strtok_r(payload, ":", &iter)); + base_dn = ldap_utf8strtok_r(iter, ":", &iter); +- /* +- * Get the maxruv from the database tombstone entry +- */ +- filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))"; +- attrs[0] = "nsds50ruv"; +- attrs[1] = NULL; +- ridstr = slapi_ch_smprintf("{replica %d ldap", rid); +- +- search_pb = slapi_pblock_new(); +- slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0); +- slapi_search_internal_pb (search_pb); +- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res); +- +- if ( LDAP_SUCCESS == res ) { +- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); +- if (NULL == entries || entries[0] == NULL) { +- /* Hmmm, no tombstpne! Error out */ +- } else { +- /* find the right ruv element, and find the maxcsn */ +- ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]); +- for(i = 0; ruv_elements && ruv_elements[i] ; i++){ +- if(strstr(ruv_elements[i], ridstr)){ +- /* get the max csn */ +- ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter); +- for(part_count = 1; ruv_part && part_count < 5; part_count++){ +- ruv_part = ldap_utf8strtok_r(iter, " ", &iter); +- } +- if(part_count == 5 && ruv_part){/* we have the maxcsn */ +- maxcsn = slapi_ch_strdup(ruv_part); +- break; +- } +- } +- } +- slapi_ch_array_free(ruv_elements); +- } +- } else { +- /* internal search failed */ +- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Get MaxCSN Task: internal search failed (%d)\n", res); +- } ++ maxcsn = replica_cleanallruv_get_local_maxcsn(rid, base_dn); + if(maxcsn == NULL){ + maxcsn = slapi_ch_strdup(CLEANRUV_NO_MAXCSN); + } +@@ -1880,11 +1832,8 @@ multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb) + } + + free_and_return: +- slapi_free_search_results_internal(search_pb); +- slapi_pblock_destroy(search_pb); + slapi_ch_free_string(&payload); + slapi_ch_free_string(&maxcsn); +- slapi_ch_free_string(&ridstr); + + return rc; + } +-- +1.8.1.4 + diff --git a/0107-Ticket-47509-Cleanallruv-jenkins-error.patch b/0107-Ticket-47509-Cleanallruv-jenkins-error.patch new file mode 100644 index 0000000..f6c4f7c --- /dev/null +++ b/0107-Ticket-47509-Cleanallruv-jenkins-error.patch @@ -0,0 +1,31 @@ +From 94f2d88ec1646054bd57640be66a1660314336b3 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Mon, 23 Sep 2013 12:21:15 -0400 +Subject: [PATCH 107/107] Ticket 47509 - Cleanallruv jenkins error + +Fixed invalid array element that was out of bounds. + +https://fedorahosted.org/389/ticket/47509 +(cherry picked from commit 24bec17a925c99fe5a655f983e53fc72a34c69ac) +(cherry picked from commit 023e1889758cdd2b3a215414180e7f1fdfd8aa5f) +(cherry picked from commit 63274beb1e24529408aac84799a9ca877744d51a) +--- + ldap/servers/plugins/replication/repl5_replica_config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c +index 0cca34e..9a0b190 100644 +--- a/ldap/servers/plugins/replication/repl5_replica_config.c ++++ b/ldap/servers/plugins/replication/repl5_replica_config.c +@@ -2424,7 +2424,7 @@ delete_cleaned_rid_config(cleanruv_data *clean_data) + /* + * Now delete the attribute + */ +- vals[5] = NULL; ++ vals[4] = NULL; + mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES; + mod.mod_type = (char *)type_replicaCleanRUV; + mod.mod_bvalues = vals; +-- +1.8.1.4 + diff --git a/0108-Ticket-47488-Users-from-AD-sub-OU-does-not-sync-to-I.patch b/0108-Ticket-47488-Users-from-AD-sub-OU-does-not-sync-to-I.patch new file mode 100644 index 0000000..5756a1f --- /dev/null +++ b/0108-Ticket-47488-Users-from-AD-sub-OU-does-not-sync-to-I.patch @@ -0,0 +1,64 @@ +From 81f26a33df3c5f369097d673edfe52535ce77cc4 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 20 Aug 2013 14:09:26 -0700 +Subject: [PATCH] Ticket #47488 - Users from AD sub OU does not sync to IPA + +Bug description: When processing a DN from AD, the DN is passed to +a helper function is_subject_of_agreement_remote (windows_protocol_ +util.c) to check if the DN is a subject of the sync service or not. +The helper function was checking if the AD DN is just one-level +child of the agreement subtree top (nsds7WindowsReplicaSubtree) but +not the subtree-level descendents. Note: the DN is an original one +in AD, which has not be flattened yet. Therefore, the AD entry was +determined not to be synchronized. + +Fix description: This bug was fixed in the master tree with the +ticket #521 - modrdn + NSMMReplicationPlugin - Consumer failed to +replay change. + 3) is_subject_of_agreement_remote (windows_protocol_util.c): + When checking if the entry was in the subtree defined in the + agreement or not, it returned true only if the entry is a + direct child of the agreement subtree top. This patch returns + true if the entry is the further descendent of the subtree. +The fix is back ported to 389-ds-base-1.3.1 branch. + +Reviewed by Rich (Thank you!!) + +https://fedorahosted.org/389/ticket/47488 +(cherry picked from commit 529a544a2fe9961d9286e191346fb5faca27d38b) +(cherry picked from commit 26c669dcad15f9dbbfdff6fbeffac579099b7718) +--- + ldap/servers/plugins/replication/windows_protocol_util.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c +index 0b3c575..75cb935 100644 +--- a/ldap/servers/plugins/replication/windows_protocol_util.c ++++ b/ldap/servers/plugins/replication/windows_protocol_util.c +@@ -3891,7 +3891,12 @@ error: + return retval; + } + +-/* Tests if the entry is subject to our agreement (i.e. is it in the sync'ed subtree in AD and either a user or a group ?) */ ++/* ++ * Tests if the entry is subject to our agreement ++ * (i.e. is it in the sync'ed subtree in AD and either a user or a group ?) ++ * return value: 1 -- it is subject to the agreement ++ * 0 -- out of scope ++ */ + static int + is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt *ra) + { +@@ -3922,7 +3927,8 @@ is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt *ra) + * 'e' as out of scope. + */ + slapi_sdn_get_parent(sdn, &psdn); +- if (0 == slapi_sdn_compare(&psdn, agreement_subtree)) { ++ if (slapi_sdn_issuffix(&psdn, agreement_subtree)) { ++ /* parent is in agreement_subtree. */ + retval = 1; + } else { + /* If parent entry is not local, the entry is out of scope */ +-- +1.8.1.4 + diff --git a/0109-Ticket-47559-hung-server-related-to-sasl-and-initial.patch b/0109-Ticket-47559-hung-server-related-to-sasl-and-initial.patch new file mode 100644 index 0000000..35b53ef --- /dev/null +++ b/0109-Ticket-47559-hung-server-related-to-sasl-and-initial.patch @@ -0,0 +1,150 @@ +From c77411b9204d7889b7c7811ff453ff5158aa87a0 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Mon, 14 Oct 2013 12:43:51 -0600 +Subject: [PATCH] Ticket #47559 hung server - related to sasl and initialize + +https://fedorahosted.org/389/ticket/47559 +Reviewed by: ??? +Branch: master +Fix Description: Use a mutex to protect calls to openldap functions that do +anything with crypto - bind, unbind, start_tls, other calls. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +--- + ldap/servers/slapd/ldaputil.c | 51 +++++++++++++++++++++++++++++++++++++--- + 1 files changed, 47 insertions(+), 4 deletions(-) + +diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c +index 331dd71..307a3a5 100644 +--- a/ldap/servers/slapd/ldaputil.c ++++ b/ldap/servers/slapd/ldaputil.c +@@ -99,10 +99,16 @@ + #if !defined(USE_OPENLDAP) + #include + #include ++#define BIND_LOCK (void)0 ++#define BIND_UNLOCK (void)0 + #else + /* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */ + static PRCallOnceType ol_init_callOnce = {0,0}; + static PRLock *ol_init_lock = NULL; ++/* need mutex around ldap_sasl_bind - see https://fedorahosted.org/389/ticket/47599 */ ++static PRLock *ol_bind_lock = NULL; ++#define BIND_LOCK PR_Lock(ol_bind_lock) ++#define BIND_UNLOCK PR_Unlock(ol_bind_lock) + + static PRStatus + internal_ol_init_init(void) +@@ -110,12 +116,20 @@ internal_ol_init_init(void) + PR_ASSERT(NULL == ol_init_lock); + if ((ol_init_lock = PR_NewLock()) == NULL) { + PRErrorCode errorCode = PR_GetError(); +- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock failed %d:%s\n", ++ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock init_lock failed %d:%s\n", + errorCode, slapd_pr_strerror(errorCode)); + return PR_FAILURE; + } + +- return PR_SUCCESS; ++ PR_ASSERT(NULL == ol_bind_lock); ++ if ((ol_bind_lock = PR_NewLock()) == NULL) { ++ PRErrorCode errorCode = PR_GetError(); ++ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock bind_lock failed %d:%s\n", ++ errorCode, slapd_pr_strerror(errorCode)); ++ return PR_FAILURE; ++ } ++ ++ return PR_SUCCESS; + } + #endif + +@@ -145,7 +159,16 @@ void + slapi_ldap_unbind( LDAP *ld ) + { + if ( ld != NULL ) { ++#if defined(USE_OPENLDAP) ++ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) { ++ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_unbind", ++ "Could not perform internal ol_init init\n"); ++ return; ++ } ++#endif ++ BIND_LOCK; + ldap_unbind_ext( ld, NULL, NULL ); ++ BIND_UNLOCK; + } + } + +@@ -1024,11 +1047,22 @@ slapi_ldap_bind( + ldap_controls_free(clientctrls); + ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, NULL); + ++#if defined(USE_OPENLDAP) ++ if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) { ++ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", ++ "Could not perform internal ol_init init\n"); ++ rc = -1; ++ goto done; ++ } ++#endif ++ + if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) { + #if defined(USE_OPENLDAP) + /* we already set up a tls context in slapi_ldap_init_ext() - this will + free those old settings and context and create a new one */ ++ PR_Lock(ol_bind_lock); + rc = setup_ol_tls_conn(ld, 1); ++ PR_Unlock(ol_bind_lock); + #else + /* SSL connections will use the server's security context + and cert for client auth */ +@@ -1053,7 +1087,9 @@ slapi_ldap_bind( + } + + if (secure == 2) { /* send start tls */ ++ BIND_LOCK; + rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL); ++ BIND_UNLOCK; + if (LDAP_SUCCESS != rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not send startTLS request: " +@@ -1075,8 +1111,11 @@ slapi_ldap_bind( + "attempting %s bind with id [%s] creds [%s]\n", + mech ? mech : "SIMPLE", + bindid, creds); +- if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls, +- NULL /* clientctrls */, &mymsgid))) { ++ BIND_LOCK; ++ rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls, ++ NULL /* clientctrls */, &mymsgid); ++ BIND_UNLOCK; ++ if (rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not send bind request for id " + "[%s] mech [%s]: error %d (%s) %d (%s) %d (%s)\n", +@@ -1091,7 +1130,9 @@ slapi_ldap_bind( + if (msgidp) { /* let caller process result */ + *msgidp = mymsgid; + } else { /* process results */ ++ BIND_LOCK; + rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, timeout, &result); ++ BIND_UNLOCK; + if (-1 == rc) { /* error */ + rc = slapi_ldap_get_lderrno(ld, NULL, NULL); + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", +@@ -1156,9 +1197,11 @@ slapi_ldap_bind( + ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX, &max_ssf); + } + #endif ++ BIND_LOCK; + rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech, + serverctrls, returnedctrls, + msgidp); ++ BIND_UNLOCK; + if (LDAP_SUCCESS != rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not perform interactive bind for id " +-- +1.7.1 + diff --git a/0110-Bug-1024552-DoS-due-to-improper-handling-of-ger-attr.patch b/0110-Bug-1024552-DoS-due-to-improper-handling-of-ger-attr.patch new file mode 100644 index 0000000..4cd0bf5 --- /dev/null +++ b/0110-Bug-1024552-DoS-due-to-improper-handling-of-ger-attr.patch @@ -0,0 +1,135 @@ +From 0e5e3049ae78eb566462c5fb572f91890bae4055 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Tue, 29 Oct 2013 13:47:35 -0600 +Subject: [PATCH] Bug 1024552 DoS due to improper handling of ger attr searches + +https://bugzilla.redhat.com/show_bug.cgi?id=1024552 +Reviewed by: nhosoi (Thanks!) +Branch: rhel-6.5 +Fix Description: The traversal of the attr list looking for GER objectclasses +was modifying the same attribute twice, removing the "@" from it. The second +time, since there was no "@" in the string, the strchr would return NULL, and +the code would not check for it. +The code was simplified and rewritten to use charray_merge_nodup +to build the gerattrs list with unique objectclass values, which I believe was +the intention of the original code. I also added some error checking to look +for invalid attributes like "@name" "name@" and "name@name@name". +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 3a1ce9e326d9788be233f7edd9d7bad20efb9690) +(cherry picked from commit 47f1769dbd1618d0385fb3e5441219f9c280486b) +--- + ldap/servers/slapd/search.c | 79 +++++++++---------------------------------- + 1 files changed, 16 insertions(+), 63 deletions(-) + +diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c +index 1a824b2..9f165a1 100644 +--- a/ldap/servers/slapd/search.c ++++ b/ldap/servers/slapd/search.c +@@ -246,8 +246,6 @@ do_search( Slapi_PBlock *pb ) + } + + if ( attrs != NULL ) { +- int gerattrsiz = 1; +- int gerattridx = 0; + int aciin = 0; + /* + * . store gerattrs if any +@@ -257,66 +255,25 @@ do_search( Slapi_PBlock *pb ) + { + char *p = NULL; + /* check if @ is included */ +- p = strchr(attrs[i], '@'); +- if ( p && '\0' != *(p+1) ) /* don't store "*@", e.g. */ ++ p = strchr(attrs[i], '@'); ++ if ( p ) + { +- int j = 0; +- if (gerattridx + 1 >= gerattrsiz) ++ char *dummyary[2]; /* need a char ** for charray_merge_nodup */ ++ if ((*(p + 1) == '\0') || (p == attrs[i]) || (strchr(p+1, '@'))) /* e.g. "foo@" or "@objectclassname" or "foo@bar@baz" */ + { +- char **tmpgerattrs; +- gerattrsiz *= 2; +- tmpgerattrs = +- (char **)slapi_ch_calloc(1, gerattrsiz*sizeof(char *)); +- if (NULL != gerattrs) +- { +- memcpy(tmpgerattrs, gerattrs, gerattrsiz*sizeof(char *)); +- slapi_ch_free((void **)&gerattrs); +- } +- gerattrs = tmpgerattrs; +- } +- for ( j = 0; gerattrs; j++ ) +- { +- char *attri = NULL; +- if ( NULL == gerattrs[j] ) +- { +- if (0 == j) +- { +- /* first time */ +- gerattrs[gerattridx++] = attrs[i]; +- /* get rid of "@" part from the attr +- list, which is needed only in gerattr list */ +- *p = '\0'; +- attri = slapi_ch_strdup(attrs[i]); +- attrs[i] = attri; +- *p = '@'; +- } +- else +- { +- break; /* done */ +- } +- } +- else if ( 0 == strcasecmp( attrs[i], gerattrs[j] )) +- { +- /* skip if attrs[i] is already in gerattrs */ +- continue; +- } +- else +- { +- char *q = strchr(gerattrs[j], '@'); /* q never be 0 */ +- if ( 0 != strcasecmp( p+1, q+1 )) +- { +- /* you don't want to display the same template +- entry multiple times */ +- gerattrs[gerattridx++] = attrs[i]; +- } +- /* get rid of "@" part from the attr +- list, which is needed only in gerattr list */ +- *p = '\0'; +- attri = slapi_ch_strdup(attrs[i]); +- attrs[i] = attri; +- *p = '@'; +- } ++ slapi_log_error( SLAPI_LOG_ARGS, "do_search", ++ "invalid attribute [%s] in list - must be of the form " ++ "attributename@objectclassname where attributename is the " ++ "name of an attribute or \"*\" or \"+\" and objectclassname " ++ "is the name of an objectclass\n", attrs[i] ); ++ continue; + } ++ dummyary[0] = p; /* p = @objectclassname */ ++ dummyary[1] = NULL; ++ /* copy string to gerattrs with leading @ - disallow dups */ ++ charray_merge_nodup(&gerattrs, dummyary, 1); ++ /* null terminate the attribute name at the @ after it has been copied */ ++ *p = '\0'; + } + else if ( !aciin && strcasecmp(attrs[i], LDAP_ALL_USER_ATTRS) == 0 ) + { +@@ -324,10 +281,6 @@ do_search( Slapi_PBlock *pb ) + aciin = 1; + } + } +- if (NULL != gerattrs) +- { +- gerattrs[gerattridx] = NULL; +- } + + /* Set attrs to SLAPI_SEARCH_ATTRS once to get rid of the forbidden attrs */ + slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS, attrs ); +-- +1.7.1 + diff --git a/0111-Revert-Ticket-47559-hung-server-related-to-sasl-and-.patch b/0111-Revert-Ticket-47559-hung-server-related-to-sasl-and-.patch new file mode 100644 index 0000000..5d380a5 --- /dev/null +++ b/0111-Revert-Ticket-47559-hung-server-related-to-sasl-and-.patch @@ -0,0 +1,143 @@ +From d580af118c7ae5d1459a841c159dc8378e6174f2 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Thu, 21 Nov 2013 20:35:39 -0700 +Subject: [PATCH] Revert "Ticket #47559 hung server - related to sasl and initialize" + +This reverts commit c77411b9204d7889b7c7811ff453ff5158aa87a0. +--- + ldap/servers/slapd/ldaputil.c | 51 +++------------------------------------- + 1 files changed, 4 insertions(+), 47 deletions(-) + +diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c +index 307a3a5..331dd71 100644 +--- a/ldap/servers/slapd/ldaputil.c ++++ b/ldap/servers/slapd/ldaputil.c +@@ -99,16 +99,10 @@ + #if !defined(USE_OPENLDAP) + #include + #include +-#define BIND_LOCK (void)0 +-#define BIND_UNLOCK (void)0 + #else + /* need mutex around ldap_initialize - see https://fedorahosted.org/389/ticket/348 */ + static PRCallOnceType ol_init_callOnce = {0,0}; + static PRLock *ol_init_lock = NULL; +-/* need mutex around ldap_sasl_bind - see https://fedorahosted.org/389/ticket/47599 */ +-static PRLock *ol_bind_lock = NULL; +-#define BIND_LOCK PR_Lock(ol_bind_lock) +-#define BIND_UNLOCK PR_Unlock(ol_bind_lock) + + static PRStatus + internal_ol_init_init(void) +@@ -116,20 +110,12 @@ internal_ol_init_init(void) + PR_ASSERT(NULL == ol_init_lock); + if ((ol_init_lock = PR_NewLock()) == NULL) { + PRErrorCode errorCode = PR_GetError(); +- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock init_lock failed %d:%s\n", ++ slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock failed %d:%s\n", + errorCode, slapd_pr_strerror(errorCode)); + return PR_FAILURE; + } + +- PR_ASSERT(NULL == ol_bind_lock); +- if ((ol_bind_lock = PR_NewLock()) == NULL) { +- PRErrorCode errorCode = PR_GetError(); +- slapi_log_error(SLAPI_LOG_FATAL, "internal_ol_init_init", "PR_NewLock bind_lock failed %d:%s\n", +- errorCode, slapd_pr_strerror(errorCode)); +- return PR_FAILURE; +- } +- +- return PR_SUCCESS; ++ return PR_SUCCESS; + } + #endif + +@@ -159,16 +145,7 @@ void + slapi_ldap_unbind( LDAP *ld ) + { + if ( ld != NULL ) { +-#if defined(USE_OPENLDAP) +- if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) { +- slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_unbind", +- "Could not perform internal ol_init init\n"); +- return; +- } +-#endif +- BIND_LOCK; + ldap_unbind_ext( ld, NULL, NULL ); +- BIND_UNLOCK; + } + } + +@@ -1047,22 +1024,11 @@ slapi_ldap_bind( + ldap_controls_free(clientctrls); + ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, NULL); + +-#if defined(USE_OPENLDAP) +- if (PR_SUCCESS != PR_CallOnce(&ol_init_callOnce, internal_ol_init_init)) { +- slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", +- "Could not perform internal ol_init init\n"); +- rc = -1; +- goto done; +- } +-#endif +- + if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) { + #if defined(USE_OPENLDAP) + /* we already set up a tls context in slapi_ldap_init_ext() - this will + free those old settings and context and create a new one */ +- PR_Lock(ol_bind_lock); + rc = setup_ol_tls_conn(ld, 1); +- PR_Unlock(ol_bind_lock); + #else + /* SSL connections will use the server's security context + and cert for client auth */ +@@ -1087,9 +1053,7 @@ slapi_ldap_bind( + } + + if (secure == 2) { /* send start tls */ +- BIND_LOCK; + rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL); +- BIND_UNLOCK; + if (LDAP_SUCCESS != rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not send startTLS request: " +@@ -1111,11 +1075,8 @@ slapi_ldap_bind( + "attempting %s bind with id [%s] creds [%s]\n", + mech ? mech : "SIMPLE", + bindid, creds); +- BIND_LOCK; +- rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls, +- NULL /* clientctrls */, &mymsgid); +- BIND_UNLOCK; +- if (rc) { ++ if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls, ++ NULL /* clientctrls */, &mymsgid))) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not send bind request for id " + "[%s] mech [%s]: error %d (%s) %d (%s) %d (%s)\n", +@@ -1130,9 +1091,7 @@ slapi_ldap_bind( + if (msgidp) { /* let caller process result */ + *msgidp = mymsgid; + } else { /* process results */ +- BIND_LOCK; + rc = ldap_result(ld, mymsgid, LDAP_MSG_ALL, timeout, &result); +- BIND_UNLOCK; + if (-1 == rc) { /* error */ + rc = slapi_ldap_get_lderrno(ld, NULL, NULL); + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", +@@ -1197,11 +1156,9 @@ slapi_ldap_bind( + ldap_set_option(ld, LDAP_OPT_X_SASL_SSF_MAX, &max_ssf); + } + #endif +- BIND_LOCK; + rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech, + serverctrls, returnedctrls, + msgidp); +- BIND_UNLOCK; + if (LDAP_SUCCESS != rc) { + slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind", + "Error: could not perform interactive bind for id " +-- +1.7.1 + diff --git a/0112-Ticket-47739-directory-server-is-insecurely-misinter.patch b/0112-Ticket-47739-directory-server-is-insecurely-misinter.patch new file mode 100644 index 0000000..2697d51 --- /dev/null +++ b/0112-Ticket-47739-directory-server-is-insecurely-misinter.patch @@ -0,0 +1,76 @@ +From 494e52332fe3200204c14d01f9771a945e0362bf Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 10 Mar 2014 16:12:08 -0700 +Subject: [PATCH] Ticket #47739 - directory server is insecurely + misinterpreting authzid on a SASL/GSSAPI bind + +Description: SASL_CB_PROXY_POLICY callback is not needed since we +don't support the case authid and authzid do not match. This patch +gets rid of the callback function ids_sasl_proxy_policy. + +https://fedorahosted.org/389/ticket/47739 + +Reviewed by nkinder@redhat.com (Thank you, Nathan!!) +(cherry picked from commit 76acff12a86110d4165f94e2cba13ef5c7ebc38a) +(cherry picked from commit 9bc2b46b7c7ee4c975d04b041f73a5992906b07c) +(cherry picked from commit d2063c889feeba122e12f152e2e2c98aed4eb442) +(cherry picked from commit 614d72196e696395d5bc0a6d62f8be9d4ee41c5b) +(cherry picked from commit 8a368a62ea22127f95017467a044df57937ed238) +--- + ldap/servers/slapd/saslbind.c | 33 --------------------------------- + 1 file changed, 33 deletions(-) + +diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c +index 2d6ec0a..a5db020 100644 +--- a/ldap/servers/slapd/saslbind.c ++++ b/ldap/servers/slapd/saslbind.c +@@ -219,34 +219,6 @@ static int ids_sasl_log( + return SASL_OK; + } + +-static int ids_sasl_proxy_policy( +- sasl_conn_t *conn, +- void *context, +- const char *requested_user, int rlen, +- const char *auth_identity, int alen, +- const char *def_realm, int urlen, +- struct propctx *propctx +-) +-{ +- int retVal = SASL_OK; +- /* do not permit sasl proxy authorization */ +- /* if the auth_identity is null or empty string, allow the sasl request to go thru */ +- if ( (auth_identity != NULL ) && ( strlen(auth_identity) > 0 ) ) { +- Slapi_DN authId , reqUser; +- slapi_sdn_init_dn_byref(&authId,auth_identity); +- slapi_sdn_init_dn_byref(&reqUser,requested_user); +- if (slapi_sdn_compare((const Slapi_DN *)&reqUser,(const Slapi_DN *) &authId) != 0) { +- LDAPDebug(LDAP_DEBUG_TRACE, +- "sasl proxy auth not permitted authid=%s user=%s\n", +- auth_identity, requested_user, 0); +- retVal = SASL_NOAUTHZ; +- } +- slapi_sdn_done(&authId); +- slapi_sdn_done(&reqUser); +- } +- return retVal; +-} +- + static void ids_sasl_user_search( + char *basedn, + int scope, +@@ -552,11 +524,6 @@ static sasl_callback_t ids_sasl_callbacks[] = + NULL + }, + { +- SASL_CB_PROXY_POLICY, +- (IFP) ids_sasl_proxy_policy, +- NULL +- }, +- { + SASL_CB_CANON_USER, + (IFP) ids_sasl_canon_user, + NULL +-- +1.8.1.4 + diff --git a/0113-Ticket-47623-fix-memleak-caused-by-47347.patch b/0113-Ticket-47623-fix-memleak-caused-by-47347.patch new file mode 100644 index 0000000..4584cf9 --- /dev/null +++ b/0113-Ticket-47623-fix-memleak-caused-by-47347.patch @@ -0,0 +1,44 @@ +From 7993502b5e00c7f2d05d1b0c3feb573cf62e1a49 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Mon, 9 Dec 2013 17:00:32 -0700 +Subject: [PATCH 113/115] Ticket #47623 fix memleak caused by 47347 + +https://fedorahosted.org/389/ticket/47623 +Reviewed by: nhosoi (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: Only need to create the mutex when creating a new PR object. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 98ccb602058270e97a3702ae2b81c17635af8d27) +(cherry picked from commit 65c51555c0ecc94c5d93f09124168697ba1db6b3) +(cherry picked from commit 8a2c666df491b7c8666f8a70a5038b35c43fbc3b) +(cherry picked from commit 8968e078caacf1021a11c19546c448a4b65db098) +(cherry picked from commit 1ad3604b8bfbd5c2a3c4ca8f55b8690a2098f3df) +--- + ldap/servers/slapd/pagedresults.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index 78bd6b0..a835d6b 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -122,6 +122,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + sizeof(PagedResults) * maxlen); + } + *index = maxlen; /* the first position in the new area */ ++ conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock(); + } else { + for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { + if (!conn->c_pagedresults.prl_list[i].pr_current_be) { +@@ -131,7 +132,6 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + } + } + conn->c_pagedresults.prl_count++; +- conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock(); + } else { + /* Repeated paged results request. + * PagedResults is already allocated. */ +-- +1.8.1.4 + diff --git a/0114-Ticket-47623-fix-memleak-caused-by-47347.patch b/0114-Ticket-47623-fix-memleak-caused-by-47347.patch new file mode 100644 index 0000000..e3f28be --- /dev/null +++ b/0114-Ticket-47623-fix-memleak-caused-by-47347.patch @@ -0,0 +1,46 @@ +From 9812613da4adcf356ef9689b3eea0f9ce795efa8 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Tue, 10 Dec 2013 08:08:35 -0700 +Subject: [PATCH 114/115] Ticket #47623 fix memleak caused by 47347 + +https://fedorahosted.org/389/ticket/47623 +Reviewed by: tbordaz, nhosoi (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: Create the mutex if it doesn't exist. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 0d4849dd7551347f0e24ac1027f4d0501084dcf3) +(cherry picked from commit 5d3ae5f709964cd7dfb73b631a22389223f5ef25) +(cherry picked from commit 5c649ddacd1d2c11b6e922b29472094b780c2a0e) +(cherry picked from commit 75ed4b36722eeff8dc2d6aad0cf5e32dc474c3a7) +(cherry picked from commit 1eb281a8a1c5d6c1a22c198a23a8ba7b65991d77) +--- + ldap/servers/slapd/pagedresults.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index a835d6b..9af5773 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -122,7 +122,6 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + sizeof(PagedResults) * maxlen); + } + *index = maxlen; /* the first position in the new area */ +- conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock(); + } else { + for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { + if (!conn->c_pagedresults.prl_list[i].pr_current_be) { +@@ -131,6 +130,9 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + } + } + } ++ if (!conn->c_pagedresults.prl_list[*index].pr_mutex) { ++ conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock(); ++ } + conn->c_pagedresults.prl_count++; + } else { + /* Repeated paged results request. +-- +1.8.1.4 + diff --git a/0115-Ticket-47707-389-DS-Server-crashes-and-dies-while-ha.patch b/0115-Ticket-47707-389-DS-Server-crashes-and-dies-while-ha.patch new file mode 100644 index 0000000..f7424a0 --- /dev/null +++ b/0115-Ticket-47707-389-DS-Server-crashes-and-dies-while-ha.patch @@ -0,0 +1,84 @@ +From 9795451b028a048021af153ac39094578e4f1e50 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Tue, 29 Apr 2014 17:34:47 -0700 +Subject: [PATCH 115/115] Ticket #47707 - 389 DS Server crashes and dies while + handles paged searches from clients + +Bug Description: If a simple paged search request was sent to the server +and the request was abandoned, the paged result slot in the connection +table was not properly released by setting NULL to pr_current_be. Since +the slot did not look available for the next request even though it was, +the next request failed to get the valid slot number, and the initial slot +number -1 failed to be replaced with the real slot number. Until the fix +for "Ticket #47623 fix memleak caused by 47347" was made, it overrode the +allocated array's [-1] location, which usually stores the meta data of the +allocated memory. That crashed the server in the next realloc since the +corrupted memory was passed to the function. + +Fix Description: This patch cleans up the abandoned/cleaned up slot for +reuse. Also, more check not to break the meta data is added. + +Special thanks to German Parente (gparente@redhat.com) for providing the +reproducer and analysing the crash. + +https://fedorahosted.org/389/ticket/47707 + +Reviewed by rmeggins@redhat.com (Thanks, Rich!) + +(cherry picked from commit 087356f7eaff2dff3c0c4f7dfcaa6aacc9979224) +(cherry picked from commit 2132875746ed9e1fc7c9c53450241c91d0c5ae55) +(cherry picked from commit 40e86e74fb4ecc0fc5a1027d8241945d9b2564e0) +(cherry picked from commit b2ee65dd6c4af4f2cab515406a6f7fd9f1dc4dcc) +--- + ldap/servers/slapd/pagedresults.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c +index 9af5773..edd76c6 100644 +--- a/ldap/servers/slapd/pagedresults.c ++++ b/ldap/servers/slapd/pagedresults.c +@@ -130,7 +130,8 @@ pagedresults_parse_control_value( Slapi_PBlock *pb, + } + } + } +- if (!conn->c_pagedresults.prl_list[*index].pr_mutex) { ++ if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen) && ++ !conn->c_pagedresults.prl_list[*index].pr_mutex) { + conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock(); + } + conn->c_pagedresults.prl_count++; +@@ -270,6 +271,7 @@ 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; + } + if (prp->pr_mutex) { + /* pr_mutex is reused; back it up and reset it. */ +@@ -307,6 +309,7 @@ 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_flags |= CONN_FLAG_PAGEDRESULTS_ABANDONED; + prp->pr_flags &= ~CONN_FLAG_PAGEDRESULTS_PROCESSING; +@@ -724,6 +727,7 @@ 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; + } + if (prp->pr_mutex) { +@@ -771,6 +775,7 @@ 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; + } + } +-- +1.8.1.4 + diff --git a/0116-Ticket-47516-replication-stops-with-excessive-clock-.patch b/0116-Ticket-47516-replication-stops-with-excessive-clock-.patch new file mode 100644 index 0000000..acf1f30 --- /dev/null +++ b/0116-Ticket-47516-replication-stops-with-excessive-clock-.patch @@ -0,0 +1,151 @@ +From 950e31275f70141fdb195162ce8d7dc5cc3b169e Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 18 Sep 2013 12:32:23 -0600 +Subject: [PATCH 116/225] Ticket #47516 replication stops with excessive clock + skew + +https://fedorahosted.org/389/ticket/47516 +Reviewed by: nhosoi (Thanks!) +Branch: master +Fix Description: Add a new configuration parameter to cn=config +nsslapd-ignore-time-skew: on|off - default off +If nsslapd-ignore-time-skew: on, the replication consumer will log errors +about excessive time skew, but will allow replication to proceed, and will +not return a time skew error to the replication supplier. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: yes - document new config param +(cherry picked from commit 9dc7a4630cb13f1da074183208b1b34962fe8101) +--- + ldap/servers/plugins/replication/repl_extop.c | 11 +++++++-- + ldap/servers/slapd/libglobs.c | 32 ++++++++++++++++++++++++++- + ldap/servers/slapd/proto-slap.h | 2 ++ + ldap/servers/slapd/slap.h | 2 ++ + 4 files changed, 44 insertions(+), 3 deletions(-) + +diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c +index 37ee1ff..cccebb4 100644 +--- a/ldap/servers/plugins/replication/repl_extop.c ++++ b/ldap/servers/plugins/replication/repl_extop.c +@@ -835,12 +835,19 @@ multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb) + rc = replica_update_csngen_state_ext (replica, supplier_ruv, replicacsn); /* too much skew */ + if (rc == CSN_LIMIT_EXCEEDED) + { +- response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW; ++ extern int config_get_ignore_time_skew(); ++ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "conn=%" NSPRIu64 " op=%d repl=\"%s\": " + "Excessive clock skew from supplier RUV\n", + connid, opid, repl_root); +- goto send_response; ++ if (!config_get_ignore_time_skew()) { ++ response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW; ++ goto send_response; ++ } else { ++ /* else just continue */ ++ rc = 0; ++ } + } + else if (rc != 0) + { +diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c +index aaee33a..930fd72 100644 +--- a/ldap/servers/slapd/libglobs.c ++++ b/ldap/servers/slapd/libglobs.c +@@ -696,7 +696,11 @@ static struct config_get_and_set { + {CONFIG_LISTEN_BACKLOG_SIZE, config_set_listen_backlog_size, + NULL, 0, + (void**)&global_slapdFrontendConfig.listen_backlog_size, CONFIG_INT, +- (ConfigGetFunc)config_get_listen_backlog_size} ++ (ConfigGetFunc)config_get_listen_backlog_size}, ++ {CONFIG_IGNORE_TIME_SKEW, config_set_ignore_time_skew, ++ NULL, 0, ++ (void**)&global_slapdFrontendConfig.ignore_time_skew, ++ CONFIG_ON_OFF, (ConfigGetFunc)config_get_ignore_time_skew} + #ifdef MEMPOOL_EXPERIMENTAL + ,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch, + NULL, 0, +@@ -1100,6 +1104,7 @@ FrontendConfig_init () { + cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE; + + cfg->listen_backlog_size = DAEMON_LISTEN_SIZE; ++ cfg->ignore_time_skew = LDAP_OFF; + #ifdef MEMPOOL_EXPERIMENTAL + cfg->mempool_switch = LDAP_ON; + cfg->mempool_maxfreelist = 1024; +@@ -6215,6 +6220,31 @@ config_get_listen_backlog_size() + return retVal; + } + ++int ++config_get_ignore_time_skew(void) ++{ ++ int retVal; ++ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); ++ CFG_LOCK_READ(slapdFrontendConfig); ++ retVal = slapdFrontendConfig->ignore_time_skew; ++ CFG_UNLOCK_READ(slapdFrontendConfig); ++ ++ return retVal; ++} ++ ++int ++config_set_ignore_time_skew( const char *attrname, char *value, ++ char *errorbuf, int apply ) ++{ ++ int retVal = LDAP_SUCCESS; ++ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); ++ ++ retVal = config_set_onoff(attrname, value, ++ &(slapdFrontendConfig->ignore_time_skew), ++ errorbuf, apply); ++ return retVal; ++} ++ + /* + * This function is intended to be used from the dse code modify callback. It + * is "optimized" for that case because it takes a berval** of values, which is +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index d4c9ab6..c87d2f2 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -392,6 +392,7 @@ int config_set_disk_logging_critical( const char *attrname, char *value, char *e + int config_set_auditlog_unhashed_pw(const char *attrname, char *value, char *errorbuf, int apply); + int config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply ); + int config_set_listen_backlog_size(const char *attrname, char *value, char *errorbuf, int apply); ++int config_set_ignore_time_skew(const char *attrname, char *value, char *errorbuf, int apply); + + #if !defined(_WIN32) && !defined(AIX) + int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply ); +@@ -548,6 +549,7 @@ int config_get_disk_grace_period(); + int config_get_disk_logging_critical(); + int config_get_sasl_maxbufsize(); + int config_get_listen_backlog_size(void); ++int config_get_ignore_time_skew(); + + int is_abspath(const char *); + char* rel2abspath( char * ); +diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h +index eaa1fee..4724f27 100644 +--- a/ldap/servers/slapd/slap.h ++++ b/ldap/servers/slapd/slap.h +@@ -2006,6 +2006,7 @@ typedef struct _slapdEntryPoints { + #define CONFIG_DISK_LOGGING_CRITICAL "nsslapd-disk-monitoring-logging-critical" + #define CONFIG_SASL_MAXBUFSIZE "nsslapd-sasl-max-buffer-size" + #define CONFIG_LISTEN_BACKLOG_SIZE "nsslapd-listen-backlog-size" ++#define CONFIG_IGNORE_TIME_SKEW "nsslapd-ignore-time-skew" + + /* + * Define the backlog number for use in listen() call. +@@ -2250,6 +2251,7 @@ typedef struct _slapdFrontendConfig { + PRUint64 disk_threshold; + int disk_grace_period; + int disk_logging_critical; ++ int ignore_time_skew; + } slapdFrontendConfig_t; + + /* possible values for slapdFrontendConfig_t.schemareplace */ +-- +1.8.1.4 + diff --git a/0117-Ticket-47492-PassSync-removes-User-must-change-passw.patch b/0117-Ticket-47492-PassSync-removes-User-must-change-passw.patch new file mode 100644 index 0000000..92ac9ce --- /dev/null +++ b/0117-Ticket-47492-PassSync-removes-User-must-change-passw.patch @@ -0,0 +1,319 @@ +From 51b3a4d6764fc460bf2b41678fe5232df15bed65 Mon Sep 17 00:00:00 2001 +From: Noriko Hosoi +Date: Mon, 23 Sep 2013 11:53:38 -0700 +Subject: [PATCH 117/225] Ticket #47492 - PassSync removes User must change + password flag on the Windows side + +Bug description: Windows Sync sends password modify even if it is +from PassSync originated on AD. The modify updates the pwdLastSet +attribute value to non-zero value. The value 0 indicates the pass- +word must change at next logon on AD. + +Fix description: Before sending the password modify, check whether +the current pwdLastSet value is 0 or not. If it is 0 (means the +password must change), reset pwdLastSet value to 0 along with the +password modify. This operation replaces the password on AD, but +the password still must change at next logon. + +Note: If "password must change at next logon" on the both DS and AD, +the password needs to be changed by the user on the both servers to +enable it on each. + +https://fedorahosted.org/389/ticket/47492 + +Reviewed by Rich (Thank you!!) +(cherry picked from commit f9d1d9e08225e5885b76cede4da677708892ee7a) +(cherry picked from commit 8d34f77f6d8d3c83dce1f29e6df709df1adef09d) +(cherry picked from commit 5005db538cc5ed33b906309715034a0d1cc62cc7) +--- + .../plugins/replication/windows_protocol_util.c | 139 +++++++++++++++------ + 1 file changed, 100 insertions(+), 39 deletions(-) + +diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c +index 75cb935..93246ec 100644 +--- a/ldap/servers/plugins/replication/windows_protocol_util.c ++++ b/ldap/servers/plugins/replication/windows_protocol_util.c +@@ -70,7 +70,7 @@ static int windows_get_local_entry(const Slapi_DN* local_dn,Slapi_Entry **local_ + static int windows_get_local_entry_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqueid,Slapi_Entry **local_entry, int is_global); + static int windows_get_local_tombstone_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqueid,Slapi_Entry **local_entry); + static int windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *uniqueid, char ** attrs, Slapi_Entry **ret_entry, int tombstone, void * component_identity, int is_global); +-static int map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry, int want_guid); ++static int map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry, int want_guid, Slapi_Entry **remote_entry); + static char* extract_ntuserdomainid_from_entry(Slapi_Entry *e); + static char* extract_container(const Slapi_DN *entry_dn, const Slapi_DN *suffix_dn); + static int windows_get_remote_entry (Private_Repl_Protocol *prp, const Slapi_DN* remote_dn,Slapi_Entry **remote_entry); +@@ -448,7 +448,7 @@ map_dn_values(Private_Repl_Protocol *prp,Slapi_ValueSet *original_values, Slapi_ + is_ours = is_subject_of_agreement_local(local_entry,prp->agmt); + if (is_ours) + { +- map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry, 0 /* don't want GUID form here */); ++ map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry, 0 /* don't want GUID form here */, NULL); + if (remote_dn) + { + if (!missing_entry) +@@ -768,7 +768,10 @@ to_little_endian_double_bytes(UChar *unicode_password, int32_t unicode_password_ + /* this entry had a password, handle it seperately */ + /* http://support.microsoft.com/?kbid=269190 */ + static int +-send_password_modify(Slapi_DN *sdn, char *password, Private_Repl_Protocol *prp) ++send_password_modify(Slapi_DN *sdn, ++ char *password, ++ Private_Repl_Protocol *prp, ++ Slapi_Entry *remote_entry) + { + ConnResult pw_return = 0; + +@@ -791,6 +794,35 @@ send_password_modify(Slapi_DN *sdn, char *password, Private_Repl_Protocol *prp) + + } else + { ++ Slapi_Attr *attr = NULL; ++ int force_reset_pw = 0; ++ /* ++ * If AD entry has password must change flag is set, ++ * we keep the flag (pwdLastSet == 0). ++ * msdn.microsoft.com: Windows Dev Centor - Desktop ++ * To force a user to change their password at next logon, ++ * set the pwdLastSet attribute to zero (0). ++ */ ++ if (remote_entry && ++ (0 == slapi_entry_attr_find(remote_entry, "pwdLastSet", &attr)) && ++ attr) { ++ Slapi_Value *v = NULL; ++ int i = 0; ++ for (i = slapi_attr_first_value(attr, &v); ++ v && (i != -1); ++ i = slapi_attr_next_value(attr, i, &v)) { ++ const char *s = slapi_value_get_string(v); ++ if (NULL == s) { ++ continue; ++ } ++ if (0 == strcmp(s, "0")) { ++ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, ++ "%s: AD entry %s set \"user must change password at next logon\". ", ++ agmt_get_long_name(prp->agmt), slapi_entry_get_dn(remote_entry)); ++ force_reset_pw = 1; ++ } ++ } ++ } + /* We will attempt to bind to AD with the new password first. We do + * this to avoid playing a password change that originated from AD + * back to AD. If we just played the password change back, then +@@ -803,38 +835,53 @@ send_password_modify(Slapi_DN *sdn, char *password, Private_Repl_Protocol *prp) + quoted_password = PR_smprintf("\"%s\"",password); + if (quoted_password) + { +- LDAPMod *pw_mods[2]; +- LDAPMod pw_mod; +- struct berval bv = {0}; + UChar *unicode_password = NULL; + int32_t unicode_password_length = 0; /* Length in _characters_ */ + int32_t buffer_size = 0; /* Size in _characters_ */ + UErrorCode error = U_ZERO_ERROR; +- struct berval *bvals[2]; + /* Need to UNICODE encode the password here */ + /* It's one of those 'ask me first and I will tell you the buffer size' functions */ + u_strFromUTF8(NULL, 0, &unicode_password_length, quoted_password, strlen(quoted_password), &error); + buffer_size = unicode_password_length; + unicode_password = (UChar *)slapi_ch_malloc(unicode_password_length * sizeof(UChar)); + if (unicode_password) { ++ LDAPMod *pw_mods[3]; ++ LDAPMod pw_mod; ++ LDAPMod reset_pw_mod; ++ struct berval bv = {0}; ++ struct berval *bvals[2]; ++ struct berval reset_bv = {0}; ++ struct berval *reset_bvals[2]; + error = U_ZERO_ERROR; + u_strFromUTF8(unicode_password, buffer_size, &unicode_password_length, quoted_password, strlen(quoted_password), &error); +- ++ + /* As an extra special twist, we need to send the unicode in little-endian order for AD to be happy */ + to_little_endian_double_bytes(unicode_password, unicode_password_length); +- ++ + bv.bv_len = unicode_password_length * sizeof(UChar); + bv.bv_val = (char*)unicode_password; +- ++ + bvals[0] = &bv; + bvals[1] = NULL; + + pw_mod.mod_type = "UnicodePwd"; + pw_mod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES; + pw_mod.mod_bvalues = bvals; +- ++ + pw_mods[0] = &pw_mod; +- pw_mods[1] = NULL; ++ if (force_reset_pw) { ++ reset_bv.bv_len = 1; ++ reset_bv.bv_val = "0"; ++ reset_bvals[0] = &reset_bv; ++ reset_bvals[1] = NULL; ++ reset_pw_mod.mod_type = "pwdLastSet"; ++ reset_pw_mod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES; ++ reset_pw_mod.mod_bvalues = reset_bvals; ++ pw_mods[1] = &reset_pw_mod; ++ pw_mods[2] = NULL; ++ } else { ++ pw_mods[1] = NULL; ++ } + + pw_return = windows_conn_send_modify(prp->conn, slapi_sdn_get_dn(sdn), pw_mods, NULL, NULL ); + +@@ -1414,6 +1461,7 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op + Slapi_DN *remote_dn = NULL; + Slapi_DN *local_dn = NULL; + Slapi_Entry *local_entry = NULL; ++ Slapi_Entry *remote_entry = NULL; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_replay_update\n", 0, 0, 0 ); + +@@ -1488,7 +1536,7 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op + if (is_ours && (is_user || is_group) ) { + int missing_entry = 0; + /* Make the entry's DN */ +- rc = map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry, 1); ++ rc = map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry, 1, &remote_entry); + if (rc || NULL == remote_dn) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, +@@ -1676,13 +1724,17 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op + * seem to work over plain LDAP. */ + if (is_guid_dn(remote_dn)) { + Slapi_DN *remote_dn_norm = NULL; +- int norm_missing = 0; + +- map_entry_dn_outbound(local_entry,&remote_dn_norm,prp,&norm_missing, 0); +- return_value = send_password_modify(remote_dn_norm, password, prp); ++ if (remote_entry) { ++ remote_dn_norm = slapi_sdn_dup(slapi_entry_get_sdn_const(remote_entry)); ++ } else { ++ int norm_missing = 0; ++ map_entry_dn_outbound(local_entry,&remote_dn_norm,prp,&norm_missing, 0, &remote_entry); ++ } ++ return_value = send_password_modify(remote_dn_norm, password, prp, remote_entry); + slapi_sdn_free(&remote_dn_norm); + } else { +- return_value = send_password_modify(remote_dn, password, prp); ++ return_value = send_password_modify(remote_dn, password, prp, remote_entry); + } + + if (return_value) +@@ -1710,18 +1762,10 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op + /* We ignore operations that target entries outside of our sync'ed subtree, or which are not Windows users or groups */ + } + error: +- if (local_entry) +- { +- slapi_entry_free(local_entry); +- } +- if (local_dn) +- { +- slapi_sdn_free (&local_dn); +- } +- if (remote_dn) +- { +- slapi_sdn_free(&remote_dn); +- } ++ slapi_entry_free(remote_entry); ++ slapi_entry_free(local_entry); ++ slapi_sdn_free (&local_dn); ++ slapi_sdn_free(&remote_dn); + slapi_ch_free_string(&password); + return return_value; + } +@@ -3388,13 +3432,27 @@ extract_container(const Slapi_DN *entry_dn, const Slapi_DN *suffix_dn) + + /* Given a non-tombstone entry, return the DN of its peer in AD (whether present or not) */ + static int +-map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry, int guid_form) ++map_entry_dn_outbound(Slapi_Entry *e, ++ Slapi_DN **dn, ++ Private_Repl_Protocol *prp, ++ int *missing_entry, ++ int guid_form, ++ Slapi_Entry **remote_entry_to_return) + { + int retval = 0; + char *guid = NULL; + Slapi_DN *new_dn = NULL; + int is_nt4 = windows_private_get_isnt4(prp->agmt); +- const char *suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt)); ++ const char *suffix = NULL; ++ Slapi_Entry *remote_entry = NULL; ++ ++ if (NULL == e) { ++ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, ++ "%s: map_entry_dn_outbound: NULL entry.\n", ++ agmt_get_long_name(prp->agmt)); ++ return -1; ++ } ++ + /* To find the DN of the peer entry we first look for an ntUniqueId attribute + * on the local entry. If that's present, we generate a GUID-form DN. + * If there's no GUID, then we look for an ntUserDomainId attribute +@@ -3417,7 +3475,6 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, + if (guid && guid_form) + { + int rc = 0; +- Slapi_Entry *remote_entry = NULL; + new_dn = make_dn_from_guid(guid, is_nt4, suffix); + if (!new_dn) { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, +@@ -3445,7 +3502,6 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, + slapi_sdn_free(&new_dn); + retval = -1; + } +- slapi_entry_free(remote_entry); + } else { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: map_entry_dn_outbound: entry not found - rc %d\n", +@@ -3486,7 +3542,6 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, + } else + { + /* No GUID found, try ntUserDomainId */ +- Slapi_Entry *remote_entry = NULL; + char *username = slapi_entry_attr_get_charptr(e,"ntUserDomainId"); + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: map_entry_dn_outbound: looking for AD entry for DS " +@@ -3562,16 +3617,22 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp, + } + slapi_ch_free_string(&username); + } +- if (remote_entry) +- { +- slapi_entry_free(remote_entry); +- } + } + done: + if (new_dn) + { + *dn = new_dn; + } ++ if (remote_entry_to_return) { ++ if (retval) { /* failed */ ++ slapi_entry_free(remote_entry); ++ *remote_entry_to_return = NULL; ++ } else { ++ *remote_entry_to_return = remote_entry; ++ } ++ } else { ++ slapi_entry_free(remote_entry); ++ } + slapi_ch_free_string(&guid); + return retval; + } +@@ -4904,7 +4965,7 @@ int windows_process_total_entry(Private_Repl_Protocol *prp,Slapi_Entry *e) + agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(slapi_entry_get_sdn_const(e)), is_ours ? "ours" : "not ours"); + if (is_ours) + { +- retval = map_entry_dn_outbound(e,&remote_dn,prp,&missing_entry,0 /* we don't want the GUID */); ++ retval = map_entry_dn_outbound(e,&remote_dn,prp,&missing_entry,0 /* we don't want the GUID */, NULL); + if (retval || NULL == remote_dn) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, +-- +1.8.1.4 + diff --git a/0118-Ticket-47504-idlistscanlimit-per-index-type-value.patch b/0118-Ticket-47504-idlistscanlimit-per-index-type-value.patch new file mode 100644 index 0000000..eaefe29 --- /dev/null +++ b/0118-Ticket-47504-idlistscanlimit-per-index-type-value.patch @@ -0,0 +1,997 @@ +From 5785161fc08729840214da0ca3368dc930257a83 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Mon, 16 Sep 2013 09:49:14 -0600 +Subject: [PATCH 118/225] Ticket #47504 idlistscanlimit per index/type/value + +https://fedorahosted.org/389/ticket/47504 +Reviewed by: nhosoi (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: Added a new attribute nsIndexIDListScanLimit to nsIndex + nsIndexIDListScanLimit: limit=NNN [type=eq[,sub,...]] [flags=ADD[,XXX..]] [values=val[,val...]] +* The limit is the idlistscanlimit to apply. The value can be -1 (unlimited), 0 +(do not use the index at all), or a number to use for the idlistscanlimit. +* The type is a comma-delimited list of index types (eq,sub,etc.) to which the +limit applies. The index type must be one of the index types configured for the index (you can't configure an id list for type=sub if you do not already have +a substring index configured for the attribute). +* The flags are a comma-delimited list of additional criteria which must match. +** flags ADD - only apply the limit when the index is used in an AND (&) filter +The values are a comma-delimited list of values which must match in the search +filter in order for the limit to be applied. Since the matches are done one +at a time (we evaluate one filter component at a time), the values will match +if any of the values match. +* The values must be used with only one type at a time. If values are specified, +type must be specified, and type must be a type that deals with values, such +as eq or sub. There must be only one type specified - you can't specify values +if you use type=eq,pres or otherwise specify more than one type. The values +must correspond to the index type (eq, sub), and must correspond to the syntax +of the attribute to which the index is applied - that is, if you have +attribute uidNumber (integer) and it is indexed for eq, you can't specify +type=eq values=abc because "abc" is not integer syntax. +If the values contain spaces, commas, nulls, other values which require +escapes, the LDAP filter escape syntax should be used - backslash '\' followed +by the 2 hex digit code for the character. +The values are processed as if they were filter values - so for "sub" values, +values like "values=*sm*ith*" will be processed as if they were values in a +substring search filter like (sn=*sm*ith*) +* nsIndexIDListScanLimit is multi-valued. If a search matches more than one +nsIndexIDListScanLimit, the rules are applied in priority order. +The priority is as follows, from highest to lowest: + * * match type, flags, value + * * match type, value + * * match type, flags + * * match type + * * match flags + * For example, if you have + * dn: cn=objectclass,... + * objectclass: nsIndex + * nsIndexType: eq + * nsIndexIDListScanLimit: limit=0 type=eq flags=AND value=inetOrgPerson + * nsIndexIDListScanLimit: limit=1 type=eq value=inetOrgPerson + * nsIndexIDListScanLimit: limit=2 type=eq flags=AND + * nsIndexIDListScanLimit: limit=3 type=eq + * nsIndexIDListScanLimit: limit=4 flags=AND + * nsIndexIDListScanLimit: limit=5 + * If the search filter is (&(objectclass=inetOrgPerson)(uid=foo)) then the limit=0 because all + * 3 of type, flags, and value match + * If the search filter is (objectclass=inetOrgPerson) then the limit=1 because type and value match + * but flag does not + * If the search filter is (&(objectclass=posixAccount)(uid=foo)) the the limit=2 because type and + * flags match + * If the search filter is (objectclass=posixAccount) then the limit=3 because only the type matches + * If the search filter is (&(objectclass=*account*)(objectclass=*)) then the limit=4 because only + * flags match but not the types (sub and pres) + * If the search filter is (objectclass=*account*) then the limit=5 because only the attribute matches + * but none of flags, type, or value matches +To add in testing/debugging, the LDAP_DEBUG_BACKLDBM log level is used to +print information about searches which exceed the idlistscanlimit. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: yes - document new attribute +(cherry picked from commit 824b3019beffa5bf2bc5ab2a2a3e579d50833577) +(cherry picked from commit b348886030318cd43855ae439ec3f30f898b8cd4) +(cherry picked from commit b5ad052dcccec7318ac4717bbda5d02d6d415c06) +--- + ldap/schema/01core389.ldif | 3 +- + ldap/servers/slapd/back-ldbm/ancestorid.c | 2 +- + ldap/servers/slapd/back-ldbm/back-ldbm.h | 9 + + ldap/servers/slapd/back-ldbm/filterindex.c | 14 +- + ldap/servers/slapd/back-ldbm/idl_new.c | 21 +- + ldap/servers/slapd/back-ldbm/index.c | 121 +++++- + ldap/servers/slapd/back-ldbm/ldbm_attr.c | 494 +++++++++++++++++++++++++ + ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 2 +- + ldap/servers/slapd/proto-slap.h | 1 + + 9 files changed, 648 insertions(+), 19 deletions(-) + +diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif +index 4f859d2..a1f993f 100644 +--- a/ldap/schema/01core389.ldif ++++ b/ldap/schema/01core389.ldif +@@ -66,6 +66,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.593 NAME 'nsSNMPName' DESC 'Netscape def + attributeTypes: ( 2.16.840.1.113730.3.1.242 NAME 'nsSystemIndex' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.327 NAME 'nsIndexType' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.328 NAME 'nsMatchingRule' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) ++attributeTypes: ( 2.16.840.1.113730.3.1.2161 NAME 'nsIndexIDListScanLimit' DESC 'fine grained idlistscanlimit - per index/type/value' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.542 NAME 'nsUniqueId' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.543 NAME 'nsState' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) + attributeTypes: ( 2.16.840.1.113730.3.1.544 NAME 'nsParentUniqueId' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) +@@ -157,7 +158,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2156 NAME 'nsslapd-sasl-max-buffer-size' + # + objectClasses: ( 2.16.840.1.113730.3.2.40 NAME 'directoryServerFeature' DESC 'Netscape defined objectclass' SUP top MAY ( oid $ cn $ multiLineDescription ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.41 NAME 'nsslapdPlugin' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsslapd-pluginPath $ nsslapd-pluginInitFunc $ nsslapd-pluginType $ nsslapd-pluginId $ nsslapd-pluginVersion $ nsslapd-pluginVendor $ nsslapd-pluginDescription $ nsslapd-pluginEnabled ) MAY ( nsslapd-pluginConfigArea $ nsslapd-plugin-depends-on-type ) X-ORIGIN 'Netscape Directory Server' ) +-objectClasses: ( 2.16.840.1.113730.3.2.44 NAME 'nsIndex' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSystemIndex ) MAY ( description $ nsIndexType $ nsMatchingRule ) X-ORIGIN 'Netscape Directory Server' ) ++objectClasses: ( 2.16.840.1.113730.3.2.44 NAME 'nsIndex' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSystemIndex ) MAY ( description $ nsIndexType $ nsMatchingRule $ nsIndexIDListScanLimit ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.109 NAME 'nsBackendInstance' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.110 NAME 'nsMappingTree' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' ) + objectClasses: ( 2.16.840.1.113730.3.2.104 NAME 'nsContainer' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' ) +diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c +index 2f32f8f..8722b68 100644 +--- a/ldap/servers/slapd/back-ldbm/ancestorid.c ++++ b/ldap/servers/slapd/back-ldbm/ancestorid.c +@@ -1008,7 +1008,7 @@ int ldbm_ancestorid_read_ext( + bv.bv_val = keybuf; + bv.bv_len = PR_snprintf(keybuf, sizeof(keybuf), "%lu", (u_long)id); + +- *idl = index_read_ext_allids(be, LDBM_ANCESTORID_STR, indextype_EQUALITY, &bv, txn, &ret, NULL, allidslimit); ++ *idl = index_read_ext_allids(NULL, be, LDBM_ANCESTORID_STR, indextype_EQUALITY, &bv, txn, &ret, NULL, allidslimit); + + return ret; + } +diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h +index 61c7af9..9635813 100644 +--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h +@@ -461,6 +461,14 @@ typedef int (*dup_compare_fn_type)( + #endif + const DBT *,const DBT *); + ++struct index_idlistsizeinfo { ++ int ai_idlistsizelimit; /* max id list size */ ++ int ai_indextype; /* index type */ ++ unsigned int ai_flags; ++#define INDEX_ALLIDS_FLAG_AND 0x01 ++ Slapi_ValueSet *ai_values; /* index keys to apply the max id list size to */ ++}; ++ + /* for the cache of attribute information (which are indexed, etc.) */ + struct attrinfo { + char *ai_type; /* type name (cn, sn, ...) */ +@@ -509,6 +517,7 @@ struct attrinfo { + * the default length triplet is 2, 3, 2. + */ + Slapi_Attr ai_sattr; /* interface to syntax and matching rule plugins */ ++ DataList *ai_idlistinfo; /* fine grained id list */ + }; + + #define MAXDBCACHE 20 +diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c +index 995a62e..a213815 100644 +--- a/ldap/servers/slapd/back-ldbm/filterindex.c ++++ b/ldap/servers/slapd/back-ldbm/filterindex.c +@@ -67,6 +67,7 @@ static IDList * range_candidates( + ); + static IDList * + keys2idl( ++ Slapi_PBlock *pb, + backend *be, + char *type, + const char *indextype, +@@ -313,7 +314,7 @@ ava_candidates( + ivals=ptr; + + slapi_attr_assertion2keys_ava_sv( &sattr, &tmp, (Slapi_Value ***)&ivals, LDAP_FILTER_EQUALITY_FAST); +- idl = keys2idl( be, type, indextype, ivals, err, &unindexed, &txn, allidslimit ); ++ idl = keys2idl( pb, be, type, indextype, ivals, err, &unindexed, &txn, allidslimit ); + if ( unindexed ) { + unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); +@@ -345,7 +346,7 @@ ava_candidates( + idl = idl_allids( be ); + goto done; + } +- idl = keys2idl( be, type, indextype, ivals, err, &unindexed, &txn, allidslimit ); ++ idl = keys2idl( pb, be, type, indextype, ivals, err, &unindexed, &txn, allidslimit ); + if ( unindexed ) { + unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED; + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); +@@ -382,7 +383,7 @@ presence_candidates( + return( NULL ); + } + slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn); +- idl = index_read_ext_allids( be, type, indextype_PRESENCE, ++ idl = index_read_ext_allids( pb, be, type, indextype_PRESENCE, + NULL, &txn, err, &unindexed, allidslimit ); + + if ( unindexed ) { +@@ -491,7 +492,7 @@ extensible_candidates( + { + int unindexed = 0; + IDList* idl3 = (mrOP == SLAPI_OP_EQUAL) ? +- index_read_ext_allids(be, mrTYPE, mrOID, *key, &txn, ++ index_read_ext_allids(pb, be, mrTYPE, mrOID, *key, &txn, + err, &unindexed, allidslimit) : + index_range_read_ext(pb, be, mrTYPE, mrOID, mrOP, + *key, NULL, 0, &txn, err, allidslimit); +@@ -928,7 +929,7 @@ substring_candidates( + * IDLists together. + */ + slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn); +- idl = keys2idl( be, type, indextype_SUB, ivals, err, &unindexed, &txn, allidslimit ); ++ idl = keys2idl( pb, be, type, indextype_SUB, ivals, err, &unindexed, &txn, allidslimit ); + if ( unindexed ) { + slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote ); + pagedresults_set_unindexed( pb->pb_conn, pb->pb_op, pr_idx ); +@@ -942,6 +943,7 @@ substring_candidates( + + static IDList * + keys2idl( ++ Slapi_PBlock *pb, + backend *be, + char *type, + const char *indextype, +@@ -961,7 +963,7 @@ keys2idl( + for ( i = 0; ivals[i] != NULL; i++ ) { + IDList *idl2; + +- idl2 = index_read_ext_allids( be, type, indextype, slapi_value_get_berval(ivals[i]), txn, err, unindexed, allidslimit ); ++ idl2 = index_read_ext_allids( pb, be, type, indextype, slapi_value_get_berval(ivals[i]), txn, err, unindexed, allidslimit ); + + #ifdef LDAP_DEBUG + /* XXX if ( slapd_ldap_debug & LDAP_DEBUG_TRACE ) { XXX */ +diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c +index 9cd3daf..936c19f 100644 +--- a/ldap/servers/slapd/back-ldbm/idl_new.c ++++ b/ldap/servers/slapd/back-ldbm/idl_new.c +@@ -266,7 +266,7 @@ IDList * idl_new_fetch( + } + memcpy(&id, dataret.data, sizeof(ID)); + if (id == lastid) { /* dup */ +- LDAPDebug1Arg(LDAP_DEBUG_TRACE, "Detedted duplicate id " ++ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "Detected duplicate id " + "%d due to DB_MULTIPLE error - skipping\n", + id); + continue; /* get next one */ +@@ -286,14 +286,17 @@ IDList * idl_new_fetch( + + LDAPDebug(LDAP_DEBUG_TRACE, "bulk fetch buffer nids=%d\n", count, 0, 0); + #if defined(DB_ALLIDS_ON_READ) +- /* enforce the allids read limit */ +- if ((NEW_IDL_NO_ALLID != *flag_err) && (NULL != a) && +- (idl != NULL) && idl_new_exceeds_allidslimit(count, a, allidslimit)) { +- idl->b_nids = 1; +- idl->b_ids[0] = ALLID; +- ret = DB_NOTFOUND; /* fool the code below into thinking that we finished the dups */ +- break; +- } ++ /* enforce the allids read limit */ ++ if ((NEW_IDL_NO_ALLID != *flag_err) && (NULL != a) && ++ (idl != NULL) && idl_new_exceeds_allidslimit(count, a, allidslimit)) { ++ idl->b_nids = 1; ++ idl->b_ids[0] = ALLID; ++ ret = DB_NOTFOUND; /* fool the code below into thinking that we finished the dups */ ++ LDAPDebug(LDAP_DEBUG_BACKLDBM, "search for key for attribute index %s " ++ "exceeded allidslimit %d - count is %d\n", ++ a->ai_type, allidslimit, count); ++ break; ++ } + #endif + ret = cursor->c_get(cursor,&key,&data,DB_NEXT_DUP|DB_MULTIPLE); + if (0 != ret) { +diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c +index 7769791..f47f63d 100644 +--- a/ldap/servers/slapd/back-ldbm/index.c ++++ b/ldap/servers/slapd/back-ldbm/index.c +@@ -52,6 +52,8 @@ + static const char *errmsg = "database index operation failed"; + + static int is_indexed (const char* indextype, int indexmask, char** index_rules); ++static int index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags ); ++ + static Slapi_Value ** + valuearray_minus_valuearray( + const Slapi_Attr *sattr, +@@ -888,6 +890,7 @@ index_read( + */ + IDList * + index_read_ext_allids( ++ Slapi_PBlock *pb, + backend *be, + char *type, + const char *indextype, +@@ -910,6 +913,8 @@ index_read_ext_allids( + char *basetmp, *basetype; + int retry_count = 0; + struct berval *encrypted_val = NULL; ++ int is_and = 0; ++ unsigned int ai_flags = 0; + + *err = 0; + +@@ -976,6 +981,23 @@ index_read_ext_allids( + slapi_ch_free_string( &basetmp ); + return( idl ); + } ++ if (pb) { ++ slapi_pblock_get(pb, SLAPI_SEARCH_IS_AND, &is_and); ++ } ++ ai_flags = is_and ? INDEX_ALLIDS_FLAG_AND : 0; ++ allidslimit = index_get_allids( allidslimit, indextype, ai, val, ai_flags ); ++ if (allidslimit == 0) { ++ idl = idl_allids( be ); ++ if (unindexed != NULL) *unindexed = 1; ++ LDAPDebug1Arg( LDAP_DEBUG_BACKLDBM, "<= index_read %lu candidates " ++ "(do not use index)\n", (u_long)IDL_NIDS(idl) ); ++ LDAPDebug( LDAP_DEBUG_BACKLDBM, "<= index_read index attr %s type %s " ++ "for value %s does not use index\n", basetype, indextype, ++ (val && val->bv_val) ? val->bv_val : "ALL" ); ++ index_free_prefix( prefix ); ++ slapi_ch_free_string( &basetmp ); ++ return( idl ); ++ } + if ( (*err = dblayer_get_index_file( be, ai, &db, DBOPEN_CREATE )) != 0 ) { + LDAPDebug( LDAP_DEBUG_TRACE, + "<= index_read NULL (index file open for attr %s)\n", +@@ -1063,7 +1085,7 @@ index_read_ext( + int *unindexed + ) + { +- return index_read_ext_allids(be, type, indextype, val, txn, err, unindexed, 0); ++ return index_read_ext_allids(NULL, be, type, indextype, val, txn, err, unindexed, 0); + } + + /* This function compares two index keys. It is assumed +@@ -2351,3 +2373,100 @@ valuearray_minus_valuearray( + + return c; + } ++ ++/* ++ * Find the most specific match for the given index type, flags, and value, and return the allids value ++ * for that match. The priority is as follows, from highest to lowest: ++ * * match type, flags, value ++ * * match type, value ++ * * match type, flags ++ * * match type ++ * * match flags ++ * Note that for value to match, the type must be one that supports values e.g. eq or sub, so that ++ * in order for value to match, there must be a type ++ * For example, if you have ++ * dn: cn=objectclass,... ++ * objectclass: nsIndex ++ * nsIndexType: eq ++ * nsIndexIDListScanLimit: limit=0 type=eq flags=AND value=inetOrgPerson ++ * nsIndexIDListScanLimit: limit=1 type=eq value=inetOrgPerson ++ * nsIndexIDListScanLimit: limit=2 type=eq flags=AND ++ * nsIndexIDListScanLimit: limit=3 type=eq ++ * nsIndexIDListScanLimit: limit=4 flags=AND ++ * nsIndexIDListScanLimit: limit=5 ++ * If the search filter is (&(objectclass=inetOrgPerson)(uid=foo)) then the limit=0 because all ++ * 3 of type, flags, and value match ++ * If the search filter is (objectclass=inetOrgPerson) then the limit=1 because type and value match ++ * but flag does not ++ * If the search filter is (&(objectclass=posixAccount)(uid=foo)) the the limit=2 because type and ++ * flags match ++ * If the search filter is (objectclass=posixAccount) then the limit=3 because only the type matches ++ * If the search filter is (&(objectclass=*account*)(objectclass=*)) then the limit=4 because only ++ * flags match but not the types (sub and pres) ++ * If the search filter is (objectclass=*account*) then the limit=5 because only the attribute matches ++ * but none of flags, type, or value matches ++ */ ++#define AI_HAS_VAL 0x04 ++#define AI_HAS_TYPE 0x02 ++#define AI_HAS_FLAG 0x01 ++static int ++index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags ) ++{ ++ int allids = default_allids; ++ Slapi_Value sval; ++ struct index_idlistsizeinfo *iter; /* iterator */ ++ int cookie = 0; ++ int best_score = 0; ++ struct index_idlistsizeinfo *best_match = NULL; ++ ++ if (!ai->ai_idlistinfo) { ++ return allids; ++ } ++ ++ if (val) { /* val should already be a Slapi_Value, but some paths do not use Slapi_Value */ ++ sval.bv.bv_val = val->bv_val; ++ sval.bv.bv_len = val->bv_len; ++ sval.v_csnset = NULL; ++ sval.v_flags = SLAPI_ATTR_FLAG_NORMALIZED; /* the value must be a normalized key */ ++ } ++ ++ /* loop through all of the idlistinfo objects to find the best match */ ++ for (iter = (struct index_idlistsizeinfo *)dl_get_first(ai->ai_idlistinfo, &cookie); iter; ++ iter = (struct index_idlistsizeinfo *)dl_get_next(ai->ai_idlistinfo, &cookie)) { ++ int iter_score = 0; ++ ++ if (iter->ai_indextype != 0) { /* info defines a type which must match */ ++ if (is_indexed(indextype, iter->ai_indextype, ai->ai_index_rules)) { ++ iter_score |= AI_HAS_TYPE; ++ } else { ++ continue; /* does not match, go to next one */ ++ } ++ } ++ if (iter->ai_flags != 0) { ++ if (flags & iter->ai_flags) { ++ iter_score |= AI_HAS_FLAG; ++ } else { ++ continue; /* does not match, go to next one */ ++ } ++ } ++ if (iter->ai_values != NULL) { ++ if ((val != NULL) && slapi_valueset_find(&ai->ai_sattr, iter->ai_values, &sval)) { ++ iter_score |= AI_HAS_VAL; ++ } else { ++ continue; /* does not match, go to next one */ ++ } ++ } ++ ++ if (iter_score >= best_score) { ++ best_score = iter_score; ++ best_match = iter; ++ } ++ } ++ ++ if (best_match) { ++ allids = best_match->ai_idlistsizelimit; ++ } ++ ++ return allids; ++} ++ +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_attr.c b/ldap/servers/slapd/back-ldbm/ldbm_attr.c +index 7433ec7..9a930bc 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_attr.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_attr.c +@@ -44,6 +44,22 @@ + + #include "back-ldbm.h" + ++static void ++attr_index_idlistsize_done(struct index_idlistsizeinfo *idlinfo) ++{ ++ if (idlinfo) { ++ slapi_valueset_free(idlinfo->ai_values); ++ idlinfo->ai_values = NULL; ++ } ++} ++ ++static void ++attr_index_idlistsize_free(struct index_idlistsizeinfo **idlinfo) ++{ ++ attr_index_idlistsize_done(*idlinfo); ++ slapi_ch_free((void **)idlinfo); ++} ++ + struct attrinfo * + attrinfo_new() + { +@@ -52,6 +68,15 @@ attrinfo_new() + } + + void ++attrinfo_delete_idlistinfo(DataList **idlinfo_dl) ++{ ++ if (idlinfo_dl && *idlinfo_dl) { ++ dl_cleanup(*idlinfo_dl, (FREEFN)attr_index_idlistsize_free); ++ dl_free(idlinfo_dl); ++ } ++} ++ ++void + attrinfo_delete(struct attrinfo **pp) + { + if(pp!=NULL && *pp!=NULL) +@@ -62,6 +87,7 @@ attrinfo_delete(struct attrinfo **pp) + slapi_ch_free((void**)(*pp)->ai_index_rules); + slapi_ch_free((void**)&((*pp)->ai_attrcrypt)); + attr_done(&((*pp)->ai_sattr)); ++ attrinfo_delete_idlistinfo(&(*pp)->ai_idlistinfo); + slapi_ch_free((void**)pp); + *pp= NULL; + } +@@ -126,6 +152,10 @@ ainfo_dup( + if ( b->ai_indexmask & INDEX_RULES ) { + charray_merge( &a->ai_index_rules, b->ai_index_rules, 1 ); + } ++ /* free the old idlistinfo from a - transfer the list from b to a */ ++ attrinfo_delete_idlistinfo(&a->ai_idlistinfo); ++ a->ai_idlistinfo = b->ai_idlistinfo; ++ b->ai_idlistinfo = NULL; + + return( 1 ); + } +@@ -166,6 +196,464 @@ _set_attr_substrlen(int index, char *str, int **substrlens) + } + } + ++#define NS_INDEX_IDLISTSCANLIMIT "nsIndexIDListScanLimit" ++#define LIMIT_KW "limit=" ++#define LIMIT_LEN sizeof(LIMIT_KW)-1 ++#define TYPE_KW "type=" ++#define TYPE_LEN sizeof(TYPE_KW)-1 ++#define FLAGS_KW "flags=" ++#define FLAGS_LEN sizeof(FLAGS_KW)-1 ++#define VALUES_KW "values=" ++#define VALUES_LEN sizeof(VALUES_KW)-1 ++#define FLAGS_AND_KW "AND" ++#define FLAGS_AND_LEN sizeof(FLAGS_AND_KW)-1 ++ ++static int ++attr_index_parse_idlistsize_values(Slapi_Attr *attr, struct index_idlistsizeinfo *idlinfo, char *values, const char *strval, char *returntext) ++{ ++ int rc = 0; ++ /* if we are here, values is non-NULL and not an empty string - parse it */ ++ char *ptr = NULL; ++ char *lasts = NULL; ++ char *val; ++ int syntaxcheck = config_get_syntaxcheck(); ++ IFP syntax_validate_fn = syntaxcheck ? attr->a_plugin->plg_syntax_validate : NULL; ++ char staticfiltstrbuf[1024]; /* for small filter strings */ ++ char *filtstrbuf = staticfiltstrbuf; /* default if not malloc'd */ ++ size_t filtstrbuflen = sizeof(staticfiltstrbuf); /* default if not malloc'd */ ++ Slapi_Filter *filt = NULL; /* for filter converting/unescaping config values */ ++ ++ /* caller should have already checked that values is valid and contains a "=" */ ++ PR_ASSERT(values); ++ ptr = PL_strchr(values, '='); ++ PR_ASSERT(ptr); ++ ++ptr; ++ for (val = ldap_utf8strtok_r(ptr, ",", &lasts); val; ++ val = ldap_utf8strtok_r(NULL, ",", &lasts)) { ++ Slapi_Value **ivals= NULL; /* for config values converted to keys */ ++ int ii; ++#define FILT_TEMPL_BEGIN "(a=" ++#define FILT_TEMPL_END ")" ++ size_t filttemplen = sizeof(FILT_TEMPL_BEGIN) - 1 + sizeof(FILT_TEMPL_END) - 1; ++ size_t vallen = strlen(val); ++ ++ if ((vallen + filttemplen + 1) > filtstrbuflen) { ++ filtstrbuflen = vallen + filttemplen + 1; ++ if (filtstrbuf == staticfiltstrbuf) { ++ filtstrbuf = (char *)slapi_ch_malloc(sizeof(char) * filtstrbuflen); ++ } else { ++ filtstrbuf = (char *)slapi_ch_realloc(filtstrbuf, sizeof(char) * filtstrbuflen); ++ } ++ } ++ /* each value is a value from a filter which should be escaped like a filter value ++ * for each value, create a dummy filter string, then parse and unescape it just ++ * like a filter ++ */ ++ PR_snprintf(filtstrbuf, filtstrbuflen, FILT_TEMPL_BEGIN "%s" FILT_TEMPL_END, val); ++ filt = slapi_str2filter(filtstrbuf); ++ if (!filt) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: invalid value %s in %s", ++ val, strval); ++ break; ++ } ++ ++ if (idlinfo->ai_indextype == INDEX_SUB) { ++ if (syntax_validate_fn) { ++ /* see if the values match the syntax, but only if checking is enabled */ ++ char **subany = filt->f_sub_any; ++ struct berval bv; ++ ++ if (filt->f_sub_initial && *filt->f_sub_initial) { ++ bv.bv_val = filt->f_sub_initial; ++ bv.bv_len = strlen(bv.bv_val); ++ if ((rc = syntax_validate_fn(&bv))) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: initial substring value %s " ++ "in value %s violates syntax for attribute %s", ++ filt->f_sub_initial, val, attr->a_type); ++ break; ++ } ++ } ++ for (; !rc && subany && *subany; ++subany) { ++ char *subval = *subany; ++ if (*subval) { ++ bv.bv_val = subval; ++ bv.bv_len = strlen(bv.bv_val); ++ if ((rc = syntax_validate_fn(&bv))) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: initial substring value %s in " ++ "value %s violates syntax for attribute %s", ++ filt->f_sub_any[ii], val, attr->a_type); ++ break; ++ } ++ } ++ } ++ if (rc) { ++ break; ++ } ++ if (filt->f_sub_final) { ++ bv.bv_val = filt->f_sub_final; ++ bv.bv_len = strlen(bv.bv_val); ++ if ((rc = syntax_validate_fn(&bv))) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: final substring value %s in value " ++ "%s violates syntax for attribute %s", ++ filt->f_sub_final, val, attr->a_type); ++ break; ++ } ++ } ++ } ++ /* if we are here, values passed syntax or no checking */ ++ /* generate index keys */ ++ (void)slapi_attr_assertion2keys_sub_sv(attr, filt->f_sub_initial, filt->f_sub_any, filt->f_sub_final, &ivals); ++ ++ } else if (idlinfo->ai_indextype == INDEX_EQUALITY) { ++ Slapi_Value sval; ++ /* see if the value matches the syntax, but only if checking is enabled */ ++ if (syntax_validate_fn && ((rc = syntax_validate_fn(&filt->f_avvalue)))) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: value %s violates syntax for attribute %s", ++ val, attr->a_type); ++ break; ++ } ++ ++ sval.bv.bv_val = filt->f_avvalue.bv_val; ++ sval.bv.bv_len = filt->f_avvalue.bv_len; ++ sval.v_flags = 0; ++ sval.v_csnset = NULL; ++ (void)slapi_attr_assertion2keys_ava_sv(attr, &sval, (Slapi_Value ***)&ivals, LDAP_FILTER_EQUALITY); ++ } ++ /* don't need filter any more */ ++ slapi_filter_free(filt, 1); ++ filt = NULL; ++ ++ /* add value(s) in ivals to our value set - disallow duplicates with error */ ++ for (ii = 0; !rc && ivals && ivals[ii]; ++ii) { ++ if (idlinfo->ai_values && ++ slapi_valueset_find(attr, idlinfo->ai_values, ivals[ii])) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: duplicate value %s in %s", ++ slapi_value_get_string(ivals[ii]), val); ++ slapi_value_free(&ivals[ii]); ++ } else { ++ if (!idlinfo->ai_values) { ++ idlinfo->ai_values = slapi_valueset_new(); ++ } ++ slapi_valueset_add_value_ext(idlinfo->ai_values, ivals[ii], SLAPI_VALUE_FLAG_PASSIN); ++ } ++ } ++ /* only free members of ivals that were not moved to ai_values */ ++ valuearray_free_ext(&ivals, ii); ++ ivals = NULL; ++ } ++ ++ slapi_filter_free(filt, 1); ++ ++ if (filtstrbuf != staticfiltstrbuf) { ++ slapi_ch_free_string(&filtstrbuf); ++ } ++ ++ return rc; ++} ++ ++static int ++attr_index_parse_idlistsize_limit(char *ptr, struct index_idlistsizeinfo *idlinfo, char *returntext) ++{ ++ int rc = 0; ++ char *endptr; ++ ++ PR_ASSERT(ptr && (*ptr == '=')); ++ ptr++; ++ idlinfo->ai_idlistsizelimit = strtol(ptr, &endptr, 10); ++ if (*endptr) { /* error in parsing */ ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: value %s for %s is not valid - " ++ "must be an integer >= -1", ++ ptr, LIMIT_KW); ++ } else if (idlinfo->ai_idlistsizelimit < -1) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: value %s for %s " ++ "must be an integer >= -1", ++ ptr, LIMIT_KW); ++ } ++ return rc; ++} ++ ++static int ++attr_index_parse_idlistsize_type(char *ptr, struct attrinfo *ai, struct index_idlistsizeinfo *idlinfo, const char *val, const char *strval, char *returntext) ++{ ++ int rc = 0; ++ char *ptr_next; ++ size_t len; ++ size_t preslen = strlen(indextype_PRESENCE); ++ size_t eqlen = strlen(indextype_EQUALITY); ++ size_t sublen = strlen(indextype_SUB); ++ ++ PR_ASSERT(ptr && (*ptr == '=')); ++ do { ++ ++ptr; ++ ptr_next = PL_strchr(ptr, ','); /* find next comma */ ++ if (!ptr_next) { ++ ptr_next = PL_strchr(ptr, '\0'); /* find end of string */ ++ } ++ len = ptr_next-ptr; ++ if ((len == preslen) && !PL_strncmp(ptr, indextype_PRESENCE, len)) { ++ if (idlinfo->ai_indextype & INDEX_PRESENCE) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: duplicate %s in value %s for %s", ++ indextype_PRESENCE, val, strval); ++ break; ++ } ++ if (!(ai->ai_indexmask & INDEX_PRESENCE)) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: attribute %s does not have index type %s", ++ ai->ai_type, indextype_PRESENCE); ++ break; ++ } ++ idlinfo->ai_indextype |= INDEX_PRESENCE; ++ } else if ((len == eqlen) && !PL_strncmp(ptr, indextype_EQUALITY, len)) { ++ if (idlinfo->ai_indextype & INDEX_EQUALITY) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: duplicate %s in value %s for %s", ++ indextype_EQUALITY, val, strval); ++ break; ++ } ++ if (!(ai->ai_indexmask & INDEX_EQUALITY)) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: attribute %s does not have index type %s", ++ ai->ai_type, indextype_EQUALITY); ++ break; ++ } ++ idlinfo->ai_indextype |= INDEX_EQUALITY; ++ } else if ((len == sublen) && !PL_strncmp(ptr, indextype_SUB, len)) { ++ if (idlinfo->ai_indextype & INDEX_SUB) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: duplicate %s in value %s for %s", ++ indextype_SUB, val, strval); ++ break; ++ } ++ if (!(ai->ai_indexmask & INDEX_SUB)) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: attribute %s does not have index type %s", ++ ai->ai_type, indextype_SUB); ++ break; ++ } ++ idlinfo->ai_indextype |= INDEX_SUB; ++ } else { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: unknown or unsupported index type " ++ "%s in value %s for %s", ++ ptr, val, strval); ++ break; ++ } ++ } while ((ptr = PL_strchr(ptr, ','))); ++ ++ return rc; ++} ++ ++static int ++attr_index_parse_idlistsize_flags(char *ptr, struct index_idlistsizeinfo *idlinfo, const char *val, const char *strval, char *returntext) ++{ ++ int rc = 0; ++ char *ptr_next; ++ size_t len; ++ ++ PR_ASSERT(ptr && (*ptr == '=')); ++ do { ++ ++ptr; ++ ptr_next = PL_strchr(ptr, ','); /* find next comma */ ++ if (!ptr_next) { ++ ptr_next = PL_strchr(ptr, '\0'); /* find end of string */ ++ } ++ len = ptr_next-ptr; ++ if ((len == FLAGS_AND_LEN) && !PL_strncmp(ptr, FLAGS_AND_KW, len)) { ++ if (idlinfo->ai_flags & INDEX_ALLIDS_FLAG_AND) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: duplicate %s in value %s for %s", ++ FLAGS_AND_KW, val, strval); ++ break; ++ } ++ idlinfo->ai_flags |= INDEX_ALLIDS_FLAG_AND; ++ } else { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: unknown or unsupported flags %s in value %s for %s", ++ ptr, val, strval); ++ break; ++ } ++ ++ } while ((ptr = PL_strchr(ptr, ','))); ++ return rc; ++} ++ ++static int ++attr_index_parse_idlistsize(struct attrinfo *ai, const char *strval, struct index_idlistsizeinfo *idlinfo, char *returntext) ++{ ++ int rc = 0; /* assume success */ ++ char *mystr = slapi_ch_strdup(strval); /* copy for strtok */ ++ char *values = NULL; ++ char *lasts, *val, *ptr; ++ int seen_limit = 0, seen_type = 0, seen_flags = 0, seen_values = 0; ++ Slapi_Attr *attr = &ai->ai_sattr; ++ ++ if (!mystr) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: value is empty"); ++ goto done; ++ } ++ ++ for (val = ldap_utf8strtok_r(mystr, " ", &lasts); val; ++ val = ldap_utf8strtok_r(NULL, " ", &lasts)) { ++ ptr = PL_strchr(val, '='); ++ if (!ptr || !(*(ptr+1))) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: invalid value %s - should be keyword=value - in %s", ++ val, strval); ++ goto done; ++ } ++ /* ptr points at first '=' in val */ ++ if (!PL_strncmp(val, LIMIT_KW, LIMIT_LEN)) { ++ if (seen_limit) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: can have only 1 %s in value %s", ++ LIMIT_KW, strval); ++ goto done; ++ } ++ if ((rc = attr_index_parse_idlistsize_limit(ptr, idlinfo, returntext))) { ++ goto done; ++ } ++ seen_limit = 1; ++ } else if (!PL_strncmp(val, TYPE_KW, TYPE_LEN)) { ++ if (seen_type) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: can have only 1 %s in value %s", ++ TYPE_KW, strval); ++ goto done; ++ } ++ if ((rc = attr_index_parse_idlistsize_type(ptr, ai, idlinfo, val, strval, returntext))) { ++ goto done; ++ } ++ ++ seen_type = 1; ++ } else if (!PL_strncmp(val, FLAGS_KW, FLAGS_LEN)) { ++ if (seen_flags) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: can have only 1 %s in value %s", ++ FLAGS_KW, strval); ++ goto done; ++ } ++ if ((rc = attr_index_parse_idlistsize_flags(ptr, idlinfo, val, strval, returntext))) { ++ goto done; ++ } ++ seen_flags = 1; ++ } else if (!PL_strncmp(val, VALUES_KW, VALUES_LEN)) { ++ if (seen_values) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: can have only 1 %s in value %s", ++ VALUES_KW, strval); ++ goto done; ++ } ++ values = val; ++ seen_values = 1; ++ } else { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: unknown keyword %s in %s", ++ val, strval); ++ goto done; ++ } ++ } ++ ++ if (!seen_limit) { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: no limit specified in %s", ++ strval); ++ goto done; ++ } ++ ++ /* parse values last ++ * can only have values if type is eq or sub, and only eq by itself or sub by itself ++ * eq and sub type values cannot be mixed, so error in that case ++ * cannot have type pres,eq and values - pres must be by itself with no values ++ */ ++ if (values) { ++ if (idlinfo->ai_indextype == INDEX_EQUALITY) { ++ ; /* ok */ ++ } else if (idlinfo->ai_indextype == INDEX_SUB) { ++ ; /* ok */ ++ } else { ++ rc = LDAP_UNWILLING_TO_PERFORM; ++ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, ++ "attr_index_parse_idlistsize: if %s is specified, the %s " ++ "must be %s or %s - not both, and not any other types", ++ VALUES_KW, TYPE_KW, indextype_PRESENCE, indextype_SUB); ++ goto done; ++ } ++ } else { ++ goto done; ++ } ++ ++ /* if we are here, values contains something - parse it */ ++ rc = attr_index_parse_idlistsize_values(attr, idlinfo, values, strval, returntext); ++ ++done: ++ slapi_ch_free_string(&mystr); ++ return rc; ++} ++ ++static int ++attr_index_idlistsize_config(Slapi_Entry *e, struct attrinfo *ai, char *returntext) ++{ ++ int rc = 0; ++ int ii; ++ Slapi_Attr *idlattr; ++ Slapi_Value *sval; ++ struct index_idlistsizeinfo *idlinfo; ++ ++ slapi_entry_attr_find(e, NS_INDEX_IDLISTSCANLIMIT, &idlattr); ++ if (!idlattr) { ++ return rc; ++ } ++ for (ii = slapi_attr_first_value(idlattr, &sval); !rc && (ii != -1); ii = slapi_attr_next_value(idlattr, ii, &sval)) { ++ idlinfo = (struct index_idlistsizeinfo *)slapi_ch_calloc(1, sizeof(struct index_idlistsizeinfo)); ++ if ((rc = attr_index_parse_idlistsize(ai, slapi_value_get_string(sval), idlinfo, returntext))) { ++ attr_index_idlistsize_free(&idlinfo); ++ attrinfo_delete_idlistinfo(&ai->ai_idlistinfo); ++ } else { ++ if (!ai->ai_idlistinfo) { ++ ai->ai_idlistinfo = dl_new(); ++ dl_init(ai->ai_idlistinfo, 1); ++ } ++ dl_add(ai->ai_idlistinfo, idlinfo); ++ } ++ } ++ return rc; ++} ++ + void + attr_index_config( + backend *be, +@@ -188,6 +676,7 @@ attr_index_config( + Slapi_Value *sval; + Slapi_Attr *attr; + int mr_count = 0; ++ char myreturntext[SLAPI_DSE_RETURNTEXT_SIZE]; + + /* Get the cn */ + if (0 == slapi_entry_attr_find(e, "cn", &attr)) { +@@ -364,6 +853,11 @@ attr_index_config( + } + } + ++ if ((return_value = attr_index_idlistsize_config(e, a, myreturntext))) { ++ LDAPDebug(LDAP_DEBUG_ANY,"attr_index_config: %s: Failed to parse idscanlimit info: %d:%s\n", ++ fname, return_value, myreturntext); ++ } ++ + /* initialize the IDL code's private data */ + return_value = idl_init_private(be, a); + if (0 != return_value) { +diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +index a7fb06d..060afe2 100644 +--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h ++++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +@@ -290,7 +290,7 @@ int id_array_init(Id_Array *new_guy, int size); + + IDList* index_read( backend *be, char *type, const char* indextype, const struct berval* val, back_txn *txn, int *err ); + IDList* index_read_ext( backend *be, char *type, const char* indextype, const struct berval* val, back_txn *txn, int *err, int *unindexed ); +-IDList* index_read_ext_allids( backend *be, char *type, const char* indextype, const struct berval* val, back_txn *txn, int *err, int *unindexed, int allidslimit ); ++IDList* index_read_ext_allids( Slapi_PBlock *pb, backend *be, char *type, const char* indextype, const struct berval* val, back_txn *txn, int *err, int *unindexed, int allidslimit ); + IDList* index_range_read( Slapi_PBlock *pb, backend *be, char *type, const char* indextype, int ftype, struct berval* val, struct berval* nextval, int range, back_txn *txn, int *err ); + IDList* index_range_read_ext( Slapi_PBlock *pb, backend *be, char *type, const char* indextype, int ftype, struct berval* val, struct berval* nextval, int range, back_txn *txn, int *err, int allidslimit ); + const char *encode( const struct berval* data, char buf[BUFSIZ] ); +diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h +index c87d2f2..4e0ef29 100644 +--- a/ldap/servers/slapd/proto-slap.h ++++ b/ldap/servers/slapd/proto-slap.h +@@ -155,6 +155,7 @@ int valuearray_init_bervalarray(struct berval **bvals, Slapi_Value ***cvals); + int valuearray_init_bervalarray_with_flags(struct berval **bvals, Slapi_Value ***cvals, unsigned long flags); + int valuearray_get_bervalarray(Slapi_Value **cvals, struct berval ***bvals); /* JCM SLOW FUNCTION */ + void valuearray_free(Slapi_Value ***va); ++void valuearray_free_ext(Slapi_Value ***va, int ii); + Slapi_Value *valuearray_remove_value(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v); + void valuearray_remove_value_atindex(Slapi_Value **va, int index); + int valuearray_isempty( Slapi_Value **va); +-- +1.8.1.4 + diff --git a/0119-Ticket-47504-idlistscanlimit-per-index-type-value.patch b/0119-Ticket-47504-idlistscanlimit-per-index-type-value.patch new file mode 100644 index 0000000..9d9320d --- /dev/null +++ b/0119-Ticket-47504-idlistscanlimit-per-index-type-value.patch @@ -0,0 +1,55 @@ +From ac1436918cafec17f453c36ad9890a2b3c72daef Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Tue, 24 Sep 2013 08:18:57 -0600 +Subject: [PATCH 119/225] Ticket #47504 idlistscanlimit per index/type/value + +https://fedorahosted.org/389/ticket/47504 +Reviewed by: nhosoi (Thanks!) +Branch: master +Fix Description: Fix compiler warning - use bv.bv_val to print syntax +errors in substring filter. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 36f506d05fb940e56c42a6b966f11ad1fdf8cba6) +(cherry picked from commit e95d7d6bd893d777c88be1bd847996f299621d99) +(cherry picked from commit 527c3e49ed14bc585f29ed873e71c6f551ad193b) +(cherry picked from commit d83311ad26de153270ef8e7297f7b1790bd58868) +--- + ldap/servers/slapd/back-ldbm/ldbm_attr.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/ldbm_attr.c b/ldap/servers/slapd/back-ldbm/ldbm_attr.c +index 9a930bc..fa18550 100644 +--- a/ldap/servers/slapd/back-ldbm/ldbm_attr.c ++++ b/ldap/servers/slapd/back-ldbm/ldbm_attr.c +@@ -273,7 +273,7 @@ attr_index_parse_idlistsize_values(Slapi_Attr *attr, struct index_idlistsizeinfo + PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, + "attr_index_parse_idlistsize: initial substring value %s " + "in value %s violates syntax for attribute %s", +- filt->f_sub_initial, val, attr->a_type); ++ bv.bv_val, val, attr->a_type); + break; + } + } +@@ -287,7 +287,7 @@ attr_index_parse_idlistsize_values(Slapi_Attr *attr, struct index_idlistsizeinfo + PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, + "attr_index_parse_idlistsize: initial substring value %s in " + "value %s violates syntax for attribute %s", +- filt->f_sub_any[ii], val, attr->a_type); ++ bv.bv_val, val, attr->a_type); + break; + } + } +@@ -303,7 +303,7 @@ attr_index_parse_idlistsize_values(Slapi_Attr *attr, struct index_idlistsizeinfo + PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, + "attr_index_parse_idlistsize: final substring value %s in value " + "%s violates syntax for attribute %s", +- filt->f_sub_final, val, attr->a_type); ++ bv.bv_val, val, attr->a_type); + break; + } + } +-- +1.8.1.4 + diff --git a/0120-Ticket-47504-idlistscanlimit-per-index-type-value.patch b/0120-Ticket-47504-idlistscanlimit-per-index-type-value.patch new file mode 100644 index 0000000..65f44db --- /dev/null +++ b/0120-Ticket-47504-idlistscanlimit-per-index-type-value.patch @@ -0,0 +1,87 @@ +From 07e15ffdf5c2913c8aaf6b6a7924a90b3da12f70 Mon Sep 17 00:00:00 2001 +From: Rich Megginson +Date: Wed, 25 Sep 2013 08:51:12 -0600 +Subject: [PATCH 120/225] Ticket #47504 idlistscanlimit per index/type/value + +https://fedorahosted.org/389/ticket/47504 +Reviewed by: nhosoi (Thanks!) +Branch: 389-ds-base-1.2.11 +Fix Description: This patch broke replication. The problem is that we cannot +compare the allidslimit to 0 unless the value is explicitly set by +index_get_allids. The fix is to only return ALLIDS if the allidslimit was +explicitly set to 0 by index_get_allids. +Platforms tested: RHEL6 x86_64 +Flag Day: no +Doc impact: no +(cherry picked from commit 058d01d7479204a2507dab822cd81e32c37be862) +(cherry picked from commit e5405e627439ccaf370d90c42e65c0a987e33e73) +(cherry picked from commit c96eaa03738e36b7cde0656edfbe6c4769847b52) +(cherry picked from commit 373e36a6835672746b2e6a97fcb8b6ede2084e32) +--- + ldap/servers/slapd/back-ldbm/index.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c +index f47f63d..66d6e7e 100644 +--- a/ldap/servers/slapd/back-ldbm/index.c ++++ b/ldap/servers/slapd/back-ldbm/index.c +@@ -52,7 +52,7 @@ + static const char *errmsg = "database index operation failed"; + + static int is_indexed (const char* indextype, int indexmask, char** index_rules); +-static int index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags ); ++static int index_get_allids( int *allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags ); + + static Slapi_Value ** + valuearray_minus_valuearray( +@@ -985,8 +985,11 @@ index_read_ext_allids( + slapi_pblock_get(pb, SLAPI_SEARCH_IS_AND, &is_and); + } + ai_flags = is_and ? INDEX_ALLIDS_FLAG_AND : 0; +- allidslimit = index_get_allids( allidslimit, indextype, ai, val, ai_flags ); +- if (allidslimit == 0) { ++ /* the caller can pass in a value of 0 - just ignore those - but if the index ++ * config sets the allidslimit to 0, this means to skip the index ++ */ ++ if (index_get_allids( &allidslimit, indextype, ai, val, ai_flags ) && ++ (allidslimit == 0)) { + idl = idl_allids( be ); + if (unindexed != NULL) *unindexed = 1; + LDAPDebug1Arg( LDAP_DEBUG_BACKLDBM, "<= index_read %lu candidates " +@@ -2410,9 +2413,9 @@ valuearray_minus_valuearray( + #define AI_HAS_TYPE 0x02 + #define AI_HAS_FLAG 0x01 + static int +-index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags ) ++index_get_allids( int *allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags ) + { +- int allids = default_allids; ++ int found = 0; + Slapi_Value sval; + struct index_idlistsizeinfo *iter; /* iterator */ + int cookie = 0; +@@ -2420,7 +2423,7 @@ index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai + struct index_idlistsizeinfo *best_match = NULL; + + if (!ai->ai_idlistinfo) { +- return allids; ++ return found; + } + + if (val) { /* val should already be a Slapi_Value, but some paths do not use Slapi_Value */ +@@ -2464,9 +2467,10 @@ index_get_allids( int default_allids, const char *indextype, struct attrinfo *ai + } + + if (best_match) { +- allids = best_match->ai_idlistsizelimit; ++ *allids = best_match->ai_idlistsizelimit; ++ found = 1; /* found a match */ + } + +- return allids; ++ return found; + } + +-- +1.8.1.4 + diff --git a/0121-Ticket-356-RFE-Track-bind-info.patch b/0121-Ticket-356-RFE-Track-bind-info.patch new file mode 100644 index 0000000..6e335f3 --- /dev/null +++ b/0121-Ticket-356-RFE-Track-bind-info.patch @@ -0,0 +1,372 @@ +From d21d33e084ceae4d8cd8f1585852cb1f40b16d09 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Wed, 9 May 2012 12:17:57 -0400 +Subject: [PATCH 121/225] Ticket #356 - RFE - Track bind info + +Bug Description: Have a way to gather bind stats (operations and IP addresses). + +Fix Description: Added a new option "-B,--bind" which takes one of three arguemnts: + [1] ALL - report on all Bind DN's + [2] ANONYMOUS - report just on anonymous binds + [3] "Bind DN" - report on the specified bind dn (uid=mark,dc=example,dc=com) + +https://fedorahosted.org/389/ticket/356 + +reviewed by: +(cherry picked from commit 9918105f615084f65a47fad693e02fce53bb7d72) +(cherry picked from commit 4ce70fed8dba0db072d4f7e4c8203f4e754352d1) +--- + ldap/admin/src/logconv.pl | 263 ++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 252 insertions(+), 11 deletions(-) + +diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl +index 3f73bb7..94ba036 100755 +--- a/ldap/admin/src/logconv.pl ++++ b/ldap/admin/src/logconv.pl +@@ -63,7 +63,7 @@ if ($#ARGV < 0){; + $x = "0"; + $fc = 0; + $sn = 0; +-$logversion = "6.1"; ++$logversion = "6.11"; + $sizeCount = "20"; + $startFlag = 0; + $startTime = 0; +@@ -80,6 +80,7 @@ GetOptions( + 's|sizeLimit=s' => \$sizeCount, + 'S|startTime=s' => \$startTime, + 'E|endTime=s' => \$endTime, ++ 'B|bind=s' => sub { $reportBinds = "yes"; $bindReportDN=($_[1]) }, + 'm|reportFileSecs=s' => sub { my ($opt,$value) = @_; $s_stats = new_stats_block($value); }, + 'M|reportFileMins=s' => sub { my ($opt,$value) = @_; $m_stats = new_stats_block($value); }, + 'h|help' => sub { displayUsage() }, +@@ -103,6 +104,19 @@ GetOptions( + ); + + # ++# setup the report Bind DN if any ++# ++if($reportBinds eq "yes"){ ++ $bindReportDN =~ tr/A-Z/a-z/; ++ if($bindReportDN eq "all"){ ++ $bindReportDN = ""; ++ } ++ if($bindReportDN eq "anonymous"){ ++ $bindReportDN = "Anonymous"; ++ } ++} ++ ++# + # set the default root DN + # + if($manager eq ""){ +@@ -490,13 +504,26 @@ $elapsedSeconds = $remainingTimeInSecs; + + + print "\n\n----------- Access Log Output ------------\n"; +-print "\nStart of Log: $start\n"; +-print "End of Log: $end\n\n"; ++print "\nStart of Logs: $start\n"; ++print "End of Logs: $end\n\n"; + if($elapsedDays eq "0"){ + print "Processed Log Time: $elapsedHours Hours, $elapsedMinutes Minutes, $elapsedSeconds Seconds\n\n"; + } else { + print "Processed Log Time: $elapsedDays Days, $elapsedHours Hours, $elapsedMinutes Minutes, $elapsedSeconds Seconds\n\n"; + } ++ ++# ++# Check here if we are producing any unqiue reports ++# ++ ++if($reportBinds eq "yes"){ ++ &displayBindReport(); ++} ++ ++# ++# Continue with standard report ++# ++ + print "Restarts: $restarts\n"; + print "Total Connections: $connectionCount\n"; + print "SSL Connections: $sslconn\n"; +@@ -1198,7 +1225,8 @@ sub displayUsage { + print " E.g. \"[28/Mar/2002:13:24:62 -0800]\"\n"; + print " -m, --reportFileSecs \n"; + print " -M, --reportFileMins \n"; +- print " -V, --verbose \n"; ++ print " -B, --bind \n"; ++ print " -V, --verbose \n"; + print " -[efcibaltnxrgjuyp]\n\n"; + + print " e Error Code stats\n"; +@@ -1221,24 +1249,162 @@ sub displayUsage { + print " Examples:\n\n"; + + print " ./logconv.pl -s 10 -V /logs/access*\n\n"; +- + print " ./logconv.pl --rootDN cn=dm /logs/access*\n\n"; +- + print " ./logconv.pl --sizeLimit 50 -ibgju /logs/access*\n\n"; +- + print " ./logconv.pl -S \"\[28/Mar/2002:13:14:22 -0800\]\" --endTime \"\[28/Mar/2002:13:50:05 -0800\]\" -e /logs/access*\n\n"; + print " ./logconv.pl -m log-minute-stats-csv.out /logs/access*\n\n"; ++ print " ./logconv.pl -B ANONYMOUS /logs/access*\n\n"; ++ print " ./logconv.pl -B \"uid=mreynolds,dc=example,dc=com\" /logs/access*\n\n"; + + exit 1; + } + + ###################################################### + # +-# Parsing Routine That Does The Actual Parsing Work ++# Parsing Routines That Do The Actual Parsing Work + # + ###################################################### + +-sub parseLine { ++sub ++parseLine { ++ if($reportBinds eq "yes"){ ++ &parseLineBind(); ++ } else { ++ &parseLineNormal(); ++ } ++} ++ ++sub ++parseLineBind { ++ $ff++; ++ $iff++; ++ local $_ = $tline; ++ ++ if ($iff >= $limit){ ++ print STDERR sprintf" %10s Lines Processed\n",$ff; ++ $iff="0"; ++ } ++ ++ # skip blank lines ++ return if $_ =~ /^\s/; ++ ++ if($firstFile eq "1" && $_ =~ /^\[/){ ++ $start = $_; ++ if ($start =~ / *([0-9a-z:\/]+)/i){$start=$1;} ++ $firstFile = "0"; ++ } ++ ++ if ($endFlag != 1 && $_ =~ /^\[/ && $_ =~ / *([0-9a-z:\/]+)/i){ ++ $end =$1; ++ } ++ ++ if ($startTime && !$startFlag) { ++ if (index($_, $startTime) == 0) { ++ $startFlag = 1; ++ ($start) = $startTime =~ /\D*(\S*)/; ++ } else { ++ return; ++ } ++ } ++ ++ if ($endTime && !$endFlag) { ++ if (index($_, $endTime) == 0) { ++ $endFlag = 1; ++ ($end) = $endTime =~ /\D*(\S*)/; ++ } ++ } ++ ++ if ($_ =~ /connection from *([0-9A-Fa-f\.\:]+)/i ) { ++ for ($excl =0; $excl <= $#exclude; $excl++){ ++ if ($exclude[$excl] eq $1){ ++ $skip = "yes"; ++ last; ++ } ++ } ++ if ($skip eq "yes"){ ++ return ; ++ } ++ $ip = $1; ++ if ($_ =~ /conn= *([0-9]+)/i ){ ++ $connList{$ip} = $connList{$ip} . " $1 "; ++ } ++ return; ++ } ++ ++ if (/ BIND/ && $_ =~ /dn=\"(.*)\" method/i ){ ++ if ($1 eq ""){ ++ $dn = "Anonymous"; ++ } else { ++ $dn = $1; ++ $dn =~ tr/A-Z/a-z/; ++ } ++ ++ if($bindReportDN ne ""){ ++ if($dn ne $bindReportDN){ ++ # We are not looking for this DN, skip it ++ return; ++ } ++ } ++ ++ $bindReport{$dn}{"binds"}++; ++ if ($bindReport{$dn}{"binds"} eq 1){ ++ # For hashes we need to init the counters ++ $bindReport{$dn}{"srch"} = 0; ++ $bindReport{$dn}{"add"} = 0; ++ $bindReport{$dn}{"mod"} = 0; ++ $bindReport{$dn}{"del"} = 0; ++ $bindReport{$dn}{"cmp"} = 0; ++ $bindReport{$dn}{"ext"} = 0; ++ $bindReport{$dn}{"modrdn"} = 0; ++ $bindReport{$dn}{"failedBind"} = 0; ++ } ++ ++ if ($_ =~ /conn= *([0-9]+)/i) { ++ $bindReport{$dn}{"conn"} = $bindReport{$dn}{"conn"} . " $1 "; ++ } ++ return; ++ } ++ ++ if (/ RESULT err=49 /){ ++ processOpForBindReport("failedBind",$tline); ++ } ++ ++ if (/ SRCH base=/){ ++ processOpForBindReport("srch",$tline); ++ } elsif (/ ADD dn=/){ ++ processOpForBindReport("add",$tline); ++ } elsif (/ MOD dn=/){ ++ processOpForBindReport("mod",$tline); ++ } elsif (/ DEL dn=/){ ++ processOpForBindReport("del",$tline); ++ } elsif (/ MODRDN dn=/){ ++ processOpForBindReport("modrdn",$tline); ++ } elsif (/ CMP dn=/){ ++ processOpForBindReport("cmp",$tline); ++ } elsif (/ EXT oid=/){ ++ processOpForBindReport("ext",$tline); ++ } ++ ++} ++ ++sub ++processOpForBindReport ++{ ++ $op = @_[0]; ++ $data = @_[1]; ++ ++ if ($data =~ /conn= *([0-9]+)/i) { ++ foreach $dn (keys %bindReport){ ++ if ($bindReport{$dn}{"conn"} =~ / $1 /){ ++ $bindDN = $dn; ++ $bindReport{$bindDN}{$op}++; ++ return; ++ } ++ } ++ } ++} ++ ++sub parseLineNormal { + local $_ = $tline; + + # lines starting blank are restart +@@ -1410,7 +1576,7 @@ if (m/ conn=1 fd=/){$restarts++} + if (m/ SSL connection from/){$sslconn++;} + if (m/ connection from/){ + $exc = "no"; +- if ($_ =~ /connection from *([0-9\.]+)/i ){ ++ if ($_ =~ /connection from *([0-9A-Fa-f\.\:]+)/i ){ + for ($xxx =0; $xxx <= $#exclude; $xxx++){ + if ($exclude[$xxx] eq $1){$exc = "yes";} + } +@@ -1561,7 +1727,7 @@ if ($usage =~ /g/ || $usage =~ /c/ || $usage =~ /i/ || $verb eq "yes"){ + + $exc = "no"; + +-if ($_ =~ /connection from *([0-9\.]+)/i ) { ++if ($_ =~ /connection from *([0-9A-fa-f\.\:]+)/i ) { + for ($xxx = 0; $xxx <= $#exclude; $xxx++){ + if ($1 eq $exclude[$xxx]){ + $exc = "yes"; +@@ -2017,6 +2183,81 @@ inc_stats + return; + } + ++sub ++displayBindReport ++{ ++ # ++ # Loop for each DN - sort alphabetically ++ # ++ # Display all the IP addresses, then counts of all the operations it did ++ # ++ ++ print "\nBind Report\n"; ++ print "====================================================================\n\n"; ++ foreach $bindDN (sort { $bindReport{$a} <=> $bindReport{$b} } keys %bindReport) { ++ print("Bind DN: $bindDN\n"); ++ print("--------------------------------------------------------------------\n"); ++ print(" Client Addresses:\n\n"); ++ &printClients($bindReport{$bindDN}{"conn"}); ++ print("\n Operations Performed:\n\n"); ++ &printOpStats($bindDN); ++ print("\n"); ++ } ++ print "Done.\n"; ++ exit (0); ++} ++ ++sub ++printClients ++{ ++ @bindConns = &cleanConns(split(' ', @_[0])); ++ $IPcount = "1"; ++ ++ foreach $ip ( keys %connList ){ # Loop over all the IP addresses ++ foreach $bc (@bindConns){ # Loop over each bind conn number and compare it ++ if($connList{$ip} =~ / $bc /){ ++ print(" [$IPcount] $ip\n"); ++ $IPcount++; ++ last; ++ } ++ } ++ } ++} ++ ++sub ++cleanConns ++{ ++ @dirtyConns = @_; ++ $#cleanConns = -1; ++ $c = 0; ++ ++ for ($i = 0; $i <=$#dirtyConns; $i++){ ++ if($dirtyConns[$i] ne ""){ ++ $cleanConns[$c++] = $dirtyConns[$i]; ++ } ++ } ++ return @cleanConns; ++} ++ ++sub ++printOpStats ++{ ++ $dn = @_[0]; ++ ++ if( $bindReport{$dn}{"failedBind"} eq "0" ){ ++ print(" Binds: " . $bindReport{$dn}{"binds"} . "\n"); ++ } else { ++ print(" Binds: " . $bindReport{$dn}{"binds"} . " (Invalid Credentials: " . $bindReport{$dn}{"failedBind"} . ")\n"); ++ } ++ print(" Searches: " . $bindReport{$dn}{"srch"} . "\n"); ++ print(" Modifies: " . $bindReport{$dn}{"mod"} . "\n"); ++ print(" Adds: " . $bindReport{$dn}{"add"} . "\n"); ++ print(" Deletes: " . $bindReport{$dn}{"del"} . "\n"); ++ print(" Compares: " . $bindReport{$dn}{"cmp"} . "\n"); ++ print(" ModRDNs: " . $bindReport{$dn}{"modrdn"} . "\n"); ++ print(" Ext Ops: " . $bindReport{$dn}{"ext"} . "\n\n"); ++} ++ + ####################################### + # # + # The End # +-- +1.8.1.4 + diff --git a/0122-Ticket-539-logconv.pl-should-handle-microsecond-timi.patch b/0122-Ticket-539-logconv.pl-should-handle-microsecond-timi.patch new file mode 100644 index 0000000..8cb6b0a --- /dev/null +++ b/0122-Ticket-539-logconv.pl-should-handle-microsecond-timi.patch @@ -0,0 +1,107 @@ +From 7dee79c02350007ea22b8e1898035682395d3314 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 8 Jan 2013 12:16:14 -0500 +Subject: [PATCH 122/225] Ticket 539 - logconv.pl should handle microsecond + timing + +Bug Description: logconv.pl can not handle microsecond etimes + +Fix Description: Update the regular expressions to handle the decimal point "." + + Also did a little code cleanup. + +https://fedorahosted.org/389/ticket/539 + +Reviewed by: nhosoi(Thanks!) +(cherry picked from commit 8965dda8d4023ab36f0a404a874c657d78631e9d) +(cherry picked from commit 67c5f1cd1584cd352da7b8db2520c268431d7812) +(cherry picked from commit 6775316c1eae432c7b40fd6418f4f9993152b59b) +--- + ldap/admin/src/logconv.pl | 55 +++++++++++++++++++++-------------------------- + 1 file changed, 25 insertions(+), 30 deletions(-) + +diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl +index 94ba036..f5342af 100755 +--- a/ldap/admin/src/logconv.pl ++++ b/ldap/admin/src/logconv.pl +@@ -948,36 +948,31 @@ if ($filter_count > 0){ + # # + ######################################### + +- +-# +-# print most often etimes +-# +- + if ($usage =~ /t/i || $verb eq "yes"){ +-print "\n\n----- Top $sizeCount Most Frequent etimes -----\n\n"; +-$eloop = 0; +-foreach $et (sort { $etime{$b} <=> $etime{$a} } keys %etime) { +- if ($eloop == $sizeCount) { last; } +- if ($retime ne "2"){ +- $first = $et; +- $retime = "2"; ++ # ++ # print most often etimes ++ # ++ print "\n\n----- Top $sizeCount Most Frequent etimes -----\n\n"; ++ $eloop = 0; ++ foreach $et (sort { $etime{$b} <=> $etime{$a} } keys %etime) { ++ if ($eloop == $sizeCount) { last; } ++ if ($retime ne "2"){ ++ $first = $et; ++ $retime = "2"; ++ } ++ printf "%-8s %-12s\n", $etime{ $et }, "etime=$et"; ++ $eloop++; + } +- printf "%-8s %-12s\n", $etime{ $et }, "etime=$et"; +- $eloop++; +-} +- +-# +-# print longest etimes +-# +- +-print "\n\n----- Top $sizeCount Longest etimes -----\n\n"; +-$eloop = 0; +-foreach $et (sort { $b <=> $a } (keys %etime)) { +- if ($eloop == $sizeCount) { last; } +- printf "%-12s %-10s\n","etime=$et",$etime{ $et }; +- $eloop++; +-} +- ++ # ++ # print longest etimes ++ # ++ print "\n\n----- Top $sizeCount Longest etimes -----\n\n"; ++ $eloop = 0; ++ foreach $et (sort { $b <=> $a } (keys %etime)) { ++ if ($eloop == $sizeCount) { last; } ++ printf "%-12s %-10s\n","etime=$et",$etime{ $et }; ++ $eloop++; ++ } + } + + ####################################### +@@ -1651,7 +1646,7 @@ if (m/ notes=U/){ + } + if ($usage =~ /u/ || $verb eq "yes"){ + if ($v eq "0" ){ +- if ($_ =~ /etime= *([0-9]+)/i ) { ++ if ($_ =~ /etime= *([0-9.]+)/i ) { + $notesEtime[$vet]=$1; + $vet++; + } +@@ -1931,7 +1926,7 @@ if ($_ =~ /err= *([0-9]+)/i){ + if ($1 ne "0"){ $errorck++;} + else { $errorsucc++;} + } +-if ($_ =~ /etime= *([0-9]+)/i ) { $etime{$1}++;} ++if ($_ =~ /etime= *([0-9.]+)/ ) { $etime{$1}++;} + if ($_ =~ / tag=101 nentries= *([0-9]+)/i ) {$nentries{$1}++} + if ($_ =~ / tag=111 nentries= *([0-9]+)/i ) {$nentries{$1}++} + if ($_ =~ / tag=100 nentries= *([0-9]+)/i ) {$nentries{$1}++} +-- +1.8.1.4 + diff --git a/0123-Ticket-471-logconv.pl-tool-removes-the-access-logs-c.patch b/0123-Ticket-471-logconv.pl-tool-removes-the-access-logs-c.patch new file mode 100644 index 0000000..af9c52e --- /dev/null +++ b/0123-Ticket-471-logconv.pl-tool-removes-the-access-logs-c.patch @@ -0,0 +1,71 @@ +From 272f7c558b16d8764c0cb82a547b94333f1b6294 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 8 Jan 2013 13:47:25 -0500 +Subject: [PATCH 123/225] Ticket 471 - logconv.pl tool removes the access logs + contents if "-M" is not correctly used + +Bug Description: If you fail to specifiy the output file, the access log is overwritten. + +Fix Description: Check if the proper files have been provbided to the script, and report error otherwise. + +https://fedorahosted.org/389/ticket/471 + +Reviewed by: nhosoi(Thanks!) +(cherry picked from commit 89fb3420c9137cb2c9813fec527b89fec3b6d63e) +(cherry picked from commit 9f0c9392ac7e27193831098f1efd4b7047432cd7) +(cherry picked from commit 96cdf89f5cb160b5906c36cb3c43013582577595) +--- + ldap/admin/src/logconv.pl | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl +index f5342af..0ec596a 100755 +--- a/ldap/admin/src/logconv.pl ++++ b/ldap/admin/src/logconv.pl +@@ -71,6 +71,7 @@ $endFlag = 0; + $endTime = 0; + $s_stats = new_stats_block( ); + $m_stats = new_stats_block( ); ++$report_opt = ""; + + GetOptions( + 'd|rootDN=s' => \$manager, +@@ -81,8 +82,8 @@ GetOptions( + 'S|startTime=s' => \$startTime, + 'E|endTime=s' => \$endTime, + 'B|bind=s' => sub { $reportBinds = "yes"; $bindReportDN=($_[1]) }, +- 'm|reportFileSecs=s' => sub { my ($opt,$value) = @_; $s_stats = new_stats_block($value); }, +- 'M|reportFileMins=s' => sub { my ($opt,$value) = @_; $m_stats = new_stats_block($value); }, ++ 'm|reportFileSecs=s' => sub { my ($opt,$value) = @_; $s_stats = new_stats_block($value); $report_opt = "-m"; }, ++ 'M|reportFileMins=s' => sub { my ($opt,$value) = @_; $m_stats = new_stats_block($value); $report_opt = "-M"; }, + 'h|help' => sub { displayUsage() }, + # usage options '-efcibaltnxgjuiryp' + 'e' => sub { $usage = $usage . "e"; }, +@@ -132,6 +133,15 @@ while($sn <= $#ARGV){ + $sn++; + } + ++if($fc == 0){ ++ if($report_opt ne ""){ ++ print "Usage error for option $report_opt, either the output file or access log is missing!\n\n"; ++ } else { ++ print "There are no access logs specified!\n\n"; ++ } ++ exit 1; ++} ++ + if ($sizeCount eq "all"){$sizeCount = "100000";} + + ####################################### +@@ -261,7 +271,7 @@ $err[68] = "Already Exists\n"; + $err[69] = "No Objectclass Mods\n"; + $err[70] = "Results Too Large\n"; + $err[71] = "Effect Multiple DSA's\n"; +-$err[80] = "Other :-)\n"; ++$err[80] = "Other\n"; + $err[81] = "Server Down\n"; + $err[82] = "Local Error\n"; + $err[83] = "Encoding Error\n"; +-- +1.8.1.4 + diff --git a/0124-TIcket-419-logconv.pl-improve-memory-management.patch b/0124-TIcket-419-logconv.pl-improve-memory-management.patch new file mode 100644 index 0000000..1f7517b --- /dev/null +++ b/0124-TIcket-419-logconv.pl-improve-memory-management.patch @@ -0,0 +1,2296 @@ +From 948fafdad56860ab7099f4137dfea4f65d39a960 Mon Sep 17 00:00:00 2001 +From: Mark Reynolds +Date: Tue, 15 Jan 2013 12:41:23 -0500 +Subject: [PATCH 124/225] TIcket 419 - logconv.pl - improve memory management + +Remove old logconv.pl script - to make room for the new rewrite of logconv.pl + +https://fedorahosted.org/389/ticket/419 +(cherry picked from commit 472373506eeca676dbbf9b9f56c2248761068752) +(cherry picked from commit fc3c9192d37631948ca17fec3cd9bd2fed1ffdbc) +(cherry picked from commit 3badb6cd2f784543e31cce7cf97958f7281951e9) +--- + ldap/admin/src/logconv.pl | 2271 --------------------------------------------- + 1 file changed, 2271 deletions(-) + delete mode 100755 ldap/admin/src/logconv.pl + +diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl +deleted file mode 100755 +index 0ec596a..0000000 +--- a/ldap/admin/src/logconv.pl ++++ /dev/null +@@ -1,2271 +0,0 @@ +-#!/usr/bin/env perl +- +-# +-# BEGIN COPYRIGHT BLOCK +-# This Program is free software; you can redistribute it and/or modify it under +-# the terms of the GNU General Public License as published by the Free Software +-# Foundation; version 2 of the License. +-# +-# This Program is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License along with +-# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple +-# Place, Suite 330, Boston, MA 02111-1307 USA. +-# +-# In addition, as a special exception, Red Hat, Inc. gives You the additional +-# right to link the code of this Program with code not covered under the GNU +-# General Public License ("Non-GPL Code") and to distribute linked combinations +-# including the two, subject to the limitations in this paragraph. Non-GPL Code +-# permitted under this exception must only link to the code of this Program +-# through those well defined interfaces identified in the file named EXCEPTION +-# found in the source code files (the "Approved Interfaces"). The files of +-# Non-GPL Code may instantiate templates or use macros or inline functions from +-# the Approved Interfaces without causing the resulting work to be covered by +-# the GNU General Public License. Only Red Hat, Inc. may make changes or +-# additions to the list of Approved Interfaces. You must obey the GNU General +-# Public License in all respects for all of the Program code and other code used +-# in conjunction with the Program except the Non-GPL Code covered by this +-# exception. If you modify this file, you may extend this exception to your +-# version of the file, but you are not obligated to do so. If you do not wish to +-# provide this exception without modification, you must delete this exception +-# statement from your version and license this file solely under the GPL without +-# exception. +-# +-# +-# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. +-# Copyright (C) 2005 Red Hat, Inc. +-# All rights reserved. +-# END COPYRIGHT BLOCK +-# +- +-# +-# Check for usage +-# +-use Time::Local; +-use IO::File; +-use Getopt::Long; +- +-Getopt::Long::Configure ("bundling"); +-Getopt::Long::Configure ("permute"); +- +-if ($#ARGV < 0){; +-&displayUsage; +-} +- +-####################################### +-# # +-# parse commandline switches # +-# # +-####################################### +- +-$x = "0"; +-$fc = 0; +-$sn = 0; +-$logversion = "6.11"; +-$sizeCount = "20"; +-$startFlag = 0; +-$startTime = 0; +-$endFlag = 0; +-$endTime = 0; +-$s_stats = new_stats_block( ); +-$m_stats = new_stats_block( ); +-$report_opt = ""; +- +-GetOptions( +- 'd|rootDN=s' => \$manager, +- 'v|version' => sub { print "Access Log Analyzer v$logversion\n"; exit (0); }, +- 'V|verbose' => sub { $verb = "yes"; }, +- 'X|excludeIP=s' => \$exclude[$xi++], +- 's|sizeLimit=s' => \$sizeCount, +- 'S|startTime=s' => \$startTime, +- 'E|endTime=s' => \$endTime, +- 'B|bind=s' => sub { $reportBinds = "yes"; $bindReportDN=($_[1]) }, +- 'm|reportFileSecs=s' => sub { my ($opt,$value) = @_; $s_stats = new_stats_block($value); $report_opt = "-m"; }, +- 'M|reportFileMins=s' => sub { my ($opt,$value) = @_; $m_stats = new_stats_block($value); $report_opt = "-M"; }, +- 'h|help' => sub { displayUsage() }, +- # usage options '-efcibaltnxgjuiryp' +- 'e' => sub { $usage = $usage . "e"; }, +- 'f' => sub { $usage = $usage . "f"; }, +- 'c' => sub { $usage = $usage . "c"; }, +- 'i' => sub { $usage = $usage . "i"; }, +- 'b' => sub { $usage = $usage . "b"; }, +- 'a' => sub { $usage = $usage . "a"; }, +- 'l' => sub { $usage = $usage . "l"; }, +- 't' => sub { $usage = $usage . "t"; }, +- 'n' => sub { $usage = $usage . "n"; }, +- 'x' => sub { $usage = $usage . "x"; }, +- 'g' => sub { $usage = $usage . "g"; }, +- 'j' => sub { $usage = $usage . "j"; }, +- 'u' => sub { $usage = $usage . "u"; }, +- 'r' => sub { $usage = $usage . "r"; }, +- 'y' => sub { $usage = $usage . "y"; }, +- 'p' => sub { $usage = $usage . "p"; } +-); +- +-# +-# setup the report Bind DN if any +-# +-if($reportBinds eq "yes"){ +- $bindReportDN =~ tr/A-Z/a-z/; +- if($bindReportDN eq "all"){ +- $bindReportDN = ""; +- } +- if($bindReportDN eq "anonymous"){ +- $bindReportDN = "Anonymous"; +- } +-} +- +-# +-# set the default root DN +-# +-if($manager eq ""){ +- $manager = "cn=directory manager"; +-} +- +-# +-# get the logs +-# +-while($sn <= $#ARGV){ +- $files[$fc] = $ARGV[$sn]; +- $fc++; +- $sn++; +-} +- +-if($fc == 0){ +- if($report_opt ne ""){ +- print "Usage error for option $report_opt, either the output file or access log is missing!\n\n"; +- } else { +- print "There are no access logs specified!\n\n"; +- } +- exit 1; +-} +- +-if ($sizeCount eq "all"){$sizeCount = "100000";} +- +-####################################### +-# # +-# Initialize Arrays and variables # +-# # +-####################################### +- +-print "\nAccess Log Analyzer $logversion\n"; +-print "\nCommand : logconv.pl @ARGV\n\n"; +- +-$dirmgr = "0"; +-$notes = "0"; +-$vlvnotes= "0"; +-$search = "0"; +-$fdtake = "0"; +-$fdreturn = "0"; +-$highfd = "0"; +-$bind = "0"; +-$unbind = "0"; +-$anony = "0"; +-$mod = "0"; +-$delete = "0"; +-$add = "0"; +-$modrdn = "0"; +-$moddn = "0"; +-$compare = "0"; +-$proxiedAuth = "0"; +-$restarts = "0"; +-$resource = "0"; +-$broken = "0"; +-$vlv = "0"; +-$version2 = "0"; +-$version3 = "0"; +-$sortvlv = "0"; +-$reset = "0"; +-$vet = "0"; +-$v = "0"; +-$errorck = "0"; +-$errorsucc = "0"; +-$sslconn = "0"; +-$sslClientBind = "0"; +-$sslClientFailed = "0"; +-$objectclass= "0"; +-$nc = "0"; +-$no = "0"; +-$nt = "0"; +-$nb = "0"; +-$bc = "0"; +-$fcc = "0"; +-$bcc = "0"; +-$scc = "0"; +-$nent = "0"; +-$allOps = "0"; +-$allResults = "0"; +-$bpc = "0"; +-$bpo = "0"; +-$bpi = 0; +-$abandon = "0"; +-$mmasterop = "0"; +-$extendedop = "0"; +-$sasl = "0"; +-$internal = "0"; +-$entryOp = "0"; +-$referral = "0"; +-$anyAttrs = "0"; +-$persistent = "0"; +-$sconn = "0"; +-$dconn = "0"; +-$aconn = "0"; +-$mconn = "0"; +-$mdconn = "0"; +-$mddconn = "0"; +-$bconn = "0"; +-$ubconn = "0"; +-$econn = "0"; +-$cconn = "0"; +-$connectionCount = "0"; +-$timerange = 0; +-$simConnection = 0; +-$maxsimConnection = 0; +-$firstFile = "1"; +-$elapsedDays = "0"; +-$logCount = "0"; +-$limit = "25000"; # number of lines processed to trigger output +- +-$err[0] = "Successful Operations\n"; +-$err[1] = "Operations Error(s)\n"; +-$err[2] = "Protocal Errors\n"; +-$err[3] = "Time Limit Exceeded\n"; +-$err[4] = "Size Limit Exceeded\n"; +-$err[5] = "Compare False\n"; +-$err[6] = "Compare True\n"; +-$err[7] = "Strong Authentication Not Supported\n"; +-$err[8] = "Strong Authentication Required\n"; +-$err[9] = "Partial Results\n"; +-$err[10] = "Referral Received\n"; +-$err[11] = "Administrative Limit Exceeded (Look Through Limit)\n"; +-$err[12] = "Unavailable Critical Extension\n"; +-$err[13] = "Confidentiality Required\n"; +-$err[14] = "SASL Bind in Progress\n"; +-$err[16] = "No Such Attribute\n"; +-$err[17] = "Undefined Type\n"; +-$err[18] = "Inappropriate Matching\n"; +-$err[19] = "Constraint Violation\n"; +-$err[20] = "Type or Value Exists\n"; +-$err[21] = "Invalid Syntax\n"; +-$err[32] = "No Such Object\n"; +-$err[33] = "Alias Problem\n"; +-$err[34] = "Invalid DN Syntax\n"; +-$err[35] = "Is Leaf\n"; +-$err[36] = "Alias Deref Problem\n"; +-$err[48] = "Inappropriate Authentication (No password presented, etc)\n"; +-$err[49] = "Invalid Credentials (Bad Password)\n"; +-$err[50] = "Insufficent (write) Privledges\n"; +-$err[51] = "Busy\n"; +-$err[52] = "Unavailable\n"; +-$err[53] = "Unwilling To Perform\n"; +-$err[54] = "Loop Detected\n"; +-$err[60] = "Sort Control Missing\n"; +-$err[61] = "Index Range Error\n"; +-$err[64] = "Naming Violation\n"; +-$err[65] = "Objectclass Violation\n"; +-$err[66] = "Not Allowed on Non Leaf\n"; +-$err[67] = "Not Allowed on RDN\n"; +-$err[68] = "Already Exists\n"; +-$err[69] = "No Objectclass Mods\n"; +-$err[70] = "Results Too Large\n"; +-$err[71] = "Effect Multiple DSA's\n"; +-$err[80] = "Other\n"; +-$err[81] = "Server Down\n"; +-$err[82] = "Local Error\n"; +-$err[83] = "Encoding Error\n"; +-$err[84] = "Decoding Error\n"; +-$err[85] = "Timeout\n"; +-$err[86] = "Authentication Unknown\n"; +-$err[87] = "Filter Error\n"; +-$err[88] = "User Canceled\n"; +-$err[89] = "Parameter Error\n"; +-$err[90] = "No Memory\n"; +-$err[91] = "Connect Error\n"; +-$err[92] = "Not Supported\n"; +-$err[93] = "Control Not Found\n"; +-$err[94] = "No Results Returned\n"; +-$err[95] = "More Results To Return\n"; +-$err[96] = "Client Loop\n"; +-$err[97] = "Referral Limit Exceeded\n"; +- +- +-$conn{"A1"} = "A1"; +-$conn{"B1"} = "B1"; +-$conn{"B4"} = "B4"; +-$conn{"T1"} = "T1"; +-$conn{"T2"} = "T2"; +-$conn{"B2"} = "B2"; +-$conn{"B3"} = "B3"; +-$conn{"R1"} = "R1"; +-$conn{"P1"} = "P1"; +-$conn{"P2"} = "P2"; +-$conn{"U1"} = "U1"; +- +-$connmsg{"A1"} = "Client Aborted Connections"; +-$connmsg{"B1"} = "Bad Ber Tag Encountered"; +-$connmsg{"B4"} = "Server failed to flush data (response) back to Client"; +-$connmsg{"T1"} = "Idle Timeout Exceeded"; +-$connmsg{"T2"} = "IO Block Timeout Exceeded or NTSSL Timeout"; +-$connmsg{"B2"} = "Ber Too Big"; +-$connmsg{"B3"} = "Ber Peek"; +-$connmsg{"R1"} = "Revents"; +-$connmsg{"P1"} = "Plugin"; +-$connmsg{"P2"} = "Poll"; +-$connmsg{"U1"} = "Cleanly Closed Connections"; +- +-%monthname = ( +- "Jan" => 0, +- "Feb" => 1, +- "Mar" => 2, +- "Apr" => 3, +- "May" => 4, +- "Jun" => 5, +- "Jul" => 6, +- "Aug" => 7, +- "Sep" => 8, +- "Oct" => 9, +- "Nov" => 10, +- "Dec" => 11, +- +-); +- +-########################################## +-# # +-# Parse Access Logs # +-# # +-########################################## +- +-if ($files[$#files] =~ m/access.rotationinfo/) { $fc--; } +- +-print "Processing $fc Access Log(s)...\n\n"; +- +-print "Filename\t\t\t Total Lines\n"; +-print "--------------------------------------------------\n"; +- +-$ofc = $fc; +- +-if ($fc > 1 && $files[0] =~ /\/access$/){ +- $files[$fc] = $files[0]; +- $fc++; +- $skipFirstFile = "1"; +-} +- +-for ($count=0; $count < $fc; $count++){ +- # we moved access to the end of the list, so if its the first file skip it +- if($fc > 1 && $count == 0 && $skipFirstFile eq "1"){ +- next; +- } +- $logCount++; +- $logsize = `wc -l $files[$count]`; +- $logsize =~ /([0-9]+)/; +- $ff="";$iff=""; +- if($logCount < 10 ){ +- # add a zero for formatting purposes +- $lc = "0" . $logCount; +- } else { +- $lc = $logCount; +- } +- print sprintf "[%s] %-30s %7s\n",$lc, $files[$count], $1; +- +- open(LOG,"$files[$count]") || die "Error: Can't open file $infile: $!"; +- +- $firstline = "yes"; +- while () { +- unless ($endFlag) { +- if ($firstline eq "yes"){ +- if (/^\[/) { +- $tline = $_; +- $firstline = "no"; +- } +- $ff++;$iff++; +- } elsif (/^\[/ && $firstline eq "no"){ +- &parseLine($tline); +- $tline = $_; +- } else { +- $tline = $tline . $_; +- $tline =~ s/\n//; +- } +- } +- } +- &parseLine($tline); +- close (LOG); +- print_stats_block( $s_stats ); +- print_stats_block( $m_stats ); +- $tlc = $tlc + $ff; +- if($ff => $limit){print sprintf " %10s Lines Processed\n\n",--$ff;} +-} +- +-print "\n\nTotal Log Lines Analysed: " . ($tlc - 1) . "\n"; +- +-$allOps = $search + $mod + $add + $delete + $modrdn + $bind + $extendedop; +- +-################################################################## +-# # +-# Calculate the total elapsed time of the processed access logs # +-# # +-################################################################## +- +-# if we are using startTime & endTime then we need to clean it up for our processing +- +-if($startTime){ +- if ($start =~ / *([0-9a-z:\/]+)/i){$start=$1;} +-} +-if($endTime){ +- if ($end =~ / *([0-9a-z:\/]+)/i){$end =$1;} +-} +- +-# +-# Get the start time in seconds +-# +- +-$logStart = $start; +- +-if ($logStart =~ / *([0-9A-Z\/]+)/i ){ +- $logDate = $1; +- @dateComps = split /\//, $logDate; +- +- $timeMonth = 1 +$monthname{$dateComps[1]}; +- $timeMonth = $timeMonth * 3600 *24 * 30; +- $timeDay= $dateComps[0] * 3600 *24; +- $timeYear = $dateComps[2] *365 * 3600 * 24; +- $dateTotal = $timeMonth + $timeDay + $timeYear; +-} +- +-if ($logStart =~ / *(:[0-9:]+)/i ){ +- $logTime = $1; +- @timeComps = split /:/, $logTime; +- +- $timeHour = $timeComps[1] * 3600; +- $timeMinute = $timeComps[2] *60; +- $timeSecond = $timeComps[3]; +- $timeTotal = $timeHour + $timeMinute + $timeSecond; +-} +- +-$startTotal = $timeTotal + $dateTotal; +- +-# +-# Get the end time in seconds +-# +- +-$logEnd = $end; +- +-if ($logEnd =~ / *([0-9A-Z\/]+)/i ){ +- $logDate = $1; +- @dateComps = split /\//, $logDate; +- +- $endDay = $dateComps[0] *3600 * 24; +- $endMonth = 1 + $monthname{$dateComps[1]}; +- $endMonth = $endMonth * 3600 * 24 * 30; +- $endYear = $endTotal + $dateComps[2] *365 * 3600 * 24 ; +- $dateTotal = $endDay + $endMonth + $endYear; +-} +- +-if ($logEnd =~ / *(:[0-9:]+)/i ){ +- $logTime = $1; +- @timeComps = split /:/, $logTime; +- +- $endHour = $timeComps[1] * 3600; +- $endMinute = $timeComps[2] *60; +- $endSecond = $timeComps[3]; +- $timeTotal = $endHour + $endMinute + $endSecond; +-} +- +-$endTotal = $timeTotal + $dateTotal; +- +-# +-# Tally the numbers +-# +-$totalTimeInSecs = $endTotal - $startTotal; +-$remainingTimeInSecs = $totalTimeInSecs; +- +-# +-# Calculate the elapsed time +-# +- +-# days +-while(($remainingTimeInSecs - 86400) > 0){ +- $elapsedDays++; +- $remainingTimeInSecs = $remainingTimeInSecs - 86400; +- +-} +- +-# hours +-while(($remainingTimeInSecs - 3600) > 0){ +- $elapsedHours++; +- $remainingTimeInSecs = $remainingTimeInSecs - 3600; +-} +- +-# minutes +-while($remainingTimeInSecs - 60 > 0){ +- $elapsedMinutes++; +- $remainingTimeInSecs = $remainingTimeInSecs - 60; +-} +- +-#seconds +-$elapsedSeconds = $remainingTimeInSecs; +- +-##################################### +-# # +-# Display Basic Results # +-# # +-##################################### +- +- +-print "\n\n----------- Access Log Output ------------\n"; +-print "\nStart of Logs: $start\n"; +-print "End of Logs: $end\n\n"; +-if($elapsedDays eq "0"){ +- print "Processed Log Time: $elapsedHours Hours, $elapsedMinutes Minutes, $elapsedSeconds Seconds\n\n"; +-} else { +- print "Processed Log Time: $elapsedDays Days, $elapsedHours Hours, $elapsedMinutes Minutes, $elapsedSeconds Seconds\n\n"; +-} +- +-# +-# Check here if we are producing any unqiue reports +-# +- +-if($reportBinds eq "yes"){ +- &displayBindReport(); +-} +- +-# +-# Continue with standard report +-# +- +-print "Restarts: $restarts\n"; +-print "Total Connections: $connectionCount\n"; +-print "SSL Connections: $sslconn\n"; +-print "Peak Concurrent Connections: $maxsimConnection\n"; +-print "Total Operations: $allOps\n"; +-print "Total Results: $allResults\n"; +-if ($allOps ne "0"){ +- print sprintf "Overall Performance: %.1f%\n\n" , ($perf = ($tmp = ($allResults / $allOps)*100) > 100 ? 100.0 : $tmp) ; +- } +-else { +- print "Overall Performance: No Operations to evaluate\n\n"; +-} +- +-$searchStat = sprintf "(%.2f/sec) (%.2f/min)\n",($search / $totalTimeInSecs), $search / ($totalTimeInSecs/60); +-$modStat = sprintf "(%.2f/sec) (%.2f/min)\n",$mod / $totalTimeInSecs, $mod/($totalTimeInSecs/60); +-$addStat = sprintf "(%.2f/sec) (%.2f/min)\n",$add/$totalTimeInSecs, $add/($totalTimeInSecs/60); +-$deleteStat = sprintf "(%.2f/sec) (%.2f/min)\n",$delete/$totalTimeInSecs, $delete/($totalTimeInSecs/60); +-$modrdnStat = sprintf "(%.2f/sec) (%.2f/min)\n",$modrdn/$totalTimeInSecs, $modrdn/($totalTimeInSecs/60); +-$compareStat = sprintf "(%.2f/sec) (%.2f/min)\n",$compare/$totalTimeInSecs, $compare/($totalTimeInSecs/60); +-$bindStat = sprintf "(%.2f/sec) (%.2f/min)\n",$bind/$totalTimeInSecs, $bind/($totalTimeInSecs/60); +- +-format STDOUT = +-Searches: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< +- $search, $searchStat +-Modifications: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< +- $mod, $modStat +-Adds: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< +- $add, $addStat +-Deletes: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< +- $delete, $deleteStat +-Mod RDNs: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< +- $modrdn, $modrdnStat +-Compares: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< +- $compare, $compareStat +-Binds: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< +- $bind $bindStat +-. +-write STDOUT; +- +-print "\n"; +-print "Proxied Auth Operations: $proxiedAuth\n"; +-print "Persistent Searches: $persistent\n"; +-print "Internal Operations: $internal\n"; +-print "Entry Operations: $entryOp\n"; +-print "Extended Operations: $extendedop\n"; +-print "Abandoned Requests: $abandon\n"; +-print "Smart Referrals Received: $referral\n"; +-print "\n"; +-print "VLV Operations: $vlv\n"; +-print "VLV Unindexed Searches: $vlvnotes\n"; +-print "SORT Operations: $sortvlv\n"; +-print "\n"; +-print "Entire Search Base Queries: $objectclass\n"; +-print "Unindexed Searches: $notes\n"; +-if ($verb eq "yes" || $usage =~ /u/){ +-if ($notes > 0){ +- $ns = "1"; +- for ($n = 0; $n <= $#notesEtime; $n++){ +- @alreadyseenDN = (); +- print "\n Unindexed Search #".$ns."\n"; +- $ns++; +- print " - Date/Time: $notesTime[$n]\n"; +- print " - Connection Number: $notesConn[$n]\n"; +- print " - Operation Number: $notesOp[$n]\n"; +- print " - Etime: $notesEtime[$n]\n"; +- print " - Nentries: $notesNentries[$n]\n"; +- print " - IP Address: $conn_hash{$notesConn[$n]}\n"; +- for ($nn = 0; $nn <= $bc; $nn++){ +- if ($notesConn[$n] eq $bindInfo[$nn][1]) { +- +- ## Here, we check if the bindDN is already printed. +- ## If not, we print it and push it to @alreadyseenDN. +- ## So, in the beginning, we iterate thru @alreadyseenDN +- +- for ($j=0, $DNisThere=0; $j <=$#alreadyseenDN; $j++) { +- if ($alreadyseenDN[$j] eq $bindInfo[$nn][0]) { +- $DNisThere = 1; +- } +- } +- unless ($DNisThere) { +- print " - Bind DN: $bindInfo[$nn][0]\n"; +- push @alreadyseenDN, $bindInfo[$nn][0]; +- } +- } +- } +- for ($nnn = 0; $nnn <= $bcc; $nnn++){ +- if ($notesConn[$n] eq $baseInfo[$nnn][1] && $notesOp[$n] eq $baseInfo[$nnn][2]){ +- print " - Search Base: $baseInfo[$nnn][0]\n"; +- } +- } +- for ($nnn = 0; $nnn <= $scc; $nnn++){ +- if ($notesConn[$n] eq $scopeInfo[$nnn][1] && $notesOp[$n] eq $scopeInfo[$nnn][2]){ +- print " - Search Scope: $scopeInfo[$nnn][0]\n"; +- } +- } +- for ($nnn = 0; $nnn <= $fcc; $nnn++){ +- if ($notesConn[$n] eq $filterInfo[$nnn][1] && $notesOp[$n] eq $filterInfo[$nnn][2]){ +- print " - Search Filter: $filterInfo[$nnn][0]\n"; +- } +- } +- } +-} +- +-} +- +-print "\n"; +-print "FDs Taken: $fdtake\n"; +-print "FDs Returned: $fdreturn\n"; +-print "Highest FD Taken: $highfd\n\n"; +-print "Broken Pipes: $broken\n"; +-if ($broken > 0){ +- foreach $key (sort { $rc{$b} <=> $rc{$a} } keys %rc) { +- if ($rc{$key} > 0){ +- if ($conn{$key} eq ""){$conn{$key} = "** Unknown **";} +- push @etext, sprintf " - %-4s (%2s) %-40s\n",$rc{$key},$conn{$key},$connmsg{$key +-}; +- } +- } +- print @etext; +- print "\n"; +-} +- +-print "Connections Reset By Peer: $reset\n"; +-if ($reset > 0){ +- foreach $key (sort { $src{$b} <=> $src{$a} } keys %src) { +- if ($src{$key} > 0){ +- if ($conn{$key} eq ""){$conn{$key} = "** Unknown **";} +- push @retext, sprintf " - %-4s (%2s) %-40s\n",$src{$key},$conn{$key},$connmsg{$key +-}; +- } +- } +- print @retext; +- print "\n"; +-} +- +-print "Resource Unavailable: $resource\n"; +-if ($resource > 0){ +- foreach $key (sort { $rsrc{$b} <=> $rsrc{$a} } keys %rsrc) { +- if ($rsrc{$key} > 0){ +- if ($conn{$key} eq ""){$conn{$key} = "** Resource Issue **";} +- push @rtext, sprintf " - %-4s (%2s) %-40s\n",$rsrc{$key},$conn{$key},$connmsg{$key}; +- } +- } +- print @rtext; +-} +-print "\n"; +-print "Binds: $bind\n"; +-print "Unbinds: $unbind\n"; +-print "\n LDAP v2 Binds: $version2\n"; +-print " LDAP v3 Binds: $version3\n"; +-print " SSL Client Binds: $sslClientBind\n"; +-print " Failed SSL Client Binds: $sslClientFailed\n"; +-print " SASL Binds: $sasl\n"; +-if ($sasl > 0){ +- foreach $saslb ( sort {$saslmech{$b} <=> $saslmech{$a} } (keys %saslmech) ){ +- printf " %-4s %-12s\n",$saslmech{$saslb}, $saslb; +- } +-} +- +-print "\n Directory Manager Binds: $dirmgr\n"; +-print " Anonymous Binds: $anony\n"; +-$other = $bind -($dirmgr + $anony); +-print " Other Binds: $other"; +- +-if ($verb eq "yes" || $usage =~ /y/){ +-print "\n\n----- Connection Latency Details -----\n\n"; +-print " (in seconds)\t\t<=1\t2\t3\t4-5\t6-10\t11-15\t>15\n"; +-print " --------------------------------------------------------------------------\n"; +-print " (# of connections)\t"; +-for ($i=0; $i <=$#latency; $i++) { +- print "$latency[$i]\t"; +-} +-} +- +-if ($verb eq "yes" || $usage =~ /p/){ +-print "\n\n----- Current Open Connection IDs ----- \n\n"; +-for ($i=0; $i <= $#openConnection ; $i++) { +- if ($openConnection[$i]) { +- print "\t$i\n"; +- } +-} +-} +- +-################################### +-# # +-# Display Error Codes # +-# # +-################################### +- +-if ($usage =~ /e/i || $verb eq "yes"){ +-print "\n\n----- Errors -----\n"; +- +-%er = sort( {$b <=> $a} %er); +-for ($i = 0; $i<98; $i++){ +- if ($err[$i] ne "" && $er[$i] >0) { +- push @errtext, sprintf "%-8s %12s %-25s","err=$i",$er[$i],$err[$i]; +- } +-} +- +-for ($i = 0; $i < $#errtext; $i++){ +- +- for ($ii = 0; $ii < $#errtext; $ii++){ +- $yy="0"; +- $zz="0"; +- while ($errtext[$ii] =~ /(\w+)\s/g){ +- $errornum[$yy]="$1"; +- $yy++; +- } +- while ($errtext[$ii+1] =~ /(\w+)\s/g){ +- $errornum2[$zz]="$1"; +- $zz++; +- } +- +- if ($errornum2[1] > $errornum[1]){ +- $tmp = $errtext[$ii]; +- $errtext[$ii] = $errtext[$ii+1]; +- $errtext[$ii+1] = $tmp; +- } +- } +-} +- +-for ($i = 0; $i <= $#errtext; $i++){ +- $errtext[$i] =~ s/\n//g; +- print "\n" . $errtext[$i]; +-} +- +-} +- +-#################################### +-# # +-# Print Failed Logins # +-# # +-#################################### +- +-if ($verb eq "yes" || $usage =~ /f/i ){ +-if ($bpc > 0){ +-print "\n\n----- Top $sizeCount Failed Logins ------\n\n"; +- +-if ($ds6x eq "true"){ +- $eloop = "0"; +- foreach $dsbp (sort { $ds6xbadpwd{$b} <=> $ds6xbadpwd{$a} } keys %ds6xbadpwd) { +- if ($eloop > $sizeCount){ last; } +- printf "%-4s %-40s\n", $ds6xbadpwd{$dsbp}, $dsbp; +- } +- +-} else { +-for ($ii =0 ; $ii < $bpc; $ii++){ +- for ($i = 0; $i < $bc; $i++){ +- if ($badPasswordConn[$ii] eq $bindInfo[$i][1] && $badPasswordOp[$ii] eq $bindInfo[$i][2] ){ +- $badPassword{ "$bindInfo[$i][0]" } = $badPassword{ "$bindInfo[$i][0]" } + 1; +- } +- } +-} +- +-# sort the new list of $badPassword{} +- +-$bpTotal = "0"; +-$bpCount = "0"; +-foreach $badpw (sort {$badPassword{$b} <=> $badPassword{$a} } keys %badPassword){ +- if ($bpCount > $sizeCount){ last;} +- $bpCount++; +- $bpTotal = $bpTotal + $badPassword{"$badpw"}; +- printf "%-4s %-40s\n", $badPassword{"$badpw"}, $badpw; +-} +- +-print "\nFrom the IP address(s) :\n\n"; +-for ($i=0; $i<$bpi; $i++) { +- print "\t\t$badPasswordIp[$i]\n"; +-} +- +-if ($bpTotal > $bpc){ +- print "\n** Warning : Wrongly reported failed login attempts : ". ($bpTotal - $bpc) . "\n"; +-} +-} # this ends the if $ds6x = true +- +-} +- +-} +- +- +-#################################### +-# # +-# Print Connection Codes # +-# # +-#################################### +- +- +-if ($concount > 0){ +-if ($usage =~ /c/i || $verb eq "yes"){ +- print "\n\n----- Total Connection Codes -----\n\n"; +- +- foreach $key (sort { $conncount{$b} <=> $conncount{$a} } keys %conncount) { +- if ($conncount{$key} > 0){ +- push @conntext, sprintf "%-4s %6s %-40s\n",$conn{ $key },$conncount{$key},$connmsg{ $key }; +- } +- } +-print @conntext; +-} +- +-} +- +-######################################## +-# # +-# Gather and Process all unique IPs # +-# # +-######################################## +- +-if ($usage =~ /i/i || $verb eq "yes"){ +-@ipkeys = keys %ip_hash; +-@exxCount = keys %exCount; +-$ip_count = ($#ipkeys + 1)-($#exxCount + 1); +-if ($ip_count > 0){ +- print "\n\n----- Top $sizeCount Clients -----\n\n"; +- print "Number of Clients: $ip_count\n\n"; +- +- foreach $key (sort { $ip_hash{$b}{"count"} <=> $ip_hash{$a}{"count"} } keys %ip_hash) { +- $exc = "no"; +- if ($ccount > $sizeCount){ last;} +- $ccount++; +- for ($xxx =0; $xxx <= $#exclude; $xxx++){ +- if ($exclude[$xxx] eq $key){$exc = "yes";} +- } +- if ($exc ne "yes"){ +- if ($ip_hash{ $key }{"count"} eq ""){$ip_hash{ $key }{"count"} = "*";} +- printf "%-6s %-17s\n", $ip_hash{ $key }{"count"}, $key; +- } +- +- if ($exc ne "yes"){ +- foreach $code (sort { $ip_hash{ $key }{$b} <=> $ip_hash{ $key }{$a} } keys %{$ip_hash{ $key }}) { +- if ($code eq 'count' ) { next; } +- printf "\t\t %6s - %3s %s\n", $ip_hash{ $key }{ $code }, $code, $connmsg{ $code }; +- } +- } +- +- if ($exc ne "yes"){ print "\n";} +- } +-} +-} +- +- +- +-################################### +-# # +-# Gather All unique Bind DN's # +-# # +-################################### +- +-if ($usage =~ /b/i || $verb eq "yes"){ +-@bindkeys = keys %bindlist; +-$bind_count = $#bindkeys + 1; +-if ($bind_count > 0){ +- print "\n----- Top $sizeCount Bind DN's -----\n\n"; +- print "Number of Unique Bind DN's: $bind_count\n\n"; +- +- $bindcount = 0; +- +- foreach $dn (sort { $bindlist{$b} <=> $bindlist{$a} } keys %bindlist) { +- if ($bindcount < $sizeCount){ +- printf "%-8s %-40s\n", $bindlist{ $dn },$dn; +- } +- $bindcount++; +- } +-} +- +-} +- +- +-######################################### +-# # +-# Gather and process search bases # +-# # +-######################################### +- +-if ($usage =~ /a/i || $verb eq "yes"){ +-@basekeys = keys %base; +-$base_count = $#basekeys + 1; +-if ($base_count > 0){ +- print "\n\n----- Top $sizeCount Search Bases -----\n\n"; +- print "Number of Unique Search Bases: $base_count\n\n"; +- +- $basecount = 0; +- +- foreach $bas (sort { $base{$b} <=> $base{$a} } keys %base) { +- if ($basecount < $sizeCount){ +- printf "%-8s %-40s\n", $base{ $bas },$bas; +- } +- $basecount++; +- } +-} +- +-} +- +-######################################### +-# # +-# Gather and process search filters # +-# # +-######################################### +- +-if ($usage =~ /l/ || $verb eq "yes"){ +- +-@filterkeys = keys %filter; +-$filter_count = $#filterkeys + 1; +-if ($filter_count > 0){ +- print "\n\n----- Top $sizeCount Search Filters -----\n"; +- print "\nNumber of Unique Search Filters: $filter_count\n\n"; +- +- $filtercount = 0; +- +- foreach $filt (sort { $filter{$b} <=> $filter{$a} } keys %filter){ +- if ($filtercount < $sizeCount){ +- printf "%-8s %-40s\n", $filter{$filt}, $filt; +- } +- $filtercount++; +- } +-} +- +-} +- +-######################################### +-# # +-# Gather and Process the unique etimes # +-# # +-######################################### +- +-if ($usage =~ /t/i || $verb eq "yes"){ +- # +- # print most often etimes +- # +- print "\n\n----- Top $sizeCount Most Frequent etimes -----\n\n"; +- $eloop = 0; +- foreach $et (sort { $etime{$b} <=> $etime{$a} } keys %etime) { +- if ($eloop == $sizeCount) { last; } +- if ($retime ne "2"){ +- $first = $et; +- $retime = "2"; +- } +- printf "%-8s %-12s\n", $etime{ $et }, "etime=$et"; +- $eloop++; +- } +- # +- # print longest etimes +- # +- print "\n\n----- Top $sizeCount Longest etimes -----\n\n"; +- $eloop = 0; +- foreach $et (sort { $b <=> $a } (keys %etime)) { +- if ($eloop == $sizeCount) { last; } +- printf "%-12s %-10s\n","etime=$et",$etime{ $et }; +- $eloop++; +- } +-} +- +-####################################### +-# # +-# Gather and Process unique nentries # +-# # +-####################################### +- +- +-if ($usage =~ /n/i || $verb eq "yes"){ +-print "\n\n----- Top $sizeCount Largest nentries -----\n\n"; +-$eloop = 0; +-foreach $nentry (sort { $b <=> $a } (keys %nentries)){ +- if ($eloop == $sizeCount) { last; } +- printf "%-18s %12s\n","nentries=$nentry", $nentries{ $nentry }; +- $eloop++; +-} +- +-print "\n\n----- Top $sizeCount Most returned nentries -----\n\n"; +-$eloop = 0; +-foreach $nentry (sort { $nentries{$b} <=> $nentries{$a} } (keys %nentries)){ +- if ($eloop == $sizeCount) { last; } +- printf "%-12s %-14s\n", $nentries{ $nentry }, "nentries=$nentry"; +- $eloop++; +-} +- +-print "\n"; +-} +- +- +-########################################## +-# # +-# Gather and process extended operations # +-# # +-########################################## +- +-if ($usage =~ /x/i || $verb eq "yes"){ +- +-if ($extendedop > 0){ +-print "\n\n----- Extended Operations -----\n\n"; +-foreach $oids (sort { $oid{$b} <=> $oid{$a} } (keys %oid) ){ +- +- if ($oids eq "2.16.840.1.113730.3.5.1"){ $oidmessage = "Transaction Request"} +- elsif ($oids eq "2.16.840.1.113730.3.5.2"){ $oidmessage = "Transaction Response"} +- elsif ($oids eq "2.16.840.1.113730.3.5.3"){ $oidmessage = "Start Replication Request (incremental update)"} +- elsif ($oids eq "2.16.840.1.113730.3.5.4"){ $oidmessage = "Replication Response"} +- elsif ($oids eq "2.16.840.1.113730.3.5.5"){ $oidmessage = "End Replication Request (incremental update)"} +- elsif ($oids eq "2.16.840.1.113730.3.5.6"){ $oidmessage = "Replication Entry Request"} +- elsif ($oids eq "2.16.840.1.113730.3.5.7"){ $oidmessage = "Start Bulk Import"} +- elsif ($oids eq "2.16.840.1.113730.3.5.8"){ $oidmessage = "Finished Bulk Import"} +- elsif ($oids eq "2.16.840.1.113730.3.6.1"){ $oidmessage = "Incremental Update Replication Protocol"} +- elsif ($oids eq "2.16.840.1.113730.3.6.2"){ $oidmessage = "Total Update Replication Protocol (Initialization)"} +- elsif ($oids eq "2.16.840.1.113730.3.5.9"){ $oidmessage = "Digest Authentication"} +- else {$oidmessage = "Other"} +- +- printf "%-6s %-23s %-60s\n", $oid{ $oids }, $oids, $oidmessage; +-} +-} +- +-} +- +-############################################ +-# +-# Print most commonly requested attributes +-# +-############################################ +- +-if ($usage =~ /r/i || $verb eq "yes"){ +-if ($anyAttrs > 0){ +-print "\n\n----- Top $sizeCount Most Requested Attributes -----\n\n"; +-$eloop = "0"; +-foreach $mostAttr (sort { $attr{$b} <=> $attr{$a} } (keys %attr) ){ +- if ($eloop eq $sizeCount){ last; } +- printf "%-10s %-19s\n", $attr{$mostAttr}, $mostAttr; +- $eloop++; +-} +-} +- +-} +- +-################################# +-# +-# abandoned operation stats +-# +-################################# +- +-if ($usage =~ /g/i || $verb eq "yes"){ +-$acTotal = $sconn + $dconn + $mconn + $aconn + $mdconn + $bconn + $ubconn + $econn + $mddconn + $cconn; +-if ($verb eq "yes" && $ac > 0 && $acTotal > 0){ +- +-print "\n\n----- Abandon Request Stats -----\n\n"; +- +- for ($g = 0; $g < $ac; $g++){ +- for ($sc = 0; $sc < $sconn; $sc++){ +- if ($srchConn[$sc] eq $targetConn[$g] && $srchOp[$sc] eq $targetOp[$g] ){ +- print " - SRCH conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($dc = 0; $dc < $dconn; $dc++){ +- if ($delConn[$dc] eq $targetConn[$g] && $delOp[$dc] eq $targetOp[$g]){ +- print " - DEL conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($adc = 0; $adc < $aconn; $adc++){ +- if ($addConn[$adc] eq $targetConn[$g] && $addOp[$adc] eq $targetOp[$g]){ +- print " - ADD conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($mc = 0; $mc < $mconn; $mc++){ +- if ($modConn[$mc] eq $targetConn[$g] && $modOp[$mc] eq $targetOp[$g]){ +- print " - MOD conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($mddc = 0; $mddc < $mddconn; $mddc++){ +- if ($moddnConn[$mdc] eq $targetConn[$g] && $moddnOp[$mdc] eq $targetOp[$g]){ +- print " - MODDN conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($cc = 0; $cc < $cconn; $cc++){ +- if ($compConn[$mdc] eq $targetConn[$g] && $compOp[$mdc] eq $targetOp[$g]){ +- print " - CMP conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($mdc = 0; $mdc < $mdconn; $mdc++){ +- if ($modrdnConn[$mdc] eq $targetConn[$g] && $modrdnOp[$mdc] eq $targetOp[$g]){ +- print " - MODRDN conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($bcb = 0; $bcb < $bconn; $bcb++){ +- if ($bindConn[$bcb] eq $targetConn[$g] && $bindOp[$bcb] eq $targetOp[$g]){ +- print " - BIND conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($ubc = 0; $ubc < $ubconn; $ubc++){ +- if ($unbindConn[$ubc] eq $targetConn[$g] && $unbindOp[$ubc] eq $targetOp[$g]){ +- print " - UNBIND conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- for ($ec = 0; $ec < $econn; $ec++){ +- if ($extConn[$ec] eq $targetConn[$g] && $extOp[$ec] eq $targetOp[$g]){ +- print " - EXT conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n"; +- } +- } +- +- +- } +-} +- +-} +- +- +- +-print "\n"; +- +-####################################### +-# # +-# Recommendations # +-# # +-####################################### +- +-if ($usage =~ /j/i || $verb eq "yes"){ +-print "\n----- Recommendations -----\n"; +-$recCount = "1"; +-if ($notes > 0){ +- print "\n $recCount. You have unindexed searches, this can be caused from a search on an unindexed attribute, or your returned results exceeded the allidsthreshold. Unindexed searches are not recommended. To refuse unindexed searches, switch \'nsslapd-require-index\' to \'on\' under your database entry (e.g. cn=UserRoot,cn=ldbm database,cn=plugins,cn=config).\n"; +- $recCount++; +- } +- +-if ($conncount{"T1"} > 0){ +- print "\n $recCount. You have some connections that are are being closed by the idletimeout setting. You may want to increase the idletimeout if it is set low.\n"; +- $recCount++; +- } +- +-if ($conncount{"T2"} > 0){ +- print "\n $recCount. You have some coonections that are being closed by the ioblocktimeout setting. You may want to increase the ioblocktimeout.\n"; +- $recCount++; +- } +- +-# compare binds to unbinds, if the difference is more than 30% of the binds, then report a issue +- +-if (($bind - $unbind) > ($bind*.3)){ +- print "\n $recCount. You have a significant difference between binds and unbinds. You may want to investigate this difference.\n"; +- $recCount++; +- } +- +-# compare fds taken and return, if the difference is more than 30% report a issue +- +-if (($fdtaken -$fdreturn) > ($fdtaken*.3)){ +- print "\n $recCount. You have a significant difference between file descriptors taken and file descriptors returned. You may want to investigate this difference.\n"; +- $recCount++; +- } +- +-if ($dirmgr > ($bind *.2)){ +- print "\n $recCount. You have a high number of Directory Manager binds. The Directory Manager account should only be used under certain circumstances. Avoid using this account for client applications.\n"; +- $recCount++; +- } +- +-if ($errorck > $errorsucc){ +- print "\n $recCount. You have more unsuccessful operations than successful operations. You should investigate this difference.\n"; +- $recCount++; +- } +- +-if ($conncount{"U1"} < ($concount - $conncount{"U1"})){ +- print "\n $recCount. You have more abnormal connection codes than cleanly closed connections. You may want to investigate this difference.\n"; +- $recCount++; +- } +- +-if ($first > 0){ +- print "\n $recCount. You have a majority of etimes that are greater than zero, you may want to investigate this performance problem.\n"; +- $recCount++; +- } +- +-if ($objectclass > ($search *.25)){ +- print "\n $recCount. You have a high number of searches that query the entire search base. Although this is not necessarily bad, it could be resource intensive if the search base contains many entries.\n"; +- $recCount++; +- } +- +-if ($recCount == 1){ +- print "\nNone.\n"; +- } +-} +- +-print "\n"; +- +-# dispaly usage +- +-sub displayUsage { +- +- print "Usage:\n\n"; +- +- print " ./logconv.pl [-h] [-d|--rootdn ] [-s|--sizeLimit ] [-v|verison] [-Vi|verbose]\n"; +- print " [-S|--startTime ] [-E|--endTime ] \n"; +- print " [-efcibaltnxrgjuyp] [ access log ... ... ]\n\n"; +- +- print "- Commandline Switches:\n\n"; +- +- print " -h, --help help/usage\n"; +- print " -d, --rootDN DEFAULT -> cn=directory manager\n"; +- print " -s, --sizeLimit DEFAULT -> 20\n"; +- print " -X, --excludeIP E.g. Load balancers\n"; +- print " -v, --version show version of tool\n"; +- print " -S, --startTime