ldap/servers
by Noriko Hosoi
ldap/servers/slapd/connection.c | 8 ++++++++
1 file changed, 8 insertions(+)
New commits:
commit 3fe24648364634649aa7379095e915e7ab9058cd
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Oct 27 17:22:46 2015 -0700
Ticket #48326 - [RFE] it could be nice to have nsslapd-maxbersize default to bigger than 2Mb
Description: In connection_dispatch_operation, if the operation sets
the flag OP_FLAG_REPLICATED, ignore the maxbersize by setting:
maxbersize = 0;
ber_sockbuf_ctrl(conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &maxbersize);
Note: openldap only.
https://fedorahosted.org/389/ticket/48326
Reviewed by mreynolds(a)redhat.com (Thank you, Mark!!)
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index fc3b741..1a9301a 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -531,6 +531,14 @@ connection_dispatch_operation(Connection *conn, Operation *op, Slapi_PBlock *pb)
/* Copy the Connection DN and SSF into the operation struct */
op_copy_identity( conn, op );
+#if defined(USE_OPENLDAP)
+ if (slapi_operation_is_flag_set(op, OP_FLAG_REPLICATED)) {
+ /* If it is replicated op, ignore the maxbersize. */
+ ber_len_t maxbersize = 0;
+ ber_sockbuf_ctrl(conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &maxbersize);
+ }
+#endif
+
/* If the minimum SSF requirements are not met, only allow
* bind and extended operations through. The bind and extop
* code will ensure that only SASL binds and startTLS are
7 years, 7 months
2 commits - dirsrvtests/tickets ldap/servers
by Noriko Hosoi
dirsrvtests/tickets/ticket548_test.py | 339 ++++++++++++++++++++++++++++++++++
ldap/servers/slapd/libglobs.c | 2
ldap/servers/slapd/log.c | 2
ldap/servers/slapd/opshared.c | 2
ldap/servers/slapd/proto-slap.h | 1
ldap/servers/slapd/pw.c | 167 ++++++++++++++--
ldap/servers/slapd/pw_mgmt.c | 45 +---
ldap/servers/slapd/slap.h | 2
8 files changed, 505 insertions(+), 55 deletions(-)
New commits:
commit cb209be7ca39b9064e7ce2c89a94715c258cd72b
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Oct 19 15:14:18 2015 -0700
Ticket #548 - CI test: added test cases for ticket 548
Description: RFE: Allow AD password sync to update shadowLastChange
https://fedorahosted.org/389/ticket/548
Reviwed by spichugi(a)redhat.com and wibrown(a)redhat.com (Thank you, Simon and William!)
diff --git a/dirsrvtests/tickets/ticket548_test.py b/dirsrvtests/tickets/ticket548_test.py
new file mode 100644
index 0000000..030ff4f
--- /dev/null
+++ b/dirsrvtests/tickets/ticket548_test.py
@@ -0,0 +1,339 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2015 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import os
+import sys
+import time
+import ldap
+import logging
+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 lib389.utils import *
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+# Assuming DEFAULT_SUFFIX is "dc=example,dc=com", otherwise it does not work... :(
+SUBTREE_CONTAINER = 'cn=nsPwPolicyContainer,' + DEFAULT_SUFFIX
+SUBTREE_PWPDN = 'cn=nsPwPolicyEntry,' + DEFAULT_SUFFIX
+SUBTREE_PWP = 'cn=cn\3DnsPwPolicyEntry\2Cdc\3Dexample\2Cdc\3Dcom,' + SUBTREE_CONTAINER
+SUBTREE_COS_TMPLDN = 'cn=nsPwTemplateEntry,' + DEFAULT_SUFFIX
+SUBTREE_COS_TMPL = 'cn=cn\3DnsPwTemplateEntry\2Cdc\3Dexample\2Cdc\3Dcom,' + SUBTREE_CONTAINER
+SUBTREE_COS_DEF = 'cn=nsPwPolicy_CoS,' + DEFAULT_SUFFIX
+
+USER1_DN = 'uid=user1,' + DEFAULT_SUFFIX
+USER2_DN = 'uid=user2,' + DEFAULT_SUFFIX
+USER3_DN = 'uid=user3,' + DEFAULT_SUFFIX
+USER_PW = 'password'
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ global installation_prefix
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ # Creating standalone instance ...
+ standalone = DirSrv(verbose=False)
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ standalone.delete()
+ standalone.create()
+ standalone.open()
+
+ # Delete each instance in the end
+ def fin():
+ standalone.delete()
+ request.addfinalizer(fin)
+
+ # Clear out the tmp dir
+ standalone.clearTmpDir(__file__)
+
+ return TopologyStandalone(standalone)
+
+
+def set_global_pwpolicy(topology):
+ log.info(" +++++ Enable global password policy +++++\n")
+ # Enable password policy
+ try:
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-pwpolicy-local', 'on')])
+ except ldap.LDAPError as e:
+ log.error('Failed to set pwpolicy-local: error ' + e.message['desc'])
+ assert False
+
+ log.info(" Set global password Min Age -- 1 day\n")
+ try:
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordMinAge', '86400')])
+ except ldap.LDAPError as e:
+ log.error('Failed to set passwordMinAge: error ' + e.message['desc'])
+ assert False
+
+ log.info(" Set global password Max Age -- 10 days\n")
+ try:
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordMaxAge', '864000')])
+ except ldap.LDAPError as e:
+ log.error('Failed to set passwordMaxAge: error ' + e.message['desc'])
+ assert False
+
+ log.info(" Set global password Warning -- 3 days\n")
+ try:
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordWarning', '259200')])
+ except ldap.LDAPError as e:
+ log.error('Failed to set passwordWarning: error ' + e.message['desc'])
+ assert False
+
+
+def set_subtree_pwpolicy(topology):
+ log.info(" +++++ Enable subtree level password policy +++++\n")
+ log.info(" Add the container")
+ try:
+ topology.standalone.add_s(Entry((SUBTREE_CONTAINER, {'objectclass': 'top nsContainer'.split(),
+ 'cn': 'nsPwPolicyContainer'})))
+ except ldap.LDAPError as e:
+ log.error('Failed to add subtree container: error ' + e.message['desc'])
+ assert False
+
+ log.info(" Add the password policy subentry {passwordMustChange: on, passwordMinAge: 2, passwordMaxAge: 20, passwordWarning: 6}")
+ try:
+ topology.standalone.add_s(Entry((SUBTREE_PWP, {'objectclass': 'top ldapsubentry passwordpolicy'.split(),
+ 'cn': SUBTREE_PWPDN,
+ 'passwordMustChange': 'on',
+ 'passwordExp': 'on',
+ 'passwordMinAge': '172800',
+ 'passwordMaxAge': '1728000',
+ 'passwordWarning': '518400',
+ 'passwordChange': 'on',
+ 'passwordStorageScheme': 'clear'})))
+ except ldap.LDAPError as e:
+ log.error('Failed to add passwordpolicy: error ' + e.message['desc'])
+ assert False
+
+ log.info(" Add the COS template")
+ try:
+ topology.standalone.add_s(Entry((SUBTREE_COS_TMPL, {'objectclass': 'top ldapsubentry costemplate extensibleObject'.split(),
+ 'cn': SUBTREE_PWPDN,
+ 'cosPriority': '1',
+ 'cn': SUBTREE_COS_TMPLDN,
+ 'pwdpolicysubentry': SUBTREE_PWP})))
+ except ldap.LDAPError as e:
+ log.error('Failed to add COS template: error ' + e.message['desc'])
+ assert False
+
+ log.info(" Add the COS definition")
+ try:
+ topology.standalone.add_s(Entry((SUBTREE_COS_DEF, {'objectclass': 'top ldapsubentry cosSuperDefinition cosPointerDefinition'.split(),
+ 'cn': SUBTREE_PWPDN,
+ 'costemplatedn': SUBTREE_COS_TMPL,
+ 'cosAttribute': 'pwdpolicysubentry default operational-default'})))
+ except ldap.LDAPError as e:
+ log.error('Failed to add COS def: error ' + e.message['desc'])
+ assert False
+
+ time.sleep(1)
+
+
+def update_passwd(topology, user, passwd, newpasswd):
+ log.info(" Bind as {%s,%s}" % (user, passwd))
+ topology.standalone.simple_bind_s(user, passwd)
+ try:
+ topology.standalone.modify_s(user, [(ldap.MOD_REPLACE, 'userpassword', newpasswd)])
+ except ldap.LDAPError as e:
+ log.fatal('test_ticket548: Failed to update the password ' + cpw + ' of user ' + user + ': error ' + e.message['desc'])
+ assert False
+
+ time.sleep(1)
+
+
+def check_shadow_attr_value(entry, attr_type, expected, dn):
+ if entry.hasAttr(attr_type):
+ actual = entry.getValue(attr_type)
+ if int(actual) == expected:
+ log.info('%s of entry %s has expected value %s' % (attr_type, dn, actual))
+ assert True
+ else:
+ log.fatal('%s %s of entry %s does not have expected value %s' % (attr_type, actual, dn, expected))
+ assert False
+ else:
+ log.fatal('entry %s does not have %s attr' % (dn, attr_type))
+ assert False
+
+
+def test_ticket548_test_with_no_policy(topology):
+ """
+ Check shadowAccount under no password policy
+ """
+ log.info("Case 1. No password policy")
+
+ log.info("Bind as %s" % DN_DM)
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ log.info('Add an entry' + USER1_DN)
+ try:
+ topology.standalone.add_s(Entry((USER1_DN, {'objectclass': "top person organizationalPerson inetOrgPerson shadowAccount".split(),
+ 'sn': '1',
+ 'cn': 'user 1',
+ 'uid': 'user1',
+ 'givenname': 'user',
+ 'mail': 'user1(a)example.com',
+ 'userpassword': USER_PW})))
+ except ldap.LDAPError as e:
+ log.fatal('test_ticket548: Failed to add user' + USER1_DN + ': error ' + e.message['desc'])
+ assert False
+
+ edate = int(time.time() / (60 * 60 * 24))
+ log.info('Search entry %s' % USER1_DN)
+
+ log.info("Bind as %s" % USER1_DN)
+ topology.standalone.simple_bind_s(USER1_DN, USER_PW)
+ entry = topology.standalone.getEntry(USER1_DN, ldap.SCOPE_BASE, "(objectclass=*)", ['shadowLastChange'])
+ check_shadow_attr_value(entry, 'shadowLastChange', edate, USER1_DN)
+
+ log.info("Check shadowAccount with no policy was successfully verified.")
+
+
+def test_ticket548_test_global_policy(topology):
+ """
+ Check shadowAccount with global password policy
+ """
+
+ log.info("Case 2. Check shadowAccount with global password policy")
+
+ log.info("Bind as %s" % DN_DM)
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ set_global_pwpolicy(topology)
+
+ log.info('Add an entry' + USER2_DN)
+ try:
+ topology.standalone.add_s(Entry((USER2_DN, {'objectclass': "top person organizationalPerson inetOrgPerson shadowAccount".split(),
+ 'sn': '2',
+ 'cn': 'user 2',
+ 'uid': 'user2',
+ 'givenname': 'user',
+ 'mail': 'user2(a)example.com',
+ 'userpassword': USER_PW})))
+ except ldap.LDAPError as e:
+ log.fatal('test_ticket548: Failed to add user' + USER2_DN + ': error ' + e.message['desc'])
+ assert False
+
+ log.info("Bind as %s" % USER2_DN)
+ topology.standalone.simple_bind_s(USER2_DN, USER_PW)
+
+ edate = int(time.time() / (60 * 60 * 24))
+ log.info('Search entry %s' % USER2_DN)
+ entry = topology.standalone.getEntry(USER2_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ check_shadow_attr_value(entry, 'shadowLastChange', edate, USER2_DN)
+
+ # passwordMinAge -- 1 day
+ check_shadow_attr_value(entry, 'shadowMin', 1, USER2_DN)
+
+ # passwordMaxAge -- 10 days
+ check_shadow_attr_value(entry, 'shadowMax', 10, USER2_DN)
+
+ # passwordWarning -- 3 days
+ check_shadow_attr_value(entry, 'shadowWarning', 3, USER2_DN)
+
+ log.info("Check shadowAccount with global policy was successfully verified.")
+
+
+def test_ticket548_test_subtree_policy(topology):
+ """
+ Check shadowAccount with subtree level password policy
+ """
+
+ log.info("Case 3. Check shadowAccount with subtree level password policy")
+
+ log.info("Bind as %s" % DN_DM)
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+ set_subtree_pwpolicy(topology)
+
+ log.info('Add an entry' + USER3_DN)
+ try:
+ topology.standalone.add_s(Entry((USER3_DN, {'objectclass': "top person organizationalPerson inetOrgPerson shadowAccount".split(),
+ 'sn': '3',
+ 'cn': 'user 3',
+ 'uid': 'user3',
+ 'givenname': 'user',
+ 'mail': 'user3(a)example.com',
+ 'userpassword': USER_PW})))
+ except ldap.LDAPError as e:
+ log.fatal('test_ticket548: Failed to add user' + USER3_DN + ': error ' + e.message['desc'])
+ assert False
+
+ log.info('Search entry %s' % USER3_DN)
+ entry0 = topology.standalone.getEntry(USER3_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+
+ log.info('Expecting shadowLastChange 0 since passwordMustChange is on')
+ check_shadow_attr_value(entry0, 'shadowLastChange', 0, USER3_DN)
+
+ # passwordMinAge -- 2 day
+ check_shadow_attr_value(entry0, 'shadowMin', 2, USER3_DN)
+
+ # passwordMaxAge -- 20 days
+ check_shadow_attr_value(entry0, 'shadowMax', 20, USER3_DN)
+
+ # passwordWarning -- 6 days
+ check_shadow_attr_value(entry0, 'shadowWarning', 6, USER3_DN)
+
+ log.info("Bind as %s" % USER3_DN)
+ topology.standalone.simple_bind_s(USER3_DN, USER_PW)
+
+ log.info('Search entry %s' % USER3_DN)
+ try:
+ entry1 = topology.standalone.getEntry(USER3_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ except ldap.UNWILLING_TO_PERFORM:
+ log.info('test_ticket548: Search by' + USER3_DN + ' failed by UNWILLING_TO_PERFORM as expected')
+ except ldap.LDAPError as e:
+ log.fatal('test_ticket548: Failed to serch user' + USER3_DN + ' by self: error ' + e.message['desc'])
+ assert False
+
+ log.info("Bind as %s and updating the password with a new one" % USER3_DN)
+ topology.standalone.simple_bind_s(USER3_DN, USER_PW)
+
+ newpasswd = USER_PW + '0'
+ update_passwd(topology, USER3_DN, USER_PW, newpasswd)
+
+ log.info("Re-bind as %s with new password" % USER3_DN)
+ topology.standalone.simple_bind_s(USER3_DN, newpasswd)
+
+ try:
+ entry2 = topology.standalone.getEntry(USER3_DN, ldap.SCOPE_BASE, "(objectclass=*)")
+ except ldap.LDAPError as e:
+ log.fatal('test_ticket548: Failed to serch user' + USER3_DN + ' by self: error ' + e.message['desc'])
+ assert False
+
+ edate = int(time.time() / (60 * 60 * 24))
+
+ log.info('Expecting shadowLastChange %d once userPassword is updated', edate)
+ check_shadow_attr_value(entry2, 'shadowLastChange', edate, USER3_DN)
+
+ log.info("Check shadowAccount with subtree level policy was successfully verified.")
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
commit 17f3624c19929ffa1d37a567b7a889fd397cca59
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Oct 26 22:11:43 2015 -0700
Ticket #548 - RFE: Allow AD password sync to update shadowLastChange
Shadow Account Support Design - http://www.port389.org/docs/389ds/design/shadow-account-support.html
https://fedorahosted.org/389/ticket/548
Reviewed by mreynolds(a)redhat.com (Thank you, Mark!!)
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index a3c4243..fde3885 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1447,7 +1447,7 @@ FrontendConfig_init () {
cfg->pw_policy.pw_mintokenlength = 3;
cfg->pw_policy.pw_maxage = 8640000; /* 100 days */
cfg->pw_policy.pw_minage = 0;
- cfg->pw_policy.pw_warning = 86400; /* 1 day */
+ cfg->pw_policy.pw_warning = _SEC_PER_DAY; /* 1 day */
init_pw_history = cfg->pw_policy.pw_history = LDAP_OFF;
cfg->pw_policy.pw_inhistory = 6;
init_pw_lockout = cfg->pw_policy.pw_lockout = LDAP_OFF;
diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c
index 2ec90de..78701c4 100644
--- a/ldap/servers/slapd/log.c
+++ b/ldap/servers/slapd/log.c
@@ -200,7 +200,7 @@ void g_log_init(int log_enabled)
loginfo.log_access_rotationsyncclock = -1;
loginfo.log_access_rotationtime = 1; /* default: 1 */
loginfo.log_access_rotationunit = LOG_UNIT_DAYS; /* default: day */
- loginfo.log_access_rotationtime_secs = 86400; /* default: 1 day */
+ loginfo.log_access_rotationtime_secs = _SEC_PER_DAY; /* default: 1 day */
loginfo.log_access_maxdiskspace = -1;
loginfo.log_access_minfreespace = -1;
loginfo.log_access_exptime = -1; /* default: -1 */
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index dcdbb04..4fe7969 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -1439,6 +1439,8 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result,
done = 1;
continue;
}
+ /* Adding shadow password attrs. */
+ add_shadow_ext_password_attrs(pb, e);
if (process_entry(pb, e, send_result))
{
/* shouldn't send this entry */
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index b10c1eb..c49f1d1 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -917,6 +917,7 @@ void add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry *e );
void mod_allowchange_aci(char *val);
void pw_mod_allowchange_aci(int pw_prohibit_change);
void pw_add_allowchange_aci(Slapi_Entry *e, int pw_prohibit_change);
+void add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry *e);
/*
* pw_retry.c
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 4e222d7..3985c2b 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -611,6 +611,13 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw)
cur_time = current_time();
slapi_mods_init(&smods, 0);
+ if (slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS, "shadowAccount")) {
+ time_t ctime = cur_time / _SEC_PER_DAY;
+ timestr = slapi_ch_smprintf("%ld", ctime);
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "shadowLastChange", timestr);
+ slapi_ch_free_string(×tr);
+ }
+
/* update passwordHistory */
if ( old_pw != NULL && pwpolicy->pw_history == 1 ) {
(void)update_pw_history(pb, sdn, old_pw);
@@ -699,7 +706,7 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw)
timestr = format_genTime ( pw_exp_date );
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestr);
- slapi_ch_free((void **)×tr);
+ slapi_ch_free_string(×tr);
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "0");
@@ -722,8 +729,7 @@ check_pw_minage ( Slapi_PBlock *pb, const Slapi_DN *sdn, struct berval **vals)
pwpolicy = new_passwdPolicy(pb, dn);
slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
- if ( !pb->pb_op->o_isroot &&
- pwpolicy->pw_minage != 0 ) {
+ if (!pb->pb_op->o_isroot && !pwpolicy->pw_minage) {
Slapi_Entry *e;
char *passwordAllowChangeTime;
@@ -753,9 +759,7 @@ check_pw_minage ( Slapi_PBlock *pb, const Slapi_DN *sdn, struct berval **vals)
slapi_pwpolicy_make_response_control ( pb, -1, -1,
LDAP_PWPOLICY_PWDTOOYOUNG );
}
- pw_send_ldap_result ( pb,
- LDAP_CONSTRAINT_VIOLATION, NULL,
- "within password minimum age", 0, NULL );
+ pw_send_ldap_result(pb, LDAP_CONSTRAINT_VIOLATION, NULL, "within password minimum age", 0, NULL);
slapi_entry_free( e );
slapi_ch_free((void **) &cur_time_str );
return ( 1 );
@@ -1379,17 +1383,23 @@ add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry *e )
const char *dn = slapi_entry_get_ndn(e);
int has_allowchangetime = 0, has_expirationtime = 0;
time_t existing_exptime = 0;
+ time_t exptime = 0;
+ int isShadowAccount = 0;
+ int has_shadowLastChange = 0;
- LDAPDebug( LDAP_DEBUG_TRACE, "add_password_attrs\n", 0, 0, 0 );
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "add_password_attrs\n");
bvals[0] = &bv;
bvals[1] = NULL;
-
+
+ if (slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS, "shadowAccount")) {
+ isShadowAccount = 1;
+ }
+
/* If passwordexpirationtime is specified by the user, don't
try to assign the initial value */
- for ( a = &e->e_attrs; *a != NULL; a = next ) {
- if ( strcasecmp( (*a)->a_type,
- "passwordexpirationtime" ) == 0) {
+ for (a = &e->e_attrs; a && *a; a = next) {
+ if (!strcasecmp((*a)->a_type, "passwordexpirationtime")) {
Slapi_Value *sval;
if (slapi_attr_first_value(*a, &sval) == 0) {
const struct berval *bv = slapi_value_get_berval(sval);
@@ -1397,32 +1407,44 @@ add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry *e )
}
has_expirationtime = 1;
- } else if ( strcasecmp( (*a)->a_type,
- "passwordallowchangetime" ) == 0) {
+ } else if (!strcasecmp((*a)->a_type, "passwordallowchangetime")) {
has_allowchangetime = 1;
+ } else if (isShadowAccount && !strcasecmp((*a)->a_type, "shadowlastchange")) {
+ has_shadowLastChange = 1;
}
next = &(*a)->a_next;
}
- if ( has_allowchangetime && has_expirationtime ) {
+ if (has_allowchangetime && has_expirationtime && has_shadowLastChange) {
return;
}
pwpolicy = new_passwdPolicy(pb, dn);
- if ( !has_expirationtime &&
- ( pwpolicy->pw_exp || pwpolicy->pw_must_change ) ) {
- if ( pwpolicy->pw_must_change) {
+ if (!has_expirationtime && (pwpolicy->pw_exp || pwpolicy->pw_must_change)) {
+ if (pwpolicy->pw_must_change) {
/* must change password when first time logon */
bv.bv_val = format_genTime ( NO_TIME );
} else if ( pwpolicy->pw_exp ) {
- bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
- pwpolicy->pw_maxage ) );
+ exptime = time_plus_sec(current_time(), pwpolicy->pw_maxage);
+ bv.bv_val = format_genTime(exptime);
}
bv.bv_len = strlen( bv.bv_val );
slapi_entry_attr_merge( e, "passwordexpirationtime", bvals );
slapi_ch_free_string( &bv.bv_val );
}
+ if (isShadowAccount && !has_shadowLastChange) {
+ if (pwpolicy->pw_must_change) {
+ /* must change password when first time logon */
+ bv.bv_val = slapi_ch_smprintf("0");
+ } else {
+ exptime = current_time() / _SEC_PER_DAY;
+ bv.bv_val = slapi_ch_smprintf("%ld", exptime);
+ }
+ bv.bv_len = strlen(bv.bv_val);
+ slapi_entry_attr_merge(e, "shadowLastChange", bvals);
+ slapi_ch_free_string(&bv.bv_val);
+ }
/*
* If the password minimum age is not 0, calculate when the password
@@ -1434,12 +1456,11 @@ add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry *e )
*/
if ( !has_allowchangetime && pwpolicy->pw_minage != 0 &&
(has_expirationtime && existing_exptime > current_time()) ) {
- bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
- pwpolicy->pw_minage ) );
+ bv.bv_val = format_genTime ( time_plus_sec ( current_time (), pwpolicy->pw_minage ) );
bv.bv_len = strlen( bv.bv_val );
-
+
slapi_entry_attr_merge( e, "passwordallowchangetime", bvals );
- slapi_ch_free((void **) &bv.bv_val );
+ slapi_ch_free_string( &bv.bv_val );
}
}
@@ -2800,3 +2821,103 @@ pw_get_ext_size(Slapi_Entry *entry, size_t *size)
}
return LDAP_SUCCESS;
}
+
+void
+add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry *e)
+{
+ const char *dn = NULL;
+ passwdPolicy *pwpolicy = NULL;
+ time_t shadowval = 0;
+ time_t exptime = 0;
+ struct berval bv;
+ struct berval *bvals[2];
+
+ if (!e) {
+ return;
+ }
+ dn = slapi_entry_get_ndn(e);
+ if (!dn) {
+ return;
+ }
+ if (!slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS, "shadowAccount")) {
+ /* Not a shadowAccount; nothing to do. */
+ return;
+ }
+ if (operation_is_flag_set(pb->pb_op, OP_FLAG_INTERNAL)) {
+ /* external only */
+ return;
+ }
+ pwpolicy = new_passwdPolicy(pb, dn);
+ if (!pwpolicy) {
+ return;
+ }
+
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> add_shadow_password_attrs\n");
+
+ bvals[0] = &bv;
+ bvals[1] = NULL;
+
+ /* shadowMin - the minimum number of days required between password changes. */
+ if (pwpolicy->pw_minage > 0) {
+ shadowval = pwpolicy->pw_minage / _SEC_PER_DAY;
+ } else {
+ shadowval = 0;
+ }
+ bv.bv_val = slapi_ch_smprintf("%ld", shadowval);
+ bv.bv_len = strlen(bv.bv_val);
+ slapi_entry_attr_replace(e, "shadowMin", bvals);
+ slapi_ch_free_string(&bv.bv_val);
+
+ /* shadowMax - the maximum number of days for which the user password remains valid. */
+ if (pwpolicy->pw_maxage > 0) {
+ shadowval = pwpolicy->pw_maxage / _SEC_PER_DAY;
+ exptime = time_plus_sec(current_time(), pwpolicy->pw_maxage);
+ } else {
+ shadowval = 99999;
+ }
+ bv.bv_val = slapi_ch_smprintf("%ld", shadowval);
+ bv.bv_len = strlen(bv.bv_val);
+ slapi_entry_attr_replace(e, "shadowMax", bvals);
+ slapi_ch_free_string(&bv.bv_val);
+
+ /* shadowWarning - the number of days of advance warning given to the user before the user password expires. */
+ if (pwpolicy->pw_warning > 0) {
+ shadowval = pwpolicy->pw_warning / _SEC_PER_DAY;
+ } else {
+ shadowval = 0;
+ }
+ bv.bv_val = slapi_ch_smprintf("%ld", shadowval);
+ bv.bv_len = strlen(bv.bv_val);
+ slapi_entry_attr_replace(e, "shadowWarning", bvals);
+ slapi_ch_free_string(&bv.bv_val);
+
+ /* shadowExpire - the date on which the user login will be disabled. */
+ if (exptime) {
+ exptime /= _SEC_PER_DAY;
+ bv.bv_val = slapi_ch_smprintf("%ld", exptime);
+ bv.bv_len = strlen(bv.bv_val);
+ slapi_entry_attr_replace(e, "shadowExpire", bvals);
+ slapi_ch_free_string(&bv.bv_val);
+ }
+
+#if 0 /* These 2 attributes are no need (or not able) to auto-fill. */
+ /*
+ * shadowInactive - the number of days of inactivity allowed for the user.
+ * Password Policy does not have the corresponding parameter.
+ */
+ shadowval = 0;
+ bv.bv_val = slapi_ch_smprintf("%ld", shadowval);
+ bv.bv_len = strlen(bv.bv_val);
+ slapi_entry_attr_replace(e, "shadowInactive", bvals);
+ slapi_ch_free_string(&bv.bv_val);
+
+ /* shadowFlag - not currently in use. */
+ bv.bv_val = slapi_ch_smprintf("%d", 0);
+ bv.bv_len = strlen(bv.bv_val);
+ slapi_entry_attr_replace(e, "shadowFlag", bvals);
+ slapi_ch_free_string(&bv.bv_val);
+#endif
+
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "<-- add_shadow_password_attrs\n");
+ return;
+}
diff --git a/ldap/servers/slapd/pw_mgmt.c b/ldap/servers/slapd/pw_mgmt.c
index 8f33751..a650b1c 100644
--- a/ldap/servers/slapd/pw_mgmt.c
+++ b/ldap/servers/slapd/pw_mgmt.c
@@ -27,11 +27,10 @@ int
need_new_pw( Slapi_PBlock *pb, long *t, Slapi_Entry *e, int pwresponse_req )
{
time_t cur_time, pw_exp_date;
- LDAPMod *mod;
Slapi_Mods smods;
double diff_t = 0;
char *cur_time_str = NULL;
- char *passwordExpirationTime;
+ char *passwordExpirationTime = NULL;
char *timestring;
char *dn;
const Slapi_DN *sdn;
@@ -67,13 +66,12 @@ need_new_pw( Slapi_PBlock *pb, long *t, Slapi_Entry *e, int pwresponse_req )
* This is ok for data that has been loaded via ldif2ldbm
* Set expiration time if needed,
* don't do further checking and return 0 */
- if ( pwpolicy->pw_exp == 1) {
- pw_exp_date = time_plus_sec ( cur_time,
- pwpolicy->pw_maxage );
+ if (pwpolicy->pw_exp == 1) {
+ pw_exp_date = time_plus_sec(cur_time, pwpolicy->pw_maxage);
timestring = format_genTime (pw_exp_date);
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestring);
- slapi_ch_free((void **)×tring);
+ slapi_ch_free_string(×tring);
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "0");
pw_apply_mods(sdn, &smods);
@@ -86,7 +84,7 @@ need_new_pw( Slapi_PBlock *pb, long *t, Slapi_Entry *e, int pwresponse_req )
pw_exp_date = parse_genTime(passwordExpirationTime);
- slapi_ch_free((void**)&passwordExpirationTime);
+ slapi_ch_free_string(&passwordExpirationTime);
/* Check if password has been reset */
if ( pw_exp_date == NO_TIME ) {
@@ -110,7 +108,7 @@ need_new_pw( Slapi_PBlock *pb, long *t, Slapi_Entry *e, int pwresponse_req )
pw_exp_date = NOT_FIRST_TIME;
timestring = format_genTime(pw_exp_date);
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestring);
- slapi_ch_free((void **)×tring);
+ slapi_ch_free_string(×tring);
}
skip:
@@ -130,11 +128,8 @@ skip:
/* check if password expired. If so, abort bind. */
cur_time_str = format_genTime ( cur_time );
- if ( pw_exp_date != NO_TIME &&
- pw_exp_date != NOT_FIRST_TIME &&
- (diff_t = difftime ( pw_exp_date,
- parse_genTime ( cur_time_str ))) <= 0 ) {
-
+ if ((pw_exp_date != NO_TIME) && (pw_exp_date != NOT_FIRST_TIME) &&
+ (diff_t = difftime(pw_exp_date, parse_genTime(cur_time_str))) <= 0) {
slapi_ch_free_string(&cur_time_str); /* only need this above */
/* password has expired. Check the value of
* passwordGraceUserTime and compare it
@@ -144,7 +139,7 @@ skip:
pwdGraceUserTime++;
sprintf ( graceUserTime, "%d", pwdGraceUserTime );
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE,
- "passwordGraceUserTime", graceUserTime);
+ "passwordGraceUserTime", graceUserTime);
pw_apply_mods(sdn, &smods);
slapi_mods_done(&smods);
if (pwresponse_req) {
@@ -190,40 +185,30 @@ skip:
pw_apply_mods(sdn, &smods);
slapi_mods_done(&smods);
return (-1);
- }
+ }
slapi_ch_free((void **) &cur_time_str );
/* check if password is going to expire within "passwordWarning" */
/* Note that if pw_exp_date is NO_TIME or NOT_FIRST_TIME,
* we must send warning first and this changes the expiration time.
* This is done just below since diff_t is 0
- */
+ */
if ( diff_t <= pwpolicy->pw_warning ) {
int pw_exp_warned = 0;
- pw_exp_warned= slapi_entry_attr_get_int( e, "passwordExpWarned");
+ pw_exp_warned = slapi_entry_attr_get_int( e, "passwordExpWarned");
if ( !pw_exp_warned ){
/* first time send out a warning */
/* reset the expiration time to current + warning time
* and set passwordExpWarned to true
*/
if (pb->pb_conn->c_needpw != 1) {
- pw_exp_date = time_plus_sec ( cur_time,
- pwpolicy->pw_warning );
+ pw_exp_date = time_plus_sec(cur_time, pwpolicy->pw_warning);
}
timestring = format_genTime(pw_exp_date);
- /* At this time passwordExpirationTime may already be
- * in the list of mods: Remove it */
- for (mod = slapi_mods_get_first_mod(&smods); mod != NULL;
- mod = slapi_mods_get_next_mod(&smods))
- {
- if (!strcmp(mod->mod_type, "passwordExpirationTime"))
- slapi_mods_remove(&smods);
- }
-
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestring);
- slapi_ch_free((void **)×tring);
+ slapi_ch_free_string(×tring);
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "1");
@@ -232,7 +217,7 @@ skip:
} else {
*t = (long)diff_t; /* jcm: had to cast double to long */
}
-
+
pw_apply_mods(sdn, &smods);
slapi_mods_done(&smods);
if (pwresponse_req) {
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 823568d..f78bc46 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2507,4 +2507,6 @@ extern char *attr_dataversion;
/* copied from replication/repl5.h */
#define RUV_STORAGE_ENTRY_UNIQUEID "ffffffff-ffffffff-ffffffff-ffffffff"
+#define _SEC_PER_DAY 86400
+
#endif /* _slap_h_ */
7 years, 7 months
Branch '389-ds-base-1.3.4' - ldap/servers
by Mark Reynolds
ldap/servers/slapd/daemon.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
New commits:
commit a8d30b356f312b24132f4ced324a67601b7cfb9b
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Oct 23 15:17:44 2015 -0400
Ticket 48311 - nunc-stans: Attempt to release connection that
is not acquired
Bug Description: ns_connection_post_io_or_closing() was not aquiring the
connection in the optimized build, which led to the connection
ref count getting out sequence.
Fix Description Do not call connection_acquire_nolock() inside a PR_ASSERT call.
Also changed other PR_ASSERTs to only be called if DEBUG is set
https://fedorahosted.org/389/ticket/48311
Reviewed by: nhosoi(Thanks!)
(cherry picked from commit 97946bd212c5094a490d6a3429e0d5763ccd39ce)
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index ba73da3..82099bc 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1836,7 +1836,11 @@ ns_handle_closure(struct ns_job_t *job)
int do_yield = 0;
/* this function must be called from the event loop thread */
+#ifdef DEBUG
PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
+#else
+ NS_JOB_IS_THREAD(ns_job_get_type(job));
+#endif
PR_Lock(c->c_mutex);
connection_release_nolock_ext(c, 1); /* release ref acquired for event framework */
PR_ASSERT(c->c_ns_close_jobs == 1); /* should be exactly 1 active close job - this one */
@@ -1889,7 +1893,11 @@ ns_connection_post_io_or_closing(Connection *conn)
/* process event normally - wait for I/O until idletimeout */
tv.tv_sec = conn->c_idletimeout;
tv.tv_usec = 0;
- PR_ASSERT(0 == connection_acquire_nolock(conn)); /* event framework now has a reference */
+#ifdef DEBUG
+ PR_ASSERT(0 == connection_acquire_nolock(conn));
+#else
+ connection_acquire_nolock(conn); /* event framework now has a reference */
+#endif
ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
NS_JOB_READ|NS_JOB_PRESERVE_FD,
ns_handle_pr_read_ready, conn, NULL);
@@ -1911,7 +1919,11 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
Connection *c = (Connection *)ns_job_get_data(job);
/* this function must be called from the event loop thread */
+#ifdef DEBUG
PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
+#else
+ NS_JOB_IS_THREAD(ns_job_get_type(job));
+#endif
PR_Lock(c->c_mutex);
LDAPDebug2Args(LDAP_DEBUG_CONNS, "activity on conn %" NSPRIu64 " for fd=%d\n",
7 years, 7 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/daemon.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
New commits:
commit 97946bd212c5094a490d6a3429e0d5763ccd39ce
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Oct 23 15:17:44 2015 -0400
Ticket 48311 - nunc-stans: Attempt to release connection that
is not acquired
Bug Description: ns_connection_post_io_or_closing() was not aquiring the
connection in the optimized build, which led to the connection
ref count getting out sequence.
Fix Description Do not call connection_acquire_nolock() inside a PR_ASSERT call.
Also changed other PR_ASSERTs to only be called if DEBUG is set
https://fedorahosted.org/389/ticket/48311
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index ba73da3..82099bc 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1836,7 +1836,11 @@ ns_handle_closure(struct ns_job_t *job)
int do_yield = 0;
/* this function must be called from the event loop thread */
+#ifdef DEBUG
PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
+#else
+ NS_JOB_IS_THREAD(ns_job_get_type(job));
+#endif
PR_Lock(c->c_mutex);
connection_release_nolock_ext(c, 1); /* release ref acquired for event framework */
PR_ASSERT(c->c_ns_close_jobs == 1); /* should be exactly 1 active close job - this one */
@@ -1889,7 +1893,11 @@ ns_connection_post_io_or_closing(Connection *conn)
/* process event normally - wait for I/O until idletimeout */
tv.tv_sec = conn->c_idletimeout;
tv.tv_usec = 0;
- PR_ASSERT(0 == connection_acquire_nolock(conn)); /* event framework now has a reference */
+#ifdef DEBUG
+ PR_ASSERT(0 == connection_acquire_nolock(conn));
+#else
+ connection_acquire_nolock(conn); /* event framework now has a reference */
+#endif
ns_add_io_timeout_job(conn->c_tp, conn->c_prfd, &tv,
NS_JOB_READ|NS_JOB_PRESERVE_FD,
ns_handle_pr_read_ready, conn, NULL);
@@ -1911,7 +1919,11 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
Connection *c = (Connection *)ns_job_get_data(job);
/* this function must be called from the event loop thread */
+#ifdef DEBUG
PR_ASSERT(0 == NS_JOB_IS_THREAD(ns_job_get_type(job)));
+#else
+ NS_JOB_IS_THREAD(ns_job_get_type(job));
+#endif
PR_Lock(c->c_mutex);
LDAPDebug2Args(LDAP_DEBUG_CONNS, "activity on conn %" NSPRIu64 " for fd=%d\n",
7 years, 7 months
dirsrvtests/tickets
by thierry bordaz
dirsrvtests/tickets/ticket48266_test.py | 431 ++++++++++++++++++++++++++++++++
1 file changed, 431 insertions(+)
New commits:
commit 9c84b9326979f6163348b0d2a1eea8607e2f0729
Author: spichugi <spichugi(a)lib389-devel.test.redhat.com>
Date: Fri Sep 18 14:17:05 2015 +0200
Ticket 48266: test case
diff --git a/dirsrvtests/tickets/ticket48266_test.py b/dirsrvtests/tickets/ticket48266_test.py
new file mode 100644
index 0000000..e509e14
--- /dev/null
+++ b/dirsrvtests/tickets/ticket48266_test.py
@@ -0,0 +1,431 @@
+import os
+import sys
+import time
+import ldap
+import logging
+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 lib389.utils import *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+installation1_prefix = None
+
+NEW_ACCOUNT = "new_account"
+MAX_ACCOUNTS = 20
+
+class TopologyReplication(object):
+ def __init__(self, master1, master2):
+ master1.open()
+ self.master1 = master1
+ master2.open()
+ self.master2 = master2
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ global installation1_prefix
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+
+ # Creating master 1...
+ master1 = DirSrv(verbose=False)
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+ args_instance[SER_HOST] = HOST_MASTER_1
+ args_instance[SER_PORT] = PORT_MASTER_1
+ args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_master = args_instance.copy()
+ master1.allocate(args_master)
+ instance_master1 = master1.exists()
+ if instance_master1:
+ master1.delete()
+ master1.create()
+ master1.open()
+ master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
+
+ # Creating master 2...
+ master2 = DirSrv(verbose=False)
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+ args_instance[SER_HOST] = HOST_MASTER_2
+ args_instance[SER_PORT] = PORT_MASTER_2
+ args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_master = args_instance.copy()
+ master2.allocate(args_master)
+ instance_master2 = master2.exists()
+ if instance_master2:
+ master2.delete()
+ master2.create()
+ master2.open()
+ master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
+
+ #
+ # Create all the agreements
+ #
+ # Creating agreement from master 1 to master 2
+ 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]}
+ m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
+ if not m1_m2_agmt:
+ log.fatal("Fail to create a master -> master replica agreement")
+ sys.exit(1)
+ log.debug("%s created" % m1_m2_agmt)
+
+ # Creating agreement from master 2 to master 1
+ 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]}
+ m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
+ if not m2_m1_agmt:
+ log.fatal("Fail to create a master -> master replica agreement")
+ sys.exit(1)
+ log.debug("%s created" % m2_m1_agmt)
+
+ # Allow the replicas to get situated with the new agreements...
+ time.sleep(5)
+
+ #
+ # Initialize all the agreements
+ #
+ master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
+ master1.waitForReplInit(m1_m2_agmt)
+
+ # Check replication is working...
+ if master1.testReplication(DEFAULT_SUFFIX, master2):
+ log.info('Replication is working.')
+ else:
+ log.fatal('Replication is not working.')
+ assert False
+
+ # Delete each instance in the end
+ def fin():
+ master1.delete()
+ master2.delete()
+ request.addfinalizer(fin)
+
+ # Clear out the tmp dir
+ master1.clearTmpDir(__file__)
+
+ return TopologyReplication(master1, master2)
+
+
+def pattern_accesslog(file, log_pattern):
+ try:
+ pattern_accesslog.last_pos += 1
+ except AttributeError:
+ pattern_accesslog.last_pos = 0
+
+
+ found = None
+ file.seek(pattern_accesslog.last_pos)
+
+ # Use a while true iteration because 'for line in file: hit a
+ # python bug that break file.tell()
+ while True:
+ line = file.readline()
+ found = log_pattern.search(line)
+ if ((line == '') or (found)):
+ break
+
+ pattern_accesslog.last_pos = file.tell()
+ if found:
+ return line
+ else:
+ return None
+
+
+(a)pytest.fixture(scope="module")
+def entries(topology):
+ # add dummy entries in the staging DIT
+ for cpt in range(MAX_ACCOUNTS):
+ name = "%s%d" % (NEW_ACCOUNT, cpt)
+ topology.master1.add_s(Entry(("cn=%s,%s" % (name, SUFFIX), {
+ 'objectclass': "top person".split(),
+ 'sn': name,
+ 'cn': name})))
+ mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '8192'),
+ (ldap.MOD_REPLACE, 'nsslapd-accesslog-level', str(256+4))]
+ topology.master1.modify_s(DN_CONFIG, mod)
+ topology.master2.modify_s(DN_CONFIG, mod)
+
+
+def test_ticket48266_fractional(topology, entries):
+ ents = topology.master1.agreement.list(suffix=SUFFIX)
+ assert len(ents) == 1
+
+ mod = [(ldap.MOD_REPLACE, 'nsDS5ReplicatedAttributeList', ['(objectclass=*) $ EXCLUDE telephonenumber']),
+ (ldap.MOD_REPLACE, 'nsds5ReplicaStripAttrs', ['modifiersname modifytimestamp'])]
+ ents = topology.master1.agreement.list(suffix=SUFFIX)
+ assert len(ents) == 1
+ m1_m2_agmt = ents[0].dn
+ topology.master1.modify_s(ents[0].dn, mod)
+
+ ents = topology.master2.agreement.list(suffix=SUFFIX)
+ assert len(ents) == 1
+ topology.master2.modify_s(ents[0].dn, mod)
+
+ topology.master1.restart(timeout=10)
+ topology.master2.restart(timeout=10)
+
+ topology.master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
+ topology.master1.waitForReplInit(m1_m2_agmt)
+
+
+def test_ticket48266_check_repl_desc(topology, entries):
+ name = "cn=%s1,%s" % (NEW_ACCOUNT, SUFFIX)
+ value = 'check repl. description'
+ mod = [(ldap.MOD_REPLACE, 'description', value)]
+ topology.master1.modify_s(name, mod)
+
+ loop = 0
+ while loop <= 10:
+ ent = topology.master2.getEntry(name, ldap.SCOPE_BASE, "(objectclass=*)")
+ if ent.hasAttr('description') and ent.getValue('description') == value:
+ break
+ time.sleep(1)
+ loop += 1
+ assert loop <= 10
+
+
+# will use this CSN as a starting point on error log
+# after this is one 'Skipped' then the first csn _get_first_not_replicated_csn
+# should no longer be Skipped in the error log
+def _get_last_not_replicated_csn(topology):
+ name = "cn=%s5,%s" % (NEW_ACCOUNT, SUFFIX)
+
+ # read the first CSN that will not be replicated
+ mod = [(ldap.MOD_REPLACE, 'telephonenumber', str(123456))]
+ topology.master1.modify_s(name, mod)
+ msgid = topology.master1.search_ext(name, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nscpentrywsi'])
+ rtype, rdata, rmsgid = topology.master1.result2(msgid)
+ attrs = None
+ for dn, raw_attrs in rdata:
+ topology.master1.log.info("dn: %s" % dn)
+ if 'nscpentrywsi' in raw_attrs:
+ attrs = raw_attrs['nscpentrywsi']
+ assert attrs
+ for attr in attrs:
+ if attr.lower().startswith('telephonenumber'):
+ break
+ assert attr
+
+ # now retrieve the CSN of the operation we are looking for
+ csn = None
+ topology.master1.stop(timeout=10)
+ file_path = os.path.join(topology.master1.prefix, "var/log/dirsrv/slapd-%s/access" % topology.master1.serverid)
+ file_obj = open(file_path, "r")
+
+ # First the conn/op of the operation
+ regex = re.compile("MOD dn=\"%s\"" % name)
+ found_op = pattern_accesslog(file_obj, regex)
+ assert found_op
+ if found_op:
+ conn_op_pattern = '.* (conn=[0-9]* op=[0-9]*) .*'
+ conn_op_re= re.compile(conn_op_pattern)
+ conn_op_match = conn_op_re.match(found_op)
+ conn_op = conn_op_match.group(1)
+
+ # now the related CSN
+ regex = re.compile("%s RESULT" % conn_op)
+ found_result = pattern_accesslog(file_obj, regex)
+ csn_pattern = '.* csn=(.*)'
+ csn_re = re.compile(csn_pattern)
+ csn_match = csn_re.match(found_result)
+ csn = csn_match.group(1)
+
+ topology.master1.start(timeout=10)
+ return csn
+
+
+def _get_first_not_replicated_csn(topology):
+ name = "cn=%s2,%s" % (NEW_ACCOUNT, SUFFIX)
+
+ # read the first CSN that will not be replicated
+ mod = [(ldap.MOD_REPLACE, 'telephonenumber', str(123456))]
+ topology.master1.modify_s(name, mod)
+ msgid = topology.master1.search_ext(name, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nscpentrywsi'])
+ rtype, rdata, rmsgid = topology.master1.result2(msgid)
+ attrs = None
+ for dn, raw_attrs in rdata:
+ topology.master1.log.info("dn: %s" % dn)
+ if 'nscpentrywsi' in raw_attrs:
+ attrs = raw_attrs['nscpentrywsi']
+ assert attrs
+ for attr in attrs:
+ if attr.lower().startswith('telephonenumber'):
+ break
+ assert attr
+
+ # now retrieve the CSN of the operation we are looking for
+ csn = None
+ topology.master1.stop(timeout=10)
+ file_path = os.path.join(topology.master1.prefix, "var/log/dirsrv/slapd-%s/access" % topology.master1.serverid)
+ file_obj = open(file_path, "r")
+
+ # First the conn/op of the operation
+ regex = re.compile("MOD dn=\"%s\"" % name)
+ found_op = pattern_accesslog(file_obj, regex)
+ assert found_op
+ if found_op:
+ conn_op_pattern = '.* (conn=[0-9]* op=[0-9]*) .*'
+ conn_op_re= re.compile(conn_op_pattern)
+ conn_op_match = conn_op_re.match(found_op)
+ conn_op = conn_op_match.group(1)
+
+ # now the related CSN
+ regex = re.compile("%s RESULT" % conn_op)
+ found_result = pattern_accesslog(file_obj, regex)
+ csn_pattern = '.* csn=(.*)'
+ csn_re = re.compile(csn_pattern)
+ csn_match = csn_re.match(found_result)
+ csn = csn_match.group(1)
+
+ topology.master1.start(timeout=10)
+ return csn
+
+
+def _count_full_session(topology):
+ file_path = os.path.join(topology.master1.prefix, "var/log/dirsrv/slapd-%s/errors" % topology.master1.serverid)
+
+ #
+ # compute the number of 'No more updates'
+ #
+ file_obj = open(file_path, "r")
+ # pattern to find
+ pattern = ".*No more updates to send.*"
+ regex = re.compile(pattern)
+ no_more_updates = 0
+
+ # check initiation number of 'No more updates
+ while True:
+ line = file_obj.readline()
+ found = regex.search(line)
+ if (found):
+ no_more_updates = no_more_updates + 1
+ if (line == ''):
+ break
+ file_obj.close()
+
+ return no_more_updates
+
+
+def test_ticket48266_count_csn_evaluation(topology, entries):
+ ents = topology.master1.agreement.list(suffix=SUFFIX)
+ assert len(ents) == 1
+ first_csn = _get_first_not_replicated_csn(topology)
+ name = "cn=%s3,%s" % (NEW_ACCOUNT, SUFFIX)
+ NB_SESSION = 102
+
+ no_more_update_cnt = _count_full_session(topology)
+ topology.master1.agreement.pause(ents[0].dn)
+ # now do a set of updates that will NOT be replicated
+ for telNumber in range(NB_SESSION):
+ mod = [(ldap.MOD_REPLACE, 'telephonenumber', str(telNumber))]
+ topology.master1.modify_s(name, mod)
+
+ topology.master1.agreement.resume(ents[0].dn)
+
+ # let's wait all replication session complete
+ MAX_LOOP = 10
+ cnt = 0
+ current_no_more_update = _count_full_session(topology)
+ while (current_no_more_update == no_more_update_cnt):
+ cnt = cnt + 1
+ if (cnt > MAX_LOOP):
+ break
+ time.sleep(5)
+ current_no_more_update = _count_full_session(topology)
+
+ log.info('after %d MODs we have completed %d replication sessions' % (NB_SESSION, (current_no_more_update - no_more_update_cnt)))
+ no_more_update_cnt = current_no_more_update
+
+
+ # At this point, with the fix a dummy update was made BUT may be not sent it
+ # make sure it was sent so that the consumer CSN will be updated
+ last_csn = _get_last_not_replicated_csn(topology)
+
+ # let's wait all replication session complete
+ MAX_LOOP = 10
+ cnt = 0
+ current_no_more_update = _count_full_session(topology)
+ while (current_no_more_update == no_more_update_cnt):
+ cnt = cnt + 1
+ if (cnt > MAX_LOOP):
+ break
+ time.sleep(5)
+ current_no_more_update = _count_full_session(topology)
+
+ log.info('This MODs %s triggered the send of the dummy update completed %d replication sessions' % (last_csn, (current_no_more_update - no_more_update_cnt)))
+ no_more_update_cnt = current_no_more_update
+
+ # so we should no longer see the first_csn in the log
+ # Let's create a new csn (last_csn) and check there is no longer first_csn
+ topology.master1.agreement.pause(ents[0].dn)
+ last_csn = _get_last_not_replicated_csn(topology)
+ topology.master1.agreement.resume(ents[0].dn)
+
+ # let's wait for the session to complete
+ MAX_LOOP = 10
+ cnt = 0
+ while (current_no_more_update == no_more_update_cnt):
+ cnt = cnt + 1
+ if (cnt > MAX_LOOP):
+ break
+ time.sleep(5)
+ current_no_more_update = _count_full_session(topology)
+
+ log.info('This MODs %s completed in %d replication sessions, should be sent without evaluating %s' % (last_csn, (current_no_more_update - no_more_update_cnt), first_csn))
+ no_more_update_cnt = current_no_more_update
+
+ # Now determine how many times we have skipped 'csn'
+ # no need to stop the server to check the error log
+ file_path = os.path.join(topology.master1.prefix, "var/log/dirsrv/slapd-%s/errors" % topology.master1.serverid)
+ file_obj = open(file_path, "r")
+
+ # find where the last_csn operation was processed
+ pattern = ".*ruv_add_csn_inprogress: successfully inserted csn %s.*" % last_csn
+ regex = re.compile(pattern)
+ cnt = 0
+
+ while True:
+ line = file_obj.readline()
+ found = regex.search(line)
+ if ((line == '') or (found)):
+ break
+ if (found):
+ log.info('last operation was found at %d' % file_obj.tell())
+ log.info(line)
+ log.info('Now check the we can not find the first csn %s in the log'% first_csn)
+
+ pattern = ".*Skipping update operation.*CSN %s.*" % first_csn
+ regex = re.compile(pattern)
+ found = False
+ while True:
+ line = file_obj.readline()
+ found = regex.search(line)
+ if ((line == '') or (found)):
+ break
+ if (found):
+ log.info('Unexpected found %s' % line)
+ assert not found
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
7 years, 7 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/tools/ldclt/ldclt.c | 5 +++++
1 file changed, 5 insertions(+)
New commits:
commit 5b33c781d2568c930a0856f0a42c1e1d53e3358f
Author: Stanislav Zidek <szidek(a)redhat.com>
Date: Wed Oct 21 17:58:31 2015 -0700
Ticket #48289 - 389-ds-base: ldclt-bin killed by SIGSEGV
Description: If NULL source string was passed to parseFilter, it caused
NULL dereference.
https://fedorahosted.org/389/ticket/48289
Reviewed by nhosoi(a)redhat.com.
diff --git a/ldap/servers/slapd/tools/ldclt/ldclt.c b/ldap/servers/slapd/tools/ldclt/ldclt.c
index 9e573a5..7296439 100644
--- a/ldap/servers/slapd/tools/ldclt/ldclt.c
+++ b/ldap/servers/slapd/tools/ldclt/ldclt.c
@@ -929,6 +929,11 @@ parseFilter (
{
int i, j;
+ if (!src) {
+ printf ("Error: NULL source string is passed.\n");
+ return (-1);
+ }
+
for (i=0 ; (i<strlen(src)) && (src[i]!='X') ; i++);
*head = (char *)malloc(i+1);
if (*head == NULL)
7 years, 7 months
2 commits - aclocal.m4 config.guess config.sub configure configure.ac m4/libtool.m4 rpm/389-ds-base.spec.in
by Noriko Hosoi
aclocal.m4 | 15 ---
config.guess | 192 +++++++++++++++++++++++++++++++++++++++++-------
config.sub | 40 +++-------
configure | 16 +---
configure.ac | 4 -
m4/libtool.m4 | 12 ---
rpm/389-ds-base.spec.in | 21 +++++
7 files changed, 211 insertions(+), 89 deletions(-)
New commits:
commit 79aa17822eacd619563611075677ec048c2bc872
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Wed Oct 21 14:34:35 2015 -0700
Ticket #48285 - The dirsrv user/group should be created in rpm %pre, and ideally with fixed uid/gid
Description: Generated files by autogen for this diff in configure.ac:
# default user, group
-defaultuser=nobody
-defaultgroup=nobody
+defaultuser=dirsrv
+defaultgroup=dirsrv
https://fedorahosted.org/389/ticket/48285
diff --git a/aclocal.m4 b/aclocal.m4
index 6681aa3..25206b5 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -220,21 +220,6 @@ m4_popdef([pkg_default])
m4_popdef([pkg_description])
]) dnl PKG_NOARCH_INSTALLDIR
-
-# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
-# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-# -------------------------------------------
-# Retrieves the value of the pkg-config variable for the given module.
-AC_DEFUN([PKG_CHECK_VAR],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
-
-_PKG_CONFIG([$1], [variable="][$3]["], [$2])
-AS_VAR_COPY([$1], [pkg_cv_][$1])
-
-AS_VAR_IF([$1], [""], [$5], [$4])dnl
-])# PKG_CHECK_VAR
-
# Copyright (C) 2002-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
diff --git a/config.guess b/config.guess
index 1f5c50c..b79252d 100755
--- a/config.guess
+++ b/config.guess
@@ -1,8 +1,8 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2014 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2014-03-23'
+timestamp='2013-06-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2014 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -149,7 +149,7 @@ Linux|GNU|GNU/*)
LIBC=gnu
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
;;
esac
@@ -826,7 +826,7 @@ EOF
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
- *:MSYS*:*)
+ i*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
@@ -969,10 +969,10 @@ EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
- openrisc*:Linux:*:*)
- echo or1k-unknown-linux-${LIBC}
+ or1k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
- or32:Linux:*:* | or1k*:Linux:*:*)
+ or32:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
@@ -1260,26 +1260,16 @@ EOF
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
- if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- case $UNAME_PROCESSOR in
- i386) UNAME_PROCESSOR=x86_64 ;;
- powerpc) UNAME_PROCESSOR=powerpc64 ;;
- esac
- fi
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
fi
- elif test "$UNAME_PROCESSOR" = i386 ; then
- # Avoid executing cc on OS X 10.9, as it ships with a stub
- # that puts up a graphical alert prompting to install
- # developer tools. Any system running Mac OS X 10.7 or
- # later (Darwin 11 and later) is required to have a 64-bit
- # processor. This is not true of the ARM version of Darwin
- # that Apple uses in portable devices.
- UNAME_PROCESSOR=x86_64
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
@@ -1371,6 +1361,154 @@ EOF
exit ;;
esac
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
cat >&2 <<EOF
$0: unable to guess system type
diff --git a/config.sub b/config.sub
index 66c5074..c765b34 100755
--- a/config.sub
+++ b/config.sub
@@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2014 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2014-07-28'
+timestamp='2013-04-24'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -68,7 +68,7 @@ Report bugs and patches to <config-patches(a)gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2014 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -257,7 +257,7 @@ case $basic_machine in
| avr | avr32 \
| be32 | be64 \
| bfin \
- | c4x | c8051 | clipper \
+ | c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
@@ -265,7 +265,6 @@ case $basic_machine in
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
- | k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
@@ -283,10 +282,8 @@ case $basic_machine in
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
@@ -298,7 +295,8 @@ case $basic_machine in
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
- | open8 | or1k | or1knd | or32 \
+ | open8 \
+ | or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
@@ -326,7 +324,7 @@ case $basic_machine in
c6x)
basic_machine=tic6x-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -374,7 +372,7 @@ case $basic_machine in
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
- | c8051-* | clipper-* | craynv-* | cydra-* \
+ | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
@@ -383,7 +381,6 @@ case $basic_machine in
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
- | k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
@@ -403,10 +400,8 @@ case $basic_machine in
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
@@ -418,7 +413,6 @@ case $basic_machine in
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
- | or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
@@ -800,7 +794,7 @@ case $basic_machine in
os=-mingw64
;;
mingw32)
- basic_machine=i686-pc
+ basic_machine=i386-pc
os=-mingw32
;;
mingw32ce)
@@ -828,10 +822,6 @@ case $basic_machine in
basic_machine=powerpc-unknown
os=-morphos
;;
- moxiebox)
- basic_machine=moxie-unknown
- os=-moxiebox
- ;;
msdos)
basic_machine=i386-pc
os=-msdos
@@ -840,7 +830,7 @@ case $basic_machine in
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
- basic_machine=i686-pc
+ basic_machine=i386-pc
os=-msys
;;
mvs)
@@ -1377,14 +1367,14 @@ case $os in
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1556,9 +1546,6 @@ case $basic_machine in
c4x-* | tic4x-*)
os=-coff
;;
- c8051-*)
- os=-elf
- ;;
hexagon-*)
os=-elf
;;
@@ -1602,6 +1589,9 @@ case $basic_machine in
mips*-*)
os=-elf
;;
+ or1k-*)
+ os=-elf
+ ;;
or32-*)
os=-coff
;;
diff --git a/configure b/configure
index 0274c94..d4219e8 100755
--- a/configure
+++ b/configure
@@ -7540,7 +7540,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# Find out which ABI we are using.
echo 'int i;' > conftest.$ac_ext
@@ -7558,10 +7558,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_i386"
;;
- powerpc64le-*linux*)
- LD="${LD-ld} -m elf32lppclinux"
- ;;
- powerpc64-*linux*)
+ ppc64-*linux*|powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -7580,10 +7577,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- powerpcle-*linux*)
- LD="${LD-ld} -m elf64lppc"
- ;;
- powerpc-*linux*)
+ ppc*-*linux*|powerpc*-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -18166,8 +18160,8 @@ configdir=/$PACKAGE_NAME/config
schemadir=/$PACKAGE_NAME/schema
# default user, group
-defaultuser=nobody
-defaultgroup=nobody
+defaultuser=dirsrv
+defaultgroup=dirsrv
if test -z "$with_tmpfiles_d" ; then
if test -d $sysconfdir/tmpfiles.d ; then
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index f12cfdf..56666f0 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -1312,7 +1312,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# Find out which ABI we are using.
echo 'int i;' > conftest.$ac_ext
@@ -1326,10 +1326,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_i386"
;;
- powerpc64le-*linux*)
- LD="${LD-ld} -m elf32lppclinux"
- ;;
- powerpc64-*linux*)
+ ppc64-*linux*|powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -1348,10 +1345,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- powerpcle-*linux*)
- LD="${LD-ld} -m elf64lppc"
- ;;
- powerpc-*linux*)
+ ppc*-*linux*|powerpc*-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
commit 44d47d566a912cf0ffbe51770ede3ea5a2cc0548
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Oct 20 17:47:43 2015 -0700
Ticket #48285 - The dirsrv user/group should be created in rpm %pre, and ideally with fixed uid/gid
Description: Adding user dirsrv (uid 389) and group dirsrv (gid 389)
if they do not exist. If the uid and the gid are in use, increase
one by one and find unused id for them. If they exists, no change
is made. The default user and group pair (nobody, nobody) is also
replaced with (dirsrv, dirsrv).
https://fedorahosted.org/389/ticket/48285
Reviewed by wibrown(a)redhat.com (Thank you, William!)
diff --git a/configure.ac b/configure.ac
index c6471a7..f683b1c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -328,8 +328,8 @@ configdir=/$PACKAGE_NAME/config
schemadir=/$PACKAGE_NAME/schema
# default user, group
-defaultuser=nobody
-defaultgroup=nobody
+defaultuser=dirsrv
+defaultgroup=dirsrv
if test -z "$with_tmpfiles_d" ; then
if test -d $sysconfdir/tmpfiles.d ; then
diff --git a/rpm/389-ds-base.spec.in b/rpm/389-ds-base.spec.in
index b589b93..52a0245 100644
--- a/rpm/389-ds-base.spec.in
+++ b/rpm/389-ds-base.spec.in
@@ -274,6 +274,27 @@ if [ -n "$DEBUGPOSTTRANS" ] ; then
output=$DEBUGPOSTTRANS
output2=${DEBUGPOSTTRANS}.upgrade
fi
+
+has_dirsrv=`/usr/bin/egrep -i "^dirsrv\>" /etc/passwd` || :
+if [ "$has_dirsrv" = "" ]; then
+ dirsrv_uid=389
+ while [ "`getent passwd | awk -F: '{print $3}' | grep $dirsrv_uid`" != "" ]; do
+ dirsrv_uid=`expr $dirsrv_uid + 1`
+ done
+ echo "User dirsrv does not exist, create it with uid %dirsrv_uid." >> $output 2>&1 || :
+ /usr/sbin/useradd -c "389-ds-base" -u $dirsrv_uid \
+ -s /sbin/nologin -r -d /usr/share/dirsrv dirsrv 2> /dev/null || :
+ fi
+ has_dirsrv=`/usr/bin/egrep -i "^dirsrv\>" /etc/group` || :
+ if [ "$has_dirsrv" = "" ]; then
+ dirsrv_gid=389
+ while [ "`getent group | grep $dirsrv_gid`" != "" ]; do
+ dirsrv_gid=`expr $dirsrv_gid + 1`
+ done
+ echo "Group dirsrv does not exist, create it with uid %dirsrv_gid." >> $output 2>&1 || :
+ /usr/sbin/groupadd -g $dirsrv_gid -r dirsrv 2> /dev/null || :
+fi
+
echo looking for instances in %{_sysconfdir}/%{pkgname} > $output 2>&1 || :
instbase="%{_sysconfdir}/%{pkgname}"
for dir in $instbase/slapd-* ; do
7 years, 7 months
dirsrvtests/tickets ldap/servers
by Mark Reynolds
dirsrvtests/tickets/ticket48312_test.py | 168 ++++++++++++++++++++++++++++++++
ldap/servers/plugins/mep/mep.c | 18 ++-
ldap/servers/slapd/modrdn.c | 24 ++--
3 files changed, 197 insertions(+), 13 deletions(-)
New commits:
commit 6f8c5550733bd7aad116230813ec85975ae7d657
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Oct 19 12:53:53 2015 -0400
Ticket 48312 - Crash when doing modrdn on managed entry
Bug Description: If performing a modrdn on a managed entry, where the new
rdn begins with a "+", the server will crash. This is
caused by the way MEP creates the new managed entry - where
it uses the rdn attribute value from the attribute,
and not the DN. So in this case the DN rdn value escapes
the "+", but it is not escaped in the rdn attribute in
the entry. Then the internal modrdn setup thinks it
is a multivalued RDN, and the first RDN ends up being null.
This actually generates an error, but we don't return an error
from slapi_rename_internal_set_pb_ext(), and the operation
is not set in the pblock. Then slapi_modrdn_internal_pb()
dereferences the operation struct, and we crash.
Fix Description: Instead when updating the managed entry during the modrdn
get the DN value from the DN(which is already escaped), and
not from the attribute value from the entry(which is not escaped).
Also improved the modrdn code to check for NULL operations
in the pblock, report an error, and not dereference them.
https://fedorahosted.org/389/ticket/48312
Reviewed by: nhosoi(Thanks!)
diff --git a/dirsrvtests/tickets/ticket48312_test.py b/dirsrvtests/tickets/ticket48312_test.py
new file mode 100644
index 0000000..0989279
--- /dev/null
+++ b/dirsrvtests/tickets/ticket48312_test.py
@@ -0,0 +1,168 @@
+import os
+import sys
+import time
+import ldap
+import logging
+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 lib389.utils import *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+installation1_prefix = None
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+(a)pytest.fixture(scope="module")
+def topology(request):
+ global installation1_prefix
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+
+ # Creating standalone instance ...
+ standalone = DirSrv(verbose=False)
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ standalone.delete()
+ standalone.create()
+ standalone.open()
+
+ # Delete each instance in the end
+ def fin():
+ standalone.delete()
+
+ request.addfinalizer(fin)
+
+ # Clear out the tmp dir
+ standalone.clearTmpDir(__file__)
+
+ return TopologyStandalone(standalone)
+
+
+def test_ticket48312(topology):
+ """
+ Configure managed entries plugins(tempalte/definition), then perform a
+ modrdn(deleteoldrdn 1), and make sure the server does not crash.
+ """
+
+ GROUP_OU = 'ou=groups,' + DEFAULT_SUFFIX
+ PEOPLE_OU = 'ou=people,' + DEFAULT_SUFFIX
+ USER_DN = 'uid=user1,ou=people,' + DEFAULT_SUFFIX
+ CONFIG_DN = 'cn=config,cn=' + PLUGIN_MANAGED_ENTRY + ',cn=plugins,cn=config'
+ TEMPLATE_DN = 'cn=MEP Template,' + DEFAULT_SUFFIX
+ USER_NEWRDN = 'uid=\+user1'
+
+ #
+ # First enable dynamic plugins
+ #
+ try:
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', 'on')])
+ except ldap.LDAPError as e:
+ ldap.fatal('Failed to enable dynamic plugin!' + e.message['desc'])
+ assert False
+ topology.standalone.plugins.enable(name=PLUGIN_MANAGED_ENTRY)
+
+ #
+ # Add our org units (they should already exist, but do it just in case)
+ #
+ try:
+ topology.standalone.add_s(Entry((PEOPLE_OU, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'ou': 'people'})))
+ except ldap.ALREADY_EXISTS:
+ pass
+ except ldap.LDAPError as e:
+ log.fatal('test_mep: Failed to add people org unit: error ' + e.message['desc'])
+ assert False
+
+ try:
+ topology.standalone.add_s(Entry((GROUP_OU, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'ou': 'people'})))
+ except ldap.ALREADY_EXISTS:
+ pass
+ except ldap.LDAPError as e:
+ log.fatal('test_mep: Failed to add people org unit: error ' + e.message['desc'])
+ assert False
+
+ #
+ # Add the template entry
+ #
+ try:
+ topology.standalone.add_s(Entry((TEMPLATE_DN, {
+ 'objectclass': 'top mepTemplateEntry extensibleObject'.split(),
+ 'cn': 'MEP Template',
+ 'mepRDNAttr': 'cn',
+ 'mepStaticAttr': ['objectclass: posixGroup', 'objectclass: extensibleObject'],
+ 'mepMappedAttr': ['cn: $uid', 'uid: $cn', 'gidNumber: $uidNumber']
+ })))
+ except ldap.LDAPError as e:
+ log.fatal('test_mep: Failed to add template entry: error ' + e.message['desc'])
+ assert False
+
+ #
+ # Add the definition entry
+ #
+ try:
+ topology.standalone.add_s(Entry((CONFIG_DN, {
+ 'objectclass': 'top extensibleObject'.split(),
+ 'cn': 'config',
+ 'originScope': PEOPLE_OU,
+ 'originFilter': 'objectclass=posixAccount',
+ 'managedBase': GROUP_OU,
+ 'managedTemplate': TEMPLATE_DN
+ })))
+ except ldap.LDAPError as e:
+ log.fatal('test_mep: Failed to add config entry: error ' + e.message['desc'])
+ assert False
+
+ #
+ # Add an entry that meets the MEP scope
+ #
+ try:
+ topology.standalone.add_s(Entry((USER_DN, {
+ 'objectclass': 'top posixAccount extensibleObject'.split(),
+ 'uid': 'user1',
+ 'cn': 'user1',
+ 'uidNumber': '1',
+ 'gidNumber': '1',
+ 'homeDirectory': '/home/user1',
+ 'description': 'uiser description'
+ })))
+ except ldap.LDAPError as e:
+ log.fatal('test_mep: Failed to user1: error ' + e.message['desc'])
+ assert False
+
+ #
+ # Perform a modrdn on USER_DN
+ #
+ try:
+ topology.standalone.rename_s(USER_DN, USER_NEWRDN, delold=1)
+ except ldap.LDAPError as e:
+ log.error('Failed to modrdn: error ' + e.message['desc'])
+ assert False
+
+ log.info('Test complete')
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
\ No newline at end of file
diff --git a/ldap/servers/plugins/mep/mep.c b/ldap/servers/plugins/mep/mep.c
index 4399851..46acb4b 100644
--- a/ldap/servers/plugins/mep/mep.c
+++ b/ldap/servers/plugins/mep/mep.c
@@ -1309,19 +1309,29 @@ mep_create_managed_entry(struct configEntry *config, Slapi_Entry *origin)
goto done;
} else {
/* Build the DN and set it in the entry. */
- char *dn = NULL;
+ char **rdn_vals = NULL;
char *rdn_val = NULL;
+ char *dn = NULL;
/* If an origin entry was supplied, the RDN value will be
* the mapped value. If no origin entry was supplied, the
* value will be the mapping rule from the template. */
- rdn_val = slapi_entry_attr_get_charptr(managed_entry, rdn_type);
+ if (origin){
+ const char *origin_dn = slapi_entry_get_dn(origin);
+ rdn_vals = slapi_ldap_explode_dn(origin_dn, 1);
+ rdn_val = rdn_vals[0];
+ } else {
+ rdn_val = slapi_entry_attr_get_charptr(managed_entry, rdn_type);
+ }
/* Create the DN using the mapped RDN value
* and the base specified in the config. */
dn = slapi_ch_smprintf("%s=%s,%s", rdn_type, rdn_val, config->managed_base);
-
- slapi_ch_free_string(&rdn_val);
+ if(origin){
+ slapi_ldap_value_free(rdn_vals);
+ } else {
+ slapi_ch_free_string(&rdn_val);
+ }
if (dn != NULL) {
slapi_sdn_set_dn_passin(slapi_entry_get_sdn(managed_entry), dn);
diff --git a/ldap/servers/slapd/modrdn.c b/ldap/servers/slapd/modrdn.c
index 798d3d4..e80e1f9 100644
--- a/ldap/servers/slapd/modrdn.c
+++ b/ldap/servers/slapd/modrdn.c
@@ -338,20 +338,26 @@ slapi_rename_internal_set_pb_ext(Slapi_PBlock *pb,
static int rename_internal_pb (Slapi_PBlock *pb)
{
- LDAPControl **controls;
- Operation *op;
- int opresult = 0;
+ LDAPControl **controls;
+ Operation *op;
+ int opresult = 0;
PR_ASSERT (pb != NULL);
slapi_pblock_get(pb, SLAPI_CONTROLS_ARG, &controls);
-
- slapi_pblock_get(pb, SLAPI_OPERATION, &op);
- op->o_handler_data = &opresult;
- op->o_result_handler = internal_getresult_callback;
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ if (!op) {
+ opresult = 1;
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
+ slapi_log_error(SLAPI_LOG_FATAL, "rename_internal_pb",
+ "Internal error: pblock was not properly initialized\n");
+ return -1;
+ }
+ op->o_handler_data = &opresult;
+ op->o_result_handler = internal_getresult_callback;
slapi_pblock_set(pb, SLAPI_REQCONTROLS, controls);
-
+
/* set parameters common for all internal operations */
set_common_params (pb);
@@ -359,7 +365,7 @@ static int rename_internal_pb (Slapi_PBlock *pb)
set_config_params (pb);
op_shared_rename (pb, 0 /* not passing ownership of args */ );
-
+
slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
return 0;
7 years, 7 months
Branch '389-ds-base-1.2.11' - ldap/servers
by thierry bordaz
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
New commits:
commit bdaed4e2fb4633d6fec16eb1ea55b7e2fcbd4df4
Author: Thierry Bordaz <tbordaz(a)redhat.com>
Date: Mon Oct 19 11:03:54 2015 +0200
Ticket 47978: Deadlock between two MODs on the same entry between entry cache and backend lock
Bug Description:
During a modify, the modified entry gets into the entry cache and is locked.
If after the be_txn_postop/txn_commit and before the modify returns
the modified entry gets out of the entry cache, the entry is not unlocked.
It can lead to hang as soon as an other write operation hit that unlocked entry.
This is a side effect of fix:
#47834 - Tombstone_to_glue: if parents are also converted to glue, the target entry's DN must be adjusted.
Fix Description:
When the entry is locked, set a flag so that can later be unlocked
independently of its presence in the entry cache
https://fedorahosted.org/389/ticket/47978
Reviewed by: Noriko Hosoi (Thanks Noriko)
Platforms tested: F22 (IPA CI test test_integration/test_vault.py, one failure out 2-4)
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index 69bf246..bfcaf3d 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -387,6 +387,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
int repl_op;
int opreturn = 0;
int mod_count = 0;
+ int ec_locked = 0;
slapi_pblock_get( pb, SLAPI_BACKEND, &be);
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
@@ -745,6 +746,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
/* lock new entry in cache to prevent usage until we are complete */
cache_lock_entry( &inst->inst_cache, ec );
+ ec_locked = 1;
postentry = slapi_entry_dup( ec->ep_entry );
slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );
@@ -861,7 +863,7 @@ common_return:
slapi_mods_done(&smods);
if(inst){
- if (cache_is_in_cache( &inst->inst_cache, ec))
+ if (ec_locked || cache_is_in_cache( &inst->inst_cache, ec))
{
cache_unlock_entry( &inst->inst_cache, ec);
} else if (e) {
7 years, 7 months
Branch '389-ds-base-1.3.3' - ldap/servers
by thierry bordaz
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
New commits:
commit 68445928510b48570cafef8badab46062d316006
Author: Thierry Bordaz <tbordaz(a)redhat.com>
Date: Fri Oct 16 18:18:01 2015 +0200
Ticket 47978: Deadlock between two MODs on the same entry between entry cache and backend lock
Bug Description:
During a modify, the modified entry gets into the entry cache and is locked.
If after the be_txn_postop/txn_commit and before the modify returns
the modified entry gets out of the entry cache, the entry is not unlocked.
It can lead to hang as soon as an other write operation hit that unlocked entry.
This is a side effect of fix:
#47834 - Tombstone_to_glue: if parents are also converted to glue, the target entry's DN must be adjusted.
Fix Description:
When the entry is locked, set a flag so that can later be unlocked
independently of its presence in the entry cache
https://fedorahosted.org/389/ticket/47978
Reviewed by: Noriko Hosoi (Thanks Noriko)
Platforms tested: F22 (IPA CI test test_integration/test_vault.py, one failure out 2-4)
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index b9f754d..80ffce4 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -420,6 +420,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
int mod_count = 0;
int not_an_error = 0;
int fixup_tombstone = 0;
+ int ec_locked = 0;
slapi_pblock_get( pb, SLAPI_BACKEND, &be);
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
@@ -827,6 +828,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
CACHE_RETURN( &inst->inst_cache, &e );
/* lock new entry in cache to prevent usage until we are complete */
cache_lock_entry( &inst->inst_cache, ec );
+ ec_locked = 1;
postentry = slapi_entry_dup( ec->ep_entry );
slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );
@@ -947,7 +949,7 @@ common_return:
slapi_mods_done(&smods);
if (inst) {
- if (cache_is_in_cache(&inst->inst_cache, ec)) {
+ if (ec_locked || cache_is_in_cache(&inst->inst_cache, ec)) {
cache_unlock_entry(&inst->inst_cache, ec);
} else if (e) {
/* if ec was not in cache, cache_replace was not done.
7 years, 7 months