Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
June
May
April
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
List overview
Download
389-commits
April 2015
----- 2025 -----
June 2025
May 2025
April 2025
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
389-commits@lists.fedoraproject.org
3 participants
43 discussions
Start a n
N
ew thread
Branch '389-ds-base-1.2.11' - 2 commits - ldap/schema ldap/servers
by Noriko Hosoi
06 Apr '15
06 Apr '15
ldap/schema/01core389.ldif | 4 ldap/servers/plugins/replication/cl5_api.c | 48 ++++- ldap/servers/plugins/replication/repl5.h | 11 + ldap/servers/plugins/replication/repl5_agmt.c | 160 +++++++++++++++++ ldap/servers/plugins/replication/repl5_agmtlist.c | 26 ++ ldap/servers/plugins/replication/repl5_connection.c | 165 +++++++++++++++++- ldap/servers/plugins/replication/repl5_inc_protocol.c | 32 +++ ldap/servers/plugins/replication/repl5_prot_private.h | 2 ldap/servers/plugins/replication/repl5_tot_protocol.c | 52 +++++ ldap/servers/plugins/replication/repl_globals.c | 3 ldap/servers/plugins/retrocl/retrocl_po.c | 6 ldap/servers/slapd/add.c | 13 - ldap/servers/slapd/libglobs.c | 84 ++++++++- ldap/servers/slapd/modify.c | 47 ++--- ldap/servers/slapd/opshared.c | 35 +-- ldap/servers/slapd/proto-slap.h | 2 ldap/servers/slapd/slap.h | 8 ldap/servers/slapd/slapi-plugin.h | 8 ldap/servers/slapd/slapi-private.h | 1 ldap/servers/slapd/util.c | 11 - 20 files changed, 644 insertions(+), 74 deletions(-) New commits: commit 88ecf0c9b43060822e5bc9a3ba38b48438c296e6 Author: Noriko Hosoi <nhosoi(a)redhat.com> Date: Thu Apr 2 13:09:12 2015 -0700 Ticket #47942 - DS hangs during online total update Backported the patch in the master branch to 389-ds-base-1.2.11 by Jatin Nansi (jnansi(a)redhat.com) commit fbafee54dc17e0673004d6d26d739ea1b19dd578 Author: Thierry bordaz (tbordaz) <tbordaz(a)redhat.com> Date: Mon Dec 15 15:12:35 2014 +0100 Ticket 47942: DS hangs during online total update Reviewed by tbordaz(a)redhat.com and nhosoi(a)redhat.com.
https://fedorahosted.org/389/ticket/47942
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif index 7febc9f..ba5b0aa 100644 --- a/ldap/schema/01core389.ldif +++ b/ldap/schema/01core389.ldif @@ -153,6 +153,8 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2152 NAME 'nsds5ReplicaProtocolTimeout' 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' ) +attributeTypes: ( 2.16.840.1.113730.3.1.2310 NAME 'nsds5ReplicaFlowControlWindow' 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.2311 NAME 'nsds5ReplicaFlowControlPause' 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 # @@ -164,7 +166,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.110 NAME 'nsMappingTree' DESC 'Netscape d objectClasses: ( 2.16.840.1.113730.3.2.104 NAME 'nsContainer' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' ) objectClasses: ( 2.16.840.1.113730.3.2.108 NAME 'nsDS5Replica' DESC 'Netscape defined objectclass' SUP top MUST ( nsDS5ReplicaRoot $ nsDS5ReplicaId ) MAY (cn $ nsds5ReplicaCleanRUV $ nsds5ReplicaAbortCleanRUV $ nsDS5ReplicaType $ nsDS5ReplicaBindDN $ nsState $ nsDS5ReplicaName $ nsDS5Flags $ nsDS5Task $ nsDS5ReplicaReferral $ nsDS5ReplicaAutoReferral $ nsds5ReplicaPurgeDelay $ nsds5ReplicaTombstonePurgeInterval $ nsds5ReplicaChangeCount $ nsds5ReplicaLegacyConsumer) X-ORIGIN 'Netscape Directory Server' ) objectClasses: ( 2.16.840.1.113730.3.2.113 NAME 'nsTombstone' DESC 'Netscape defined objectclass' SUP top MAY ( nsParentUniqueId $ nscpEntryDN ) X-ORIGIN 'Netscape Directory Server' ) -objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsds5ReplicaCleanRUVNotified $ nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5ReplicaEnabled $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime ) X-ORIGIN 'Netscape Directory Server' ) +objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsds5ReplicaCleanRUVNotified $ nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5ReplicaEnabled $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime $ nsds5ReplicaFlowControlWindow $ nsds5ReplicaFlowControlPause ) X-ORIGIN 'Netscape Directory Server' ) objectClasses: ( 2.16.840.1.113730.3.2.39 NAME 'nsslapdConfig' DESC 'Netscape defined objectclass' SUP top MAY ( cn ) X-ORIGIN 'Netscape Directory Server' ) objectClasses: ( 2.16.840.1.113730.3.2.317 NAME 'nsSaslMapping' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSaslMapRegexString $ nsSaslMapBaseDNTemplate $ nsSaslMapFilterTemplate ) X-ORIGIN 'Netscape Directory Server' ) objectClasses: ( 2.16.840.1.113730.3.2.43 NAME 'nsSNMP' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSNMPEnabled ) MAY ( nsSNMPOrganization $ nsSNMPLocation $ nsSNMPContact $ nsSNMPDescription $ nsSNMPName $ nsSNMPMasterHost $ nsSNMPMasterPort ) X-ORIGIN 'Netscape Directory Server' ) diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h index a5761be..231daf5 100644 --- a/ldap/servers/plugins/replication/repl5.h +++ b/ldap/servers/plugins/replication/repl5.h @@ -168,6 +168,9 @@ extern const char *type_nsds5ReplicaSessionPauseTime; extern const char *type_nsds5ReplicaEnabled; extern const char *type_nsds5ReplicaStripAttrs; extern const char *type_nsds5ReplicaCleanRUVnotified; +extern const char *type_nsds5ReplicaFlowControlWindow; +extern const char *type_nsds5ReplicaFlowControlPause; + /* Attribute names for windows replication agreements */ extern const char *type_nsds7WindowsReplicaArea; @@ -312,6 +315,8 @@ int agmt_get_auto_initialize(const Repl_Agmt *ra); long agmt_get_timeout(const Repl_Agmt *ra); long agmt_get_busywaittime(const Repl_Agmt *ra); long agmt_get_pausetime(const Repl_Agmt *ra); +long agmt_get_flowcontrolwindow(const Repl_Agmt *ra); +long agmt_get_flowcontrolpause(const Repl_Agmt *ra); int agmt_start(Repl_Agmt *ra); int windows_agmt_start(Repl_Agmt *ra); int agmt_stop(Repl_Agmt *ra); @@ -332,6 +337,8 @@ int agmt_replarea_matches(const Repl_Agmt *ra, const Slapi_DN *name); int agmt_schedule_in_window_now(const Repl_Agmt *ra); int agmt_set_schedule_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); int agmt_set_timeout_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); +int agmt_set_flowcontrolwindow_from_entry(Repl_Agmt *ra, const Slapi_Entry *e); +int agmt_set_flowcontrolpause_from_entry(Repl_Agmt *ra, const Slapi_Entry *e); int agmt_set_busywaittime_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); int agmt_set_pausetime_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); int agmt_set_credentials_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); @@ -463,6 +470,10 @@ 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); +void conn_set_tot_update_cb(Repl_Connection *conn, void *cb_data); +void conn_set_tot_update_cb_nolock(Repl_Connection *conn, void *cb_data); +void conn_get_tot_update_cb(Repl_Connection *conn, void **cb_data); +void conn_get_tot_update_cb_nolock(Repl_Connection *conn, void **cb_data); /* In repl5_protocol.c */ typedef struct repl_protocol Repl_Protocol; diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c index 708966a..41a81ca 100644 --- a/ldap/servers/plugins/replication/repl5_agmt.c +++ b/ldap/servers/plugins/replication/repl5_agmt.c @@ -87,6 +87,8 @@ #include "slapi-plugin.h" #define DEFAULT_TIMEOUT 600 /* (seconds) default outbound LDAP connection */ +#define DEFAULT_FLOWCONTROL_WINDOW 1000 /* #entries sent without acknowledgment */ +#define DEFAULT_FLOWCONTROL_PAUSE 2000 /* msec of pause when #entries sent witout acknowledgment */ #define STATUS_LEN 1024 struct changecounter { @@ -142,6 +144,12 @@ 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; + long flowControlWindow; /* This is the maximum number of entries + * sent without acknowledgment + */ + long flowControlPause; /* When nb of not acknowledged entries overpass totalUpdateWindow + * This is the duration (in msec) that the RA will pause before sending the next entry + */ } repl5agmt; /* Forward declarations */ @@ -332,6 +340,27 @@ agmt_new_from_entry(Slapi_Entry *e) ra->timeout = slapi_value_get_long(sval); } } + /* flow control update window. */ + ra->flowControlWindow = DEFAULT_FLOWCONTROL_WINDOW; + if (slapi_entry_attr_find(e, type_nsds5ReplicaFlowControlWindow, &sattr) == 0) + { + Slapi_Value *sval; + if (slapi_attr_first_value(sattr, &sval) == 0) + { + ra->flowControlWindow = slapi_value_get_long(sval); + } + } + + /* flow control update pause. */ + ra->flowControlPause = DEFAULT_FLOWCONTROL_PAUSE; + if (slapi_entry_attr_find(e, type_nsds5ReplicaFlowControlPause, &sattr) == 0) + { + Slapi_Value *sval; + if (slapi_attr_first_value(sattr, &sval) == 0) + { + ra->flowControlPause = slapi_value_get_long(sval); + } + } /* DN of entry at root of replicated area */ tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaRoot); @@ -963,6 +992,26 @@ agmt_get_pausetime(const Repl_Agmt *ra) return return_value; } +long +agmt_get_flowcontrolwindow(const Repl_Agmt *ra) +{ + long return_value; + PR_ASSERT(NULL != ra); + PR_Lock(ra->lock); + return_value = ra->flowControlWindow; + PR_Unlock(ra->lock); + return return_value; +} +long +agmt_get_flowcontrolpause(const Repl_Agmt *ra) +{ + long return_value; + PR_ASSERT(NULL != ra); + PR_Lock(ra->lock); + return_value = ra->flowControlPause; + PR_Unlock(ra->lock); + return return_value; +} /* * Warning - reference to the long name of the agreement is returned. * The long name of an agreement is the DN of the agreement entry, @@ -1694,6 +1743,90 @@ agmt_set_timeout_from_entry(Repl_Agmt *ra, const Slapi_Entry *e) return return_value; } +/* + * Set or reset the windows of entries sent without acknowledgment. + * The window is used during update to determine the number of + * entries will be send by the replica agreement without acknowledgment from the consumer + * + * Returns 0 if window set, or -1 if an error occurred. + */ +int +agmt_set_flowcontrolwindow_from_entry(Repl_Agmt *ra, const Slapi_Entry *e) +{ + Slapi_Attr *sattr = NULL; + int return_value = -1; + + PR_ASSERT(NULL != ra); + PR_Lock(ra->lock); + if (ra->stop_in_progress) + { + PR_Unlock(ra->lock); + return return_value; + } + + slapi_entry_attr_find(e, type_nsds5ReplicaFlowControlWindow, &sattr); + if (NULL != sattr) + { + Slapi_Value *sval = NULL; + slapi_attr_first_value(sattr, &sval); + if (NULL != sval) + { + long tmpval = slapi_value_get_long(sval); + if (tmpval >= 0) { + ra->flowControlWindow = tmpval; + return_value = 0; /* success! */ + } + } + } + PR_Unlock(ra->lock); + if (return_value == 0) + { + prot_notify_agmt_changed(ra->protocol, ra->long_name); + } + return return_value; +} + +/* + * Set or reset the pause duration when #entries sent without acknowledgment overpass flow control window + * + * Returns 0 if pause set, or -1 if an error occurred. + */ +int +agmt_set_flowcontrolpause_from_entry(Repl_Agmt *ra, const Slapi_Entry *e) +{ + Slapi_Attr *sattr = NULL; + int return_value = -1; + + PR_ASSERT(NULL != ra); + PR_Lock(ra->lock); + if (ra->stop_in_progress) + { + PR_Unlock(ra->lock); + return return_value; + } + + slapi_entry_attr_find(e, type_nsds5ReplicaFlowControlPause, &sattr); + if (NULL != sattr) + { + Slapi_Value *sval = NULL; + slapi_attr_first_value(sattr, &sval); + if (NULL != sval) + { + long tmpval = slapi_value_get_long(sval); + if (tmpval >= 0) { + ra->flowControlPause = tmpval; + return_value = 0; /* success! */ + } + } + } + PR_Unlock(ra->lock); + if (return_value == 0) + { + prot_notify_agmt_changed(ra->protocol, ra->long_name); + } + return return_value; +} + int agmt_set_timeout(Repl_Agmt *ra, long timeout) { @@ -1708,6 +1841,33 @@ agmt_set_timeout(Repl_Agmt *ra, long timeout) return 0; } +int +agmt_set_flowcontrolwindow(Repl_Agmt *ra, long window) +{ + PR_Lock(ra->lock); + if (ra->stop_in_progress){ + PR_Unlock(ra->lock); + return -1; + } + ra->flowControlWindow = window; + PR_Unlock(ra->lock); + + return 0; +} +int +agmt_set_flowcontrolpause(Repl_Agmt *ra, long pause) +{ + PR_Lock(ra->lock); + if (ra->stop_in_progress){ + PR_Unlock(ra->lock); + return -1; + } + ra->flowControlPause = pause; + PR_Unlock(ra->lock); + + return 0; +} + /* * Set or reset the busywaittime * diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c index d37704d..caa41af 100644 --- a/ldap/servers/plugins/replication/repl5_agmtlist.c +++ b/ldap/servers/plugins/replication/repl5_agmtlist.c @@ -345,6 +345,32 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, + type_nsds5ReplicaFlowControlWindow)) + { + /* New replica timeout */ + if (agmt_set_flowcontrolwindow_from_entry(agmt, e) != 0) + { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " + "failed to update the flow control window for agreement %s\n", + agmt_get_long_name(agmt)); + *returncode = LDAP_OPERATIONS_ERROR; + rc = SLAPI_DSE_CALLBACK_ERROR; + } + } + else if (slapi_attr_types_equivalent(mods[i]->mod_type, + type_nsds5ReplicaFlowControlPause)) + { + /* New replica timeout */ + if (agmt_set_flowcontrolpause_from_entry(agmt, e) != 0) + { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " + "failed to update the flow control pause for agreement %s\n", + agmt_get_long_name(agmt)); + *returncode = LDAP_OPERATIONS_ERROR; + rc = SLAPI_DSE_CALLBACK_ERROR; + } + } + else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaBusyWaitTime)) { /* New replica busywaittime */ diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c index 5efd0e6..e080a3f 100644 --- a/ldap/servers/plugins/replication/repl5_connection.c +++ b/ldap/servers/plugins/replication/repl5_connection.c @@ -52,6 +52,7 @@ replica locked. Seems like right thing to do. */ #include "repl5.h" +#include "repl5_prot_private.h" #if defined(USE_OPENLDAP) #include "ldap.h" #else @@ -90,6 +91,7 @@ typedef struct repl_connection struct timeval timeout; int flag_agmt_changed; char *plain; + void *tot_init_callback; /* Used during total update to do flow control */ } repl_connection; /* #define DEFAULT_LINGER_TIME (5 * 60) */ /* 5 minutes */ @@ -277,6 +279,32 @@ conn_get_error(Repl_Connection *conn, int *operation, int *error) PR_Unlock(conn->lock); } +void +conn_set_tot_update_cb_nolock(Repl_Connection *conn, void *cb_data) +{ + conn->tot_init_callback = (void *) cb_data; +} +void +conn_set_tot_update_cb(Repl_Connection *conn, void *cb_data) +{ + PR_Lock(conn->lock); + conn_set_tot_update_cb_nolock(conn, cb_data); + PR_Unlock(conn->lock); +} + +void +conn_get_tot_update_cb_nolock(Repl_Connection *conn, void **cb_data) +{ + *cb_data = (void *) conn->tot_init_callback; +} +void +conn_get_tot_update_cb(Repl_Connection *conn, void **cb_data) +{ + PR_Lock(conn->lock); + conn_get_tot_update_cb_nolock(conn, cb_data); + PR_Unlock(conn->lock); +} + /* * Return the last operation type processed by the connection * object, and the LDAP error encountered. @@ -629,6 +657,133 @@ see_if_write_available(Repl_Connection *conn, PRIntervalTime timeout) } #endif /* ! USE_OPENLDAP */ +/* + * During a total update, this function checks how much entries + * have been sent to the consumer without having received their acknowledgment. + * Basically it checks how late is the consumer. + * + * If the consumer is too late, it pause the RA.sender (releasing the lock) to + * let the consumer to catch up and RA.reader to receive the acknowledgments. + * + * Caller must hold conn->lock + */ +static void +check_flow_control_tot_init(Repl_Connection *conn, int optype, const char *extop_oid, int sent_msgid) +{ + int rcv_msgid; + int once; + + if ((sent_msgid != 0) && (optype == CONN_EXTENDED_OPERATION) && (strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) == 0)) { + /* We are sending entries part of the total update of a consumer + * Wait a bit if the consumer needs to catchup from the current sent entries + */ + rcv_msgid = repl5_tot_last_rcv_msgid(conn); + if (rcv_msgid == -1) { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "%s: check_flow_control_tot_init no callback data [ msgid sent: %d]\n", + agmt_get_long_name(conn->agmt), + sent_msgid); + } else if (sent_msgid < rcv_msgid) { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: check_flow_control_tot_init invalid message ids [ msgid sent: %d, rcv: %d]\n", + agmt_get_long_name(conn->agmt), + sent_msgid, + rcv_msgid); + } else if ((sent_msgid - rcv_msgid) > agmt_get_flowcontrolwindow(conn->agmt)) { + int totalUpdatePause; + + totalUpdatePause = agmt_get_flowcontrolpause(conn->agmt); + if (totalUpdatePause) { + /* The consumer is late. Last sent entry compare to last acknowledged entry + * overpass the allowed limit (flowcontrolwindow) + * Give some time to the consumer to catch up + */ + once = repl5_tot_flowcontrol_detection(conn, 1); + PR_Unlock(conn->lock); + if (once == 1) { + /* This is the first time we hit total update flow control. + * Log it at least once to inform administrator there is + * a potential configuration issue here + */ + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "%s: Total update flow control gives time (%d msec) to the consumer before sending more entries [ msgid sent: %d, rcv: %d])\n" + "If total update fails you can try to increase %s and/or decrease %s in the replica agreement configuration\n", + agmt_get_long_name(conn->agmt), + totalUpdatePause, + sent_msgid, + rcv_msgid, + type_nsds5ReplicaFlowControlPause, + type_nsds5ReplicaFlowControlWindow); + } + DS_Sleep(PR_MillisecondsToInterval(totalUpdatePause)); + PR_Lock(conn->lock); + } + } + } + +} +/* + * Test if the connection is available to do a write. + * This function is doing a periodic polling of the connection. + * If the polling times out: + * - it releases the connection lock (to let other thread ,i.e. + * replication result thread, the opportunity to use the connection) + * - Sleeps for a short period (100ms) + * - acquires the connection lock + * + * It loops until + * - it is available + * - exceeds RA complete timeout + * - server is shutdown + * - connection is disconnected (Disable, stop, delete the RA + * 'terminate' the replication protocol and disconnect the connection) + * + * Return: + * - CONN_OPERATION_SUCCESS if the connection is available + * - CONN_TIMEOUT if the overall polling/sleeping delay exceeds RA timeout + * - CONN_NOT_CONNECTED if the replication connection state is disconnected + * - other ConnResult + * + * Caller must hold conn->Lock. At the exit, conn->lock is held + */ +static ConnResult +conn_is_available(Repl_Connection *conn) +{ + time_t poll_timeout_sec = 1; /* Polling for 1sec */ + time_t yield_delay_msec = 100; /* Delay to wait */ + time_t start_time = time( NULL ); + time_t time_now; + ConnResult return_value = CONN_OPERATION_SUCCESS; + + while (!slapi_is_shutting_down() && (conn->state != STATE_DISCONNECTED)) { + return_value = see_if_write_available(conn, PR_SecondsToInterval(poll_timeout_sec)); + if (return_value == CONN_TIMEOUT) { + /* in case of timeout we return CONN_TIMEOUT only + * if the RA.timeout is exceeded + */ + time_now = time(NULL); + if (conn->timeout.tv_sec <= (time_now - start_time)) { + break; + } else { + /* Else give connection to others threads */ + PR_Unlock(conn->lock); + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: perform_operation transient timeout. retry)\n", + agmt_get_long_name(conn->agmt)); + DS_Sleep(PR_MillisecondsToInterval(yield_delay_msec)); + PR_Lock(conn->lock); + } + } else { + break; + } + } + if (conn->state == STATE_DISCONNECTED) { + return_value = CONN_NOT_CONNECTED; + } + return return_value; +} + + /* * Common code to send an LDAPv3 operation and collect the result. * Return values: @@ -670,10 +825,13 @@ perform_operation(Repl_Connection *conn, int optype, const char *dn, Slapi_Eq_Context eqctx = repl5_start_debug_timeout(&setlevel); - return_value = see_if_write_available( - conn, PR_SecondsToInterval(conn->timeout.tv_sec)); + return_value = conn_is_available(conn); if (return_value != CONN_OPERATION_SUCCESS) { PR_Unlock(conn->lock); + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "%s: perform_operation connection is not available (%d)\n", + agmt_get_long_name(conn->agmt), + return_value); return return_value; } conn->last_operation = optype; @@ -745,6 +903,9 @@ perform_operation(Repl_Connection *conn, int optype, const char *dn, */ return_value = CONN_NOT_CONNECTED; } + + check_flow_control_tot_init(conn, optype, extop_oid, msgid); + PR_Unlock(conn->lock); /* release the lock */ if (message_id) { diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c index ae26380..f5516a3 100644 --- a/ldap/servers/plugins/replication/repl5_inc_protocol.c +++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c @@ -108,6 +108,7 @@ typedef struct result_data int stop_result_thread; /* Flag used to tell the result thread to exit */ int last_message_id_sent; int last_message_id_received; + int flowcontrol_detection; int result; /* The UPDATE_TRANSIENT_ERROR etc */ } result_data; @@ -460,6 +461,23 @@ repl5_inc_destroy_async_result_thread(result_data *rd) return retval; } +/* The interest of this routine is to give time to the consumer + * to apply the sent updates and return the acks. + * So the caller should not hold the replication connection lock + * to let the RA.reader receives the acks. + */ +static void +repl5_inc_flow_control_results(Repl_Agmt *agmt, result_data *rd) +{ + PR_Lock(rd->lock); + if ((rd->last_message_id_received <= rd->last_message_id_sent) && + ((rd->last_message_id_sent - rd->last_message_id_received) >= agmt_get_flowcontrolwindow(agmt))) { + rd->flowcontrol_detection++; + DS_Sleep(PR_MillisecondsToInterval(agmt_get_flowcontrolpause(agmt))); + } + PR_Unlock(rd->lock); +} + static void repl5_inc_waitfor_async_results(result_data *rd) { @@ -1669,7 +1687,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu { int finished = 0; ConnResult replay_crc; - char csn_str[CSN_STRSIZE]; + char csn_str[CSN_STRSIZE]; /* Start the results reading thread */ rd = repl5_inc_rd_new(prp); @@ -1804,6 +1822,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu sop->replica_id = replica_id; PL_strncpyz(sop->uniqueid, uniqueid, sizeof(sop->uniqueid)); repl5_int_push_operation(rd,sop); + repl5_inc_flow_control_results(prp->agmt, rd); } else { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "%s: Skipping update operation with no message_id (uniqueid %s, CSN %s):\n", @@ -1892,6 +1911,17 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu } *num_changes_sent = rd->num_changes_sent; } + PR_Lock(rd->lock); + if (rd->flowcontrol_detection) { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, + "%s: Incremental update flow control triggered %d times\n" + "You may increase %s and/or decrease %s in the replica agreement configuration\n", + agmt_get_long_name(prp->agmt), + rd->flowcontrol_detection, + type_nsds5ReplicaFlowControlPause, + type_nsds5ReplicaFlowControlWindow); + } + PR_Unlock(rd->lock); repl5_inc_rd_destroy(&rd); cl5_operation_parameters_done ( entry.op ); diff --git a/ldap/servers/plugins/replication/repl5_prot_private.h b/ldap/servers/plugins/replication/repl5_prot_private.h index 10aa02b..7ca31ca 100644 --- a/ldap/servers/plugins/replication/repl5_prot_private.h +++ b/ldap/servers/plugins/replication/repl5_prot_private.h @@ -79,6 +79,8 @@ typedef struct private_repl_protocol extern Private_Repl_Protocol *Repl_5_Inc_Protocol_new(); extern Private_Repl_Protocol *Repl_5_Tot_Protocol_new(); +extern int repl5_tot_last_rcv_msgid(Repl_Connection *conn); +extern int repl5_tot_flowcontrol_detection(Repl_Connection *conn, int increment); extern Private_Repl_Protocol *Windows_Inc_Protocol_new(); extern Private_Repl_Protocol *Windows_Tot_Protocol_new(); diff --git a/ldap/servers/plugins/replication/repl5_tot_protocol.c b/ldap/servers/plugins/replication/repl5_tot_protocol.c index 9829984..e514dc6 100644 --- a/ldap/servers/plugins/replication/repl5_tot_protocol.c +++ b/ldap/servers/plugins/replication/repl5_tot_protocol.c @@ -82,6 +82,7 @@ typedef struct callback_data int stop_result_thread; /* Flag used to tell the result thread to exit */ int last_message_id_sent; int last_message_id_received; + int flowcontrol_detection; } callback_data; /* @@ -416,12 +417,17 @@ repl5_tot_run(Private_Repl_Protocol *prp) LDAP_SCOPE_SUBTREE, "(|(objectclass=ldapsubentry)(objectclass=nstombstone)(nsuniqueid=*))", NULL, 0, ctrls, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); - cb_data.prp = prp; - cb_data.rc = 0; + cb_data.prp = prp; + cb_data.rc = 0; cb_data.num_entries = 0UL; cb_data.sleep_on_busy = 0UL; cb_data.last_busy = current_time (); + cb_data.flowcontrol_detection = 0; cb_data.lock = PR_NewLock(); + /* This allows during perform_operation to check the callback data + * especially to do flow contol on delta send msgid / recv msgid + */ + conn_set_tot_update_cb(prp->conn, (void *) &cb_data); /* Before we get started on sending entries to the replica, we need to * setup things for async propagation: @@ -492,6 +498,17 @@ repl5_tot_run(Private_Repl_Protocol *prp) done: slapi_sdn_free(&area_sdn); slapi_ch_free_string(&hostname); + if (cb_data.flowcontrol_detection > 1) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, + "%s: Total update flow control triggered %d times\n" + "You may increase %s and/or decrease %s in the replica agreement configuration\n", + agmt_get_long_name(prp->agmt), + cb_data.flowcontrol_detection, + type_nsds5ReplicaFlowControlPause, + type_nsds5ReplicaFlowControlWindow); + } + conn_set_tot_update_cb(prp->conn, NULL); if (cb_data.lock) { PR_DestroyLock(cb_data.lock); @@ -619,6 +636,37 @@ void get_result (int rc, void *cb_data) ((callback_data*)cb_data)->rc = rc; } +/* Call must hold the connection lock */ +int +repl5_tot_last_rcv_msgid(Repl_Connection *conn) +{ + struct callback_data *cb_data; + + conn_get_tot_update_cb_nolock(conn, (void **) &cb_data); + if (cb_data == NULL) { + return -1; + } else { + return cb_data->last_message_id_received; + } +} + +/* Increase the flowcontrol counter + * Call must hold the connection lock + */ +int +repl5_tot_flowcontrol_detection(Repl_Connection *conn, int increment) +{ + struct callback_data *cb_data; + + conn_get_tot_update_cb_nolock(conn, (void **) &cb_data); + if (cb_data == NULL) { + return -1; + } else { + cb_data->flowcontrol_detection += increment; + return cb_data->flowcontrol_detection; + } +} + static int send_entry (Slapi_Entry *e, void *cb_data) { diff --git a/ldap/servers/plugins/replication/repl_globals.c b/ldap/servers/plugins/replication/repl_globals.c index f31a476..bfcff03 100644 --- a/ldap/servers/plugins/replication/repl_globals.c +++ b/ldap/servers/plugins/replication/repl_globals.c @@ -131,6 +131,9 @@ const char *type_nsds5ReplicaSessionPauseTime = "nsds5ReplicaSessionPauseTime"; const char *type_nsds5ReplicaEnabled = "nsds5ReplicaEnabled"; const char *type_nsds5ReplicaStripAttrs = "nsds5ReplicaStripAttrs"; const char *type_nsds5ReplicaCleanRUVnotified = "nsds5ReplicaCleanRUVNotified"; +const char* type_nsds5ReplicaFlowControlWindow = "nsds5ReplicaFlowControlWindow"; +const char* type_nsds5ReplicaFlowControlPause = "nsds5ReplicaFlowControlPause"; + /* windows sync specific attributes */ const char *type_nsds7WindowsReplicaArea = "nsds7WindowsReplicaSubtree"; commit bb565bd8e664a22aed754af092121d293d2fee5d Author: Noriko Hosoi <nhosoi(a)redhat.com> Date: Thu Apr 2 11:49:46 2015 -0700 Ticket #561 - disable writing unhashed#user#password to changelog Backported: . commit c4bd52e2211c043087765f74df6cf6cd41b8f234 Ticket #561 - disable writing unhashed#user#password to changelog . commit da3be3fbf497775f608d1289f72cfe427850f950 Fix optimization issue introduced with fix for ticket #561, . commit 1d4f3ca2e931e6d930056aeb683256965503c5e1 Fixing a compiler warning introduced by Ticket #561 . commit 84b8bfd7d18a0613920dce36f1d3775d75e45a3e Fix for CVE-2014-8112 Description: Introducing a config parameter nsslapd-unhashed-pw-switch to cn=config. The parameter takes 3 values: on - unhashed password is stored in the entry extension and logged in the changelog. nolog - unhashed password is stored in the entry extension but not logged in the changelog. off - unhashed password is not stored in the entry extension.
https://fedorahosted.org/389/ticket/561
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c index ae522a3..0618d9b 100644 --- a/ldap/servers/plugins/replication/cl5_api.c +++ b/ldap/servers/plugins/replication/cl5_api.c @@ -322,7 +322,7 @@ static int _cl5Str2OperationType (const char *str); static void _cl5WriteString (const char *str, char **buff); static void _cl5ReadString (char **str, char **buff); static void _cl5WriteMods (LDAPMod **mods, char **buff); -static void _cl5WriteMod (LDAPMod *mod, char **buff); +static int _cl5WriteMod (LDAPMod *mod, char **buff); static int _cl5ReadMods (LDAPMod ***mods, char **buff); static int _cl5ReadMod (Slapi_Mod *mod, char **buff); static int _cl5GetModsSize (LDAPMod **mods); @@ -2474,7 +2474,7 @@ static void _cl5WriteMods (LDAPMod **mods, char **buff) { PRInt32 i; char *mod_start; - PRInt32 count; + PRInt32 count = 0; if (mods == NULL) return; @@ -2483,30 +2483,49 @@ static void _cl5WriteMods (LDAPMod **mods, char **buff) mod_start = (*buff) + sizeof (count); /* write mods*/ - for (i=0; mods[i]; i++) - { - _cl5WriteMod (mods[i], &mod_start); + for (i = 0; mods[i]; i++) { + if (0 <= _cl5WriteMod (mods[i], &mod_start)) { + count++; + } } - count = PR_htonl(i); + count = PR_htonl(count); memcpy (*buff, &count, sizeof (count)); (*buff) = mod_start; } -static void _cl5WriteMod (LDAPMod *mod, char **buff) +/* + * return values: + * positive: no need to encrypt && succeeded to write a mod + * 0: succeeded to encrypt && write a mod + * netative: failed to encrypt && no write to the changelog + */ +static int +_cl5WriteMod (LDAPMod *mod, char **buff) { + char *orig_pos; char *pos; PRInt32 count; struct berval *bv; struct berval *encbv; struct berval *bv_to_use; Slapi_Mod smod; - int rc = 0; + int rc = -1; + + if (NULL == mod) { + return rc; + } + if (SLAPD_UNHASHED_PW_NOLOG == slapi_config_get_unhashed_pw_switch()) { + if (0 == strcasecmp(mod->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) { + /* If nsslapd-unhashed-pw-switch == nolog, skip writing it to cl. */ + return rc; + } + } slapi_mod_init_byref(&smod, mod); - pos = *buff; + orig_pos = pos = *buff; /* write mod op */ *pos = (PRUint8)slapi_mod_get_operation (&smod); pos ++; @@ -2516,7 +2535,7 @@ static void _cl5WriteMod (LDAPMod *mod, char **buff) /* write value count */ count = PR_htonl(slapi_mod_get_num_values(&smod)); memcpy (pos, &count, sizeof (count)); - pos += sizeof (PRInt32); + pos += sizeof (PRInt32); bv = slapi_mod_get_first_value (&smod); while (bv) @@ -2536,6 +2555,8 @@ static void _cl5WriteMod (LDAPMod *mod, char **buff) "_cl5WriteMod: encrypting \"%s: %s\" failed\n", slapi_mod_get_type(&smod), bv->bv_val); bv_to_use = NULL; + rc = -1; + break; } if (bv_to_use) { _cl5WriteBerval (bv_to_use, &pos); @@ -2544,9 +2565,14 @@ static void _cl5WriteMod (LDAPMod *mod, char **buff) bv = slapi_mod_get_next_value (&smod); } - (*buff) = pos; + if (rc < 0) { + (*buff) = orig_pos; + } else { + (*buff) = pos; + } slapi_mod_done (&smod); + return rc; } /* mods format: diff --git a/ldap/servers/plugins/retrocl/retrocl_po.c b/ldap/servers/plugins/retrocl/retrocl_po.c index c3d1c41..3fdf887 100644 --- a/ldap/servers/plugins/retrocl/retrocl_po.c +++ b/ldap/servers/plugins/retrocl/retrocl_po.c @@ -101,6 +101,12 @@ static lenstr *make_changes_string(LDAPMod **ldm, const char **includeattrs) continue; } } + if (SLAPD_UNHASHED_PW_NOLOG == slapi_config_get_unhashed_pw_switch()) { + if (0 == strcasecmp(ldm[ i ]->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) { + /* If nsslapd-unhashed-pw-switch == nolog, skip writing it to cl. */ + continue; + } + } switch ( ldm[ i ]->mod_op & ~LDAP_MOD_BVALUES ) { case LDAP_MOD_ADD: addlenstr( l, "add: " ); diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c index f52f766..37060df 100644 --- a/ldap/servers/slapd/add.c +++ b/ldap/servers/slapd/add.c @@ -447,7 +447,6 @@ static void op_shared_add (Slapi_PBlock *pb) int err; int internal_op, repl_op, legacy_op, lastmod; char *pwdtype = NULL; - Slapi_Value **unhashed_password_vals = NULL; Slapi_Attr *attr = NULL; Slapi_Entry *referral; char errorbuf[BUFSIZ]; @@ -545,6 +544,7 @@ static void op_shared_add (Slapi_PBlock *pb) { Slapi_Value **present_values; present_values= attr_get_present_values(attr); + Slapi_Value **unhashed_password_vals = NULL; /* Set the backend in the pblock. The slapi_access_allowed function * needs this set to work properly. */ @@ -576,11 +576,13 @@ static void op_shared_add (Slapi_PBlock *pb) add_password_attrs(pb, operation, e); slapi_entry_attr_replace_sv(e, SLAPI_USERPWD_ATTR, vals); valuearray_free(&vals); - - /* Add the unhashed password pseudo-attribute to the entry */ - pwdtype = slapi_attr_syntax_normalize(PSEUDO_ATTR_UNHASHEDUSERPASSWORD); - slapi_entry_add_values_sv(e, pwdtype, unhashed_password_vals); + if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) { + /* Add the unhashed password pseudo-attribute to the entry */ + pwdtype = slapi_attr_syntax_normalize(PSEUDO_ATTR_UNHASHEDUSERPASSWORD); + slapi_entry_add_values_sv(e, pwdtype, unhashed_password_vals); + } } + valuearray_free(&unhashed_password_vals); } /* look for multiple backend local credentials or replication local credentials */ @@ -751,7 +753,6 @@ done: slapi_ch_free((void **)&operation->o_params.p.p_add.parentuniqueid); slapi_entry_free(e); slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL); - valuearray_free(&unhashed_password_vals); slapi_ch_free((void**)&pwdtype); slapi_ch_free_string(&proxydn); slapi_ch_free_string(&proxystr); diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c index 825dcee..dbb0fa8 100644 --- a/ldap/servers/slapd/libglobs.c +++ b/ldap/servers/slapd/libglobs.c @@ -121,7 +121,8 @@ typedef enum { CONFIG_SPECIAL_ERRORLOGLEVEL, /* requires & with LDAP_DEBUG_ANY */ CONFIG_STRING_OR_EMPTY, /* use an empty string */ CONFIG_SPECIAL_ANON_ACCESS_SWITCH, /* maps strings to an enumeration */ - CONFIG_SPECIAL_VALIDATE_CERT_SWITCH /* maps strings to an enumeration */ + CONFIG_SPECIAL_VALIDATE_CERT_SWITCH, /* maps strings to an enumeration */ + CONFIG_SPECIAL_UNHASHED_PW_SWITCH /* unhashed pw: on/off/nolog */ } ConfigVarType; static int config_set_onoff( const char *attrname, char *value, @@ -269,6 +270,7 @@ int init_mempool_switch; #define DEFAULT_SSLCLIENTAPTH "off" #define DEFAULT_ALLOW_ANON_ACCESS "on" #define DEFAULT_VALIDATE_CERT "warn" +#define DEFAULT_UNHASHED_PW_SWITCH "on" static int isInt(ConfigVarType type) @@ -1041,6 +1043,11 @@ static struct config_get_and_set { NULL, 0, (void**)&global_slapdFrontendConfig.ndn_cache_max_size, CONFIG_INT, (ConfigGetFunc)config_get_ndn_cache_size}, + {CONFIG_UNHASHED_PW_SWITCH_ATTRIBUTE, config_set_unhashed_pw_switch, + NULL, 0, + (void**)&global_slapdFrontendConfig.unhashed_pw_switch, + CONFIG_SPECIAL_UNHASHED_PW_SWITCH, + (ConfigGetFunc)config_get_unhashed_pw_switch} #ifdef MEMPOOL_EXPERIMENTAL ,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch, NULL, 0, @@ -1459,6 +1466,7 @@ FrontendConfig_init () { cfg->disk_grace_period = 60; /* 1 hour */ init_disk_logging_critical = cfg->disk_logging_critical = LDAP_OFF; cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE; + cfg->unhashed_pw_switch = SLAPD_UNHASHED_PW_ON; init_listen_backlog_size = cfg->listen_backlog_size = DAEMON_LISTEN_SIZE; init_ignore_time_skew = cfg->ignore_time_skew = LDAP_OFF; @@ -6552,7 +6560,6 @@ config_get_allowed_to_delete_attrs(void) return retVal; } - int config_set_allowed_to_delete_attrs( const char *attrname, char *value, char *errorbuf, int apply ) @@ -6711,6 +6718,62 @@ config_initvalue_to_onoff(struct config_get_and_set *cgas, char *initvalbuf, siz return retval; } +int +config_set_unhashed_pw_switch(const char *attrname, char *value, + char *errorbuf, int apply) +{ + int retVal = LDAP_SUCCESS; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + if (config_value_is_null(attrname, value, errorbuf, 0)) { + return LDAP_OPERATIONS_ERROR; + } + + if ((strcasecmp(value, "on") != 0) && (strcasecmp(value, "off") != 0) && + (strcasecmp(value, "nolog") != 0)) { + PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, + "%s: invalid value \"%s\". Valid values are \"on\", " + "\"off\", or \"nolog\".", attrname, value); + retVal = LDAP_OPERATIONS_ERROR; + } + + if (!apply) { + /* we can return now if we aren't applying the changes */ + return retVal; + } + + CFG_LOCK_WRITE(slapdFrontendConfig); + + if (strcasecmp(value, "on") == 0 ) { + slapdFrontendConfig->unhashed_pw_switch = SLAPD_UNHASHED_PW_ON; + } else if (strcasecmp(value, "off") == 0 ) { + slapdFrontendConfig->unhashed_pw_switch = SLAPD_UNHASHED_PW_OFF; + } else if (strcasecmp(value, "nolog") == 0) { + slapdFrontendConfig->unhashed_pw_switch = SLAPD_UNHASHED_PW_NOLOG; + } + + CFG_UNLOCK_WRITE(slapdFrontendConfig); + return retVal; +} + +int +slapi_config_get_unhashed_pw_switch() +{ + return config_get_unhashed_pw_switch(); +} + +int +config_get_unhashed_pw_switch() +{ + int retVal = 0; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + CFG_LOCK_READ(slapdFrontendConfig); + retVal = slapdFrontendConfig->unhashed_pw_switch; + CFG_UNLOCK_READ(slapdFrontendConfig); + + 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 @@ -6931,6 +6994,23 @@ config_set_value( slapi_entry_attr_set_charptr(e, cgas->attr_name, sval); break; + case CONFIG_SPECIAL_UNHASHED_PW_SWITCH: + if (!value) { + slapi_entry_attr_set_charptr(e, cgas->attr_name, "on"); + break; + } + + if (*((int *)value) == SLAPD_UNHASHED_PW_OFF) { + sval = "off"; + } else if (*((int *)value) == SLAPD_UNHASHED_PW_NOLOG) { + sval = "nolog"; + } else { + sval = "on"; + } + slapi_entry_attr_set_charptr(e, cgas->attr_name, sval); + + break; + case CONFIG_SPECIAL_VALIDATE_CERT_SWITCH: if (!value) { slapi_entry_attr_set_charptr(e, cgas->attr_name, "off"); diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c index 90c9f8c..c67ef14 100644 --- a/ldap/servers/slapd/modify.c +++ b/ldap/servers/slapd/modify.c @@ -894,13 +894,15 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw) /* * Finally, delete the unhashed userpassword */ - bval.bv_val = password; - bval.bv_len = strlen(password); - bv[0] = &bval; - bv[1] = NULL; - valuearray_init_bervalarray(bv, &va); - slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va); - valuearray_free(&va); + if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) { + bval.bv_val = password; + bval.bv_len = strlen(password); + bv[0] = &bval; + bv[1] = NULL; + valuearray_init_bervalarray(bv, &va); + slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va); + valuearray_free(&va); + } } else { /* * Password is encoded, try and find a matching unhashed_password to delete @@ -924,28 +926,31 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw) bval.bv_len = strlen(unhashed_pwd); bv[0] = &bval; bv[1] = NULL; - /* * Compare the clear text unhashed password, to the encoded password * provided by the client. */ - unhashed_pwsp = pw_val2scheme( unhashed_pwd, NULL, 1 ); + unhashed_pwsp = pw_val2scheme( (char *)unhashed_pwd, NULL, 1 ); if(strcmp(unhashed_pwsp->pws_name, "CLEAR") == 0){ - if((*(pwsp->pws_cmp))(unhashed_pwd , valpwd) == 0 ){ + if((*(pwsp->pws_cmp))((char *)unhashed_pwd , valpwd) == 0 ){ /* match, add the delete mod for this particular unhashed userpassword */ - valuearray_init_bervalarray(bv, &va); - slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va); - valuearray_free(&va); - free_pw_scheme( unhashed_pwsp ); + if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) { + valuearray_init_bervalarray(bv, &va); + slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va); + valuearray_free(&va); + free_pw_scheme( unhashed_pwsp ); + } break; } } else { /* * We have a hashed unhashed_userpassword! We must delete it. */ - valuearray_init_bervalarray(bv, &va); - slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va); - valuearray_free(&va); + if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) { + valuearray_init_bervalarray(bv, &va); + slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va); + valuearray_free(&va); + } } free_pw_scheme( unhashed_pwsp ); } @@ -958,13 +963,13 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw) if (remove_unhashed_pw && !slapi_entry_attr_find(e, unhashed_pw_attr, &a)){ slapi_mods_add_mod_values(&smods, pw_mod->mod_op,unhashed_pw_attr, va); } - } else { - /* add pseudo password attribute - only if it's value is clear text */ + } else if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) { + /* add pseudo password attribute */ valuearray_init_bervalarray_unhashed_only(pw_mod->mod_bvalues, &va); - if(va){ + if(va && va[0]){ slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va); - valuearray_free(&va); } + valuearray_free(&va); } /* Init new value array for hashed value */ diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c index a7367a7..bef19d1 100644 --- a/ldap/servers/slapd/opshared.c +++ b/ldap/servers/slapd/opshared.c @@ -52,10 +52,7 @@ static void compute_limits (Slapi_PBlock *pb); /* attributes that no clients are allowed to add or modify */ -/* PSEUDO_ATTR_UNHASHEDUSERPASSWORD used to be in protected_attrs_all. - * Now it's moved to back-ldbm/id2entry.c to share it among repl masters. - * (bz 182507)*/ -static char *protected_attrs_all [] = { NULL }; +static char *protected_attrs_all [] = { PSEUDO_ATTR_UNHASHEDUSERPASSWORD, NULL }; static char *pwpolicy_lock_attrs_all [] = { "passwordRetryCount", "retryCountResetTime", "accountUnlockTime", @@ -70,30 +67,26 @@ int op_shared_is_allowed_attr (const char *attr_name, int replicated_op) int i; slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); - /* check list of attributes that no client is allowed to specify */ - for (i = 0; protected_attrs_all[i]; i ++) - { - if (strcasecmp (attr_name, protected_attrs_all[i]) == 0) - { - /* this attribute is not allowed */ - return 0; - } - } - /* ONREPL - should allow backends to plugin here to specify attributes that are not allowed */ - if (!replicated_op) - { - /* - * check to see if attribute is marked as one clients can't modify - */ + if (!replicated_op) { struct asyntaxinfo *asi; int no_user_mod = 0; + /* check list of attributes that no client is allowed to specify */ + for (i = 0; protected_attrs_all[i]; i ++) { + if (strcasecmp (attr_name, protected_attrs_all[i]) == 0) { + /* this attribute is not allowed */ + return 0; + } + } + /* + * check to see if attribute is marked as one clients can't modify + */ asi = attr_syntax_get_by_name( attr_name, 0 ); if ( NULL != asi && - 0 != ( asi->asi_flags & SLAPI_ATTR_FLAG_NOUSERMOD )) + 0 != ( asi->asi_flags & SLAPI_ATTR_FLAG_NOUSERMOD )) { /* this attribute is not allowed */ no_user_mod = 1; @@ -187,7 +180,7 @@ modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods) /* anonymous bind */ bv.bv_val = ""; bv.bv_len = strlen(bv.bv_val); - } else { + } else { bv.bv_val = binddn; bv.bv_len = strlen(bv.bv_val); } diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index da9c925..c497c14 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -403,6 +403,7 @@ int config_set_malloc_mmap_threshold(const char *attrname, char *value, char *er int config_set_ndn_cache_enabled(const char *attrname, char *value, char *errorbuf, int apply); int config_set_ndn_cache_max_size(const char *attrname, char *value, char *errorbuf, int apply); +int config_set_unhashed_pw_switch(const char *attrname, char *value, char *errorbuf, int apply); #if !defined(_WIN32) && !defined(AIX) @@ -572,6 +573,7 @@ int config_get_malloc_mmap_threshold(); int config_get_ndn_cache_count(); size_t config_get_ndn_cache_size(); int config_get_ndn_cache_enabled(); +int config_get_unhashed_pw_switch(); PLHashNumber hashNocaseString(const void *key); PRIntn hashNocaseCompare(const void *v1, const void *v2); diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index 70e8a51..c298033 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -306,9 +306,6 @@ typedef void (*VFPV)(); /* takes undefined arguments */ #define ATTR_NETSCAPEMDSUFFIX "netscapemdsuffix" -/* Used to make unhashed passwords available to plugins. */ -#define PSEUDO_ATTR_UNHASHEDUSERPASSWORD "unhashed#user#password" - #define REFERRAL_REMOVE_CMD "remove" /* Filenames for DSE storage */ @@ -339,6 +336,8 @@ typedef void (*VFPV)(); /* takes undefined arguments */ #define SLAPD_VALIDATE_CERT_ON 1 #define SLAPD_VALIDATE_CERT_WARN 2 +typedef int slapi_onoff_t; + struct subfilt { char *sf_type; char *sf_initial; @@ -1891,6 +1890,7 @@ typedef struct _slapdEntryPoints { #define CONFIG_ERRORLOG_LOGGING_ENABLED_ATTRIBUTE "nsslapd-errorlog-logging-enabled" #define CONFIG_AUDITLOG_LOGGING_ENABLED_ATTRIBUTE "nsslapd-auditlog-logging-enabled" #define CONFIG_AUDITLOG_LOGGING_HIDE_UNHASHED_PW "nsslapd-auditlog-logging-hide-unhashed-pw" +#define CONFIG_UNHASHED_PW_SWITCH_ATTRIBUTE "nsslapd-unhashed-pw-switch" #define CONFIG_ROOTDN_ATTRIBUTE "nsslapd-rootdn" #define CONFIG_ROOTPW_ATTRIBUTE "nsslapd-rootpw" #define CONFIG_ROOTPWSTORAGESCHEME_ATTRIBUTE "nsslapd-rootpwstoragescheme" @@ -2277,7 +2277,7 @@ typedef struct _slapdFrontendConfig { PRInt64 disk_threshold; int disk_grace_period; int disk_logging_critical; - + slapi_onoff_t unhashed_pw_switch; /* switch to on/off/nolog unhashed pw */ int ignore_time_skew; #if defined(LINUX) int malloc_mxfast; /* mallopt M_MXFAST */ diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 24d43e8..b170271 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -7061,6 +7061,14 @@ char **slapi_str2charray_ext( char *str, char *brkstr, int allow_dups ); #endif #endif +/* Used to make unhashed passwords available to plugins. */ +#define PSEUDO_ATTR_UNHASHEDUSERPASSWORD "unhashed#user#password" + +/* Unhashed password */ +#define SLAPD_UNHASHED_PW_OFF 0 +#define SLAPD_UNHASHED_PW_ON 1 +#define SLAPD_UNHASHED_PW_NOLOG 2 + /** * Set given "type: value" to the plugin default config entry * (cn=plugin default config,cn=config) unless the same "type: value" pair diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h index 18f0e94..9a4e339 100644 --- a/ldap/servers/slapd/slapi-private.h +++ b/ldap/servers/slapd/slapi-private.h @@ -816,6 +816,7 @@ int pw_rever_decode(char *cipher, char **plain, const char * attr_name); /* config routines */ int slapi_config_get_readonly(); +int slapi_config_get_unhashed_pw_switch(); /* * charray.c diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c index 7a753f8..8c0b7ee 100644 --- a/ldap/servers/slapd/util.c +++ b/ldap/servers/slapd/util.c @@ -325,13 +325,15 @@ int slapi_mods2entry (Slapi_Entry **e, const char *idn, LDAPMod **iattrs) return rc; } -int slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs) +int +slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs) { Slapi_Mods smods; Slapi_Attr *attr; Slapi_Value **va; char *type; int rc; + int unhashed_pw_on = (SLAPD_UNHASHED_PW_ON == config_get_unhashed_pw_switch()); PR_ASSERT (e && attrs); @@ -343,8 +345,11 @@ int slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs) while (rc == 0) { if ( NULL != ( va = attr_get_present_values( attr ))) { - slapi_attr_get_type(attr, &type); - slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va ); + slapi_attr_get_type(attr, &type); + if (unhashed_pw_on || strcasecmp(type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) { + /* SLAPD_UNHASHED_PW_ON or type is not unhashed pw */ + slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va ); + } } rc = slapi_entry_next_attr(e, attr, &attr); }
1
0
0
0
Branch '389-ds-base-1.3.3' - ldap/servers
by Ludwig Krispenz
01 Apr '15
01 Apr '15
ldap/servers/plugins/replication/repl5_agmtlist.c | 54 +++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) New commits: commit 891d4cece7072e545ec6d651c06e4f923b4294cc Author: Ludwig Krispenz <lkrispen(a)redhat.com> Date: Tue Mar 31 10:15:08 2015 +0200 Ticket 48136 -v2v2 accept auxilliary objectclasse in replication agreements Bug Description: the check for allowed modifications of an replication agreement handles only the standard agreement attributes, so extensions by adding another objectclass fails. Fix Description: Extend the check and allow additions of auxiliary objectclasses and if an extra obejectclass is present allow adding of other attributes.
https://fedorahosted.org/389/ticket/48136
Reviewed by: MarkR, thanks diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c index 5b419c6..21823a4 100644 --- a/ldap/servers/plugins/replication/repl5_agmtlist.c +++ b/ldap/servers/plugins/replication/repl5_agmtlist.c @@ -177,6 +177,57 @@ add_new_agreement(Slapi_Entry *e) return rc; } +int +id_extended_agreement(Repl_Agmt *agmt, LDAPMod** mods, Slapi_Entry *e) +{ + Slapi_Attr *sattr = NULL; + char *val = NULL; + int return_value = 0; + int i; + + slapi_entry_attr_find(e, "objectclass", &sattr); + if (sattr) { + Slapi_Value *sval = NULL; + const char *val = NULL; + for (i = slapi_attr_first_value(sattr, &sval); + i >= 0; i = slapi_attr_next_value(sattr, i, &sval)) { + val = slapi_value_get_string(sval); + if ((0 == strcasecmp(val,"top")) || + (0 == strcasecmp(val,"nsds5replicationAgreement"))) { + continue; + } else { + /* the entry has an additional objectclass, accept mods */ + return 1; + } + } + } + /* This modification could remove an additional objectclass. + * In the entry we check this mod has already been applied, + * so check list of mods + */ + for (i = 0; NULL != mods && NULL != mods[i]; i++) { + if (strcasecmp(mods[i]->mod_type, "objectclass")) continue; + if (mods[i]->mod_bvalues){ + int j; + for (j = 0; mods[i]->mod_bvalues[j]; j++){ + slapi_ch_free_string(&val); + val = slapi_berval_get_string_copy (mods[i]->mod_bvalues[j]); + if ((0 == strcasecmp(val,"top")) || + (0 == strcasecmp(val,"nsds5replicationAgreement"))) { + continue; + } else { + /* an additional objectclass was modified */ + return_value = 1; + break; + } + } + } + break; + } + slapi_ch_free_string(&val); + return return_value; +} + static int agmtlist_add_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg) @@ -583,7 +634,8 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry (void) agmt_set_WaitForAsyncResults(agmt, e); } } - else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e)) + else if ((0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e)) && + (0 == id_extended_agreement(agmt, mods, e))) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "modification of %s attribute is not allowed\n", mods[i]->mod_type);
1
0
0
0
ldap/servers
by Ludwig Krispenz
01 Apr '15
01 Apr '15
ldap/servers/plugins/replication/repl5_agmtlist.c | 54 +++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) New commits: commit fd816432a280ccfcc5d733a02daa486ba40fd27b Author: Ludwig Krispenz <lkrispen(a)redhat.com> Date: Tue Mar 31 10:15:08 2015 +0200 Ticket 48136 -v2v2 accept auxilliary objectclasse in replication agreements Bug Description: the check for allowed modifications of an replication agreement handles only the standard agreement attributes, so extensions by adding another objectclass fails. Fix Description: Extend the check and allow additions of auxiliary objectclasses and if an extra obejectclass is present allow adding of other attributes.
https://fedorahosted.org/389/ticket/48136
Reviewed by: MarkR, thanks diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c index 5b419c6..21823a4 100644 --- a/ldap/servers/plugins/replication/repl5_agmtlist.c +++ b/ldap/servers/plugins/replication/repl5_agmtlist.c @@ -177,6 +177,57 @@ add_new_agreement(Slapi_Entry *e) return rc; } +int +id_extended_agreement(Repl_Agmt *agmt, LDAPMod** mods, Slapi_Entry *e) +{ + Slapi_Attr *sattr = NULL; + char *val = NULL; + int return_value = 0; + int i; + + slapi_entry_attr_find(e, "objectclass", &sattr); + if (sattr) { + Slapi_Value *sval = NULL; + const char *val = NULL; + for (i = slapi_attr_first_value(sattr, &sval); + i >= 0; i = slapi_attr_next_value(sattr, i, &sval)) { + val = slapi_value_get_string(sval); + if ((0 == strcasecmp(val,"top")) || + (0 == strcasecmp(val,"nsds5replicationAgreement"))) { + continue; + } else { + /* the entry has an additional objectclass, accept mods */ + return 1; + } + } + } + /* This modification could remove an additional objectclass. + * In the entry we check this mod has already been applied, + * so check list of mods + */ + for (i = 0; NULL != mods && NULL != mods[i]; i++) { + if (strcasecmp(mods[i]->mod_type, "objectclass")) continue; + if (mods[i]->mod_bvalues){ + int j; + for (j = 0; mods[i]->mod_bvalues[j]; j++){ + slapi_ch_free_string(&val); + val = slapi_berval_get_string_copy (mods[i]->mod_bvalues[j]); + if ((0 == strcasecmp(val,"top")) || + (0 == strcasecmp(val,"nsds5replicationAgreement"))) { + continue; + } else { + /* an additional objectclass was modified */ + return_value = 1; + break; + } + } + } + break; + } + slapi_ch_free_string(&val); + return return_value; +} + static int agmtlist_add_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg) @@ -583,7 +634,8 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry (void) agmt_set_WaitForAsyncResults(agmt, e); } } - else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e)) + else if ((0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e)) && + (0 == id_extended_agreement(agmt, mods, e))) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "modification of %s attribute is not allowed\n", mods[i]->mod_type);
1
0
0
0
← Newer
1
2
3
4
5
Older →
Jump to page:
1
2
3
4
5
Results per page:
10
25
50
100
200