ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
New commits:
commit f9ba01b4b9ce3881cf08433b0c43db93ab207507
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Fri Jan 31 14:21:59 2014 -0700
Ticket #47374 - flush.pl is not included in perl5
https://fedorahosted.org/389/ticket/47374
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: Change opt_b to BeginNum and opt_r to Random_Seed.
Have to specify option as j=i because -j has an integer argument.
Get rid of opt_j and use ZeroPad instead.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in b/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
index 51af0db..2ef76f2 100755
--- a/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
+++ b/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
@@ -543,13 +543,14 @@ sub flush {
my $Number_To_Generate = 1;
$Output_File_Name = "output.ldif";
-$Random_Seed = 1;
+$Random_Seed = 0;
$Suffix = 'dc=example,dc=com';
$NamingType = "uid";
$inetOrgPerson = "objectClass: inetOrgPerson\n";
$PrintOrgChartDat = 0;
-$DataDir = "/usr/share/dirsrv/data";
+$DataDir = "@templatedir@";
$BeginNum = 0;
+$ZeroPad = 0;
$Verbose = 0;
$debug = 0;
@@ -572,7 +573,7 @@ GetOptions('number=i' => \$Number_To_Generate,
'x' => \$opt_x,
'y' => \$opt_y,
'z' => \$opt_z,
- 'j' => \$opt_j,
+ 'j=i' => \$ZeroPad,
'verbose' => \$Verbose,
'debug' => \$debug,
'quiet' => \$Quiet,
@@ -598,7 +599,6 @@ if ("" != $opt_y)
{
$printorgunit = 0;
}
-$ZeroPad = $opt_j;
if ($Suffix =~ /o=/) {
($Organization) = $Suffix =~ /o=([^,]+)/;
@@ -1029,8 +1029,8 @@ sub MakeRandomLocality {
sub MakeRandomName {
local($Given_Name, $Surname, $Full_Name, $UID, $uniq, $first, $last, $RDN);
# Get the unique number depending if a seed was set or not.
- $uniq = int rand($Random_Seed) if ($opt_r);
- $uniq = $x if (!$opt_r);
+ $uniq = int rand($Random_Seed) if ($Random_Seed);
+ $uniq = $x if (!$Random_Seed);
$Given_Name = $given_names[rand @given_names];
$Surname = $family_names[rand @family_names];
@@ -1040,7 +1040,7 @@ sub MakeRandomName {
$UID = $first . $last . "$uniq";
# Create the uid based on the DN naming type defined
- if ($opt_b) { # use a uniquenumber for the RDN value
+ if ($BeginNum) { # use a uniquenumber for the RDN value
if ($ZeroPad) {
$RDN = sprintf "%0.${ZeroPad}d", $x;
} else {
9 years, 8 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
New commits:
commit ea868566c49869b3fa0f6e2c7194b743d22f77fe
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Fri Jan 31 14:21:59 2014 -0700
Ticket #47374 - flush.pl is not included in perl5
https://fedorahosted.org/389/ticket/47374
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.3.1
Fix Description: Change opt_b to BeginNum and opt_r to Random_Seed.
Have to specify option as j=i because -j has an integer argument.
Get rid of opt_j and use ZeroPad instead.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit f9ba01b4b9ce3881cf08433b0c43db93ab207507)
(cherry picked from commit 55df132065f109b8f548100461011c10b58843ea)
diff --git a/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in b/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
index 51af0db..2ef76f2 100755
--- a/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
+++ b/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
@@ -543,13 +543,14 @@ sub flush {
my $Number_To_Generate = 1;
$Output_File_Name = "output.ldif";
-$Random_Seed = 1;
+$Random_Seed = 0;
$Suffix = 'dc=example,dc=com';
$NamingType = "uid";
$inetOrgPerson = "objectClass: inetOrgPerson\n";
$PrintOrgChartDat = 0;
-$DataDir = "/usr/share/dirsrv/data";
+$DataDir = "@templatedir@";
$BeginNum = 0;
+$ZeroPad = 0;
$Verbose = 0;
$debug = 0;
@@ -572,7 +573,7 @@ GetOptions('number=i' => \$Number_To_Generate,
'x' => \$opt_x,
'y' => \$opt_y,
'z' => \$opt_z,
- 'j' => \$opt_j,
+ 'j=i' => \$ZeroPad,
'verbose' => \$Verbose,
'debug' => \$debug,
'quiet' => \$Quiet,
@@ -598,7 +599,6 @@ if ("" != $opt_y)
{
$printorgunit = 0;
}
-$ZeroPad = $opt_j;
if ($Suffix =~ /o=/) {
($Organization) = $Suffix =~ /o=([^,]+)/;
@@ -1029,8 +1029,8 @@ sub MakeRandomLocality {
sub MakeRandomName {
local($Given_Name, $Surname, $Full_Name, $UID, $uniq, $first, $last, $RDN);
# Get the unique number depending if a seed was set or not.
- $uniq = int rand($Random_Seed) if ($opt_r);
- $uniq = $x if (!$opt_r);
+ $uniq = int rand($Random_Seed) if ($Random_Seed);
+ $uniq = $x if (!$Random_Seed);
$Given_Name = $given_names[rand @given_names];
$Surname = $family_names[rand @family_names];
@@ -1040,7 +1040,7 @@ sub MakeRandomName {
$UID = $first . $last . "$uniq";
# Create the uid based on the DN naming type defined
- if ($opt_b) { # use a uniquenumber for the RDN value
+ if ($BeginNum) { # use a uniquenumber for the RDN value
if ($ZeroPad) {
$RDN = sprintf "%0.${ZeroPad}d", $x;
} else {
9 years, 8 months
Branch '389-ds-base-1.3.2' - ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
New commits:
commit 55df132065f109b8f548100461011c10b58843ea
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Fri Jan 31 14:21:59 2014 -0700
Ticket #47374 - flush.pl is not included in perl5
https://fedorahosted.org/389/ticket/47374
Reviewed by: nhosoi (Thanks!)
Branch: 389-ds-base-1.3.2
Fix Description: Change opt_b to BeginNum and opt_r to Random_Seed.
Have to specify option as j=i because -j has an integer argument.
Get rid of opt_j and use ZeroPad instead.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit f9ba01b4b9ce3881cf08433b0c43db93ab207507)
diff --git a/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in b/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
index 51af0db..2ef76f2 100755
--- a/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
+++ b/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in
@@ -543,13 +543,14 @@ sub flush {
my $Number_To_Generate = 1;
$Output_File_Name = "output.ldif";
-$Random_Seed = 1;
+$Random_Seed = 0;
$Suffix = 'dc=example,dc=com';
$NamingType = "uid";
$inetOrgPerson = "objectClass: inetOrgPerson\n";
$PrintOrgChartDat = 0;
-$DataDir = "/usr/share/dirsrv/data";
+$DataDir = "@templatedir@";
$BeginNum = 0;
+$ZeroPad = 0;
$Verbose = 0;
$debug = 0;
@@ -572,7 +573,7 @@ GetOptions('number=i' => \$Number_To_Generate,
'x' => \$opt_x,
'y' => \$opt_y,
'z' => \$opt_z,
- 'j' => \$opt_j,
+ 'j=i' => \$ZeroPad,
'verbose' => \$Verbose,
'debug' => \$debug,
'quiet' => \$Quiet,
@@ -598,7 +599,6 @@ if ("" != $opt_y)
{
$printorgunit = 0;
}
-$ZeroPad = $opt_j;
if ($Suffix =~ /o=/) {
($Organization) = $Suffix =~ /o=([^,]+)/;
@@ -1029,8 +1029,8 @@ sub MakeRandomLocality {
sub MakeRandomName {
local($Given_Name, $Surname, $Full_Name, $UID, $uniq, $first, $last, $RDN);
# Get the unique number depending if a seed was set or not.
- $uniq = int rand($Random_Seed) if ($opt_r);
- $uniq = $x if (!$opt_r);
+ $uniq = int rand($Random_Seed) if ($Random_Seed);
+ $uniq = $x if (!$Random_Seed);
$Given_Name = $given_names[rand @given_names];
$Surname = $family_names[rand @family_names];
@@ -1040,7 +1040,7 @@ sub MakeRandomName {
$UID = $first . $last . "$uniq";
# Create the uid based on the DN naming type defined
- if ($opt_b) { # use a uniquenumber for the RDN value
+ if ($BeginNum) { # use a uniquenumber for the RDN value
if ($ZeroPad) {
$RDN = sprintf "%0.${ZeroPad}d", $x;
} else {
9 years, 8 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/libglobs.c | 2
ldap/servers/slapd/snmp_collator.c | 89 ++++++++++++++++++-------------------
2 files changed, 46 insertions(+), 45 deletions(-)
New commits:
commit 03533f254530307ab6b831e1e1a9d7e7d41711f7
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Jan 30 17:57:09 2014 -0800
Ticket #47570 - slapi_ldap_init unusable during independent plugin development
Description:
RFE: making slapi_ldap_init callable without snmp_collator_init.
The api slapi_ldap_init calls set_snmp_interaction_row, in which
interaction_table_mutex is held. This patch replaces NSPR PR_(Un)Lock with
slapi_(un)lock_mutex. The slapi_(un)lock_mutex skips locking if the mutex
is not initialized.
https://fedorahosted.org/389/ticket/47570
Reviewed by rmeggins(a)redhat.com (Thank you, Rich!!)
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index e887ace..7ef06a8 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1556,7 +1556,7 @@ void libldap_init_debug_level(int *val_ptr)
}
#endif
-struct snmp_vars_t global_snmp_vars;
+static struct snmp_vars_t global_snmp_vars;
struct snmp_vars_t * g_get_global_snmp_vars(){
return &global_snmp_vars;
diff --git a/ldap/servers/slapd/snmp_collator.c b/ldap/servers/slapd/snmp_collator.c
index 4724b6f..f33202d 100644
--- a/ldap/servers/slapd/snmp_collator.c
+++ b/ldap/servers/slapd/snmp_collator.c
@@ -117,8 +117,8 @@ static Slapi_Eq_Context snmp_eq_ctx;
static int snmp_collator_stopped = 0;
/* synchronization stuff */
-static PRLock *interaction_table_mutex;
-static sem_t *stats_sem;
+static Slapi_Mutex *interaction_table_mutex = NULL;
+static sem_t *stats_sem = NULL;
/***********************************************************************************
@@ -129,7 +129,9 @@ static sem_t *stats_sem;
*
************************************************************************************/
-static int snmp_collator_init(){
+static int
+snmp_collator_init()
+{
int i;
/*
@@ -207,7 +209,9 @@ static int snmp_collator_init(){
sem_post(stats_sem);
/* create lock for interaction table */
- interaction_table_mutex = PR_NewLock();
+ if (!interaction_table_mutex) {
+ interaction_table_mutex = slapi_new_mutex();
+ }
return 0;
}
@@ -224,7 +228,7 @@ static int snmp_collator_init(){
void set_snmp_interaction_row(char *host, int port, int error)
{
int index;
- int isnew;
+ int isnew = 0;
char *dsName;
char *dsURL;
@@ -239,43 +243,42 @@ void set_snmp_interaction_row(char *host, int port, int error)
dsURL= make_ds_url(host, port);
/* lock around here to avoid race condition of two threads trying to update table at same time */
- PR_Lock(interaction_table_mutex);
- index = search_interaction_table(dsURL, &isnew);
-
- if(isnew){
- /* fillin the new row from scratch*/
- g_get_global_snmp_vars()->int_tbl[index].dsIntIndex = index;
- strncpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName,
- sizeof(g_get_global_snmp_vars()->int_tbl[index].dsName));
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation = time(0);
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0);
- if(error == 0){
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0);
- g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
- g_get_global_snmp_vars()->int_tbl[index].dsFailures = 0;
- g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 1;
- }else{
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = 0;
- g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 1;
- g_get_global_snmp_vars()->int_tbl[index].dsFailures = 1;
- g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 0;
- }
- strncpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL,
- sizeof(g_get_global_snmp_vars()->int_tbl[index].dsURL));
+ slapi_lock_mutex(interaction_table_mutex);
+ index = search_interaction_table(dsURL, &isnew);
+ if(isnew){
+ /* fillin the new row from scratch*/
+ g_get_global_snmp_vars()->int_tbl[index].dsIntIndex = index;
+ strncpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName,
+ sizeof(g_get_global_snmp_vars()->int_tbl[index].dsName));
+ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation = time(0);
+ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0);
+ if(error == 0){
+ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0);
+ g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
+ g_get_global_snmp_vars()->int_tbl[index].dsFailures = 0;
+ g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 1;
}else{
- /* just update the appropriate fields */
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0);
- if(error == 0){
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0);
- g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
- g_get_global_snmp_vars()->int_tbl[index].dsSuccesses += 1;
- }else{
- g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess +=1;
- g_get_global_snmp_vars()->int_tbl[index].dsFailures +=1;
- }
-
+ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = 0;
+ g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 1;
+ g_get_global_snmp_vars()->int_tbl[index].dsFailures = 1;
+ g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 0;
}
- PR_Unlock(interaction_table_mutex);
+ strncpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL,
+ sizeof(g_get_global_snmp_vars()->int_tbl[index].dsURL));
+ }else{
+ /* just update the appropriate fields */
+ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0);
+ if(error == 0){
+ g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0);
+ g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
+ g_get_global_snmp_vars()->int_tbl[index].dsSuccesses += 1;
+ }else{
+ g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess +=1;
+ g_get_global_snmp_vars()->int_tbl[index].dsFailures +=1;
+ }
+
+ }
+ slapi_unlock_mutex(interaction_table_mutex);
/* free the memory allocated for dsURL in call to ds_make_url */
if(dsURL != NULL){
slapi_ch_free( (void**)&dsURL );
@@ -298,8 +301,8 @@ static char *make_ds_url(char *host, int port){
return url;
}
-
/***********************************************************************************
+ * search_interaction_table is not used.
* searches the table for the url specified
* If there, returns index to update stats
* if, not there returns index of oldest interaction, and isnew flag is set
@@ -512,9 +515,7 @@ int snmp_collator_stop()
sem_unlink(stats_sem_name);
/* delete lock */
- if (interaction_table_mutex) {
- PR_DestroyLock(interaction_table_mutex);
- }
+ slapi_destroy_mutex(interaction_table_mutex);
#ifdef _WIN32
/* send the event so server down trap gets set on NT */
9 years, 8 months
dirsrvtests/tickets ldap/servers
by thierry bordaz
dirsrvtests/tickets/ticket47653MMR_test.py | 552 +++++++++++++++++++++++++++++
dirsrvtests/tickets/ticket47653_test.py | 432 ++++++++++++++++++++++
ldap/servers/plugins/acl/acl.h | 1
ldap/servers/plugins/acl/acllas.c | 55 ++
4 files changed, 1030 insertions(+), 10 deletions(-)
New commits:
commit 4db4a0eb62a428891aac4241c14498170930881f
Author: Thierry bordaz (tbordaz) <tbordaz(a)redhat.com>
Date: Thu Jan 30 19:09:32 2014 +0100
Ticket 47653 - Need a way to allow users to create entries assigned to themselves.
Bug Description:
Users need to be able to create, edit and delete their own entries.
An entry (i.e. cn=token1_user1234,dc=example,dc=com) has an attribute (i.e. ipatokenOwner)
that contains the entry DN of the user (i.e. uid=user1234,dc=example,dc=com).
Being bound as 'uid=user1234,dc=example,dc=com', we should be able to
any ldap operation on 'user1234' entries like cn=token1_user1234.
Fix Description:
It adds a BindRule: SELFDN, implemented in DS_LASUserDnAttrEval (called by DS_LASUserAttrEval).
The syntax in the aci is :
<userattr> = <attribute>#SELFDN
If the BindDN (lasinfo.clientDn) exists in entry.<attribute>
(lasinfo.resourceEntry[attrName]), then the aci matched
https://fedorahosted.org/389/ticket/47653
Reviewed by: Ludwig Krispenz, Rich Megginson
Platforms tested: F17/F19(jenkins)
Flag Day: no
Doc impact: no
diff --git a/dirsrvtests/tickets/ticket47653MMR_test.py b/dirsrvtests/tickets/ticket47653MMR_test.py
new file mode 100644
index 0000000..1f221c6
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47653MMR_test.py
@@ -0,0 +1,552 @@
+'''
+Created on Nov 7, 2013
+
+@author: tbordaz
+'''
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import time
+import logging
+import pytest
+import re
+from lib389 import DirSrv, Entry, tools
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from constants import *
+from lib389._constants import *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+#
+# important part. We can deploy Master1 and Master2 on different versions
+#
+installation1_prefix = None
+installation2_prefix = None
+
+TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
+OC_NAME = 'OCticket47653'
+MUST = "(postalAddress $ postalCode)"
+MAY = "(member $ street)"
+
+OTHER_NAME = 'other_entry'
+MAX_OTHERS = 10
+
+BIND_NAME = 'bind_entry'
+BIND_DN = 'cn=%s, %s' % (BIND_NAME, SUFFIX)
+BIND_PW = 'password'
+
+ENTRY_NAME = 'test_entry'
+ENTRY_DN = 'cn=%s, %s' % (ENTRY_NAME, SUFFIX)
+ENTRY_OC = "top person %s" % OC_NAME
+
+def _oc_definition(oid_ext, name, must=None, may=None):
+ oid = "1.2.3.4.5.6.7.8.9.10.%d" % oid_ext
+ desc = 'To test ticket 47490'
+ sup = 'person'
+ if not must:
+ must = MUST
+ if not may:
+ may = MAY
+
+ new_oc = "( %s NAME '%s' DESC '%s' SUP %s AUXILIARY MUST %s MAY %s )" % (oid, name, desc, sup, must, may)
+ return new_oc
+class TopologyMaster1Master2(object):
+ def __init__(self, master1, master2):
+ master1.open()
+ self.master1 = master1
+
+ master2.open()
+ self.master2 = master2
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ '''
+ This fixture is used to create a replicated topology for the 'module'.
+ The replicated topology is MASTER1 <-> Master2.
+ At the beginning, It may exists a master2 instance and/or a master2 instance.
+ It may also exists a backup for the master1 and/or the master2.
+
+ Principle:
+ If master1 instance exists:
+ restart it
+ If master2 instance exists:
+ restart it
+ If backup of master1 AND backup of master2 exists:
+ create or rebind to master1
+ create or rebind to master2
+
+ restore master1 from backup
+ restore master2 from backup
+ else:
+ Cleanup everything
+ remove instances
+ remove backups
+ Create instances
+ Initialize replication
+ Create backups
+ '''
+ global installation1_prefix
+ global installation2_prefix
+
+ # allocate master1 on a given deployement
+ master1 = DirSrv(verbose=False)
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+
+ # Args for the master1 instance
+ args_instance[SER_HOST] = HOST_MASTER_1
+ args_instance[SER_PORT] = PORT_MASTER_1
+ args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
+ args_master = args_instance.copy()
+ master1.allocate(args_master)
+
+ # allocate master1 on a given deployement
+ master2 = DirSrv(verbose=False)
+ if installation2_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation2_prefix
+
+ # Args for the consumer instance
+ args_instance[SER_HOST] = HOST_MASTER_2
+ args_instance[SER_PORT] = PORT_MASTER_2
+ args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
+ args_master = args_instance.copy()
+ master2.allocate(args_master)
+
+
+ # Get the status of the backups
+ backup_master1 = master1.checkBackupFS()
+ backup_master2 = master2.checkBackupFS()
+
+ # Get the status of the instance and restart it if it exists
+ instance_master1 = master1.exists()
+ if instance_master1:
+ master1.stop(timeout=10)
+ master1.start(timeout=10)
+
+ instance_master2 = master2.exists()
+ if instance_master2:
+ master2.stop(timeout=10)
+ master2.start(timeout=10)
+
+ if backup_master1 and backup_master2:
+ # The backups exist, assuming they are correct
+ # we just re-init the instances with them
+ if not instance_master1:
+ master1.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ master1.open()
+
+ if not instance_master2:
+ master2.create()
+ # Used to retrieve configuration information (dbdir, confdir...)
+ master2.open()
+
+ # restore master1 from backup
+ master1.stop(timeout=10)
+ master1.restoreFS(backup_master1)
+ master1.start(timeout=10)
+
+ # restore master2 from backup
+ master2.stop(timeout=10)
+ master2.restoreFS(backup_master2)
+ master2.start(timeout=10)
+ else:
+ # We should be here only in two conditions
+ # - This is the first time a test involve master-consumer
+ # so we need to create everything
+ # - Something weird happened (instance/backup destroyed)
+ # so we discard everything and recreate all
+
+ # Remove all the backups. So even if we have a specific backup file
+ # (e.g backup_master) we clear all backups that an instance my have created
+ if backup_master1:
+ master1.clearBackupFS()
+ if backup_master2:
+ master2.clearBackupFS()
+
+ # Remove all the instances
+ if instance_master1:
+ master1.delete()
+ if instance_master2:
+ master2.delete()
+
+ # Create the instances
+ master1.create()
+ master1.open()
+ master2.create()
+ master2.open()
+
+ #
+ # Now prepare the Master-Consumer topology
+ #
+ # First Enable replication
+ master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
+ master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
+
+ # Initialize the supplier->consumer
+
+ properties = {RA_NAME: r'meTo_$host:$port',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+ repl_agreement = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
+
+ if not repl_agreement:
+ log.fatal("Fail to create a replica agreement")
+ sys.exit(1)
+
+ log.debug("%s created" % repl_agreement)
+
+ properties = {RA_NAME: r'meTo_$host:$port',
+ RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
+ RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
+ RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
+ RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
+ master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
+
+ master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
+ master1.waitForReplInit(repl_agreement)
+
+ # Check replication is working fine
+ master1.add_s(Entry((TEST_REPL_DN, {
+ 'objectclass': "top person".split(),
+ 'sn': 'test_repl',
+ 'cn': 'test_repl'})))
+ loop = 0
+ while loop <= 10:
+ try:
+ ent = master2.getEntry(TEST_REPL_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ break
+ except ldap.NO_SUCH_OBJECT:
+ time.sleep(1)
+ loop += 1
+
+ # Time to create the backups
+ master1.stop(timeout=10)
+ master1.backupfile = master1.backupFS()
+ master1.start(timeout=10)
+
+ master2.stop(timeout=10)
+ master2.backupfile = master2.backupFS()
+ master2.start(timeout=10)
+
+ #
+ # Here we have two instances master and consumer
+ # with replication working. Either coming from a backup recovery
+ # or from a fresh (re)init
+ # Time to return the topology
+ return TopologyMaster1Master2(master1, master2)
+
+
+def test_ticket47653_init(topology):
+ """
+ It adds
+ - Objectclass with MAY 'member'
+ - an entry ('bind_entry') with which we bind to test the 'SELFDN' operation
+ It deletes the anonymous aci
+
+ """
+
+
+ topology.master1.log.info("Add %s that allows 'member' attribute" % OC_NAME)
+ new_oc = _oc_definition(2, OC_NAME, must = MUST, may = MAY)
+ topology.master1.addSchema('objectClasses', new_oc)
+
+
+ # entry used to bind with
+ topology.master1.log.info("Add %s" % BIND_DN)
+ topology.master1.add_s(Entry((BIND_DN, {
+ 'objectclass': "top person".split(),
+ 'sn': BIND_NAME,
+ 'cn': BIND_NAME,
+ 'userpassword': BIND_PW})))
+
+ # enable acl error logging
+ mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', str(128+8192))] # ACL + REPL
+ topology.master1.modify_s(DN_CONFIG, mod)
+ topology.master2.modify_s(DN_CONFIG, mod)
+
+ # get read of anonymous ACI for use 'read-search' aci in SEARCH test
+ ACI_ANONYMOUS = "(targetattr!=\"userPassword\")(version 3.0; acl \"Enable anonymous access\"; allow (read, search, compare) userdn=\"ldap:///anyone\";)"
+ mod = [(ldap.MOD_DELETE, 'aci', ACI_ANONYMOUS)]
+ topology.master1.modify_s(SUFFIX, mod)
+ topology.master2.modify_s(SUFFIX, mod)
+
+ # add dummy entries
+ for cpt in range(MAX_OTHERS):
+ name = "%s%d" % (OTHER_NAME, cpt)
+ topology.master1.add_s(Entry(("cn=%s,%s" % (name, SUFFIX), {
+ 'objectclass': "top person".split(),
+ 'sn': name,
+ 'cn': name})))
+
+def test_ticket47653_add(topology):
+ '''
+ This test ADD an entry on MASTER1 where 47653 is fixed. Then it checks that entry is replicated
+ on MASTER2 (even if on MASTER2 47653 is NOT fixed). Then update on MASTER2 and check the update on MASTER1
+
+ It checks that, bound as bind_entry,
+ - we can not ADD an entry without the proper SELFDN aci.
+ - with the proper ACI we can not ADD with 'member' attribute
+ - with the proper ACI and 'member' it succeeds to ADD
+ '''
+ topology.master1.log.info("\n\n######################### ADD ######################\n")
+
+ # bind as bind_entry
+ topology.master1.log.info("Bind as %s" % BIND_DN)
+ topology.master1.simple_bind_s(BIND_DN, BIND_PW)
+
+ # Prepare the entry with multivalued members
+ entry_with_members = Entry(ENTRY_DN)
+ entry_with_members.setValues('objectclass', 'top', 'person', 'OCticket47653')
+ entry_with_members.setValues('sn', ENTRY_NAME)
+ entry_with_members.setValues('cn', ENTRY_NAME)
+ entry_with_members.setValues('postalAddress', 'here')
+ entry_with_members.setValues('postalCode', '1234')
+ members = []
+ for cpt in range(MAX_OTHERS):
+ name = "%s%d" % (OTHER_NAME, cpt)
+ members.append("cn=%s,%s" % (name, SUFFIX))
+ members.append(BIND_DN)
+ entry_with_members.setValues('member', members)
+
+ # Prepare the entry with only one member value
+ entry_with_member = Entry(ENTRY_DN)
+ entry_with_member.setValues('objectclass', 'top', 'person', 'OCticket47653')
+ entry_with_member.setValues('sn', ENTRY_NAME)
+ entry_with_member.setValues('cn', ENTRY_NAME)
+ entry_with_member.setValues('postalAddress', 'here')
+ entry_with_member.setValues('postalCode', '1234')
+ member = []
+ member.append(BIND_DN)
+ entry_with_member.setValues('member', member)
+
+ # entry to add WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
+ try:
+ topology.master1.log.info("Try to add Add %s (aci is missing): %r" % (ENTRY_DN, entry_with_member))
+
+ topology.master1.add_s(entry_with_member)
+ except Exception as e:
+ topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+
+ # Ok Now add the proper ACI
+ topology.master1.log.info("Bind as %s and add the ADD SELFDN aci" % DN_DM)
+ topology.master1.simple_bind_s(DN_DM, PASSWORD)
+
+ ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+ ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+ ACI_ALLOW = "(version 3.0; acl \"SelfDN add\"; allow (add)"
+ ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+ ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+ mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+ topology.master1.modify_s(SUFFIX, mod)
+
+ # bind as bind_entry
+ topology.master1.log.info("Bind as %s" % BIND_DN)
+ topology.master1.simple_bind_s(BIND_DN, BIND_PW)
+
+ # entry to add WITHOUT member and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
+ try:
+ topology.master1.log.info("Try to add Add %s (member is missing)" % ENTRY_DN)
+ topology.master1.add_s(Entry((ENTRY_DN, {
+ 'objectclass': ENTRY_OC.split(),
+ 'sn': ENTRY_NAME,
+ 'cn': ENTRY_NAME,
+ 'postalAddress': 'here',
+ 'postalCode': '1234'})))
+ except Exception as e:
+ topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+ # entry to add WITH memberS and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
+ # member should contain only one value
+ try:
+ topology.master1.log.info("Try to add Add %s (with several member values)" % ENTRY_DN)
+ topology.master1.add_s(entry_with_members)
+ except Exception as e:
+ topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+ topology.master1.log.info("Try to add Add %s should be successful" % ENTRY_DN)
+ topology.master1.add_s(entry_with_member)
+
+ #
+ # Now check the entry as been replicated
+ #
+ topology.master2.simple_bind_s(DN_DM, PASSWORD)
+ topology.master1.log.info("Try to retrieve %s from Master2" % ENTRY_DN)
+ loop = 0
+ while loop <= 10:
+ try:
+ ent = topology.master2.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ break
+ except ldap.NO_SUCH_OBJECT:
+ time.sleep(1)
+ loop += 1
+ assert loop <= 10
+
+ # Now update the entry on Master2 (as DM because 47653 is possibly not fixed on M2)
+ topology.master1.log.info("Update %s on M2" % ENTRY_DN)
+ mod = [(ldap.MOD_REPLACE, 'description', 'test_add')]
+ topology.master2.modify_s(ENTRY_DN, mod)
+
+ topology.master1.simple_bind_s(DN_DM, PASSWORD)
+ loop = 0
+ while loop <= 10:
+ try:
+ ent = topology.master1.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ if ent.hasAttr('description') and (ent.getValue('description') == 'test_add'):
+ break
+ except ldap.NO_SUCH_OBJECT:
+ time.sleep(1)
+ loop += 1
+
+ assert ent.getValue('description') == 'test_add'
+
+def test_ticket47653_modify(topology):
+ '''
+ This test MOD an entry on MASTER1 where 47653 is fixed. Then it checks that update is replicated
+ on MASTER2 (even if on MASTER2 47653 is NOT fixed). Then update on MASTER2 (bound as BIND_DN).
+ This update may fail whether or not 47653 is fixed on MASTER2
+
+ It checks that, bound as bind_entry,
+ - we can not modify an entry without the proper SELFDN aci.
+ - adding the ACI, we can modify the entry
+ '''
+ # bind as bind_entry
+ topology.master1.log.info("Bind as %s" % BIND_DN)
+ topology.master1.simple_bind_s(BIND_DN, BIND_PW)
+
+ topology.master1.log.info("\n\n######################### MODIFY ######################\n")
+
+ # entry to modify WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
+ try:
+ topology.master1.log.info("Try to modify %s (aci is missing)" % ENTRY_DN)
+ mod = [(ldap.MOD_REPLACE, 'postalCode', '9876')]
+ topology.master1.modify_s(ENTRY_DN, mod)
+ except Exception as e:
+ topology.master1.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+
+ # Ok Now add the proper ACI
+ topology.master1.log.info("Bind as %s and add the WRITE SELFDN aci" % DN_DM)
+ topology.master1.simple_bind_s(DN_DM, PASSWORD)
+
+ ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+ ACI_TARGETATTR = "(targetattr = *)"
+ ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+ ACI_ALLOW = "(version 3.0; acl \"SelfDN write\"; allow (write)"
+ ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+ ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+ mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+ topology.master1.modify_s(SUFFIX, mod)
+
+ # bind as bind_entry
+ topology.master1.log.info("M1: Bind as %s" % BIND_DN)
+ topology.master1.simple_bind_s(BIND_DN, BIND_PW)
+
+ # modify the entry and checks the value
+ topology.master1.log.info("M1: Try to modify %s. It should succeeds" % ENTRY_DN)
+ mod = [(ldap.MOD_REPLACE, 'postalCode', '1928')]
+ topology.master1.modify_s(ENTRY_DN, mod)
+
+ topology.master1.log.info("M1: Bind as %s" % DN_DM)
+ topology.master1.simple_bind_s(DN_DM, PASSWORD)
+
+ topology.master1.log.info("M1: Check the update of %s" % ENTRY_DN)
+ ents = topology.master1.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
+ assert len(ents) == 1
+ assert ents[0].postalCode == '1928'
+
+
+ #
+ # Now check the update has been replicated on M2
+ topology.master1.log.info("M2: Bind as %s" % DN_DM)
+ topology.master2.simple_bind_s(DN_DM, PASSWORD)
+ topology.master1.log.info("M2: Try to retrieve %s" % ENTRY_DN)
+ loop = 0
+ while loop <= 10:
+ try:
+ ent = topology.master2.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ if ent.hasAttr('postalCode') and (ent.getValue('postalCode') == '1928'):
+ break
+ except ldap.NO_SUCH_OBJECT:
+ time.sleep(1)
+ loop += 1
+ assert loop <= 10
+ assert ent.getValue('postalCode') == '1928'
+
+
+ # Now update the entry on Master2 bound as BIND_DN (update may fail if 47653 is not fixed on M2)
+ topology.master1.log.info("M2: Update %s (bound as %s)" % (ENTRY_DN, BIND_DN))
+ topology.master2.simple_bind_s(BIND_DN, PASSWORD)
+ fail = False
+ try:
+ mod = [(ldap.MOD_REPLACE, 'postalCode', '1929')]
+ topology.master2.modify_s(ENTRY_DN, mod)
+ fail = False
+ except ldap.INSUFFICIENT_ACCESS:
+ topology.master1.log.info("M2: Exception (INSUFFICIENT_ACCESS): that is fine the bug is possibly not fixed on M2")
+ fail = True
+ except Exception as e:
+ topology.master1.log.info("M2: Exception (not expected): %s" % type(e).__name__)
+ assert 0
+
+ if not fail:
+ # Check the update has been replicaed on M1
+ topology.master1.log.info("M1: Bind as %s" % DN_DM)
+ topology.master1.simple_bind_s(DN_DM, PASSWORD)
+ topology.master1.log.info("M1: Check %s.postalCode=1929)" % (ENTRY_DN))
+ loop = 0
+ while loop <= 10:
+ try:
+ ent = topology.master1.getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ if ent.hasAttr('postalCode') and (ent.getValue('postalCode') == '1929'):
+ break
+ except ldap.NO_SUCH_OBJECT:
+ time.sleep(1)
+ loop += 1
+ assert ent.getValue('postalCode') == '1929'
+
+def test_ticket47653_final(topology):
+ topology.master1.stop(timeout=10)
+ topology.master2.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 installation1_prefix
+ global installation2_prefix
+ installation1_prefix = None
+ installation2_prefix = None
+
+ topo = topology(True)
+ test_ticket47653_init(topo)
+
+ test_ticket47653_add(topo)
+ test_ticket47653_modify(topo)
+
+ test_ticket47653_final(topo)
+
+
+
+
+if __name__ == '__main__':
+ run_isolated()
+
diff --git a/dirsrvtests/tickets/ticket47653_test.py b/dirsrvtests/tickets/ticket47653_test.py
new file mode 100644
index 0000000..2693093
--- /dev/null
+++ b/dirsrvtests/tickets/ticket47653_test.py
@@ -0,0 +1,432 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import socket
+import time
+import logging
+import pytest
+from lib389 import DirSrv, Entry, tools
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from constants import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+OC_NAME = 'OCticket47653'
+MUST = "(postalAddress $ postalCode)"
+MAY = "(member $ street)"
+
+OTHER_NAME = 'other_entry'
+MAX_OTHERS = 10
+
+BIND_NAME = 'bind_entry'
+BIND_DN = 'cn=%s, %s' % (BIND_NAME, SUFFIX)
+BIND_PW = 'password'
+
+ENTRY_NAME = 'test_entry'
+ENTRY_DN = 'cn=%s, %s' % (ENTRY_NAME, SUFFIX)
+ENTRY_OC = "top person %s" % OC_NAME
+
+def _oc_definition(oid_ext, name, must=None, may=None):
+ oid = "1.2.3.4.5.6.7.8.9.10.%d" % oid_ext
+ desc = 'To test ticket 47490'
+ sup = 'person'
+ if not must:
+ must = MUST
+ if not may:
+ may = MAY
+
+ new_oc = "( %s NAME '%s' DESC '%s' SUP %s AUXILIARY MUST %s MAY %s )" % (oid, name, desc, sup, must, may)
+ return new_oc
+
+
+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)
+
+ #
+ # 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_ticket47653_init(topology):
+ """
+ It adds
+ - Objectclass with MAY 'member'
+ - an entry ('bind_entry') with which we bind to test the 'SELFDN' operation
+ It deletes the anonymous aci
+
+ """
+
+
+ topology.standalone.log.info("Add %s that allows 'member' attribute" % OC_NAME)
+ new_oc = _oc_definition(2, OC_NAME, must = MUST, may = MAY)
+ topology.standalone.addSchema('objectClasses', new_oc)
+
+
+ # entry used to bind with
+ topology.standalone.log.info("Add %s" % BIND_DN)
+ topology.standalone.add_s(Entry((BIND_DN, {
+ 'objectclass': "top person".split(),
+ 'sn': BIND_NAME,
+ 'cn': BIND_NAME,
+ 'userpassword': BIND_PW})))
+
+ # enable acl error logging
+ mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '128')]
+ topology.standalone.modify_s(DN_CONFIG, mod)
+
+ # get read of anonymous ACI for use 'read-search' aci in SEARCH test
+ ACI_ANONYMOUS = "(targetattr!=\"userPassword\")(version 3.0; acl \"Enable anonymous access\"; allow (read, search, compare) userdn=\"ldap:///anyone\";)"
+ mod = [(ldap.MOD_DELETE, 'aci', ACI_ANONYMOUS)]
+ topology.standalone.modify_s(SUFFIX, mod)
+
+ # add dummy entries
+ for cpt in range(MAX_OTHERS):
+ name = "%s%d" % (OTHER_NAME, cpt)
+ topology.standalone.add_s(Entry(("cn=%s,%s" % (name, SUFFIX), {
+ 'objectclass': "top person".split(),
+ 'sn': name,
+ 'cn': name})))
+
+
+def test_ticket47653_add(topology):
+ '''
+ It checks that, bound as bind_entry,
+ - we can not ADD an entry without the proper SELFDN aci.
+ - with the proper ACI we can not ADD with 'member' attribute
+ - with the proper ACI and 'member' it succeeds to ADD
+ '''
+ topology.standalone.log.info("\n\n######################### ADD ######################\n")
+
+ # bind as bind_entry
+ topology.standalone.log.info("Bind as %s" % BIND_DN)
+ topology.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+ # Prepare the entry with multivalued members
+ entry_with_members = Entry(ENTRY_DN)
+ entry_with_members.setValues('objectclass', 'top', 'person', 'OCticket47653')
+ entry_with_members.setValues('sn', ENTRY_NAME)
+ entry_with_members.setValues('cn', ENTRY_NAME)
+ entry_with_members.setValues('postalAddress', 'here')
+ entry_with_members.setValues('postalCode', '1234')
+ members = []
+ for cpt in range(MAX_OTHERS):
+ name = "%s%d" % (OTHER_NAME, cpt)
+ members.append("cn=%s,%s" % (name, SUFFIX))
+ members.append(BIND_DN)
+ entry_with_members.setValues('member', members)
+
+ # Prepare the entry with one member
+ entry_with_member = Entry(ENTRY_DN)
+ entry_with_member.setValues('objectclass', 'top', 'person', 'OCticket47653')
+ entry_with_member.setValues('sn', ENTRY_NAME)
+ entry_with_member.setValues('cn', ENTRY_NAME)
+ entry_with_member.setValues('postalAddress', 'here')
+ entry_with_member.setValues('postalCode', '1234')
+ member = []
+ member.append(BIND_DN)
+ entry_with_member.setValues('member', member)
+
+ # entry to add WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
+ try:
+ topology.standalone.log.info("Try to add Add %s (aci is missing): %r" % (ENTRY_DN, entry_with_member))
+
+ topology.standalone.add_s(entry_with_member)
+ except Exception as e:
+ topology.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+
+ # Ok Now add the proper ACI
+ topology.standalone.log.info("Bind as %s and add the ADD SELFDN aci" % DN_DM)
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+ ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+ ACI_ALLOW = "(version 3.0; acl \"SelfDN add\"; allow (add)"
+ ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+ ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+ mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+ topology.standalone.modify_s(SUFFIX, mod)
+
+ # bind as bind_entry
+ topology.standalone.log.info("Bind as %s" % BIND_DN)
+ topology.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+ # entry to add WITHOUT member and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
+ try:
+ topology.standalone.log.info("Try to add Add %s (member is missing)" % ENTRY_DN)
+ topology.standalone.add_s(Entry((ENTRY_DN, {
+ 'objectclass': ENTRY_OC.split(),
+ 'sn': ENTRY_NAME,
+ 'cn': ENTRY_NAME,
+ 'postalAddress': 'here',
+ 'postalCode': '1234'})))
+ except Exception as e:
+ topology.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+ # entry to add WITH memberS and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
+ # member should contain only one value
+ try:
+ topology.standalone.log.info("Try to add Add %s (with several member values)" % ENTRY_DN)
+ topology.standalone.add_s(entry_with_members)
+ except Exception as e:
+ topology.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+ topology.standalone.log.info("Try to add Add %s should be successful" % ENTRY_DN)
+ topology.standalone.add_s(entry_with_member)
+
+def test_ticket47653_search(topology):
+ '''
+ It checks that, bound as bind_entry,
+ - we can not search an entry without the proper SELFDN aci.
+ - adding the ACI, we can search the entry
+ '''
+ topology.standalone.log.info("\n\n######################### SEARCH ######################\n")
+ # bind as bind_entry
+ topology.standalone.log.info("Bind as %s" % BIND_DN)
+ topology.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+ # entry to search WITH member being BIND_DN but WITHOUT the ACI -> no entry returned
+ topology.standalone.log.info("Try to search %s (aci is missing)" % ENTRY_DN)
+ ents = topology.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
+ assert len(ents) == 0
+
+
+ # Ok Now add the proper ACI
+ topology.standalone.log.info("Bind as %s and add the READ/SEARCH SELFDN aci" % DN_DM)
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+ ACI_TARGETATTR = "(targetattr = *)"
+ ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+ ACI_ALLOW = "(version 3.0; acl \"SelfDN search-read\"; allow (read, search, compare)"
+ ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+ ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+ mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+ topology.standalone.modify_s(SUFFIX, mod)
+
+ # bind as bind_entry
+ topology.standalone.log.info("Bind as %s" % BIND_DN)
+ topology.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+ # entry to search with the proper aci
+ topology.standalone.log.info("Try to search %s should be successful" % ENTRY_DN)
+ ents = topology.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
+ assert len(ents) == 1
+
+def test_ticket47653_modify(topology):
+ '''
+ It checks that, bound as bind_entry,
+ - we can not modify an entry without the proper SELFDN aci.
+ - adding the ACI, we can modify the entry
+ '''
+ # bind as bind_entry
+ topology.standalone.log.info("Bind as %s" % BIND_DN)
+ topology.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+ topology.standalone.log.info("\n\n######################### MODIFY ######################\n")
+
+ # entry to modify WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
+ try:
+ topology.standalone.log.info("Try to modify %s (aci is missing)" % ENTRY_DN)
+ mod = [(ldap.MOD_REPLACE, 'postalCode', '9876')]
+ topology.standalone.modify_s(ENTRY_DN, mod)
+ except Exception as e:
+ topology.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+
+ # Ok Now add the proper ACI
+ topology.standalone.log.info("Bind as %s and add the WRITE SELFDN aci" % DN_DM)
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+ ACI_TARGETATTR = "(targetattr = *)"
+ ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+ ACI_ALLOW = "(version 3.0; acl \"SelfDN write\"; allow (write)"
+ ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+ ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+ mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+ topology.standalone.modify_s(SUFFIX, mod)
+
+ # bind as bind_entry
+ topology.standalone.log.info("Bind as %s" % BIND_DN)
+ topology.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+ # modify the entry and checks the value
+ topology.standalone.log.info("Try to modify %s. It should succeeds" % ENTRY_DN)
+ mod = [(ldap.MOD_REPLACE, 'postalCode', '1928')]
+ topology.standalone.modify_s(ENTRY_DN, mod)
+
+ ents = topology.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
+ assert len(ents) == 1
+ assert ents[0].postalCode == '1928'
+
+def test_ticket47653_delete(topology):
+ '''
+ It checks that, bound as bind_entry,
+ - we can not delete an entry without the proper SELFDN aci.
+ - adding the ACI, we can delete the entry
+ '''
+ topology.standalone.log.info("\n\n######################### DELETE ######################\n")
+
+ # bind as bind_entry
+ topology.standalone.log.info("Bind as %s" % BIND_DN)
+ topology.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+ # entry to delete WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
+ try:
+ topology.standalone.log.info("Try to delete %s (aci is missing)" % ENTRY_DN)
+ topology.standalone.delete_s(ENTRY_DN)
+ except Exception as e:
+ topology.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+ assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+ # Ok Now add the proper ACI
+ topology.standalone.log.info("Bind as %s and add the READ/SEARCH SELFDN aci" % DN_DM)
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+ ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+ ACI_ALLOW = "(version 3.0; acl \"SelfDN delete\"; allow (delete)"
+ ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+ ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+ mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+ topology.standalone.modify_s(SUFFIX, mod)
+
+ # bind as bind_entry
+ topology.standalone.log.info("Bind as %s" % BIND_DN)
+ topology.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+ # entry to search with the proper aci
+ topology.standalone.log.info("Try to delete %s should be successful" % ENTRY_DN)
+ topology.standalone.delete_s(ENTRY_DN)
+
+def test_ticket47653_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_ticket47653_init(topo)
+
+ test_ticket47653_add(topo)
+ test_ticket47653_search(topo)
+ test_ticket47653_modify(topo)
+ test_ticket47653_delete(topo)
+
+ test_ticket47653_final(topo)
+
+
+if __name__ == '__main__':
+ run_isolated()
+
diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h
index cc042d6..1a05e1f 100644
--- a/ldap/servers/plugins/acl/acl.h
+++ b/ldap/servers/plugins/acl/acl.h
@@ -145,6 +145,7 @@ static char* const access_str_proxy = "proxy";
#define DS_LAS_GROUP "group"
#define DS_LAS_USERDN "userdn"
#define DS_LAS_GROUPDN "groupdn"
+#define DS_LAS_SELFDNATTR "selfdnattr"
#define DS_LAS_USERDNATTR "userdnattr"
#define DS_LAS_AUTHMETHOD "authmethod"
#define DS_LAS_GROUPDNATTR "groupdnattr"
diff --git a/ldap/servers/plugins/acl/acllas.c b/ldap/servers/plugins/acl/acllas.c
index 3646fcd..38bc9a1 100644
--- a/ldap/servers/plugins/acl/acllas.c
+++ b/ldap/servers/plugins/acl/acllas.c
@@ -179,7 +179,7 @@
DS_LASRoleDnEval - LAS Evaluation for ROLEDN -
three-valued logic
logical combination: || and !=
- DS_LASUserDnAttrEval - LAS Evaluation for USERDNATTR -
+ DS_LASUserDnAttrEval - LAS Evaluation for USERDNATTR and SELFDNATTR-
three-valued logic
logical combination || (over specified attribute values and
parent keyword levels), !=
@@ -1170,11 +1170,21 @@ DS_LASUserDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
char *attrs[2] = { LDAP_ALL_USER_ATTRS, NULL };
lasInfo lasinfo;
int got_undefined = 0;
+ PRBool selfdn;
+
+ if (attr_name == NULL ||
+ (strcmp(DS_LAS_SELFDNATTR, attr_name) && strcmp(DS_LAS_USERDNATTR, attr_name))) {
+ slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+ "DS_LASUserDnattr: invalid attr_name (should be %s or %s)\n",
+ DS_LAS_SELFDNATTR, DS_LAS_USERDNATTR);
+ return LAS_EVAL_FAIL;
+ }
+ selfdn = (strcmp(DS_LAS_SELFDNATTR, attr_name) == 0) ? PR_TRUE : PR_FALSE;
if ( 0 != (rc = __acllas_setup (errp, attr_name, comparator, 0, /* Don't allow range comparators */
attr_pattern,cachable,LAS_cookie,
subject, resource, auth_info,global_auth,
- DS_LAS_USERDNATTR, "DS_LASUserDnAttrEval",
+ attr_name, "DS_LASUserDnAttrEval",
&lasinfo )) ) {
return LAS_EVAL_FAIL;
}
@@ -1269,6 +1279,7 @@ DS_LASUserDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
if ( levels[i] == 0 ) {
Slapi_Value *sval=NULL;
const struct berval *attrVal;
+ int numValues = 0;
int j;
/*
@@ -1280,13 +1291,32 @@ DS_LASUserDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
*/
if ( lasinfo.aclpb->aclpb_optype == SLAPI_OPERATION_ADD) {
- slapi_log_error( SLAPI_LOG_ACL, plugin_name,
- "ACL info: userdnAttr does not allow ADD permission at level 0.\n");
- got_undefined = 1;
- continue;
+ if (selfdn) {
+ slapi_log_error(SLAPI_LOG_ACL, plugin_name,
+ "ACL info: %s DOES allow ADD permission at level 0.\n", attr_name);
+ } else {
+ slapi_log_error(SLAPI_LOG_ACL, plugin_name,
+ "ACL info: %s does not allow ADD permission at level 0.\n", attr_name);
+ got_undefined = 1;
+ continue;
+ }
}
slapi_entry_attr_find( lasinfo.resourceEntry, attrName, &a);
if ( NULL == a ) continue;
+
+ if (selfdn) {
+ /* Checks that attrName has only one value. This is the only condition enforced
+ * when using SELFDN
+ */
+ slapi_attr_get_numvalues((const Slapi_Attr *) a, &numValues);
+ if (numValues != 1) {
+ slapi_log_error(SLAPI_LOG_ACL, plugin_name,
+ "DS_LASSelfDnAttrEval: fail because the retrieved %s in resource has more than one value (%d)\n",
+ attrName, numValues);
+ got_undefined = 1;
+ continue;
+ }
+ }
j= slapi_attr_first_value ( a,&sval );
while ( j != -1 ) {
attrVal = slapi_value_get_berval ( sval );
@@ -1304,7 +1334,7 @@ DS_LASUserDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
char ebuf [ BUFSIZ ];
/* Wow it matches */
slapi_log_error( SLAPI_LOG_ACL, plugin_name,
- "userdnAttr matches(%s, %s) level (%d)\n",
+ "%s matches(%s, %s) level (%d)\n", attr_name,
val,
ACL_ESCAPE_STRING_WITH_PUNCTUATION (lasinfo.clientDn, ebuf),
0);
@@ -1356,7 +1386,7 @@ DS_LASUserDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
if (info.result) {
matched = ACL_TRUE;
slapi_log_error( SLAPI_LOG_ACL, plugin_name,
- "userdnAttr matches at level (%d)\n", levels[i]);
+ "%s matches at level (%d)\n", attr_name, levels[i]);
}
}
if (matched == ACL_TRUE) {
@@ -1380,7 +1410,7 @@ DS_LASUserDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
} else {
rc = LAS_EVAL_FAIL;
slapi_log_error( SLAPI_LOG_ACL, plugin_name,
- "Returning UNDEFINED for userdnattr evaluation.\n");
+ "Returning UNDEFINED for %s evaluation.\n", attr_name);
}
return rc;
@@ -3385,7 +3415,12 @@ DS_LASUserAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
attrName, cachable, LAS_cookie,
subject, resource, auth_info, global_auth);
goto done_las;
- }
+ } else if (0 == strncasecmp ( attrValue, "SELFDN", 6)) {
+ matched = DS_LASUserDnAttrEval (errp,DS_LAS_SELFDNATTR, comparator,
+ attrName, cachable, LAS_cookie,
+ subject, resource, auth_info, global_auth);
+ goto done_las;
+ }
if ( lasinfo.aclpb && ( NULL == lasinfo.aclpb->aclpb_client_entry )) {
/* SD 00/16/03 pass NULL in case the req is chained */
9 years, 8 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/dbhelp.c | 53 +++++++++++++++++++++++++++++++--
ldap/servers/slapd/back-ldbm/dblayer.c | 25 +++++++--------
ldap/servers/slapd/back-ldbm/dblayer.h | 2 -
ldap/servers/slapd/control.c | 2 -
4 files changed, 64 insertions(+), 18 deletions(-)
New commits:
commit 0e7f59d6c22e02a0604e028b878003ac0baf5a1c
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Jan 28 14:20:23 2014 -0800
Ticket #47463 - IDL-style can become mismatched during partial restoration
The commit to 389-ds-base-1.3.2 and newer is back ported to 389-ds-
1.2.11 trough 1.3.1 by Thomas E Lackey.
commit b43145218dccc8c9c16ecadad80f94bf58c73d57
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Sep 27 17:58:03 2013 -0700
Description by telackey:
When doing a partial/FRI restoration the database files are copied
key-by-key. This is necessary to reset the LSNs so the restored
files can merge into the existing DB environment (cf. dblayer_copy_
file_resetlsns()) in a recoverable way.
However, dblayer_copy_file_keybykey() does not set the comparison
function before calling DB->put(), which means that the restored
files will not necessarily be using the proper function.
While all the keys are technically present, indexed searches can
still fail to return relevant results because the key order is
significant when intersecting the results with the other indices.
Note: The bug was reported and the patch was provided by telackey.
(Thank you, Thomas!)
Additional fix by nhosoi:
The entryrdn index uses its special dup compare function. The dup
compare function is set when the restoring index file is entryrdn.
https://fedorahosted.org/389/ticket/47463
Reviewed by rmeggins (Thank you, Rich!)
(cherry picked from commit abe5c894686f46b60f069f8cbd8aa909b34d81a1)
(cherry picked from commit 9ebe2e80d090537e8f905ef54990bfdec088e267)
diff --git a/ldap/servers/slapd/back-ldbm/dbhelp.c b/ldap/servers/slapd/back-ldbm/dbhelp.c
index 1165831..b0d17d3 100644
--- a/ldap/servers/slapd/back-ldbm/dbhelp.c
+++ b/ldap/servers/slapd/back-ldbm/dbhelp.c
@@ -49,7 +49,13 @@
#include "back-ldbm.h"
#include "dblayer.h"
-static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv)
+static int
+dblayer_copy_file_keybykey(DB_ENV *env,
+ char *source_file_name,
+ char *destination_file_name,
+ int overwrite,
+ dblayer_private *priv,
+ ldbm_instance *inst)
{
int retval = 0;
int retval_cleanup = 0;
@@ -62,6 +68,7 @@ static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char
int cursor_flag = 0;
int finished = 0;
int mode = 0;
+ char *p = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> dblayer_copy_file_keybykey\n", 0, 0, 0 );
@@ -119,6 +126,40 @@ static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_keybykey, set_pagesize error %d: %s\n", retval, db_strerror(retval), 0);
goto error;
}
+
+ /* TEL 20130412: Make sure to set the dup comparison function if needed.
+ * We key our decision off of the presence of new IDL and dup flags on
+ * the source database. This is similar dblayer_open_file, except that
+ * we don't have the attribute info index mask for VLV. That should be OK
+ * since the DB_DUP and DB_DUPSORT flags wouldn't have been toggled on
+ * unless they passed the check on the source.
+ */
+ /* Entryrdn index has its own dup compare function */
+ if ((p = PL_strcasestr(source_file_name, LDBM_ENTRYRDN_STR)) &&
+ (*(p + sizeof(LDBM_ENTRYRDN_STR) - 1) == '.')) {
+ /* entryrdn.db */
+ struct attrinfo *ai = NULL;
+ ainfo_get(inst->inst_be, LDBM_ENTRYRDN_STR, &ai);
+ if (ai->ai_dup_cmp_fn) {
+ /* If set, use the special dup compare callback */
+ retval = destination_file->set_dup_compare(destination_file, ai->ai_dup_cmp_fn);
+ if (retval) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "dblayer_copy_file_keybykey(entryrdn), set_dup_compare error %d: %s\n",
+ retval, db_strerror(retval));
+ goto error;
+ }
+ }
+ } else if (idl_get_idl_new() && (dbflags & DB_DUP) && (dbflags & DB_DUPSORT)) {
+ retval = destination_file->set_dup_compare(destination_file, idl_new_compare_dups);
+ if (retval) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "dblayer_copy_file_keybykey, set_dup_compare error %d: %s\n",
+ retval, db_strerror(retval));
+ goto error;
+ }
+ }
+
retval = (destination_file->open)(destination_file, NULL, destination_file_name, NULL, dbtype, DB_CREATE | DB_EXCL, mode);
if (retval) {
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_keybykey, Open error %d: %s\n", retval, db_strerror(retval), 0);
@@ -190,7 +231,13 @@ error:
return retval;
}
-int dblayer_copy_file_resetlsns(char *home_dir ,char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv)
+int
+dblayer_copy_file_resetlsns(char *home_dir,
+ char *source_file_name,
+ char *destination_file_name,
+ int overwrite,
+ dblayer_private *priv,
+ ldbm_instance *inst)
{
int retval = 0;
DB_ENV *env = NULL;
@@ -205,7 +252,7 @@ int dblayer_copy_file_resetlsns(char *home_dir ,char *source_file_name, char *de
goto out;
}
/* Do the copy */
- retval = dblayer_copy_file_keybykey(env, source_file_name, destination_file_name, overwrite, priv);
+ retval = dblayer_copy_file_keybykey(env, source_file_name, destination_file_name, overwrite, priv, inst);
if (retval) {
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_resetlsns: Copy not completed successfully.", 0, 0, 0);
}
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 46334bd..844b3b7 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -5653,6 +5653,7 @@ dblayer_copy_directory(struct ldbminfo *li,
char inst_dir[MAXPATHLEN];
char sep;
int suffix_len = 0;
+ ldbm_instance *inst = NULL;
if (!src_dir || '\0' == *src_dir)
{
@@ -5676,6 +5677,14 @@ dblayer_copy_directory(struct ldbminfo *li,
else
relative_instance_name++;
+ inst = ldbm_instance_find_by_name(li, relative_instance_name);
+ if (NULL == inst) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; "
+ "Instance path %s could be invalid.\n",
+ relative_instance_name, src_dir, 0);
+ return return_value;
+ }
+
if (is_fullpath(src_dir))
{
new_src_dir = src_dir;
@@ -5683,15 +5692,6 @@ dblayer_copy_directory(struct ldbminfo *li,
else
{
int len;
- ldbm_instance *inst =
- ldbm_instance_find_by_name(li, relative_instance_name);
- if (NULL == inst)
- {
- LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; "
- "Instance path %s could be invalid.\n",
- relative_instance_name, src_dir, 0);
- return return_value;
- }
inst_dirp = dblayer_get_full_inst_dir(inst->inst_li, inst,
inst_dir, MAXPATHLEN);
@@ -5811,13 +5811,12 @@ dblayer_copy_directory(struct ldbminfo *li,
/* If the file is a database file, and resetlsns is set, then we need to do a key by key copy */
/* PL_strcmp takes NULL arg */
if (resetlsns &&
- (PL_strcmp(LDBM_FILENAME_SUFFIX, strrchr(filename1, '.'))
- == 0)) {
+ (PL_strcmp(LDBM_FILENAME_SUFFIX, strrchr(filename1, '.')) == 0)) {
return_value = dblayer_copy_file_resetlsns(src_dir, filename1, filename2,
- 0, priv);
+ 0, priv, inst);
} else {
return_value = dblayer_copyfile(filename1, filename2,
- 0, priv->dblayer_file_mode);
+ 0, priv->dblayer_file_mode);
}
slapi_ch_free((void**)&filename1);
slapi_ch_free((void**)&filename2);
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.h b/ldap/servers/slapd/back-ldbm/dblayer.h
index 7f3200c..4ff9d53 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.h
+++ b/ldap/servers/slapd/back-ldbm/dblayer.h
@@ -201,7 +201,7 @@ int dblayer_make_private_simple_env(char *db_home_dir, DB_ENV **env);
/* Copy a database file, preserving all its contents (used to reset the LSNs in the file in order to move
* it from one transacted environment to another.
*/
-int dblayer_copy_file_resetlsns(char *home_dir, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv);
+int dblayer_copy_file_resetlsns(char *home_dir, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv, ldbm_instance *inst);
/* Turn on the various logging and debug options for DB */
void dblayer_set_env_debugging(DB_ENV *pEnv, dblayer_private *priv);
diff --git a/ldap/servers/slapd/control.c b/ldap/servers/slapd/control.c
index e614d50..e7b7562 100644
--- a/ldap/servers/slapd/control.c
+++ b/ldap/servers/slapd/control.c
@@ -361,7 +361,7 @@ get_ldapmessage_controls_ext(
slapi_pblock_set(pb, SLAPI_MANAGEDSAIT, &ctrl_not_found);
slapi_pblock_set(pb, SLAPI_PWPOLICY, &ctrl_not_found);
slapi_log_error(SLAPI_LOG_CONNS, "connection", "Warning: conn=%d op=%d contains an empty list of controls\n",
- pb->pb_conn->c_connid, pb->pb_op->o_opid);
+ (int)pb->pb_conn->c_connid, pb->pb_op->o_opid);
} else {
if ((tag != LBER_END_OF_SEQORSET) && (len != -1)) {
goto free_and_return;
9 years, 8 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/dbhelp.c | 53 +++++++++++++++++++++++++++++++--
ldap/servers/slapd/back-ldbm/dblayer.c | 29 ++++++++----------
ldap/servers/slapd/back-ldbm/dblayer.h | 2 -
3 files changed, 65 insertions(+), 19 deletions(-)
New commits:
commit 9ebe2e80d090537e8f905ef54990bfdec088e267
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Jan 28 11:25:34 2014 -0800
Ticket #47463 - IDL-style can become mismatched during partial restoration
The commit to 389-ds-base-1.3.2 and newer is back ported to 389-ds-
1.2.11 trough 1.3.1 by Thomas E Lackey.
commit b43145218dccc8c9c16ecadad80f94bf58c73d57
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Sep 27 17:58:03 2013 -0700
Description by telackey:
When doing a partial/FRI restoration the database files are copied
key-by-key. This is necessary to reset the LSNs so the restored
files can merge into the existing DB environment (cf. dblayer_copy_
file_resetlsns()) in a recoverable way.
However, dblayer_copy_file_keybykey() does not set the comparison
function before calling DB->put(), which means that the restored
files will not necessarily be using the proper function.
While all the keys are technically present, indexed searches can
still fail to return relevant results because the key order is
significant when intersecting the results with the other indices.
Note: The bug was reported and the patch was provided by telackey.
(Thank you, Thomas!)
Additional fix by nhosoi:
The entryrdn index uses its special dup compare function. The dup
compare function is set when the restoring index file is entryrdn.
https://fedorahosted.org/389/ticket/47463
Reviewed by rmeggins (Thank you, Rich!)
(cherry picked from commit abe5c894686f46b60f069f8cbd8aa909b34d81a1)
diff --git a/ldap/servers/slapd/back-ldbm/dbhelp.c b/ldap/servers/slapd/back-ldbm/dbhelp.c
index 1165831..b0d17d3 100644
--- a/ldap/servers/slapd/back-ldbm/dbhelp.c
+++ b/ldap/servers/slapd/back-ldbm/dbhelp.c
@@ -49,7 +49,13 @@
#include "back-ldbm.h"
#include "dblayer.h"
-static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv)
+static int
+dblayer_copy_file_keybykey(DB_ENV *env,
+ char *source_file_name,
+ char *destination_file_name,
+ int overwrite,
+ dblayer_private *priv,
+ ldbm_instance *inst)
{
int retval = 0;
int retval_cleanup = 0;
@@ -62,6 +68,7 @@ static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char
int cursor_flag = 0;
int finished = 0;
int mode = 0;
+ char *p = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> dblayer_copy_file_keybykey\n", 0, 0, 0 );
@@ -119,6 +126,40 @@ static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_keybykey, set_pagesize error %d: %s\n", retval, db_strerror(retval), 0);
goto error;
}
+
+ /* TEL 20130412: Make sure to set the dup comparison function if needed.
+ * We key our decision off of the presence of new IDL and dup flags on
+ * the source database. This is similar dblayer_open_file, except that
+ * we don't have the attribute info index mask for VLV. That should be OK
+ * since the DB_DUP and DB_DUPSORT flags wouldn't have been toggled on
+ * unless they passed the check on the source.
+ */
+ /* Entryrdn index has its own dup compare function */
+ if ((p = PL_strcasestr(source_file_name, LDBM_ENTRYRDN_STR)) &&
+ (*(p + sizeof(LDBM_ENTRYRDN_STR) - 1) == '.')) {
+ /* entryrdn.db */
+ struct attrinfo *ai = NULL;
+ ainfo_get(inst->inst_be, LDBM_ENTRYRDN_STR, &ai);
+ if (ai->ai_dup_cmp_fn) {
+ /* If set, use the special dup compare callback */
+ retval = destination_file->set_dup_compare(destination_file, ai->ai_dup_cmp_fn);
+ if (retval) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "dblayer_copy_file_keybykey(entryrdn), set_dup_compare error %d: %s\n",
+ retval, db_strerror(retval));
+ goto error;
+ }
+ }
+ } else if (idl_get_idl_new() && (dbflags & DB_DUP) && (dbflags & DB_DUPSORT)) {
+ retval = destination_file->set_dup_compare(destination_file, idl_new_compare_dups);
+ if (retval) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "dblayer_copy_file_keybykey, set_dup_compare error %d: %s\n",
+ retval, db_strerror(retval));
+ goto error;
+ }
+ }
+
retval = (destination_file->open)(destination_file, NULL, destination_file_name, NULL, dbtype, DB_CREATE | DB_EXCL, mode);
if (retval) {
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_keybykey, Open error %d: %s\n", retval, db_strerror(retval), 0);
@@ -190,7 +231,13 @@ error:
return retval;
}
-int dblayer_copy_file_resetlsns(char *home_dir ,char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv)
+int
+dblayer_copy_file_resetlsns(char *home_dir,
+ char *source_file_name,
+ char *destination_file_name,
+ int overwrite,
+ dblayer_private *priv,
+ ldbm_instance *inst)
{
int retval = 0;
DB_ENV *env = NULL;
@@ -205,7 +252,7 @@ int dblayer_copy_file_resetlsns(char *home_dir ,char *source_file_name, char *de
goto out;
}
/* Do the copy */
- retval = dblayer_copy_file_keybykey(env, source_file_name, destination_file_name, overwrite, priv);
+ retval = dblayer_copy_file_keybykey(env, source_file_name, destination_file_name, overwrite, priv, inst);
if (retval) {
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_resetlsns: Copy not completed successfully.", 0, 0, 0);
}
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 5bbc34d..0de7bd9 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -5630,6 +5630,7 @@ dblayer_copy_directory(struct ldbminfo *li,
char inst_dir[MAXPATHLEN];
char sep;
int suffix_len = 0;
+ ldbm_instance *inst = NULL;
if (!src_dir || '\0' == *src_dir)
{
@@ -5653,6 +5654,14 @@ dblayer_copy_directory(struct ldbminfo *li,
else
relative_instance_name++;
+ inst = ldbm_instance_find_by_name(li, relative_instance_name);
+ if (NULL == inst) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; "
+ "Instance path %s could be invalid.\n",
+ relative_instance_name, src_dir, 0);
+ return return_value;
+ }
+
if (is_fullpath(src_dir))
{
new_src_dir = src_dir;
@@ -5660,15 +5669,6 @@ dblayer_copy_directory(struct ldbminfo *li,
else
{
int len;
- ldbm_instance *inst =
- ldbm_instance_find_by_name(li, relative_instance_name);
- if (NULL == inst)
- {
- LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; "
- "Instance path %s could be invalid.\n",
- relative_instance_name, src_dir, 0);
- return return_value;
- }
inst_dirp = dblayer_get_full_inst_dir(inst->inst_li, inst,
inst_dir, MAXPATHLEN);
@@ -5726,7 +5726,7 @@ dblayer_copy_directory(struct ldbminfo *li,
if (NULL == new_dest_dir) {
/* Need to create the new directory where the files will be
* copied to. */
- PRFileInfo info;
+ PRFileInfo64 info;
char *prefix = "";
char mysep = 0;
@@ -5747,7 +5747,7 @@ dblayer_copy_directory(struct ldbminfo *li,
new_dest_dir = slapi_ch_smprintf("%s/%s",
dest_dir, relative_instance_name);
/* } */
- if (PR_SUCCESS == PR_GetFileInfo(new_dest_dir, &info))
+ if (PR_SUCCESS == PR_GetFileInfo64(new_dest_dir, &info))
{
ldbm_delete_dirs(new_dest_dir);
}
@@ -5788,13 +5788,12 @@ dblayer_copy_directory(struct ldbminfo *li,
/* If the file is a database file, and resetlsns is set, then we need to do a key by key copy */
/* PL_strcmp takes NULL arg */
if (resetlsns &&
- (PL_strcmp(LDBM_FILENAME_SUFFIX, strrchr(filename1, '.'))
- == 0)) {
+ (PL_strcmp(LDBM_FILENAME_SUFFIX, strrchr(filename1, '.')) == 0)) {
return_value = dblayer_copy_file_resetlsns(src_dir, filename1, filename2,
- 0, priv);
+ 0, priv, inst);
} else {
return_value = dblayer_copyfile(filename1, filename2,
- 0, priv->dblayer_file_mode);
+ 0, priv->dblayer_file_mode);
}
slapi_ch_free((void**)&filename1);
slapi_ch_free((void**)&filename2);
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.h b/ldap/servers/slapd/back-ldbm/dblayer.h
index 7f3200c..4ff9d53 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.h
+++ b/ldap/servers/slapd/back-ldbm/dblayer.h
@@ -201,7 +201,7 @@ int dblayer_make_private_simple_env(char *db_home_dir, DB_ENV **env);
/* Copy a database file, preserving all its contents (used to reset the LSNs in the file in order to move
* it from one transacted environment to another.
*/
-int dblayer_copy_file_resetlsns(char *home_dir, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv);
+int dblayer_copy_file_resetlsns(char *home_dir, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv, ldbm_instance *inst);
/* Turn on the various logging and debug options for DB */
void dblayer_set_env_debugging(DB_ENV *pEnv, dblayer_private *priv);
9 years, 8 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/dbhelp.c | 53 +++++++++++++++++++++++++++++++--
ldap/servers/slapd/back-ldbm/dblayer.c | 29 ++++++++----------
ldap/servers/slapd/back-ldbm/dblayer.h | 2 -
3 files changed, 65 insertions(+), 19 deletions(-)
New commits:
commit abe5c894686f46b60f069f8cbd8aa909b34d81a1
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Jan 28 11:25:34 2014 -0800
Ticket #47463 - IDL-style can become mismatched during partial restoration
The commit to 389-ds-base-1.3.2 and newer is back ported to 389-ds-
1.2.11 trough 1.3.1 by Thomas E Lackey.
commit b43145218dccc8c9c16ecadad80f94bf58c73d57
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Sep 27 17:58:03 2013 -0700
Description by telackey:
When doing a partial/FRI restoration the database files are copied
key-by-key. This is necessary to reset the LSNs so the restored
files can merge into the existing DB environment (cf. dblayer_copy_
file_resetlsns()) in a recoverable way.
However, dblayer_copy_file_keybykey() does not set the comparison
function before calling DB->put(), which means that the restored
files will not necessarily be using the proper function.
While all the keys are technically present, indexed searches can
still fail to return relevant results because the key order is
significant when intersecting the results with the other indices.
Note: The bug was reported and the patch was provided by telackey.
(Thank you, Thomas!)
Additional fix by nhosoi:
The entryrdn index uses its special dup compare function. The dup
compare function is set when the restoring index file is entryrdn.
https://fedorahosted.org/389/ticket/47463
Reviewed by rmeggins (Thank you, Rich!)
diff --git a/ldap/servers/slapd/back-ldbm/dbhelp.c b/ldap/servers/slapd/back-ldbm/dbhelp.c
index 1165831..b0d17d3 100644
--- a/ldap/servers/slapd/back-ldbm/dbhelp.c
+++ b/ldap/servers/slapd/back-ldbm/dbhelp.c
@@ -49,7 +49,13 @@
#include "back-ldbm.h"
#include "dblayer.h"
-static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv)
+static int
+dblayer_copy_file_keybykey(DB_ENV *env,
+ char *source_file_name,
+ char *destination_file_name,
+ int overwrite,
+ dblayer_private *priv,
+ ldbm_instance *inst)
{
int retval = 0;
int retval_cleanup = 0;
@@ -62,6 +68,7 @@ static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char
int cursor_flag = 0;
int finished = 0;
int mode = 0;
+ char *p = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> dblayer_copy_file_keybykey\n", 0, 0, 0 );
@@ -119,6 +126,40 @@ static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_keybykey, set_pagesize error %d: %s\n", retval, db_strerror(retval), 0);
goto error;
}
+
+ /* TEL 20130412: Make sure to set the dup comparison function if needed.
+ * We key our decision off of the presence of new IDL and dup flags on
+ * the source database. This is similar dblayer_open_file, except that
+ * we don't have the attribute info index mask for VLV. That should be OK
+ * since the DB_DUP and DB_DUPSORT flags wouldn't have been toggled on
+ * unless they passed the check on the source.
+ */
+ /* Entryrdn index has its own dup compare function */
+ if ((p = PL_strcasestr(source_file_name, LDBM_ENTRYRDN_STR)) &&
+ (*(p + sizeof(LDBM_ENTRYRDN_STR) - 1) == '.')) {
+ /* entryrdn.db */
+ struct attrinfo *ai = NULL;
+ ainfo_get(inst->inst_be, LDBM_ENTRYRDN_STR, &ai);
+ if (ai->ai_dup_cmp_fn) {
+ /* If set, use the special dup compare callback */
+ retval = destination_file->set_dup_compare(destination_file, ai->ai_dup_cmp_fn);
+ if (retval) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "dblayer_copy_file_keybykey(entryrdn), set_dup_compare error %d: %s\n",
+ retval, db_strerror(retval));
+ goto error;
+ }
+ }
+ } else if (idl_get_idl_new() && (dbflags & DB_DUP) && (dbflags & DB_DUPSORT)) {
+ retval = destination_file->set_dup_compare(destination_file, idl_new_compare_dups);
+ if (retval) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "dblayer_copy_file_keybykey, set_dup_compare error %d: %s\n",
+ retval, db_strerror(retval));
+ goto error;
+ }
+ }
+
retval = (destination_file->open)(destination_file, NULL, destination_file_name, NULL, dbtype, DB_CREATE | DB_EXCL, mode);
if (retval) {
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_keybykey, Open error %d: %s\n", retval, db_strerror(retval), 0);
@@ -190,7 +231,13 @@ error:
return retval;
}
-int dblayer_copy_file_resetlsns(char *home_dir ,char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv)
+int
+dblayer_copy_file_resetlsns(char *home_dir,
+ char *source_file_name,
+ char *destination_file_name,
+ int overwrite,
+ dblayer_private *priv,
+ ldbm_instance *inst)
{
int retval = 0;
DB_ENV *env = NULL;
@@ -205,7 +252,7 @@ int dblayer_copy_file_resetlsns(char *home_dir ,char *source_file_name, char *de
goto out;
}
/* Do the copy */
- retval = dblayer_copy_file_keybykey(env, source_file_name, destination_file_name, overwrite, priv);
+ retval = dblayer_copy_file_keybykey(env, source_file_name, destination_file_name, overwrite, priv, inst);
if (retval) {
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_resetlsns: Copy not completed successfully.", 0, 0, 0);
}
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 6b29890..a26c2f0 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -5546,6 +5546,7 @@ dblayer_copy_directory(struct ldbminfo *li,
char inst_dir[MAXPATHLEN];
char sep;
int suffix_len = 0;
+ ldbm_instance *inst = NULL;
if (!src_dir || '\0' == *src_dir)
{
@@ -5569,6 +5570,14 @@ dblayer_copy_directory(struct ldbminfo *li,
else
relative_instance_name++;
+ inst = ldbm_instance_find_by_name(li, relative_instance_name);
+ if (NULL == inst) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; "
+ "Instance path %s could be invalid.\n",
+ relative_instance_name, src_dir, 0);
+ return return_value;
+ }
+
if (is_fullpath(src_dir))
{
new_src_dir = src_dir;
@@ -5576,15 +5585,6 @@ dblayer_copy_directory(struct ldbminfo *li,
else
{
int len;
- ldbm_instance *inst =
- ldbm_instance_find_by_name(li, relative_instance_name);
- if (NULL == inst)
- {
- LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; "
- "Instance path %s could be invalid.\n",
- relative_instance_name, src_dir, 0);
- return return_value;
- }
inst_dirp = dblayer_get_full_inst_dir(inst->inst_li, inst,
inst_dir, MAXPATHLEN);
@@ -5642,7 +5642,7 @@ dblayer_copy_directory(struct ldbminfo *li,
if (NULL == new_dest_dir) {
/* Need to create the new directory where the files will be
* copied to. */
- PRFileInfo info;
+ PRFileInfo64 info;
char *prefix = "";
char mysep = 0;
@@ -5663,7 +5663,7 @@ dblayer_copy_directory(struct ldbminfo *li,
new_dest_dir = slapi_ch_smprintf("%s/%s",
dest_dir, relative_instance_name);
/* } */
- if (PR_SUCCESS == PR_GetFileInfo(new_dest_dir, &info))
+ if (PR_SUCCESS == PR_GetFileInfo64(new_dest_dir, &info))
{
ldbm_delete_dirs(new_dest_dir);
}
@@ -5704,13 +5704,12 @@ dblayer_copy_directory(struct ldbminfo *li,
/* If the file is a database file, and resetlsns is set, then we need to do a key by key copy */
/* PL_strcmp takes NULL arg */
if (resetlsns &&
- (PL_strcmp(LDBM_FILENAME_SUFFIX, strrchr(filename1, '.'))
- == 0)) {
+ (PL_strcmp(LDBM_FILENAME_SUFFIX, strrchr(filename1, '.')) == 0)) {
return_value = dblayer_copy_file_resetlsns(src_dir, filename1, filename2,
- 0, priv);
+ 0, priv, inst);
} else {
return_value = dblayer_copyfile(filename1, filename2,
- 0, priv->dblayer_file_mode);
+ 0, priv->dblayer_file_mode);
}
slapi_ch_free((void**)&filename1);
slapi_ch_free((void**)&filename2);
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.h b/ldap/servers/slapd/back-ldbm/dblayer.h
index 7f3200c..4ff9d53 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.h
+++ b/ldap/servers/slapd/back-ldbm/dblayer.h
@@ -201,7 +201,7 @@ int dblayer_make_private_simple_env(char *db_home_dir, DB_ENV **env);
/* Copy a database file, preserving all its contents (used to reset the LSNs in the file in order to move
* it from one transacted environment to another.
*/
-int dblayer_copy_file_resetlsns(char *home_dir, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv);
+int dblayer_copy_file_resetlsns(char *home_dir, char *source_file_name, char *destination_file_name, int overwrite, dblayer_private *priv, ldbm_instance *inst);
/* Turn on the various logging and debug options for DB */
void dblayer_set_env_debugging(DB_ENV *pEnv, dblayer_private *priv);
9 years, 8 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/ldbm_usn.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
New commits:
commit a6f66e7fcbd5d17d975cc2ac65806d7c64571254
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Jan 27 15:15:01 2014 -0800
Ticket #47659 - ldbm_usn_init: Valgrind reports Invalid read / SIGSEGV
Bug description: A suffix mapping tree could exist without the corresponding
backend. The existing code did not properly check the backend returned from
slapi_mapping_tree_find_backend_for_sdn. When NULL backend is returned, it
triggers the NULL pointer dereference.
Fix description: This patch added a NULL backend check to usn_get_last_usn,
and moved a logging to the if clause where the backend is not NULL.
https://fedorahosted.org/389/ticket/47659
Reviewed by rmeggins(a)redhat.com (Thank you, Rich!!)
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_usn.c b/ldap/servers/slapd/back-ldbm/ldbm_usn.c
index 7c11a68..1ca16b1 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_usn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_usn.c
@@ -80,10 +80,11 @@ ldbm_usn_init(struct ldbminfo *li)
for ( sdn = slapi_get_first_suffix( &node, 0 ); sdn != NULL;
sdn = slapi_get_next_suffix_ext( &node, 0 )) {
be = slapi_mapping_tree_find_backend_for_sdn(sdn);
- slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_usn_init",
- "backend: %s%s\n", be->be_name, isglobal?" (global mode)":"");
rc = usn_get_last_usn(be, &last_usn);
if (0 == rc) { /* only when the last usn is available */
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_usn_init",
+ "backend: %s%s\n", be->be_name,
+ isglobal?" (global mode)":"");
if (isglobal) {
if (isfirst) {
li->li_global_usn_counter = slapi_counter_new();
@@ -126,7 +127,7 @@ usn_get_last_usn(Slapi_Backend *be, PRUint64 *last_usn)
DBT value;
PRInt64 signed_last_usn;
- if (NULL == last_usn) {
+ if ((NULL == be) || (NULL == last_usn)) {
return rc;
}
9 years, 8 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Noriko Hosoi
ldap/servers/plugins/cos/cos_cache.c | 82 ++++++++++++++++++++---------------
1 file changed, 48 insertions(+), 34 deletions(-)
New commits:
commit 1ebad4bd50fb1483998a32b5d3e232e89aeda0f7
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Jan 24 18:12:32 2014 -0800
Ticket #47649 - Server hangs in cos_cache when adding a user entry
Bug description: cos_dn_defs_cb reads cosDefinition and sets up the cos
Definition part of cos cache. In the function, when processing
cosAttribute, cosTargetTree and cosTemlpateDn are missing, it sets the
parent dn of the cos definition dn. This parent setting is needed only
when the 2 attributes are completely missing from the cos definition.
But if the attributes are located below cosAttribute (see the Example
cos definition), in addition to "cn=cosTemplates,ou=people,dc=example,
dc=com", the parent of "cn=generatePostalCode,ou=People,dc=example,dc=com"
is added to the cos cache as cosTemplateDn.
Example cos definition:
dn: cn=generatePostalCode,ou=People,dc=example,dc=com
description: generate postalCode attr based on location
objectClass: top
objectClass: ldapsubentry
objectClass: cossuperdefinition
objectClass: cosClassicDefinition
cosAttribute: postalCode
costemplatedn: cn=cosTemplates,ou=people,dc=example,dc=com
cosSpecifier: l
cn: generatePostalCode
The mistakenly added cosTemplatedDn makes adding an entry under ou=People
notify recreating the cos cache. The notification needs to be outside of
backend transaction since it causes a deadlock with the cos_cache_wait_
on_change thread which cannot read the DB due to the transaction but holds
the lock that the notifier thread is waiting for.
Fix description: The parent of the cos definition dn is set to the
cosTargetTree and the cosTemlpateDn, only when the attributes are
completely missing.
https://fedorahosted.org/389/ticket/47649
Reviewed by rmeggins(a)redhat.com (Thank you, Rich!!)
(cherry picked from commit 1e52401d3abd0377f55676f4a1508a02aaa7f955)
(cherry picked from commit 01c0794cde7eb91a1a4e477a0286533df4a4ae38)
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
index fed2aa9..a68e59f 100644
--- a/ldap/servers/plugins/cos/cos_cache.c
+++ b/ldap/servers/plugins/cos/cos_cache.c
@@ -727,7 +727,8 @@ struct dn_defs_info {
* if a particular attempt to add a definition fails: info.ret gets set to
* zero only if we succed to add a def.
*/
-static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
+static int
+cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
{
struct dn_defs_info *info;
cosAttrValue **pSneakyVal = 0;
@@ -877,31 +878,10 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
dnVals[valIndex]->bv_val);
}
- if(!pCosTargetTree)
- {
- /* get the parent of the definition */
- char *orig = slapi_dn_parent(pDn->val);
- Slapi_DN *psdn = slapi_sdn_new_dn_byval(orig);
- char *parent = (char *)slapi_sdn_get_dn(psdn);
- if (!parent) {
- parent = (char *)slapi_sdn_get_udn(psdn);
- LDAPDebug(LDAP_DEBUG_ANY,
- "cos_cache_build_definition_list: "
- "failed to normalize parent dn %s. "
- "Adding the pre normalized dn.\n",
- parent, 0, 0);
- }
- cos_cache_add_attrval(&pCosTargetTree, parent);
- if (!pCosTemplateDn) {
- cos_cache_add_attrval(&pCosTemplateDn, parent);
- }
- slapi_sdn_free(&psdn);
- }
-
slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle,
dnVals[valIndex]->bv_val, NULL, NULL);
} /* if(attrType is cosAttribute) */
-
+
/*
* Add the attributetype to the appropriate
* list.
@@ -913,6 +893,47 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
ber_bvecfree( dnVals );
dnVals = NULL;
} while(!slapi_entry_next_attr(e, dnAttr, &dnAttr));
+
+ if (pCosAttribute && (!pCosTargetTree || !pCosTemplateDn)) {
+ /* get the parent of the definition */
+ char *orig = slapi_dn_parent(pDn->val);
+ char *parent = NULL;
+ if (orig) {
+ parent = slapi_create_dn_string("%s", orig);
+ if (!parent) {
+ parent = orig;
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "cos_dn_defs_cb: "
+ "failed to normalize parent dn %s. "
+ "Adding the pre normalized dn.\n",
+ parent);
+ }
+ if (!pCosTargetTree) {
+ cos_cache_add_attrval(&pCosTargetTree, parent);
+ }
+ if (!pCosTemplateDn) {
+ cos_cache_add_attrval(&pCosTemplateDn, parent);
+ }
+ if (parent != orig) {
+ slapi_ch_free_string(&parent);
+ }
+ slapi_ch_free_string(&orig);
+ } else {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "cos_dn_defs_cb: "
+ "failed to get parent dn of cos definition %s.\n",
+ pDn->val);
+ if (!pCosTemplateDn) {
+ if (!pCosTargetTree) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTargetTree and cosTemplateDn are not set.\n");
+ } else {
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTemplateDn is not set.\n");
+ }
+ } else if (!pCosTargetTree) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTargetTree is not set.\n");
+ }
+ }
+ }
/*
determine the type of class of service scheme
@@ -951,9 +972,7 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
*/
/* these must exist */
- if( pDn &&
- pObjectclass &&
-
+ if(pDn && pObjectclass &&
(
(cosType == COSTYPE_CLASSIC &&
pCosTemplateDn &&
@@ -3582,14 +3601,9 @@ static int cos_cache_entry_is_cos_related( Slapi_Entry *e) {
{
pObj = (char*)slapi_value_get_string(val);
- /*
- * objectclasses are ascii--maybe strcasecmp() is faster than
- * slapi_utf8casecmp()
- */
- if( !strcasecmp(pObj, "cosdefinition") ||
- !strcasecmp(pObj, "cossuperdefinition") ||
- !strcasecmp(pObj, "costemplate")
- )
+ if(!strcasecmp(pObj, "cosdefinition") ||
+ !strcasecmp(pObj, "cossuperdefinition") ||
+ !strcasecmp(pObj, "costemplate"))
{
rc = 1;
}
9 years, 8 months