ldap/servers
by Mark Reynolds
ldap/servers/plugins/referint/referint.c | 32 ++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
New commits:
commit c5cc125915023d03caa3548b8d55c5b8b8ce59aa
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Nov 24 12:39:52 2014 -0500
Ticket 47810 - RI plugin does not return result code if update fails
Bug Description: If using backend txns the initial delete operation should fail
if we fail to update the integrity.
Fix Description: If using backend txns, stop and return an error if we fail to
update the membership integrity.
https://fedorahosted.org/389/ticket/47810
Reviewed by: rmeggins(Thanks!)
diff --git a/ldap/servers/plugins/referint/referint.c b/ldap/servers/plugins/referint/referint.c
index 9ffd038..66bb95e 100644
--- a/ldap/servers/plugins/referint/referint.c
+++ b/ldap/servers/plugins/referint/referint.c
@@ -1250,7 +1250,18 @@ update_integrity(Slapi_DN *origSDN,
slapi_sdn_get_dn(newsuperior),
mod_pb);
}
- /* Should we stop if one modify returns an error? */
+ if (rc) {
+ if (use_txn) {
+ /*
+ * We're using backend transactions,
+ * so we need to stop on failure.
+ */
+ rc = SLAPI_PLUGIN_FAILURE;
+ goto free_and_return;
+ } else {
+ rc = SLAPI_PLUGIN_SUCCESS;
+ }
+ }
}
}
}
@@ -1267,17 +1278,16 @@ update_integrity(Slapi_DN *origSDN,
}
slapi_free_search_results_internal(search_result_pb);
}
- if (plugin_ContainerScope) {
- /* at the moment only a single scope is supported
- * so the loop ends after the first iteration
- */
- sdn = NULL;
- } else {
- sdn = slapi_get_next_suffix( &node, 0 );
- }
+ if (plugin_ContainerScope) {
+ /* at the moment only a single scope is supported
+ * so the loop ends after the first iteration
+ */
+ sdn = NULL;
+ } else {
+ sdn = slapi_get_next_suffix( &node, 0 );
+ }
}
- /* if got here, then everything good rc = 0 */
- rc = SLAPI_PLUGIN_SUCCESS;
+
free_and_return:
/* free filter and search_results_pb */
9 years, 5 months
ldap/servers
by Mark Reynolds
ldap/servers/plugins/memberof/memberof.c | 6 +++-
ldap/servers/plugins/memberof/memberof.h | 2 +
ldap/servers/plugins/memberof/memberof_config.c | 31 ++++++++++++++++++++++--
3 files changed, 35 insertions(+), 4 deletions(-)
New commits:
commit b01cf4dbf9c8995081da81e39f8766d2df9e0c2d
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Nov 24 16:58:57 2014 -0500
Ticket 47963 - RFE - memberOf - add option to skip nested
group lookups during delete operations
Bug Description: The recursive nested group lookups performed during a group delete
operation can take a very long time to complete if there are very
large static groups(groups with with over 10K members).
If there are no nested groups, then it would be nice to have an option
to skip the nested group check, which would significantly improve
delete performance.
Fix Description: Added a new memberOf plugin configuration attribute:
memberOfSkipNested: on|off
https://fedorahosted.org/389/ticket/47963
Reviewed by: rmeggins(Thanks!)
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index b1c51a1..118d232 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -2816,8 +2816,10 @@ int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
memberof_del_dn_data del_data = {0, config->memberof_attr};
Slapi_ValueSet *groups = 0;
- /* get a list of all of the groups this user belongs to */
- groups = memberof_get_groups(config, sdn);
+ if(!config->skip_nested){
+ /* get a list of all of the groups this user belongs to */
+ groups = memberof_get_groups(config, sdn);
+ }
/* If we found some groups, replace the existing memberOf attribute
* with the found values. */
diff --git a/ldap/servers/plugins/memberof/memberof.h b/ldap/servers/plugins/memberof/memberof.h
index 6d56081..93f031b 100644
--- a/ldap/servers/plugins/memberof/memberof.h
+++ b/ldap/servers/plugins/memberof/memberof.h
@@ -69,6 +69,7 @@
#define MEMBEROF_BACKEND_ATTR "memberOfAllBackends"
#define MEMBEROF_ENTRY_SCOPE_ATTR "memberOfEntryScope"
#define MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE "memberOfEntryScopeExcludeSubtree"
+#define MEMBEROF_SKIP_NESTED_ATTR "memberOfSkipNested"
#define DN_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.12"
#define NAME_OPT_UID_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.34"
@@ -84,6 +85,7 @@ typedef struct memberofconfig {
Slapi_DN *entryScopeExcludeSubtree;
Slapi_Filter *group_filter;
Slapi_Attr **group_slapiattrs;
+ int skip_nested;
} MemberOfConfig;
diff --git a/ldap/servers/plugins/memberof/memberof_config.c b/ldap/servers/plugins/memberof/memberof_config.c
index df8ddcb..8efbe2f 100644
--- a/ldap/servers/plugins/memberof/memberof_config.c
+++ b/ldap/servers/plugins/memberof/memberof_config.c
@@ -193,6 +193,7 @@ memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
Slapi_DN *config_sdn = NULL;
char *syntaxoid = NULL;
char *config_dn = NULL;
+ char *skip_nested = NULL;
int not_dn_syntax = 0;
*returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */
@@ -272,6 +273,16 @@ memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
goto done;
}
+ if ((skip_nested = slapi_entry_attr_get_charptr(e, MEMBEROF_SKIP_NESTED_ATTR))){
+ if(strcasecmp(skip_nested, "on") != 0 && strcasecmp(skip_nested, "off") != 0){
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "The %s configuration attribute must be set to "
+ "\"on\" or \"off\". (illegal value: %s)",
+ MEMBEROF_SKIP_NESTED_ATTR, skip_nested);
+ goto done;
+ }
+ }
+
if ((config_dn = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA))){
/* Now check the shared config attribute, validate it now */
@@ -305,6 +316,7 @@ memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
done:
slapi_sdn_free(&config_sdn);
slapi_ch_free_string(&config_dn);
+ slapi_ch_free_string(&skip_nested);
if (*returncode != LDAP_SUCCESS)
{
@@ -336,8 +348,9 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
int groupattr_name_len = 0;
char *allBackends = NULL;
char *entryScope = NULL;
- char *entryScopeExcludeSubtree = NULL;
+ char *entryScopeExcludeSubtree = NULL;
char *sharedcfg = NULL;
+ char *skip_nested = NULL;
*returncode = LDAP_SUCCESS;
@@ -388,7 +401,8 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
allBackends = slapi_entry_attr_get_charptr(e, MEMBEROF_BACKEND_ATTR);
entryScope = slapi_entry_attr_get_charptr(e, MEMBEROF_ENTRY_SCOPE_ATTR);
- entryScopeExcludeSubtree = slapi_entry_attr_get_charptr(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE);
+ entryScopeExcludeSubtree = slapi_entry_attr_get_charptr(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE);
+ skip_nested = slapi_entry_attr_get_charptr(e, MEMBEROF_SKIP_NESTED_ATTR);
/* We want to be sure we don't change the config in the middle of
* a memberOf operation, so we obtain an exclusive lock here */
@@ -487,6 +501,14 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
memberof_attr = NULL; /* config now owns memory */
}
+ if (skip_nested){
+ if(strcasecmp(skip_nested,"on") == 0){
+ theConfig.skip_nested = 1;
+ } else {
+ theConfig.skip_nested = 0;
+ }
+ }
+
if (allBackends)
{
if(strcasecmp(allBackends,"on")==0){
@@ -556,6 +578,7 @@ done:
slapi_ch_array_free(groupattrs);
slapi_ch_free_string(&memberof_attr);
slapi_ch_free_string(&allBackends);
+ slapi_ch_free_string(&skip_nested);
if (*returncode != LDAP_SUCCESS)
{
@@ -628,6 +651,10 @@ memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src)
dest->memberof_attr = slapi_ch_strdup(src->memberof_attr);
}
+ if(src->skip_nested){
+ dest->skip_nested = src->skip_nested;
+ }
+
if(src->allBackends)
{
dest->allBackends = src->allBackends;
9 years, 5 months
Branch '389-ds-base-1.2.11' - dirsrvtests/tickets ldap/servers
by Mark Reynolds
dirsrvtests/tickets/ticket47950_test.py | 273 ++++++++++++++++
ldap/servers/plugins/acl/acl.c | 6
ldap/servers/plugins/replication/cl5_config.c | 9
ldap/servers/plugins/replication/repl5_agmtlist.c | 3
ldap/servers/plugins/replication/repl5_replica_config.c | 3
ldap/servers/slapd/add.c | 4
ldap/servers/slapd/back-ldbm/ldbm_config.c | 3
ldap/servers/slapd/configdse.c | 5
ldap/servers/slapd/opshared.c | 17
ldap/servers/slapd/result.c | 2
ldap/servers/slapd/slapi-plugin.h | 2
ldap/servers/slapd/task.c | 4
ldap/servers/slapd/tools/mmldif.c | 12
13 files changed, 313 insertions(+), 30 deletions(-)
New commits:
commit 0c47dfb627ab4fc5f7d8d067028cc74c90f61dad
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Nov 18 09:24:21 2014 -0500
Ticket 47950 - Bind DN tracking unable to write to internalModifiersName without special permissions
Bug Description: When a non-rootDN entry makes an update when plugin bind dn tracking
is enabled, it is incorrectly rejected with an error 50.
Fix Description: Create a function to check if an attribute is one of last mod attributes,
including the internalModfieresname/internalModifytimestamp. Use this
new function wherever we are checking for last mod attributes.
https://fedorahosted.org/389/ticket/47950
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit c973e7150cf1e7fb3f61a76cf1baf3c0fa91f756)
Conflicts:
ldap/servers/plugins/acl/acl.c
ldap/servers/slapd/configdse.c
diff --git a/dirsrvtests/tickets/ticket47950_test.py b/dirsrvtests/tickets/ticket47950_test.py
new file mode 100644
index 0000000..976f964
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47950_test.py
@@ -0,0 +1,273 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from constants import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+USER1_DN = "uid=user1,%s" % DEFAULT_SUFFIX
+USER2_DN = "uid=user2,%s" % DEFAULT_SUFFIX
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to standalone topology for the 'module'.
+ At the beginning, It may exists a standalone instance.
+ It may also exists a backup for the standalone instance.
+
+ Principle:
+ If standalone instance exists:
+ restart it
+ If backup of standalone exists:
+ create/rebind to standalone
+
+ restore standalone instance from backup
+ else:
+ Cleanup everything
+ remove instance
+ remove backup
+ Create instance
+ Create backup
+ '''
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ standalone = DirSrv(verbose=False)
+
+ # Args for the standalone instance
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+
+ # Get the status of the backups
+ backup_standalone = standalone.checkBackupFS()
+
+ # Get the status of the instance and restart it if it exists
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ # assuming the instance is already stopped, just wait 5 sec max
+ standalone.stop(timeout=5)
+ standalone.start(timeout=10)
+
+ if backup_standalone:
+ # The backup exist, assuming it is correct
+ # we just re-init the instance with it
+ if not instance_standalone:
+ standalone.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # restore standalone instance from backup
+ standalone.stop(timeout=10)
+ standalone.restoreFS(backup_standalone)
+ standalone.start(timeout=10)
+
+ else:
+ # We should be here only in two conditions
+ # - This is the first time a test involve standalone instance
+ # - Something weird happened (instance/backup destroyed)
+ # so we discard everything and recreate all
+
+ # Remove the backup. So even if we have a specific backup file
+ # (e.g backup_standalone) we clear backup that an instance may have created
+ if backup_standalone:
+ standalone.clearBackupFS()
+
+ # Remove the instance
+ if instance_standalone:
+ standalone.delete()
+
+ # Create the instance
+ standalone.create()
+
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # Time to create the backups
+ standalone.stop(timeout=10)
+ standalone.backupfile = standalone.backupFS()
+ standalone.start(timeout=10)
+
+ # clear the tmp directory
+ standalone.clearTmpDir(__file__)
+
+ #
+ # Here we have standalone instance up and running
+ # Either coming from a backup recovery
+ # or from a fresh (re)init
+ # Time to return the topology
+ return TopologyStandalone(standalone)
+
+
+def test_ticket47950(topology):
+ """
+ Testing nsslapd-plugin-binddn-tracking does not cause issues around
+ access control and reconfiguring replication/repl agmt.
+ """
+
+ log.info('Testing Ticket 47950 - Testing nsslapd-plugin-binddn-tracking')
+
+ #
+ # Turn on bind dn tracking
+ #
+ try:
+ topology.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE, 'nsslapd-plugin-binddn-tracking', 'on')])
+ log.info('nsslapd-plugin-binddn-tracking enabled.')
+ except ldap.LDAPError, e:
+ log.error('Failed to enable bind dn tracking: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add two users
+ #
+ try:
+ topology.standalone.add_s(Entry((USER1_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'userpassword': "password",
+ 'sn': "1",
+ 'cn': "user 1"})))
+ log.info('Added test user %s' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add %s: %s' % (USER1_DN, e.message['desc']))
+ assert False
+
+ try:
+ topology.standalone.add_s(Entry((USER2_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'sn': "2",
+ 'cn': "user 2"})))
+ log.info('Added test user %s' % USER2_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add user1: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add an aci
+ #
+ try:
+ acival = '(targetattr ="cn")(version 3.0;acl "Test bind dn tracking"' + \
+ ';allow (all) (userdn = "ldap:///%s");)' % USER1_DN
+
+ topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci', acival)])
+ log.info('Added aci')
+ except ldap.LDAPError, e:
+ log.error('Failed to add aci: ' + e.message['desc'])
+ assert False
+
+ #
+ # Make modification as user
+ #
+ try:
+ topology.standalone.simple_bind_s(USER1_DN, "password")
+ log.info('Bind as user %s successful' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as user1: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.modify_s(USER2_DN, [(ldap.MOD_REPLACE, 'cn', 'new value')])
+ log.info('%s successfully modified user %s' % (USER1_DN, USER2_DN))
+ except ldap.LDAPError, e:
+ log.error('Failed to update user2: ' + e.message['desc'])
+ assert False
+
+ #
+ # Setup replica and create a repl agmt
+ #
+ try:
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ log.info('Bind as %s successful' % DN_DM)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as rootDN: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.replica.enableReplication(suffix=DEFAULT_SUFFIX, role=REPLICAROLE_MASTER,
+ replicaId=REPLICAID_MASTER)
+ log.info('Successfully enabled replication.')
+ except ValueError:
+ log.error('Failed to enable replication')
+ assert False
+
+ properties = {RA_NAME: r'test plugin internal bind dn',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+
+ try:
+ repl_agreement = topology.standalone.agreement.create(suffix=DEFAULT_SUFFIX, host="127.0.0.1",
+ port="7777", properties=properties)
+ log.info('Successfully created replication agreement')
+ except InvalidArgumentError, e:
+ log.error('Failed to create replication agreement: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify replica
+ #
+ try:
+ properties = {REPLICA_ID: "7"}
+ topology.standalone.replica.setProperties(DEFAULT_SUFFIX, None, None, properties)
+ log.info('Successfully modified replica')
+ except ldap.LDAPError, e:
+ log.error('Failed to update replica config: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify repl agmt
+ #
+ try:
+ properties = {RA_CONSUMER_PORT: "8888"}
+ topology.standalone.agreement.setProperties(None, repl_agreement, None, properties)
+ log.info('Successfully modified replication agreement')
+ except ValueError:
+ log.error('Failed to update replica agreement: ' + repl_agreement)
+ assert False
+
+ # We passed
+ log.info("Test Passed.")
+
+
+def test_ticket47953_final(topology):
+ topology.standalone.stop(timeout=10)
+
+
+def run_isolated():
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '@pytest.fixture' line before 'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ topo = topology(True)
+ test_ticket47950(topo)
+
+if __name__ == '__main__':
+ run_isolated()
\ No newline at end of file
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
index 598601b..ad929c5 100644
--- a/ldap/servers/plugins/acl/acl.c
+++ b/ldap/servers/plugins/acl/acl.c
@@ -1383,9 +1383,9 @@ acl_check_mods(
if (be != NULL)
slapi_pblock_get ( pb, SLAPI_BE_LASTMOD, &lastmod );
}
- if (lastmod &&
- (strcmp (mod->mod_type, "modifiersname")== 0 ||
- strcmp (mod->mod_type, "modifytimestamp")== 0)) {
+
+ if (lastmod && slapi_attr_is_last_mod(mod->mod_type)) {
+ /* skip pseudo attr(s) */
continue;
}
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index 900cfc0..f99fde9 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -355,15 +355,10 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
config_attr = (char *) mods[i]->mod_type;
config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
-#define ATTR_MODIFIERSNAME "modifiersname"
-#define ATTR_MODIFYTIMESTAMP "modifytimestamp"
-
- if ( strcasecmp ( config_attr, ATTR_MODIFIERSNAME ) == 0 ) {
- continue;
- }
- if ( strcasecmp ( config_attr, ATTR_MODIFYTIMESTAMP ) == 0 ) {
+ if ( slapi_attr_is_last_mod(config_attr)){
continue;
}
+
/* replace existing value */
if ( strcasecmp (config_attr, CONFIG_CHANGELOG_DIR_ATTRIBUTE ) == 0 )
{
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 70f71a8..d37704d 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -488,8 +488,7 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
repl5_set_debug_timeout(val);
slapi_ch_free_string(&val);
}
- else if (strcasecmp (mods[i]->mod_type, "modifytimestamp") == 0 ||
- strcasecmp (mods[i]->mod_type, "modifiersname") == 0 ||
+ else if (slapi_attr_is_last_mod(mods[i]->mod_type) ||
strcasecmp (mods[i]->mod_type, "description") == 0)
{
/* ignore modifier's name and timestamp attributes and the description. */
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index b8dd605..94ab71b 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -484,8 +484,7 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
}
}
/* ignore modifiers attributes added by the server */
- else if (strcasecmp (config_attr, "modifytimestamp") == 0 ||
- strcasecmp (config_attr, "modifiersname") == 0)
+ else if (slapi_attr_is_last_mod(config_attr))
{
*returncode = LDAP_SUCCESS;
}
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 5b3b5ee..e03bc6c 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -865,8 +865,8 @@ static int check_rdn_for_created_attrs(Slapi_Entry *e)
int i, rc = 0;
Slapi_RDN *rdn = NULL;
char *value = NULL;
- char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "createtimestamp",
- "creatorsname", "modifiersname", 0};
+ char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "modifiersname", "internalmodifytimestamp",
+ "internalmodifiersname", "createtimestamp", "creatorsname", 0};
if ((rdn = slapi_rdn_new())) {
slapi_rdn_init_dn(rdn, slapi_entry_get_dn_const(e));
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
index b35004a..11aa42d 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
@@ -1731,10 +1731,9 @@ int ldbm_config_ignored_attr(char *attr_name)
if (!strcasecmp("objectclass", attr_name) ||
!strcasecmp("cn", attr_name) ||
!strcasecmp("creatorsname", attr_name) ||
- !strcasecmp("modifiersname", attr_name) ||
!strcasecmp("createtimestamp", attr_name) ||
!strcasecmp(LDBM_NUMSUBORDINATES_STR, attr_name) ||
- !strcasecmp("modifytimestamp", attr_name)) {
+ slapi_attr_is_last_mod(attr_name)){
return 1;
} else {
return 0;
diff --git a/ldap/servers/slapd/configdse.c b/ldap/servers/slapd/configdse.c
index 9265b98..fff7353 100644
--- a/ldap/servers/slapd/configdse.c
+++ b/ldap/servers/slapd/configdse.c
@@ -117,7 +117,10 @@ ignore_attr_type(const char *attr_type)
(strcasecmp (attr_type, "numsubordinates") == 0) ||
(strcasecmp (attr_type, "internalModifiersname") == 0) ||
(strcasecmp (attr_type, "modifytimestamp") == 0) ||
- (strcasecmp (attr_type, "modifiersname") == 0)) {
+ (strcasecmp (attr_type, "modifiersname") == 0) ||
+ (strcasecmp (attr_type, "internalCreatorsname") == 0) ||
+ slapi_attr_is_last_mod((char *)attr_type))
+ {
return 1;
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 65fcea6..7a0b544 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -224,6 +224,23 @@ modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
}
/*
+ * If the attribute is one of the last mod attributes return 1,
+ * otherwise return 0;
+ */
+int
+slapi_attr_is_last_mod(char *attr)
+{
+ if(strcasecmp (attr, "modifytimestamp") == 0 ||
+ strcasecmp (attr, "modifiersname") == 0 ||
+ strcasecmp (attr, "internalmodifytimestamp") == 0 ||
+ strcasecmp (attr, "internalmodifiersname") == 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*
* Returns: 0 - if the operation is successful
* < 0 - if operation fails.
* Note that an operation is considered "failed" if a result is sent
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 5463592..993dc9e 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -805,6 +805,8 @@ encode_attr(
#define LASTMODATTR( x ) (strcasecmp( x, "modifytimestamp" ) == 0 \
|| strcasecmp( x, "modifiersname" ) == 0 \
+ || strcasecmp( x, "internalmodifytimestamp" ) == 0 \
+ || strcasecmp( x, "internalmodifiersname" ) == 0 \
|| strcasecmp( x, "createtimestamp" ) == 0 \
|| strcasecmp( x, "creatorsname" ) == 0)
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 6da4f52..24d43e8 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -4982,6 +4982,8 @@ int slapi_filter_compare(struct slapi_filter *f1, struct slapi_filter *f2);
Slapi_Filter *slapi_filter_dup(Slapi_Filter *f);
int slapi_filter_changetype(Slapi_Filter *f, const char *newtype);
+int slapi_attr_is_last_mod(char *attr);
+
/**
* Normalize in-place the given filter. Normalizes the attribute types always.
* If norm_values is true, will also normalize the values.
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index 2fe1de7..0488640 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -779,8 +779,8 @@ static int task_modify(Slapi_PBlock *pb, Slapi_Entry *e,
* stuck in by the server */
if ((strcasecmp(mods[i]->mod_type, "ttl") != 0) &&
(strcasecmp(mods[i]->mod_type, "nsTaskCancel") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifiersName") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifyTimestamp") != 0)) {
+ !slapi_attr_is_last_mod(mods[i]->mod_type))
+ {
/* you aren't allowed to change this! */
*returncode = LDAP_UNWILLING_TO_PERFORM;
return SLAPI_DSE_CALLBACK_ERROR;
diff --git a/ldap/servers/slapd/tools/mmldif.c b/ldap/servers/slapd/tools/mmldif.c
index 4213e65..ebadf13 100644
--- a/ldap/servers/slapd/tools/mmldif.c
+++ b/ldap/servers/slapd/tools/mmldif.c
@@ -1017,9 +1017,7 @@ addnew(FILE * edf3, const char *changetype, record_t * first)
for (attnum = 1, att = &first->data;
attnum <= first->nattrs;
attnum++, att = attribnext(att)) {
- if (!stricmp(attribname(att), "modifytimestamp"))
- continue;
- if (!stricmp(attribname(att), "modifiersname"))
+ if (slapi_attr_is_last_mod(attribname(att)))
continue;
if (!putvalue(edf3, NULL, attribname(att), att->namelen,
attribvalue(att), att->valuelen)) {
@@ -1074,15 +1072,11 @@ addmodified(FILE * edf3, attrib1_t * attrib, record_t * first)
*/
while (a != NULL || num_b <= tot_b) {
/* ignore operational attrs */
- if (num_b <= tot_b &&
- (stricmp(attribname(b), "modifytimestamp") == 0 ||
- stricmp(attribname(b), "modifiersname") == 0)) {
+ if ( num_b <= tot_b && slapi_attr_is_last_mod(attribname(b)) ){
b = attribnext(b); num_b++;
continue;
}
- if (a != NULL &&
- (stricmp(a->name, "modifytimestamp") == 0 ||
- stricmp(a->name, "modifiersname") == 0)) {
+ if (a != NULL && slapi_attr_is_last_mod(a->name)) {
a = a->next;
continue;
}
9 years, 5 months
Branch '389-ds-base-1.3.1' - dirsrvtests/tickets ldap/servers
by Mark Reynolds
dirsrvtests/tickets/ticket47950_test.py | 273 ++++++++++++++++
ldap/servers/plugins/acl/acl.c | 4
ldap/servers/plugins/replication/cl5_config.c | 9
ldap/servers/plugins/replication/repl5_agmtlist.c | 3
ldap/servers/plugins/replication/repl5_replica_config.c | 3
ldap/servers/slapd/add.c | 4
ldap/servers/slapd/back-ldbm/ldbm_config.c | 3
ldap/servers/slapd/configdse.c | 5
ldap/servers/slapd/opshared.c | 17
ldap/servers/slapd/result.c | 2
ldap/servers/slapd/slapi-plugin.h | 2
ldap/servers/slapd/task.c | 4
ldap/servers/slapd/tools/mmldif.c | 12
13 files changed, 309 insertions(+), 32 deletions(-)
New commits:
commit cd0627116c602036eabab8387d0ed65e798a85f9
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Nov 18 09:24:21 2014 -0500
Ticket 47950 - Bind DN tracking unable to write to internalModifiersName without special permissions
Bug Description: When a non-rootDN entry makes an update when plugin bind dn tracking
is enabled, it is incorrectly rejected with an error 50.
Fix Description: Create a function to check if an attribute is one of last mod attributes,
including the internalModfieresname/internalModifytimestamp. Use this
new function wherever we are checking for last mod attributes.
https://fedorahosted.org/389/ticket/47950
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit c973e7150cf1e7fb3f61a76cf1baf3c0fa91f756)
diff --git a/dirsrvtests/tickets/ticket47950_test.py b/dirsrvtests/tickets/ticket47950_test.py
new file mode 100644
index 0000000..976f964
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47950_test.py
@@ -0,0 +1,273 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from constants import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+USER1_DN = "uid=user1,%s" % DEFAULT_SUFFIX
+USER2_DN = "uid=user2,%s" % DEFAULT_SUFFIX
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to standalone topology for the 'module'.
+ At the beginning, It may exists a standalone instance.
+ It may also exists a backup for the standalone instance.
+
+ Principle:
+ If standalone instance exists:
+ restart it
+ If backup of standalone exists:
+ create/rebind to standalone
+
+ restore standalone instance from backup
+ else:
+ Cleanup everything
+ remove instance
+ remove backup
+ Create instance
+ Create backup
+ '''
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ standalone = DirSrv(verbose=False)
+
+ # Args for the standalone instance
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+
+ # Get the status of the backups
+ backup_standalone = standalone.checkBackupFS()
+
+ # Get the status of the instance and restart it if it exists
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ # assuming the instance is already stopped, just wait 5 sec max
+ standalone.stop(timeout=5)
+ standalone.start(timeout=10)
+
+ if backup_standalone:
+ # The backup exist, assuming it is correct
+ # we just re-init the instance with it
+ if not instance_standalone:
+ standalone.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # restore standalone instance from backup
+ standalone.stop(timeout=10)
+ standalone.restoreFS(backup_standalone)
+ standalone.start(timeout=10)
+
+ else:
+ # We should be here only in two conditions
+ # - This is the first time a test involve standalone instance
+ # - Something weird happened (instance/backup destroyed)
+ # so we discard everything and recreate all
+
+ # Remove the backup. So even if we have a specific backup file
+ # (e.g backup_standalone) we clear backup that an instance may have created
+ if backup_standalone:
+ standalone.clearBackupFS()
+
+ # Remove the instance
+ if instance_standalone:
+ standalone.delete()
+
+ # Create the instance
+ standalone.create()
+
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # Time to create the backups
+ standalone.stop(timeout=10)
+ standalone.backupfile = standalone.backupFS()
+ standalone.start(timeout=10)
+
+ # clear the tmp directory
+ standalone.clearTmpDir(__file__)
+
+ #
+ # Here we have standalone instance up and running
+ # Either coming from a backup recovery
+ # or from a fresh (re)init
+ # Time to return the topology
+ return TopologyStandalone(standalone)
+
+
+def test_ticket47950(topology):
+ """
+ Testing nsslapd-plugin-binddn-tracking does not cause issues around
+ access control and reconfiguring replication/repl agmt.
+ """
+
+ log.info('Testing Ticket 47950 - Testing nsslapd-plugin-binddn-tracking')
+
+ #
+ # Turn on bind dn tracking
+ #
+ try:
+ topology.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE, 'nsslapd-plugin-binddn-tracking', 'on')])
+ log.info('nsslapd-plugin-binddn-tracking enabled.')
+ except ldap.LDAPError, e:
+ log.error('Failed to enable bind dn tracking: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add two users
+ #
+ try:
+ topology.standalone.add_s(Entry((USER1_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'userpassword': "password",
+ 'sn': "1",
+ 'cn': "user 1"})))
+ log.info('Added test user %s' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add %s: %s' % (USER1_DN, e.message['desc']))
+ assert False
+
+ try:
+ topology.standalone.add_s(Entry((USER2_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'sn': "2",
+ 'cn': "user 2"})))
+ log.info('Added test user %s' % USER2_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add user1: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add an aci
+ #
+ try:
+ acival = '(targetattr ="cn")(version 3.0;acl "Test bind dn tracking"' + \
+ ';allow (all) (userdn = "ldap:///%s");)' % USER1_DN
+
+ topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci', acival)])
+ log.info('Added aci')
+ except ldap.LDAPError, e:
+ log.error('Failed to add aci: ' + e.message['desc'])
+ assert False
+
+ #
+ # Make modification as user
+ #
+ try:
+ topology.standalone.simple_bind_s(USER1_DN, "password")
+ log.info('Bind as user %s successful' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as user1: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.modify_s(USER2_DN, [(ldap.MOD_REPLACE, 'cn', 'new value')])
+ log.info('%s successfully modified user %s' % (USER1_DN, USER2_DN))
+ except ldap.LDAPError, e:
+ log.error('Failed to update user2: ' + e.message['desc'])
+ assert False
+
+ #
+ # Setup replica and create a repl agmt
+ #
+ try:
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ log.info('Bind as %s successful' % DN_DM)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as rootDN: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.replica.enableReplication(suffix=DEFAULT_SUFFIX, role=REPLICAROLE_MASTER,
+ replicaId=REPLICAID_MASTER)
+ log.info('Successfully enabled replication.')
+ except ValueError:
+ log.error('Failed to enable replication')
+ assert False
+
+ properties = {RA_NAME: r'test plugin internal bind dn',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+
+ try:
+ repl_agreement = topology.standalone.agreement.create(suffix=DEFAULT_SUFFIX, host="127.0.0.1",
+ port="7777", properties=properties)
+ log.info('Successfully created replication agreement')
+ except InvalidArgumentError, e:
+ log.error('Failed to create replication agreement: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify replica
+ #
+ try:
+ properties = {REPLICA_ID: "7"}
+ topology.standalone.replica.setProperties(DEFAULT_SUFFIX, None, None, properties)
+ log.info('Successfully modified replica')
+ except ldap.LDAPError, e:
+ log.error('Failed to update replica config: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify repl agmt
+ #
+ try:
+ properties = {RA_CONSUMER_PORT: "8888"}
+ topology.standalone.agreement.setProperties(None, repl_agreement, None, properties)
+ log.info('Successfully modified replication agreement')
+ except ValueError:
+ log.error('Failed to update replica agreement: ' + repl_agreement)
+ assert False
+
+ # We passed
+ log.info("Test Passed.")
+
+
+def test_ticket47953_final(topology):
+ topology.standalone.stop(timeout=10)
+
+
+def run_isolated():
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '@pytest.fixture' line before 'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ topo = topology(True)
+ test_ticket47950(topo)
+
+if __name__ == '__main__':
+ run_isolated()
\ No newline at end of file
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
index ed78935..74f72ff 100644
--- a/ldap/servers/plugins/acl/acl.c
+++ b/ldap/servers/plugins/acl/acl.c
@@ -1387,9 +1387,7 @@ acl_check_mods(
if (be != NULL)
slapi_pblock_get ( pb, SLAPI_BE_LASTMOD, &lastmod );
}
- if (lastmod &&
- (strcmp (mod->mod_type, "modifiersname")== 0 ||
- strcmp (mod->mod_type, "modifytimestamp")== 0)) {
+ if (lastmod && slapi_attr_is_last_mod(mod->mod_type)) {
/* skip pseudo attr(s) */
continue;
}
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index 900cfc0..f99fde9 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -355,15 +355,10 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
config_attr = (char *) mods[i]->mod_type;
config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
-#define ATTR_MODIFIERSNAME "modifiersname"
-#define ATTR_MODIFYTIMESTAMP "modifytimestamp"
-
- if ( strcasecmp ( config_attr, ATTR_MODIFIERSNAME ) == 0 ) {
- continue;
- }
- if ( strcasecmp ( config_attr, ATTR_MODIFYTIMESTAMP ) == 0 ) {
+ if ( slapi_attr_is_last_mod(config_attr)){
continue;
}
+
/* replace existing value */
if ( strcasecmp (config_attr, CONFIG_CHANGELOG_DIR_ATTRIBUTE ) == 0 )
{
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 0edf28a..81d55c6 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -470,8 +470,7 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
repl5_set_debug_timeout(val);
slapi_ch_free_string(&val);
}
- else if (strcasecmp (mods[i]->mod_type, "modifytimestamp") == 0 ||
- strcasecmp (mods[i]->mod_type, "modifiersname") == 0 ||
+ else if (slapi_attr_is_last_mod(mods[i]->mod_type) ||
strcasecmp (mods[i]->mod_type, "description") == 0)
{
/* ignore modifier's name and timestamp attributes and the description. */
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 91f5c32..80bc193 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -511,8 +511,7 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
}
}
/* ignore modifiers attributes added by the server */
- else if (strcasecmp (config_attr, "modifytimestamp") == 0 ||
- strcasecmp (config_attr, "modifiersname") == 0)
+ else if (slapi_attr_is_last_mod(config_attr))
{
*returncode = LDAP_SUCCESS;
}
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 4559951..4fb6540 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -916,8 +916,8 @@ static int check_rdn_for_created_attrs(Slapi_Entry *e)
int i, rc = 0;
Slapi_RDN *rdn = NULL;
char *value = NULL;
- char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "createtimestamp",
- "creatorsname", "modifiersname", 0};
+ char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "modifiersname", "internalmodifytimestamp",
+ "internalmodifiersname", "createtimestamp", "creatorsname", 0};
if ((rdn = slapi_rdn_new())) {
slapi_rdn_init_dn(rdn, slapi_entry_get_dn_const(e));
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
index 08f3490..b5bf1bf 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
@@ -1731,10 +1731,9 @@ int ldbm_config_ignored_attr(char *attr_name)
if (!strcasecmp("objectclass", attr_name) ||
!strcasecmp("cn", attr_name) ||
!strcasecmp("creatorsname", attr_name) ||
- !strcasecmp("modifiersname", attr_name) ||
!strcasecmp("createtimestamp", attr_name) ||
!strcasecmp(LDBM_NUMSUBORDINATES_STR, attr_name) ||
- !strcasecmp("modifytimestamp", attr_name)) {
+ slapi_attr_is_last_mod(attr_name)){
return 1;
} else {
return 0;
diff --git a/ldap/servers/slapd/configdse.c b/ldap/servers/slapd/configdse.c
index 14e8a5e..c8e490a 100644
--- a/ldap/servers/slapd/configdse.c
+++ b/ldap/servers/slapd/configdse.c
@@ -116,10 +116,9 @@ ignore_attr_type(const char *attr_type)
(strcasecmp (attr_type, "aci") == 0) ||
(strcasecmp (attr_type, "objectclass") == 0) ||
(strcasecmp (attr_type, "numsubordinates") == 0) ||
- (strcasecmp (attr_type, "internalModifiersname") == 0) ||
(strcasecmp (attr_type, "internalCreatorsname") == 0) ||
- (strcasecmp (attr_type, "modifytimestamp") == 0) ||
- (strcasecmp (attr_type, "modifiersname") == 0)) {
+ slapi_attr_is_last_mod((char *)attr_type))
+ {
return 1;
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 3fb23fa..eb890b0 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -218,6 +218,23 @@ modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
}
/*
+ * If the attribute is one of the last mod attributes return 1,
+ * otherwise return 0;
+ */
+int
+slapi_attr_is_last_mod(char *attr)
+{
+ if(strcasecmp (attr, "modifytimestamp") == 0 ||
+ strcasecmp (attr, "modifiersname") == 0 ||
+ strcasecmp (attr, "internalmodifytimestamp") == 0 ||
+ strcasecmp (attr, "internalmodifiersname") == 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*
* Returns: 0 - if the operation is successful
* < 0 - if operation fails.
* Note that an operation is considered "failed" if a result is sent
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index bdbfd77..0fc3349 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -804,6 +804,8 @@ encode_attr(
#define LASTMODATTR( x ) (strcasecmp( x, "modifytimestamp" ) == 0 \
|| strcasecmp( x, "modifiersname" ) == 0 \
+ || strcasecmp( x, "internalmodifytimestamp" ) == 0 \
+ || strcasecmp( x, "internalmodifiersname" ) == 0 \
|| strcasecmp( x, "createtimestamp" ) == 0 \
|| strcasecmp( x, "creatorsname" ) == 0)
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index a93feda..12ec290 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5099,6 +5099,8 @@ int slapi_filter_compare(struct slapi_filter *f1, struct slapi_filter *f2);
Slapi_Filter *slapi_filter_dup(Slapi_Filter *f);
int slapi_filter_changetype(Slapi_Filter *f, const char *newtype);
+int slapi_attr_is_last_mod(char *attr);
+
/**
* Normalize in-place the given filter. Normalizes the attribute types always.
* If norm_values is true, will also normalize the values.
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index 2fe1de7..0488640 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -779,8 +779,8 @@ static int task_modify(Slapi_PBlock *pb, Slapi_Entry *e,
* stuck in by the server */
if ((strcasecmp(mods[i]->mod_type, "ttl") != 0) &&
(strcasecmp(mods[i]->mod_type, "nsTaskCancel") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifiersName") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifyTimestamp") != 0)) {
+ !slapi_attr_is_last_mod(mods[i]->mod_type))
+ {
/* you aren't allowed to change this! */
*returncode = LDAP_UNWILLING_TO_PERFORM;
return SLAPI_DSE_CALLBACK_ERROR;
diff --git a/ldap/servers/slapd/tools/mmldif.c b/ldap/servers/slapd/tools/mmldif.c
index 4213e65..ebadf13 100644
--- a/ldap/servers/slapd/tools/mmldif.c
+++ b/ldap/servers/slapd/tools/mmldif.c
@@ -1017,9 +1017,7 @@ addnew(FILE * edf3, const char *changetype, record_t * first)
for (attnum = 1, att = &first->data;
attnum <= first->nattrs;
attnum++, att = attribnext(att)) {
- if (!stricmp(attribname(att), "modifytimestamp"))
- continue;
- if (!stricmp(attribname(att), "modifiersname"))
+ if (slapi_attr_is_last_mod(attribname(att)))
continue;
if (!putvalue(edf3, NULL, attribname(att), att->namelen,
attribvalue(att), att->valuelen)) {
@@ -1074,15 +1072,11 @@ addmodified(FILE * edf3, attrib1_t * attrib, record_t * first)
*/
while (a != NULL || num_b <= tot_b) {
/* ignore operational attrs */
- if (num_b <= tot_b &&
- (stricmp(attribname(b), "modifytimestamp") == 0 ||
- stricmp(attribname(b), "modifiersname") == 0)) {
+ if ( num_b <= tot_b && slapi_attr_is_last_mod(attribname(b)) ){
b = attribnext(b); num_b++;
continue;
}
- if (a != NULL &&
- (stricmp(a->name, "modifytimestamp") == 0 ||
- stricmp(a->name, "modifiersname") == 0)) {
+ if (a != NULL && slapi_attr_is_last_mod(a->name)) {
a = a->next;
continue;
}
9 years, 5 months
Branch '389-ds-base-1.3.2' - dirsrvtests/tickets ldap/servers
by Mark Reynolds
dirsrvtests/tickets/ticket47950_test.py | 273 ++++++++++++++++
ldap/servers/plugins/acl/acl.c | 4
ldap/servers/plugins/replication/cl5_config.c | 9
ldap/servers/plugins/replication/repl5_agmtlist.c | 3
ldap/servers/plugins/replication/repl5_replica_config.c | 3
ldap/servers/slapd/add.c | 4
ldap/servers/slapd/back-ldbm/ldbm_config.c | 3
ldap/servers/slapd/configdse.c | 5
ldap/servers/slapd/opshared.c | 17
ldap/servers/slapd/result.c | 2
ldap/servers/slapd/slapi-plugin.h | 2
ldap/servers/slapd/task.c | 4
ldap/servers/slapd/tools/mmldif.c | 12
13 files changed, 309 insertions(+), 32 deletions(-)
New commits:
commit 9c44c634a2187d7aa50c4e906d94bf4fa228c203
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Nov 18 09:24:21 2014 -0500
Ticket 47950 - Bind DN tracking unable to write to internalModifiersName without special permissions
Bug Description: When a non-rootDN entry makes an update when plugin bind dn tracking
is enabled, it is incorrectly rejected with an error 50.
Fix Description: Create a function to check if an attribute is one of last mod attributes,
including the internalModfieresname/internalModifytimestamp. Use this
new function wherever we are checking for last mod attributes.
https://fedorahosted.org/389/ticket/47950
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit c973e7150cf1e7fb3f61a76cf1baf3c0fa91f756)
diff --git a/dirsrvtests/tickets/ticket47950_test.py b/dirsrvtests/tickets/ticket47950_test.py
new file mode 100644
index 0000000..976f964
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47950_test.py
@@ -0,0 +1,273 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from constants import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+USER1_DN = "uid=user1,%s" % DEFAULT_SUFFIX
+USER2_DN = "uid=user2,%s" % DEFAULT_SUFFIX
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to standalone topology for the 'module'.
+ At the beginning, It may exists a standalone instance.
+ It may also exists a backup for the standalone instance.
+
+ Principle:
+ If standalone instance exists:
+ restart it
+ If backup of standalone exists:
+ create/rebind to standalone
+
+ restore standalone instance from backup
+ else:
+ Cleanup everything
+ remove instance
+ remove backup
+ Create instance
+ Create backup
+ '''
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ standalone = DirSrv(verbose=False)
+
+ # Args for the standalone instance
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+
+ # Get the status of the backups
+ backup_standalone = standalone.checkBackupFS()
+
+ # Get the status of the instance and restart it if it exists
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ # assuming the instance is already stopped, just wait 5 sec max
+ standalone.stop(timeout=5)
+ standalone.start(timeout=10)
+
+ if backup_standalone:
+ # The backup exist, assuming it is correct
+ # we just re-init the instance with it
+ if not instance_standalone:
+ standalone.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # restore standalone instance from backup
+ standalone.stop(timeout=10)
+ standalone.restoreFS(backup_standalone)
+ standalone.start(timeout=10)
+
+ else:
+ # We should be here only in two conditions
+ # - This is the first time a test involve standalone instance
+ # - Something weird happened (instance/backup destroyed)
+ # so we discard everything and recreate all
+
+ # Remove the backup. So even if we have a specific backup file
+ # (e.g backup_standalone) we clear backup that an instance may have created
+ if backup_standalone:
+ standalone.clearBackupFS()
+
+ # Remove the instance
+ if instance_standalone:
+ standalone.delete()
+
+ # Create the instance
+ standalone.create()
+
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # Time to create the backups
+ standalone.stop(timeout=10)
+ standalone.backupfile = standalone.backupFS()
+ standalone.start(timeout=10)
+
+ # clear the tmp directory
+ standalone.clearTmpDir(__file__)
+
+ #
+ # Here we have standalone instance up and running
+ # Either coming from a backup recovery
+ # or from a fresh (re)init
+ # Time to return the topology
+ return TopologyStandalone(standalone)
+
+
+def test_ticket47950(topology):
+ """
+ Testing nsslapd-plugin-binddn-tracking does not cause issues around
+ access control and reconfiguring replication/repl agmt.
+ """
+
+ log.info('Testing Ticket 47950 - Testing nsslapd-plugin-binddn-tracking')
+
+ #
+ # Turn on bind dn tracking
+ #
+ try:
+ topology.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE, 'nsslapd-plugin-binddn-tracking', 'on')])
+ log.info('nsslapd-plugin-binddn-tracking enabled.')
+ except ldap.LDAPError, e:
+ log.error('Failed to enable bind dn tracking: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add two users
+ #
+ try:
+ topology.standalone.add_s(Entry((USER1_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'userpassword': "password",
+ 'sn': "1",
+ 'cn': "user 1"})))
+ log.info('Added test user %s' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add %s: %s' % (USER1_DN, e.message['desc']))
+ assert False
+
+ try:
+ topology.standalone.add_s(Entry((USER2_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'sn': "2",
+ 'cn': "user 2"})))
+ log.info('Added test user %s' % USER2_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add user1: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add an aci
+ #
+ try:
+ acival = '(targetattr ="cn")(version 3.0;acl "Test bind dn tracking"' + \
+ ';allow (all) (userdn = "ldap:///%s");)' % USER1_DN
+
+ topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci', acival)])
+ log.info('Added aci')
+ except ldap.LDAPError, e:
+ log.error('Failed to add aci: ' + e.message['desc'])
+ assert False
+
+ #
+ # Make modification as user
+ #
+ try:
+ topology.standalone.simple_bind_s(USER1_DN, "password")
+ log.info('Bind as user %s successful' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as user1: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.modify_s(USER2_DN, [(ldap.MOD_REPLACE, 'cn', 'new value')])
+ log.info('%s successfully modified user %s' % (USER1_DN, USER2_DN))
+ except ldap.LDAPError, e:
+ log.error('Failed to update user2: ' + e.message['desc'])
+ assert False
+
+ #
+ # Setup replica and create a repl agmt
+ #
+ try:
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ log.info('Bind as %s successful' % DN_DM)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as rootDN: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.replica.enableReplication(suffix=DEFAULT_SUFFIX, role=REPLICAROLE_MASTER,
+ replicaId=REPLICAID_MASTER)
+ log.info('Successfully enabled replication.')
+ except ValueError:
+ log.error('Failed to enable replication')
+ assert False
+
+ properties = {RA_NAME: r'test plugin internal bind dn',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+
+ try:
+ repl_agreement = topology.standalone.agreement.create(suffix=DEFAULT_SUFFIX, host="127.0.0.1",
+ port="7777", properties=properties)
+ log.info('Successfully created replication agreement')
+ except InvalidArgumentError, e:
+ log.error('Failed to create replication agreement: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify replica
+ #
+ try:
+ properties = {REPLICA_ID: "7"}
+ topology.standalone.replica.setProperties(DEFAULT_SUFFIX, None, None, properties)
+ log.info('Successfully modified replica')
+ except ldap.LDAPError, e:
+ log.error('Failed to update replica config: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify repl agmt
+ #
+ try:
+ properties = {RA_CONSUMER_PORT: "8888"}
+ topology.standalone.agreement.setProperties(None, repl_agreement, None, properties)
+ log.info('Successfully modified replication agreement')
+ except ValueError:
+ log.error('Failed to update replica agreement: ' + repl_agreement)
+ assert False
+
+ # We passed
+ log.info("Test Passed.")
+
+
+def test_ticket47953_final(topology):
+ topology.standalone.stop(timeout=10)
+
+
+def run_isolated():
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '@pytest.fixture' line before 'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ topo = topology(True)
+ test_ticket47950(topo)
+
+if __name__ == '__main__':
+ run_isolated()
\ No newline at end of file
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
index 37299ed..1a94426 100644
--- a/ldap/servers/plugins/acl/acl.c
+++ b/ldap/servers/plugins/acl/acl.c
@@ -1389,9 +1389,7 @@ acl_check_mods(
if (be != NULL)
slapi_pblock_get ( pb, SLAPI_BE_LASTMOD, &lastmod );
}
- if (lastmod &&
- (strcmp (mod->mod_type, "modifiersname")== 0 ||
- strcmp (mod->mod_type, "modifytimestamp")== 0)) {
+ if (lastmod && slapi_attr_is_last_mod(mod->mod_type)) {
/* skip pseudo attr(s) */
continue;
}
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index 55727c2..a3a0fb3 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -357,15 +357,10 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
config_attr = (char *) mods[i]->mod_type;
config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
-#define ATTR_MODIFIERSNAME "modifiersname"
-#define ATTR_MODIFYTIMESTAMP "modifytimestamp"
-
- if ( strcasecmp ( config_attr, ATTR_MODIFIERSNAME ) == 0 ) {
- continue;
- }
- if ( strcasecmp ( config_attr, ATTR_MODIFYTIMESTAMP ) == 0 ) {
+ if ( slapi_attr_is_last_mod(config_attr)){
continue;
}
+
/* replace existing value */
if ( strcasecmp (config_attr, CONFIG_CHANGELOG_DIR_ATTRIBUTE ) == 0 )
{
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 1cf2976..dfaef94 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -473,8 +473,7 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
repl5_set_debug_timeout(val);
slapi_ch_free_string(&val);
}
- else if (strcasecmp (mods[i]->mod_type, "modifytimestamp") == 0 ||
- strcasecmp (mods[i]->mod_type, "modifiersname") == 0 ||
+ else if (slapi_attr_is_last_mod(mods[i]->mod_type) ||
strcasecmp (mods[i]->mod_type, "description") == 0)
{
/* ignore modifier's name and timestamp attributes and the description. */
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index e6c495c..4635c21 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -512,8 +512,7 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
}
}
/* ignore modifiers attributes added by the server */
- else if (strcasecmp (config_attr, "modifytimestamp") == 0 ||
- strcasecmp (config_attr, "modifiersname") == 0)
+ else if (slapi_attr_is_last_mod(config_attr))
{
*returncode = LDAP_SUCCESS;
}
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 2a89358..243ef63 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -916,8 +916,8 @@ static int check_rdn_for_created_attrs(Slapi_Entry *e)
int i, rc = 0;
Slapi_RDN *rdn = NULL;
char *value = NULL;
- char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "createtimestamp",
- "creatorsname", "modifiersname", 0};
+ char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "modifiersname", "internalmodifytimestamp",
+ "internalmodifiersname", "createtimestamp", "creatorsname", 0};
if ((rdn = slapi_rdn_new())) {
slapi_rdn_init_dn(rdn, slapi_entry_get_dn_const(e));
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
index 4faf235..1a8d8a9 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
@@ -1825,10 +1825,9 @@ int ldbm_config_ignored_attr(char *attr_name)
if (!strcasecmp("objectclass", attr_name) ||
!strcasecmp("cn", attr_name) ||
!strcasecmp("creatorsname", attr_name) ||
- !strcasecmp("modifiersname", attr_name) ||
!strcasecmp("createtimestamp", attr_name) ||
!strcasecmp(LDBM_NUMSUBORDINATES_STR, attr_name) ||
- !strcasecmp("modifytimestamp", attr_name)) {
+ slapi_attr_is_last_mod(attr_name)){
return 1;
} else {
return 0;
diff --git a/ldap/servers/slapd/configdse.c b/ldap/servers/slapd/configdse.c
index 14e8a5e..c8e490a 100644
--- a/ldap/servers/slapd/configdse.c
+++ b/ldap/servers/slapd/configdse.c
@@ -116,10 +116,9 @@ ignore_attr_type(const char *attr_type)
(strcasecmp (attr_type, "aci") == 0) ||
(strcasecmp (attr_type, "objectclass") == 0) ||
(strcasecmp (attr_type, "numsubordinates") == 0) ||
- (strcasecmp (attr_type, "internalModifiersname") == 0) ||
(strcasecmp (attr_type, "internalCreatorsname") == 0) ||
- (strcasecmp (attr_type, "modifytimestamp") == 0) ||
- (strcasecmp (attr_type, "modifiersname") == 0)) {
+ slapi_attr_is_last_mod((char *)attr_type))
+ {
return 1;
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index e222b05..2e4bbda 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -218,6 +218,23 @@ modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
}
/*
+ * If the attribute is one of the last mod attributes return 1,
+ * otherwise return 0;
+ */
+int
+slapi_attr_is_last_mod(char *attr)
+{
+ if(strcasecmp (attr, "modifytimestamp") == 0 ||
+ strcasecmp (attr, "modifiersname") == 0 ||
+ strcasecmp (attr, "internalmodifytimestamp") == 0 ||
+ strcasecmp (attr, "internalmodifiersname") == 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*
* Returns: 0 - if the operation is successful
* < 0 - if operation fails.
* Note that an operation is considered "failed" if a result is sent
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 05a3b67..6795ea1 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -1059,6 +1059,8 @@ encode_attr(
#define LASTMODATTR( x ) (strcasecmp( x, "modifytimestamp" ) == 0 \
|| strcasecmp( x, "modifiersname" ) == 0 \
+ || strcasecmp( x, "internalmodifytimestamp" ) == 0 \
+ || strcasecmp( x, "internalmodifiersname" ) == 0 \
|| strcasecmp( x, "createtimestamp" ) == 0 \
|| strcasecmp( x, "creatorsname" ) == 0)
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index d7c5ea7..1284a47 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5226,6 +5226,8 @@ int slapi_filter_compare(struct slapi_filter *f1, struct slapi_filter *f2);
Slapi_Filter *slapi_filter_dup(Slapi_Filter *f);
int slapi_filter_changetype(Slapi_Filter *f, const char *newtype);
+int slapi_attr_is_last_mod(char *attr);
+
/**
* Normalize in-place the given filter. Normalizes the attribute types always.
* If norm_values is true, will also normalize the values.
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index d7a3fda..45c81c2 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -779,8 +779,8 @@ static int task_modify(Slapi_PBlock *pb, Slapi_Entry *e,
* stuck in by the server */
if ((strcasecmp(mods[i]->mod_type, "ttl") != 0) &&
(strcasecmp(mods[i]->mod_type, "nsTaskCancel") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifiersName") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifyTimestamp") != 0)) {
+ !slapi_attr_is_last_mod(mods[i]->mod_type))
+ {
/* you aren't allowed to change this! */
*returncode = LDAP_UNWILLING_TO_PERFORM;
return SLAPI_DSE_CALLBACK_ERROR;
diff --git a/ldap/servers/slapd/tools/mmldif.c b/ldap/servers/slapd/tools/mmldif.c
index 4213e65..ebadf13 100644
--- a/ldap/servers/slapd/tools/mmldif.c
+++ b/ldap/servers/slapd/tools/mmldif.c
@@ -1017,9 +1017,7 @@ addnew(FILE * edf3, const char *changetype, record_t * first)
for (attnum = 1, att = &first->data;
attnum <= first->nattrs;
attnum++, att = attribnext(att)) {
- if (!stricmp(attribname(att), "modifytimestamp"))
- continue;
- if (!stricmp(attribname(att), "modifiersname"))
+ if (slapi_attr_is_last_mod(attribname(att)))
continue;
if (!putvalue(edf3, NULL, attribname(att), att->namelen,
attribvalue(att), att->valuelen)) {
@@ -1074,15 +1072,11 @@ addmodified(FILE * edf3, attrib1_t * attrib, record_t * first)
*/
while (a != NULL || num_b <= tot_b) {
/* ignore operational attrs */
- if (num_b <= tot_b &&
- (stricmp(attribname(b), "modifytimestamp") == 0 ||
- stricmp(attribname(b), "modifiersname") == 0)) {
+ if ( num_b <= tot_b && slapi_attr_is_last_mod(attribname(b)) ){
b = attribnext(b); num_b++;
continue;
}
- if (a != NULL &&
- (stricmp(a->name, "modifytimestamp") == 0 ||
- stricmp(a->name, "modifiersname") == 0)) {
+ if (a != NULL && slapi_attr_is_last_mod(a->name)) {
a = a->next;
continue;
}
9 years, 5 months
Branch '389-ds-base-1.3.3' - dirsrvtests/tickets ldap/servers
by Mark Reynolds
dirsrvtests/tickets/ticket47950_test.py | 273 ++++++++++++++++
ldap/servers/plugins/acl/acl.c | 4
ldap/servers/plugins/replication/cl5_config.c | 9
ldap/servers/plugins/replication/repl5_agmtlist.c | 3
ldap/servers/plugins/replication/repl5_replica_config.c | 3
ldap/servers/slapd/add.c | 4
ldap/servers/slapd/back-ldbm/ldbm_config.c | 3
ldap/servers/slapd/configdse.c | 5
ldap/servers/slapd/opshared.c | 17
ldap/servers/slapd/result.c | 2
ldap/servers/slapd/slapi-plugin.h | 2
ldap/servers/slapd/task.c | 4
ldap/servers/slapd/tools/mmldif.c | 12
13 files changed, 309 insertions(+), 32 deletions(-)
New commits:
commit fa8f7dc3d1ab508c762fc2e18de0cb860ed84657
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Nov 18 09:24:21 2014 -0500
Ticket 47950 - Bind DN tracking unable to write to internalModifiersName without special permissions
Bug Description: When a non-rootDN entry makes an update when plugin bind dn tracking
is enabled, it is incorrectly rejected with an error 50.
Fix Description: Create a function to check if an attribute is one of last mod attributes,
including the internalModfieresname/internalModifytimestamp. Use this
new function wherever we are checking for last mod attributes.
https://fedorahosted.org/389/ticket/47950
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit c973e7150cf1e7fb3f61a76cf1baf3c0fa91f756)
diff --git a/dirsrvtests/tickets/ticket47950_test.py b/dirsrvtests/tickets/ticket47950_test.py
new file mode 100644
index 0000000..976f964
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47950_test.py
@@ -0,0 +1,273 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from constants import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+USER1_DN = "uid=user1,%s" % DEFAULT_SUFFIX
+USER2_DN = "uid=user2,%s" % DEFAULT_SUFFIX
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to standalone topology for the 'module'.
+ At the beginning, It may exists a standalone instance.
+ It may also exists a backup for the standalone instance.
+
+ Principle:
+ If standalone instance exists:
+ restart it
+ If backup of standalone exists:
+ create/rebind to standalone
+
+ restore standalone instance from backup
+ else:
+ Cleanup everything
+ remove instance
+ remove backup
+ Create instance
+ Create backup
+ '''
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ standalone = DirSrv(verbose=False)
+
+ # Args for the standalone instance
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+
+ # Get the status of the backups
+ backup_standalone = standalone.checkBackupFS()
+
+ # Get the status of the instance and restart it if it exists
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ # assuming the instance is already stopped, just wait 5 sec max
+ standalone.stop(timeout=5)
+ standalone.start(timeout=10)
+
+ if backup_standalone:
+ # The backup exist, assuming it is correct
+ # we just re-init the instance with it
+ if not instance_standalone:
+ standalone.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # restore standalone instance from backup
+ standalone.stop(timeout=10)
+ standalone.restoreFS(backup_standalone)
+ standalone.start(timeout=10)
+
+ else:
+ # We should be here only in two conditions
+ # - This is the first time a test involve standalone instance
+ # - Something weird happened (instance/backup destroyed)
+ # so we discard everything and recreate all
+
+ # Remove the backup. So even if we have a specific backup file
+ # (e.g backup_standalone) we clear backup that an instance may have created
+ if backup_standalone:
+ standalone.clearBackupFS()
+
+ # Remove the instance
+ if instance_standalone:
+ standalone.delete()
+
+ # Create the instance
+ standalone.create()
+
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # Time to create the backups
+ standalone.stop(timeout=10)
+ standalone.backupfile = standalone.backupFS()
+ standalone.start(timeout=10)
+
+ # clear the tmp directory
+ standalone.clearTmpDir(__file__)
+
+ #
+ # Here we have standalone instance up and running
+ # Either coming from a backup recovery
+ # or from a fresh (re)init
+ # Time to return the topology
+ return TopologyStandalone(standalone)
+
+
+def test_ticket47950(topology):
+ """
+ Testing nsslapd-plugin-binddn-tracking does not cause issues around
+ access control and reconfiguring replication/repl agmt.
+ """
+
+ log.info('Testing Ticket 47950 - Testing nsslapd-plugin-binddn-tracking')
+
+ #
+ # Turn on bind dn tracking
+ #
+ try:
+ topology.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE, 'nsslapd-plugin-binddn-tracking', 'on')])
+ log.info('nsslapd-plugin-binddn-tracking enabled.')
+ except ldap.LDAPError, e:
+ log.error('Failed to enable bind dn tracking: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add two users
+ #
+ try:
+ topology.standalone.add_s(Entry((USER1_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'userpassword': "password",
+ 'sn': "1",
+ 'cn': "user 1"})))
+ log.info('Added test user %s' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add %s: %s' % (USER1_DN, e.message['desc']))
+ assert False
+
+ try:
+ topology.standalone.add_s(Entry((USER2_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'sn': "2",
+ 'cn': "user 2"})))
+ log.info('Added test user %s' % USER2_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add user1: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add an aci
+ #
+ try:
+ acival = '(targetattr ="cn")(version 3.0;acl "Test bind dn tracking"' + \
+ ';allow (all) (userdn = "ldap:///%s");)' % USER1_DN
+
+ topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci', acival)])
+ log.info('Added aci')
+ except ldap.LDAPError, e:
+ log.error('Failed to add aci: ' + e.message['desc'])
+ assert False
+
+ #
+ # Make modification as user
+ #
+ try:
+ topology.standalone.simple_bind_s(USER1_DN, "password")
+ log.info('Bind as user %s successful' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as user1: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.modify_s(USER2_DN, [(ldap.MOD_REPLACE, 'cn', 'new value')])
+ log.info('%s successfully modified user %s' % (USER1_DN, USER2_DN))
+ except ldap.LDAPError, e:
+ log.error('Failed to update user2: ' + e.message['desc'])
+ assert False
+
+ #
+ # Setup replica and create a repl agmt
+ #
+ try:
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ log.info('Bind as %s successful' % DN_DM)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as rootDN: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.replica.enableReplication(suffix=DEFAULT_SUFFIX, role=REPLICAROLE_MASTER,
+ replicaId=REPLICAID_MASTER)
+ log.info('Successfully enabled replication.')
+ except ValueError:
+ log.error('Failed to enable replication')
+ assert False
+
+ properties = {RA_NAME: r'test plugin internal bind dn',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+
+ try:
+ repl_agreement = topology.standalone.agreement.create(suffix=DEFAULT_SUFFIX, host="127.0.0.1",
+ port="7777", properties=properties)
+ log.info('Successfully created replication agreement')
+ except InvalidArgumentError, e:
+ log.error('Failed to create replication agreement: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify replica
+ #
+ try:
+ properties = {REPLICA_ID: "7"}
+ topology.standalone.replica.setProperties(DEFAULT_SUFFIX, None, None, properties)
+ log.info('Successfully modified replica')
+ except ldap.LDAPError, e:
+ log.error('Failed to update replica config: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify repl agmt
+ #
+ try:
+ properties = {RA_CONSUMER_PORT: "8888"}
+ topology.standalone.agreement.setProperties(None, repl_agreement, None, properties)
+ log.info('Successfully modified replication agreement')
+ except ValueError:
+ log.error('Failed to update replica agreement: ' + repl_agreement)
+ assert False
+
+ # We passed
+ log.info("Test Passed.")
+
+
+def test_ticket47953_final(topology):
+ topology.standalone.stop(timeout=10)
+
+
+def run_isolated():
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '@pytest.fixture' line before 'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ topo = topology(True)
+ test_ticket47950(topo)
+
+if __name__ == '__main__':
+ run_isolated()
\ No newline at end of file
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
index 5416330..403c5b3 100644
--- a/ldap/servers/plugins/acl/acl.c
+++ b/ldap/servers/plugins/acl/acl.c
@@ -1450,9 +1450,7 @@ acl_check_mods(
if (be != NULL)
slapi_pblock_get ( pb, SLAPI_BE_LASTMOD, &lastmod );
}
- if (lastmod &&
- (strcmp (mod->mod_type, "modifiersname")== 0 ||
- strcmp (mod->mod_type, "modifytimestamp")== 0)) {
+ if (lastmod && slapi_attr_is_last_mod(mod->mod_type)) {
/* skip pseudo attr(s) */
continue;
}
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index 55727c2..a3a0fb3 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -357,15 +357,10 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
config_attr = (char *) mods[i]->mod_type;
config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
-#define ATTR_MODIFIERSNAME "modifiersname"
-#define ATTR_MODIFYTIMESTAMP "modifytimestamp"
-
- if ( strcasecmp ( config_attr, ATTR_MODIFIERSNAME ) == 0 ) {
- continue;
- }
- if ( strcasecmp ( config_attr, ATTR_MODIFYTIMESTAMP ) == 0 ) {
+ if ( slapi_attr_is_last_mod(config_attr)){
continue;
}
+
/* replace existing value */
if ( strcasecmp (config_attr, CONFIG_CHANGELOG_DIR_ATTRIBUTE ) == 0 )
{
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 8a70055..90bf7e9 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -498,8 +498,7 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
repl5_set_debug_timeout(val);
slapi_ch_free_string(&val);
}
- else if (strcasecmp (mods[i]->mod_type, "modifytimestamp") == 0 ||
- strcasecmp (mods[i]->mod_type, "modifiersname") == 0 ||
+ else if (slapi_attr_is_last_mod(mods[i]->mod_type) ||
strcasecmp (mods[i]->mod_type, "description") == 0)
{
/* ignore modifier's name and timestamp attributes and the description. */
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 2810b11..3bc3916 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -534,8 +534,7 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
}
}
/* ignore modifiers attributes added by the server */
- else if (strcasecmp (config_attr, "modifytimestamp") == 0 ||
- strcasecmp (config_attr, "modifiersname") == 0)
+ else if (slapi_attr_is_last_mod(config_attr))
{
*returncode = LDAP_SUCCESS;
}
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 2a89358..243ef63 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -916,8 +916,8 @@ static int check_rdn_for_created_attrs(Slapi_Entry *e)
int i, rc = 0;
Slapi_RDN *rdn = NULL;
char *value = NULL;
- char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "createtimestamp",
- "creatorsname", "modifiersname", 0};
+ char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "modifiersname", "internalmodifytimestamp",
+ "internalmodifiersname", "createtimestamp", "creatorsname", 0};
if ((rdn = slapi_rdn_new())) {
slapi_rdn_init_dn(rdn, slapi_entry_get_dn_const(e));
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
index 0f8cc76..294999c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
@@ -1849,10 +1849,9 @@ int ldbm_config_ignored_attr(char *attr_name)
if (!strcasecmp("objectclass", attr_name) ||
!strcasecmp("cn", attr_name) ||
!strcasecmp("creatorsname", attr_name) ||
- !strcasecmp("modifiersname", attr_name) ||
!strcasecmp("createtimestamp", attr_name) ||
!strcasecmp(LDBM_NUMSUBORDINATES_STR, attr_name) ||
- !strcasecmp("modifytimestamp", attr_name)) {
+ slapi_attr_is_last_mod(attr_name)){
return 1;
} else {
return 0;
diff --git a/ldap/servers/slapd/configdse.c b/ldap/servers/slapd/configdse.c
index 339be42..e70e340 100644
--- a/ldap/servers/slapd/configdse.c
+++ b/ldap/servers/slapd/configdse.c
@@ -116,10 +116,9 @@ ignore_attr_type(const char *attr_type)
(strcasecmp (attr_type, "aci") == 0) ||
(strcasecmp (attr_type, "objectclass") == 0) ||
(strcasecmp (attr_type, "numsubordinates") == 0) ||
- (strcasecmp (attr_type, "internalModifiersname") == 0) ||
(strcasecmp (attr_type, "internalCreatorsname") == 0) ||
- (strcasecmp (attr_type, "modifytimestamp") == 0) ||
- (strcasecmp (attr_type, "modifiersname") == 0)) {
+ slapi_attr_is_last_mod((char *)attr_type))
+ {
return 1;
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 4e06652..ebd4fdf 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -218,6 +218,23 @@ modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
}
/*
+ * If the attribute is one of the last mod attributes return 1,
+ * otherwise return 0;
+ */
+int
+slapi_attr_is_last_mod(char *attr)
+{
+ if(strcasecmp (attr, "modifytimestamp") == 0 ||
+ strcasecmp (attr, "modifiersname") == 0 ||
+ strcasecmp (attr, "internalmodifytimestamp") == 0 ||
+ strcasecmp (attr, "internalmodifiersname") == 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*
* Returns: 0 - if the operation is successful
* < 0 - if operation fails.
* Note that an operation is considered "failed" if a result is sent
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 92573d5..ca2fa43 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -1059,6 +1059,8 @@ encode_attr(
#define LASTMODATTR( x ) (strcasecmp( x, "modifytimestamp" ) == 0 \
|| strcasecmp( x, "modifiersname" ) == 0 \
+ || strcasecmp( x, "internalmodifytimestamp" ) == 0 \
+ || strcasecmp( x, "internalmodifiersname" ) == 0 \
|| strcasecmp( x, "createtimestamp" ) == 0 \
|| strcasecmp( x, "creatorsname" ) == 0)
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 885e28e..cb8aad0 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5278,6 +5278,8 @@ int slapi_filter_compare(struct slapi_filter *f1, struct slapi_filter *f2);
Slapi_Filter *slapi_filter_dup(Slapi_Filter *f);
int slapi_filter_changetype(Slapi_Filter *f, const char *newtype);
+int slapi_attr_is_last_mod(char *attr);
+
/**
* Normalize in-place the given filter. Normalizes the attribute types always.
* If norm_values is true, will also normalize the values.
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index 62cf294..006ae53 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -821,8 +821,8 @@ static int task_modify(Slapi_PBlock *pb, Slapi_Entry *e,
* stuck in by the server */
if ((strcasecmp(mods[i]->mod_type, "ttl") != 0) &&
(strcasecmp(mods[i]->mod_type, "nsTaskCancel") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifiersName") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifyTimestamp") != 0)) {
+ !slapi_attr_is_last_mod(mods[i]->mod_type))
+ {
/* you aren't allowed to change this! */
*returncode = LDAP_UNWILLING_TO_PERFORM;
return SLAPI_DSE_CALLBACK_ERROR;
diff --git a/ldap/servers/slapd/tools/mmldif.c b/ldap/servers/slapd/tools/mmldif.c
index bf20945..156d892 100644
--- a/ldap/servers/slapd/tools/mmldif.c
+++ b/ldap/servers/slapd/tools/mmldif.c
@@ -1009,9 +1009,7 @@ addnew(FILE * edf3, const char *changetype, record_t * first)
for (attnum = 1, att = &first->data;
attnum <= first->nattrs;
attnum++, att = attribnext(att)) {
- if (!stricmp(attribname(att), "modifytimestamp"))
- continue;
- if (!stricmp(attribname(att), "modifiersname"))
+ if (slapi_attr_is_last_mod(attribname(att)))
continue;
if (!putvalue(edf3, NULL, attribname(att), att->namelen,
attribvalue(att), att->valuelen)) {
@@ -1066,15 +1064,11 @@ addmodified(FILE * edf3, attrib1_t * attrib, record_t * first)
*/
while (a != NULL || num_b <= tot_b) {
/* ignore operational attrs */
- if (num_b <= tot_b &&
- (stricmp(attribname(b), "modifytimestamp") == 0 ||
- stricmp(attribname(b), "modifiersname") == 0)) {
+ if ( num_b <= tot_b && slapi_attr_is_last_mod(attribname(b)) ){
b = attribnext(b); num_b++;
continue;
}
- if (a != NULL &&
- (stricmp(a->name, "modifytimestamp") == 0 ||
- stricmp(a->name, "modifiersname") == 0)) {
+ if (a != NULL && slapi_attr_is_last_mod(a->name)) {
a = a->next;
continue;
}
9 years, 5 months
dirsrvtests/tickets ldap/servers
by Mark Reynolds
dirsrvtests/tickets/ticket47950_test.py | 273 ++++++++++++++++
ldap/servers/plugins/acl/acl.c | 4
ldap/servers/plugins/replication/cl5_config.c | 9
ldap/servers/plugins/replication/repl5_agmtlist.c | 3
ldap/servers/plugins/replication/repl5_replica_config.c | 3
ldap/servers/slapd/add.c | 4
ldap/servers/slapd/back-ldbm/ldbm_config.c | 3
ldap/servers/slapd/configdse.c | 5
ldap/servers/slapd/opshared.c | 17
ldap/servers/slapd/result.c | 2
ldap/servers/slapd/slapi-plugin.h | 2
ldap/servers/slapd/task.c | 4
ldap/servers/slapd/tools/mmldif.c | 12
13 files changed, 309 insertions(+), 32 deletions(-)
New commits:
commit c973e7150cf1e7fb3f61a76cf1baf3c0fa91f756
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Nov 18 09:24:21 2014 -0500
Ticket 47950 - Bind DN tracking unable to write to internalModifiersName without special permissions
Bug Description: When a non-rootDN entry makes an update when plugin bind dn tracking
is enabled, it is incorrectly rejected with an error 50.
Fix Description: Create a function to check if an attribute is one of last mod attributes,
including the internalModfieresname/internalModifytimestamp. Use this
new function wherever we are checking for last mod attributes.
https://fedorahosted.org/389/ticket/47950
Reviewed by: rmeggins(Thanks!)
diff --git a/dirsrvtests/tickets/ticket47950_test.py b/dirsrvtests/tickets/ticket47950_test.py
new file mode 100644
index 0000000..976f964
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47950_test.py
@@ -0,0 +1,273 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from constants import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+USER1_DN = "uid=user1,%s" % DEFAULT_SUFFIX
+USER2_DN = "uid=user2,%s" % DEFAULT_SUFFIX
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to standalone topology for the 'module'.
+ At the beginning, It may exists a standalone instance.
+ It may also exists a backup for the standalone instance.
+
+ Principle:
+ If standalone instance exists:
+ restart it
+ If backup of standalone exists:
+ create/rebind to standalone
+
+ restore standalone instance from backup
+ else:
+ Cleanup everything
+ remove instance
+ remove backup
+ Create instance
+ Create backup
+ '''
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ standalone = DirSrv(verbose=False)
+
+ # Args for the standalone instance
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+
+ # Get the status of the backups
+ backup_standalone = standalone.checkBackupFS()
+
+ # Get the status of the instance and restart it if it exists
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ # assuming the instance is already stopped, just wait 5 sec max
+ standalone.stop(timeout=5)
+ standalone.start(timeout=10)
+
+ if backup_standalone:
+ # The backup exist, assuming it is correct
+ # we just re-init the instance with it
+ if not instance_standalone:
+ standalone.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # restore standalone instance from backup
+ standalone.stop(timeout=10)
+ standalone.restoreFS(backup_standalone)
+ standalone.start(timeout=10)
+
+ else:
+ # We should be here only in two conditions
+ # - This is the first time a test involve standalone instance
+ # - Something weird happened (instance/backup destroyed)
+ # so we discard everything and recreate all
+
+ # Remove the backup. So even if we have a specific backup file
+ # (e.g backup_standalone) we clear backup that an instance may have created
+ if backup_standalone:
+ standalone.clearBackupFS()
+
+ # Remove the instance
+ if instance_standalone:
+ standalone.delete()
+
+ # Create the instance
+ standalone.create()
+
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # Time to create the backups
+ standalone.stop(timeout=10)
+ standalone.backupfile = standalone.backupFS()
+ standalone.start(timeout=10)
+
+ # clear the tmp directory
+ standalone.clearTmpDir(__file__)
+
+ #
+ # Here we have standalone instance up and running
+ # Either coming from a backup recovery
+ # or from a fresh (re)init
+ # Time to return the topology
+ return TopologyStandalone(standalone)
+
+
+def test_ticket47950(topology):
+ """
+ Testing nsslapd-plugin-binddn-tracking does not cause issues around
+ access control and reconfiguring replication/repl agmt.
+ """
+
+ log.info('Testing Ticket 47950 - Testing nsslapd-plugin-binddn-tracking')
+
+ #
+ # Turn on bind dn tracking
+ #
+ try:
+ topology.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE, 'nsslapd-plugin-binddn-tracking', 'on')])
+ log.info('nsslapd-plugin-binddn-tracking enabled.')
+ except ldap.LDAPError, e:
+ log.error('Failed to enable bind dn tracking: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add two users
+ #
+ try:
+ topology.standalone.add_s(Entry((USER1_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'userpassword': "password",
+ 'sn': "1",
+ 'cn': "user 1"})))
+ log.info('Added test user %s' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add %s: %s' % (USER1_DN, e.message['desc']))
+ assert False
+
+ try:
+ topology.standalone.add_s(Entry((USER2_DN, {
+ 'objectclass': "top person inetuser".split(),
+ 'sn': "2",
+ 'cn': "user 2"})))
+ log.info('Added test user %s' % USER2_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to add user1: ' + e.message['desc'])
+ assert False
+
+ #
+ # Add an aci
+ #
+ try:
+ acival = '(targetattr ="cn")(version 3.0;acl "Test bind dn tracking"' + \
+ ';allow (all) (userdn = "ldap:///%s");)' % USER1_DN
+
+ topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci', acival)])
+ log.info('Added aci')
+ except ldap.LDAPError, e:
+ log.error('Failed to add aci: ' + e.message['desc'])
+ assert False
+
+ #
+ # Make modification as user
+ #
+ try:
+ topology.standalone.simple_bind_s(USER1_DN, "password")
+ log.info('Bind as user %s successful' % USER1_DN)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as user1: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.modify_s(USER2_DN, [(ldap.MOD_REPLACE, 'cn', 'new value')])
+ log.info('%s successfully modified user %s' % (USER1_DN, USER2_DN))
+ except ldap.LDAPError, e:
+ log.error('Failed to update user2: ' + e.message['desc'])
+ assert False
+
+ #
+ # Setup replica and create a repl agmt
+ #
+ try:
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ log.info('Bind as %s successful' % DN_DM)
+ except ldap.LDAPError, e:
+ log.error('Failed to bind as rootDN: ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.replica.enableReplication(suffix=DEFAULT_SUFFIX, role=REPLICAROLE_MASTER,
+ replicaId=REPLICAID_MASTER)
+ log.info('Successfully enabled replication.')
+ except ValueError:
+ log.error('Failed to enable replication')
+ assert False
+
+ properties = {RA_NAME: r'test plugin internal bind dn',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+
+ try:
+ repl_agreement = topology.standalone.agreement.create(suffix=DEFAULT_SUFFIX, host="127.0.0.1",
+ port="7777", properties=properties)
+ log.info('Successfully created replication agreement')
+ except InvalidArgumentError, e:
+ log.error('Failed to create replication agreement: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify replica
+ #
+ try:
+ properties = {REPLICA_ID: "7"}
+ topology.standalone.replica.setProperties(DEFAULT_SUFFIX, None, None, properties)
+ log.info('Successfully modified replica')
+ except ldap.LDAPError, e:
+ log.error('Failed to update replica config: ' + e.message['desc'])
+ assert False
+
+ #
+ # modify repl agmt
+ #
+ try:
+ properties = {RA_CONSUMER_PORT: "8888"}
+ topology.standalone.agreement.setProperties(None, repl_agreement, None, properties)
+ log.info('Successfully modified replication agreement')
+ except ValueError:
+ log.error('Failed to update replica agreement: ' + repl_agreement)
+ assert False
+
+ # We passed
+ log.info("Test Passed.")
+
+
+def test_ticket47953_final(topology):
+ topology.standalone.stop(timeout=10)
+
+
+def run_isolated():
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '@pytest.fixture' line before 'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ topo = topology(True)
+ test_ticket47950(topo)
+
+if __name__ == '__main__':
+ run_isolated()
\ No newline at end of file
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
index 5416330..403c5b3 100644
--- a/ldap/servers/plugins/acl/acl.c
+++ b/ldap/servers/plugins/acl/acl.c
@@ -1450,9 +1450,7 @@ acl_check_mods(
if (be != NULL)
slapi_pblock_get ( pb, SLAPI_BE_LASTMOD, &lastmod );
}
- if (lastmod &&
- (strcmp (mod->mod_type, "modifiersname")== 0 ||
- strcmp (mod->mod_type, "modifytimestamp")== 0)) {
+ if (lastmod && slapi_attr_is_last_mod(mod->mod_type)) {
/* skip pseudo attr(s) */
continue;
}
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index 55727c2..a3a0fb3 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -357,15 +357,10 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr
config_attr = (char *) mods[i]->mod_type;
config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
-#define ATTR_MODIFIERSNAME "modifiersname"
-#define ATTR_MODIFYTIMESTAMP "modifytimestamp"
-
- if ( strcasecmp ( config_attr, ATTR_MODIFIERSNAME ) == 0 ) {
- continue;
- }
- if ( strcasecmp ( config_attr, ATTR_MODIFYTIMESTAMP ) == 0 ) {
+ if ( slapi_attr_is_last_mod(config_attr)){
continue;
}
+
/* replace existing value */
if ( strcasecmp (config_attr, CONFIG_CHANGELOG_DIR_ATTRIBUTE ) == 0 )
{
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 8a70055..90bf7e9 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -498,8 +498,7 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
repl5_set_debug_timeout(val);
slapi_ch_free_string(&val);
}
- else if (strcasecmp (mods[i]->mod_type, "modifytimestamp") == 0 ||
- strcasecmp (mods[i]->mod_type, "modifiersname") == 0 ||
+ else if (slapi_attr_is_last_mod(mods[i]->mod_type) ||
strcasecmp (mods[i]->mod_type, "description") == 0)
{
/* ignore modifier's name and timestamp attributes and the description. */
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 2810b11..3bc3916 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -534,8 +534,7 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
}
}
/* ignore modifiers attributes added by the server */
- else if (strcasecmp (config_attr, "modifytimestamp") == 0 ||
- strcasecmp (config_attr, "modifiersname") == 0)
+ else if (slapi_attr_is_last_mod(config_attr))
{
*returncode = LDAP_SUCCESS;
}
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 2a89358..243ef63 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -916,8 +916,8 @@ static int check_rdn_for_created_attrs(Slapi_Entry *e)
int i, rc = 0;
Slapi_RDN *rdn = NULL;
char *value = NULL;
- char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "createtimestamp",
- "creatorsname", "modifiersname", 0};
+ char *type[] = {SLAPI_ATTR_UNIQUEID, "modifytimestamp", "modifiersname", "internalmodifytimestamp",
+ "internalmodifiersname", "createtimestamp", "creatorsname", 0};
if ((rdn = slapi_rdn_new())) {
slapi_rdn_init_dn(rdn, slapi_entry_get_dn_const(e));
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
index 0f8cc76..294999c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
@@ -1849,10 +1849,9 @@ int ldbm_config_ignored_attr(char *attr_name)
if (!strcasecmp("objectclass", attr_name) ||
!strcasecmp("cn", attr_name) ||
!strcasecmp("creatorsname", attr_name) ||
- !strcasecmp("modifiersname", attr_name) ||
!strcasecmp("createtimestamp", attr_name) ||
!strcasecmp(LDBM_NUMSUBORDINATES_STR, attr_name) ||
- !strcasecmp("modifytimestamp", attr_name)) {
+ slapi_attr_is_last_mod(attr_name)){
return 1;
} else {
return 0;
diff --git a/ldap/servers/slapd/configdse.c b/ldap/servers/slapd/configdse.c
index 339be42..e70e340 100644
--- a/ldap/servers/slapd/configdse.c
+++ b/ldap/servers/slapd/configdse.c
@@ -116,10 +116,9 @@ ignore_attr_type(const char *attr_type)
(strcasecmp (attr_type, "aci") == 0) ||
(strcasecmp (attr_type, "objectclass") == 0) ||
(strcasecmp (attr_type, "numsubordinates") == 0) ||
- (strcasecmp (attr_type, "internalModifiersname") == 0) ||
(strcasecmp (attr_type, "internalCreatorsname") == 0) ||
- (strcasecmp (attr_type, "modifytimestamp") == 0) ||
- (strcasecmp (attr_type, "modifiersname") == 0)) {
+ slapi_attr_is_last_mod((char *)attr_type))
+ {
return 1;
}
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 4e06652..ebd4fdf 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -218,6 +218,23 @@ modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
}
/*
+ * If the attribute is one of the last mod attributes return 1,
+ * otherwise return 0;
+ */
+int
+slapi_attr_is_last_mod(char *attr)
+{
+ if(strcasecmp (attr, "modifytimestamp") == 0 ||
+ strcasecmp (attr, "modifiersname") == 0 ||
+ strcasecmp (attr, "internalmodifytimestamp") == 0 ||
+ strcasecmp (attr, "internalmodifiersname") == 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*
* Returns: 0 - if the operation is successful
* < 0 - if operation fails.
* Note that an operation is considered "failed" if a result is sent
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 92573d5..ca2fa43 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -1059,6 +1059,8 @@ encode_attr(
#define LASTMODATTR( x ) (strcasecmp( x, "modifytimestamp" ) == 0 \
|| strcasecmp( x, "modifiersname" ) == 0 \
+ || strcasecmp( x, "internalmodifytimestamp" ) == 0 \
+ || strcasecmp( x, "internalmodifiersname" ) == 0 \
|| strcasecmp( x, "createtimestamp" ) == 0 \
|| strcasecmp( x, "creatorsname" ) == 0)
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 885e28e..cb8aad0 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5278,6 +5278,8 @@ int slapi_filter_compare(struct slapi_filter *f1, struct slapi_filter *f2);
Slapi_Filter *slapi_filter_dup(Slapi_Filter *f);
int slapi_filter_changetype(Slapi_Filter *f, const char *newtype);
+int slapi_attr_is_last_mod(char *attr);
+
/**
* Normalize in-place the given filter. Normalizes the attribute types always.
* If norm_values is true, will also normalize the values.
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
index 62cf294..006ae53 100644
--- a/ldap/servers/slapd/task.c
+++ b/ldap/servers/slapd/task.c
@@ -821,8 +821,8 @@ static int task_modify(Slapi_PBlock *pb, Slapi_Entry *e,
* stuck in by the server */
if ((strcasecmp(mods[i]->mod_type, "ttl") != 0) &&
(strcasecmp(mods[i]->mod_type, "nsTaskCancel") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifiersName") != 0) &&
- (strcasecmp(mods[i]->mod_type, "modifyTimestamp") != 0)) {
+ !slapi_attr_is_last_mod(mods[i]->mod_type))
+ {
/* you aren't allowed to change this! */
*returncode = LDAP_UNWILLING_TO_PERFORM;
return SLAPI_DSE_CALLBACK_ERROR;
diff --git a/ldap/servers/slapd/tools/mmldif.c b/ldap/servers/slapd/tools/mmldif.c
index bf20945..156d892 100644
--- a/ldap/servers/slapd/tools/mmldif.c
+++ b/ldap/servers/slapd/tools/mmldif.c
@@ -1009,9 +1009,7 @@ addnew(FILE * edf3, const char *changetype, record_t * first)
for (attnum = 1, att = &first->data;
attnum <= first->nattrs;
attnum++, att = attribnext(att)) {
- if (!stricmp(attribname(att), "modifytimestamp"))
- continue;
- if (!stricmp(attribname(att), "modifiersname"))
+ if (slapi_attr_is_last_mod(attribname(att)))
continue;
if (!putvalue(edf3, NULL, attribname(att), att->namelen,
attribvalue(att), att->valuelen)) {
@@ -1066,15 +1064,11 @@ addmodified(FILE * edf3, attrib1_t * attrib, record_t * first)
*/
while (a != NULL || num_b <= tot_b) {
/* ignore operational attrs */
- if (num_b <= tot_b &&
- (stricmp(attribname(b), "modifytimestamp") == 0 ||
- stricmp(attribname(b), "modifiersname") == 0)) {
+ if ( num_b <= tot_b && slapi_attr_is_last_mod(attribname(b)) ){
b = attribnext(b); num_b++;
continue;
}
- if (a != NULL &&
- (stricmp(a->name, "modifytimestamp") == 0 ||
- stricmp(a->name, "modifiersname") == 0)) {
+ if (a != NULL && slapi_attr_is_last_mod(a->name)) {
a = a->next;
continue;
}
9 years, 5 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/pw.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
New commits:
commit d9274e23f8132c2624413915d3e2e040d48bf152
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Nov 17 09:46:33 2014 -0500
Ticket 47958 - Memory leak in password admin if the admin entry does not exist
Bug Description: If passwordAdminDN is set to an entry that does not exist memory
is leaked.
Fix Description: The leak occurs because we do not free the internal search results,
even when zero entries are returned.
https://fedorahosted.org/389/ticket/47958
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit 6ee9a1bd3aa5014aff3b8b07a032c35a1c66d2e2)
Conflicts:
ldap/servers/slapd/pw.c
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index c88abc4..8af2b3e 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1573,20 +1573,25 @@ pw_get_admin_users(passwdPolicy *pwp)
if(binddn == NULL){
return;
}
- pb = slapi_pblock_new();
+
/*
* Check if the DN exists and has "group" objectclasses
*/
- slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,"(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
- NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
+ pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,
+ "(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
+ NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
slapi_search_internal_pb(pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
if (res != LDAP_SUCCESS) {
+ slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
- LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - Password Policy Administrators can not be set\n",
- slapi_sdn_get_dn(sdn), res, 0);
+ LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - "
+ "Password Policy Administrators can not be set\n",
+ slapi_sdn_get_dn(sdn), res, 0);
return;
}
+
/*
* Ok, we know we have a valid DN, and nentries will tell us if its a group or a user
*/
@@ -1600,7 +1605,8 @@ pw_get_admin_users(passwdPolicy *pwp)
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
uniquemember_vals = slapi_entry_attr_get_charray_ext(entries[0], "uniquemember", &uniquemember_count);
member_vals = slapi_entry_attr_get_charray_ext(entries[0], "member", &member_count);
- pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1), sizeof(Slapi_DN *));
+ pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1),
+ sizeof(Slapi_DN *));
if(uniquemember_count > 0){
for(i = 0; i < uniquemember_count; i++){
pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(uniquemember_vals[i]);
9 years, 5 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/pw.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
New commits:
commit 972396da9cf92d67e5ff597854d62c089b93ae9d
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Nov 17 09:46:33 2014 -0500
Ticket 47958 - Memory leak in password admin if the admin entry does not exist
Bug Description: If passwordAdminDN is set to an entry that does not exist memory
is leaked.
Fix Description: The leak occurs because we do not free the internal search results,
even when zero entries are returned.
https://fedorahosted.org/389/ticket/47958
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit 6ee9a1bd3aa5014aff3b8b07a032c35a1c66d2e2)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 7b803dd..65ba627 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1549,14 +1549,17 @@ pw_get_admin_users(passwdPolicy *pwp)
* Check if the DN exists and has "group" objectclasses
*/
pb = slapi_pblock_new();
- slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,"(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
- NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
+ slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,
+ "(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
+ NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
slapi_search_internal_pb(pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
if (res != LDAP_SUCCESS) {
+ slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
- LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - Password Policy Administrators can not be set\n",
- slapi_sdn_get_dn(sdn), res, 0);
+ LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - "
+ "Password Policy Administrators can not be set\n",
+ slapi_sdn_get_dn(sdn), res, 0);
return;
}
/*
@@ -1572,7 +1575,8 @@ pw_get_admin_users(passwdPolicy *pwp)
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
uniquemember_vals = slapi_entry_attr_get_charray_ext(entries[0], "uniquemember", &uniquemember_count);
member_vals = slapi_entry_attr_get_charray_ext(entries[0], "member", &member_count);
- pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1), sizeof(Slapi_DN *));
+ pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1),
+ sizeof(Slapi_DN *));
if(uniquemember_count > 0){
for(i = 0; i < uniquemember_count; i++){
pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(uniquemember_vals[i]);
9 years, 5 months
Branch '389-ds-base-1.3.2' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/pw.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
New commits:
commit 0d6f6ca269912e41a248c283fdb8929e11120605
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Nov 17 09:46:33 2014 -0500
Ticket 47958 - Memory leak in password admin if the admin entry does not exist
Bug Description: If passwordAdminDN is set to an entry that does not exist memory
is leaked.
Fix Description: The leak occurs because we do not free the internal search results,
even when zero entries are returned.
https://fedorahosted.org/389/ticket/47958
Reviewed by: rmeggins(Thanks!)
(cherry picked from commit 6ee9a1bd3aa5014aff3b8b07a032c35a1c66d2e2)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 9c541c5..7f80612 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1558,14 +1558,17 @@ pw_get_admin_users(passwdPolicy *pwp)
* Check if the DN exists and has "group" objectclasses
*/
pb = slapi_pblock_new();
- slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,"(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
- NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
+ slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,
+ "(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
+ NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
slapi_search_internal_pb(pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
if (res != LDAP_SUCCESS) {
+ slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
- LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - Password Policy Administrators can not be set\n",
- slapi_sdn_get_dn(sdn), res, 0);
+ LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - "
+ "Password Policy Administrators can not be set\n",
+ slapi_sdn_get_dn(sdn), res, 0);
return;
}
/*
@@ -1581,7 +1584,8 @@ pw_get_admin_users(passwdPolicy *pwp)
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
uniquemember_vals = slapi_entry_attr_get_charray_ext(entries[0], "uniquemember", &uniquemember_count);
member_vals = slapi_entry_attr_get_charray_ext(entries[0], "member", &member_count);
- pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1), sizeof(Slapi_DN *));
+ pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1),
+ sizeof(Slapi_DN *));
if(uniquemember_count > 0){
for(i = 0; i < uniquemember_count; i++){
pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(uniquemember_vals[i]);
9 years, 5 months