import 389-ds-base-1.3.6.1-21.el7_4

This commit is contained in:
CentOS Sources 2017-10-19 09:23:47 -04:00
parent 1c155e2849
commit 6405dba47e
12 changed files with 2829 additions and 6 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
From c9817ebe42a97ac7df155582957927b4d1d08c5f Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 18 Sep 2017 14:55:14 -0400
Subject: [PATCH] Ticket 49330 - Add endian header file
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 67217af..163db7d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,7 +39,7 @@ AC_PROG_LIBTOOL
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS([arpa/inet.h errno.h fcntl.h malloc.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/file.h sys/socket.h sys/time.h syslog.h unistd.h inttypes.h mntent.h sys/sysinfo.h])
+AC_CHECK_HEADERS([arpa/inet.h errno.h fcntl.h malloc.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/file.h sys/socket.h sys/time.h syslog.h unistd.h mntent.h sys/sysinfo.h sys/endian.h endian.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STAT
--
2.9.5

View file

@ -0,0 +1,87 @@
From bbe3403a88f9adecbd5d4187ceeb080fb51d9d14 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 31 May 2017 11:15:13 -0400
Subject: [PATCH] Ticket 49257 - only register modify callbacks
Bug Description: Regression. In the previous fix we called
ldbm_instance_config_load_dse_info() to register all
the dse preop callbacks. Previously this was only done
when creating an instance. It was not designed to be
used outside of that context, and it caused error 53's
when trying to add a backend after instance creation.
Fix Description: Just register the "modify" DSE preop callbacks.
https://pagure.io/389-ds-base/issue/49257
Reviewed by: ?
(cherry picked from commit 75a32a8829297a5cab303590d049f581740cf87e)
---
ldap/servers/slapd/back-ldbm/instance.c | 12 +++---------
ldap/servers/slapd/back-ldbm/ldbm_config.h | 2 +-
ldap/servers/slapd/back-ldbm/ldbm_instance_config.c | 13 +++++++++++++
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/ldap/servers/slapd/back-ldbm/instance.c b/ldap/servers/slapd/back-ldbm/instance.c
index 8b38644..f067d22 100644
--- a/ldap/servers/slapd/back-ldbm/instance.c
+++ b/ldap/servers/slapd/back-ldbm/instance.c
@@ -305,15 +305,9 @@ ldbm_instance_startall(struct ldbminfo *li)
if (rc1 != 0) {
rc = rc1;
} else {
- if(ldbm_instance_config_load_dse_info(inst) != 0){
- slapi_log_err(SLAPI_LOG_ERR, "ldbm_instance_startall",
- "Loading database instance configuration failed for (%s)\n",
- inst->inst_name);
- rc = -1;
- } else {
- vlv_init(inst);
- slapi_mtn_be_started(inst->inst_be);
- }
+ ldbm_instance_register_modify_callback(inst);
+ vlv_init(inst);
+ slapi_mtn_be_started(inst->inst_be);
}
inst_obj = objset_next_obj(li->li_instance_set, inst_obj);
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.h b/ldap/servers/slapd/back-ldbm/ldbm_config.h
index ddec3a8..ea59739 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.h
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.h
@@ -157,6 +157,6 @@ int
ldbm_instance_index_config_enable_index(ldbm_instance *inst, Slapi_Entry* e);
int ldbm_instance_create_default_user_indexes(ldbm_instance *inst);
void ldbm_config_destroy(struct ldbminfo *li);
-
+void ldbm_instance_register_modify_callback(ldbm_instance *inst);
#endif /* _LDBM_CONFIG_H_ */
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
index 49a6cac..8fb4119 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
@@ -554,6 +554,19 @@ static int ldbm_instance_deny_config(Slapi_PBlock *pb, Slapi_Entry *e,
return SLAPI_DSE_CALLBACK_ERROR;
}
+void
+ldbm_instance_register_modify_callback(ldbm_instance *inst)
+{
+ struct ldbminfo *li = inst->inst_li;
+ char *dn = NULL;
+
+ dn = slapi_create_dn_string("cn=%s,cn=%s,cn=plugins,cn=config",
+ inst->inst_name, li->li_plugin->plg_name);
+ slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
+ LDAP_SCOPE_BASE, "(objectclass=*)",
+ ldbm_instance_modify_config_entry_callback, (void *) inst);
+ slapi_ch_free_string(&dn);
+}
/* Reads in any config information held in the dse for the given
* entry. Creates dse entries used to configure the given instance
* if they don't already exist. Registers dse callback functions to
--
2.9.5

View file

@ -0,0 +1,46 @@
From 28529671057c95327a35c326ee99fcafccad9de9 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Wed, 14 Jun 2017 18:36:55 +0200
Subject: [PATCH] Ticket 49291 - slapi_search_internal_callback_pb may SIGSEV
if related pblock has not operation set
Bug Description:
if slapi_search_internal_set_pb is called with an invalid (NULL) base, the pblock should not
be used to call send_ldap_result. If it is, the send_ldap_result trying to derefence the
operation pointer will crash
Fix Description:
Check that the operation is set before derefencing it
https://pagure.io/389-ds-base/issue/49291
Reviewed by: Mark Reynolds
Platforms tested: F23
Flag Day: no
Doc impact: no
---
ldap/servers/slapd/result.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 56257c3..f3016ca 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -350,6 +350,11 @@ send_ldap_result_ext(
slapi_pblock_get (pb, SLAPI_BIND_METHOD, &bind_method);
slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
+ if (operation == NULL) {
+ slapi_log_err(SLAPI_LOG_ERR, "send_ldap_result_ext", "No operation found: slapi_search_internal_set_pb was incomplete (invalid 'base' ?)\n");
+ return;
+ }
+
if (operation->o_status == SLAPI_OP_STATUS_RESULT_SENT) {
return; /* result already sent */
}
--
2.9.5

View file

@ -0,0 +1,51 @@
From 1ec56936d29985a55f9529c1ea3e71056557b3ff Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 1 Sep 2017 09:24:55 -0400
Subject: [PATCH] Ticket 49370 - local password policies should use the same
defaults as the global policy
Description: When a local password policy (subtree/user) is created it does not use
the same defaults as the global policy. This causes inconsistent behavior.
https://pagure.io/389-ds-base/issue/49370
Reviewed by: firstyear(Thanks!)
---
ldap/servers/slapd/pw.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 378d148..19a863a 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1768,6 +1768,27 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
goto done;
}
+ /* Set the default values */
+ pwdpolicy->pw_mintokenlength = SLAPD_DEFAULT_PW_MINTOKENLENGTH;
+ pwdpolicy->pw_minlength = SLAPD_DEFAULT_PW_MINLENGTH;
+ pwdpolicy->pw_mindigits = SLAPD_DEFAULT_PW_MINDIGITS;
+ pwdpolicy->pw_minalphas = SLAPD_DEFAULT_PW_MINALPHAS;
+ pwdpolicy->pw_minuppers = SLAPD_DEFAULT_PW_MINUPPERS;
+ pwdpolicy->pw_minlowers = SLAPD_DEFAULT_PW_MINLOWERS;
+ pwdpolicy->pw_minspecials = SLAPD_DEFAULT_PW_MINSPECIALS;
+ pwdpolicy->pw_min8bit = SLAPD_DEFAULT_PW_MIN8BIT;
+ pwdpolicy->pw_maxrepeats = SLAPD_DEFAULT_PW_MAXREPEATS;
+ pwdpolicy->pw_mincategories = SLAPD_DEFAULT_PW_MINCATEGORIES;
+ pwdpolicy->pw_mintokenlength = SLAPD_DEFAULT_PW_MINTOKENLENGTH;
+ pwdpolicy->pw_maxage = SLAPD_DEFAULT_PW_MAXAGE;
+ pwdpolicy->pw_minage = SLAPD_DEFAULT_PW_MINAGE;
+ pwdpolicy->pw_warning = SLAPD_DEFAULT_PW_WARNING;
+ pwdpolicy->pw_inhistory = SLAPD_DEFAULT_PW_INHISTORY;
+ pwdpolicy->pw_maxfailure = SLAPD_DEFAULT_PW_MAXFAILURE;
+ pwdpolicy->pw_lockduration = SLAPD_DEFAULT_PW_LOCKDURATION;
+ pwdpolicy->pw_resetfailurecount = SLAPD_DEFAULT_PW_RESETFAILURECOUNT;
+ pwdpolicy->pw_gracelimit = SLAPD_DEFAULT_PW_GRACELIMIT;
+
/* set the default passwordLegacyPolicy setting */
pwdpolicy->pw_is_legacy = 1;
--
2.9.5

View file

@ -0,0 +1,55 @@
From af59afa03296160577e419257772d5319796a992 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 14 Sep 2017 08:32:11 -0400
Subject: [PATCH] Ticket 49380 - Crash when adding invalid replication
agreement
Bug Description: If you add a replication agreement with an invalid "replicaEnabled" value
the server crashes when freeing the replica schedule. This is because the
schedule never gets allocated before the rror conidtion is hit, and then
it get dereferenced.
Fix Description: Check for a NULL schedule before trying to destroy it.
https://pagure.io/389-ds-base/issue/49380
Reviewed by: tbordaz(Thanks!)
---
ldap/servers/plugins/replication/repl5_schedule.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/ldap/servers/plugins/replication/repl5_schedule.c b/ldap/servers/plugins/replication/repl5_schedule.c
index 60ee6f2..4572e63 100644
--- a/ldap/servers/plugins/replication/repl5_schedule.c
+++ b/ldap/servers/plugins/replication/repl5_schedule.c
@@ -130,6 +130,10 @@ schedule_destroy(Schedule *s)
{
int i;
+ if (s == NULL) {
+ return;
+ }
+
/* unschedule update window event if exists */
unschedule_window_state_change_event (s);
@@ -177,11 +181,15 @@ free_schedule_list(schedule_item **schedule_list)
int
schedule_set(Schedule *sch, Slapi_Attr *attr)
{
- int return_value;
+ int return_value = -1;
schedule_item *si = NULL;
schedule_item *new_schedule_list = NULL;
int valid = 1;
+ if (sch == NULL) {
+ return return_value;
+ }
+
if (NULL != attr)
{
int ind;
--
2.9.5

View file

@ -0,0 +1,81 @@
From d336e3558655d44f8ba797392af882e33d492958 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 14 Sep 2017 14:15:25 -0400
Subject: [PATCH] Ticket 49380 - Add CI test
Description: Add test to verify invalid agreement is rejected, and it
does not cause a crash
https://pagure.io/389-ds-base/issue/49380
Reviewed by: spichugi(Thanks!)
(cherry picked from commit 02d76b61489f105f81d72d4f3848e2444463289b)
---
.../tests/suites/replication/acceptance_test.py | 43 ++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/dirsrvtests/tests/suites/replication/acceptance_test.py b/dirsrvtests/tests/suites/replication/acceptance_test.py
index e6f2ef7..2f8b180 100644
--- a/dirsrvtests/tests/suites/replication/acceptance_test.py
+++ b/dirsrvtests/tests/suites/replication/acceptance_test.py
@@ -3,6 +3,12 @@ from lib389.tasks import *
from lib389.utils import *
from lib389.topologies import topology_m4 as topo
+from lib389._constants import (BACKEND_NAME, DEFAULT_SUFFIX, LOG_REPLICA, REPLICA_RUV_FILTER,
+ ReplicaRole, REPLICATION_BIND_DN, REPLICATION_BIND_PW,
+ REPLICATION_BIND_METHOD, REPLICATION_TRANSPORT, defaultProperties,
+ RA_NAME, RA_BINDDN, RA_BINDPW, RA_METHOD, RA_TRANSPORT_PROT,
+ DN_DM, PASSWORD, LOG_DEFAULT, RA_ENABLED, RA_SCHEDULE)
+
TEST_ENTRY_NAME = 'mmrepl_test'
TEST_ENTRY_DN = 'uid={},{}'.format(TEST_ENTRY_NAME, DEFAULT_SUFFIX)
@@ -193,6 +199,43 @@ def test_modrdn_entry(topo, test_entry, delold):
topo.ms["master1"].delete_s(newrdn_dn)
+def test_invalid_agmt(topo_m4):
+ """Test adding that an invalid agreement is properly rejected and does not crash the server
+
+ :id: 6c3b2a7e-edcd-4327-a003-6bd878ff722b
+ :setup: MMR with four masters
+ :steps:
+ 1. Add invalid agreement (nsds5ReplicaEnabled set to invalid value)
+ 2. Verify the server is still running
+ :expectedresults:
+ 1. Invalid repl agreement should be rejected
+ 2. Server should be still running
+ """
+ m1 = topo_m4.ms["master1"]
+
+ # Add invalid agreement (nsds5ReplicaEnabled set to invalid value)
+ AGMT_DN = 'cn=whatever,cn=replica,cn="dc=example,dc=com",cn=mapping tree,cn=config'
+ try:
+ invalid_props = {RA_ENABLED: 'True', # Invalid value
+ RA_SCHEDULE: '0001-2359 0123456'}
+ m1.agreement.create(suffix=DEFAULT_SUFFIX, host='localhost', port=389, properties=invalid_props)
+ except ldap.UNWILLING_TO_PERFORM:
+ m1.log.info('Invalid repl agreement correctly rejected')
+ except ldap.LDAPError as e:
+ m1.log.fatal('Got unexpected error adding invalid agreement: ' + str(e))
+ assert False
+ else:
+ m1.log.fatal('Invalid agreement was incorrectly accepted by the server')
+ assert False
+
+ # Verify the server is still running
+ try:
+ m1.simple_bind_s(DN_DM, PASSWORD)
+ except ldap.LDAPError as e:
+ m1.log.fatal('Failed to bind: ' + str(e))
+ assert False
+
+
if __name__ == '__main__':
# Run isolated
# -s for DEBUG mode
--
2.9.5

View file

@ -0,0 +1,610 @@
From 3ab8a78cd27cc8d2ad7a2b322a4fe73c43a3db08 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 14 Sep 2017 15:47:53 -0400
Subject: [PATCH] Ticket 49327 - password expired control not sent during grace
logins
Bug Description: When a password is expired, but within the grace login limit,
we should still send the expired control even though we allowed
the bind.
Fix Description: new_new_passwd() returned a variety of result codes that required
the caller to set the response controls. This was hard to read and
process. Instead I added all the controls inside the function, and
return success or failure to the caller.
https://pagure.io/389-ds-base/issue/49327
Reviewed by: gparente & tbordaz (Thanks!!)
(cherry picked from commit fbd32c4e27af9f331ee3a42dec944895a6efe2ad)
---
ldap/servers/plugins/replication/repl_extop.c | 5 +-
ldap/servers/slapd/bind.c | 18 +-
ldap/servers/slapd/proto-slap.h | 3 +-
ldap/servers/slapd/pw_mgmt.c | 453 +++++++++++++-------------
ldap/servers/slapd/saslbind.c | 20 +-
5 files changed, 238 insertions(+), 261 deletions(-)
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index a39d918..96ad7dd 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -1173,8 +1173,9 @@ send_response:
* On the supplier, we need to close the connection so
* that the RA will restart a new session in a clear state
*/
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "multimaster_extop_StartNSDS50ReplicationRequest - "
- "already acquired replica: disconnect conn=%d\n", connid);
+ slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
+ "multimaster_extop_StartNSDS50ReplicationRequest - "
+ "already acquired replica: disconnect conn=%" PRIu64 "\n", connid);
slapi_disconnect_server(conn);
}
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index d6c7668..e6cad7f 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -673,8 +673,7 @@ do_bind( Slapi_PBlock *pb )
slapi_entry_free(referral);
goto free_and_return;
} else if (auto_bind || rc == SLAPI_BIND_SUCCESS || rc == SLAPI_BIND_ANONYMOUS) {
- long t;
- char* authtype = NULL;
+ char *authtype = NULL;
/* rc is SLAPI_BIND_SUCCESS or SLAPI_BIND_ANONYMOUS */
if(auto_bind) {
rc = SLAPI_BIND_SUCCESS;
@@ -761,19 +760,8 @@ do_bind( Slapi_PBlock *pb )
slapi_ch_strdup(slapi_sdn_get_ndn(sdn)),
NULL, NULL, NULL, bind_target_entry);
if (!slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA)) {
- /* check if need new password before sending
- the bind success result */
- myrc = need_new_pw(pb, &t, bind_target_entry, pw_response_requested);
- switch (myrc) {
- case 1:
- (void)slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
- break;
- case 2:
- (void)slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRING, t);
- break;
- default:
- break;
- }
+ /* check if need new password before sending the bind success result */
+ myrc = need_new_pw(pb, bind_target_entry, pw_response_requested);
}
}
if (auth_response_requested) {
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 9696ead..0ba61d7 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -972,7 +972,7 @@ int plugin_call_acl_verify_syntax ( Slapi_PBlock *pb, Slapi_Entry *e, char **err
* pw_mgmt.c
*/
void pw_init( void );
-int need_new_pw( Slapi_PBlock *pb, long *t, Slapi_Entry *e, int pwresponse_req );
+int need_new_pw(Slapi_PBlock *pb, Slapi_Entry *e, int pwresponse_req);
int update_pw_info( Slapi_PBlock *pb , char *old_pw );
int check_pw_syntax( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
char **old_pw, Slapi_Entry *e, int mod_op );
@@ -982,7 +982,6 @@ void get_old_pw( Slapi_PBlock *pb, const Slapi_DN *sdn, char **old_pw);
int check_account_lock( Slapi_PBlock *pb, Slapi_Entry * bind_target_entry, int pwresponse_req, int account_inactivation_only /*no wire/no pw policy*/);
int check_pw_minage( Slapi_PBlock *pb, const Slapi_DN *sdn, struct berval **vals) ;
void add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry *e );
-
int add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e);
/*
diff --git a/ldap/servers/slapd/pw_mgmt.c b/ldap/servers/slapd/pw_mgmt.c
index 7252c08..b06e3f1 100644
--- a/ldap/servers/slapd/pw_mgmt.c
+++ b/ldap/servers/slapd/pw_mgmt.c
@@ -22,234 +22,239 @@
/* prototypes */
/****************************************************************************/
-/* need_new_pw() is called when non rootdn bind operation succeeds with authentication */
+/*
+ * need_new_pw() is called when non rootdn bind operation succeeds with authentication
+ *
+ * Return 0 - password is okay
+ * Return -1 - password is expired, abort bind
+ */
int
-need_new_pw( Slapi_PBlock *pb, long *t, Slapi_Entry *e, int pwresponse_req )
+need_new_pw(Slapi_PBlock *pb, Slapi_Entry *e, int pwresponse_req)
{
- time_t cur_time, pw_exp_date;
- Slapi_Mods smods;
- double diff_t = 0;
- char *cur_time_str = NULL;
- char *passwordExpirationTime = NULL;
- char *timestring;
- char *dn;
- const Slapi_DN *sdn;
- passwdPolicy *pwpolicy = NULL;
- int pwdGraceUserTime = 0;
- char graceUserTime[8];
-
- if (NULL == e) {
- return (-1);
- }
- slapi_mods_init (&smods, 0);
- sdn = slapi_entry_get_sdn_const( e );
- dn = slapi_entry_get_ndn( e );
- pwpolicy = new_passwdPolicy(pb, dn);
-
- /* after the user binds with authentication, clear the retry count */
- if ( pwpolicy->pw_lockout == 1)
- {
- if(slapi_entry_attr_get_int( e, "passwordRetryCount") > 0)
- {
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordRetryCount", "0");
- }
- }
-
- cur_time = current_time();
-
- /* get passwordExpirationTime attribute */
- passwordExpirationTime= slapi_entry_attr_get_charptr(e, "passwordExpirationTime");
-
- if (passwordExpirationTime == NULL)
- {
- /* password expiration date is not set.
- * 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);
-
- timestring = format_genTime (pw_exp_date);
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestring);
- slapi_ch_free_string(&timestring);
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "0");
-
- pw_apply_mods(sdn, &smods);
- } else if (pwpolicy->pw_lockout == 1) {
- pw_apply_mods(sdn, &smods);
- }
- slapi_mods_done(&smods);
- return ( 0 );
- }
-
- pw_exp_date = parse_genTime(passwordExpirationTime);
-
- slapi_ch_free_string(&passwordExpirationTime);
-
- /* Check if password has been reset */
- if ( pw_exp_date == NO_TIME ) {
-
- /* check if changing password is required */
- if ( pwpolicy->pw_must_change ) {
- /* set c_needpw for this connection to be true. this client
- now can only change its own password */
- pb->pb_conn->c_needpw = 1;
- *t=0;
- /* We need to include "changeafterreset" error in
- * passwordpolicy response control. So, we will not be
- * done here. We remember this scenario by (c_needpw=1)
- * and check it before sending the control from various
- * places. We will also add LDAP_CONTROL_PWEXPIRED control
- * as the return value used to be (1).
- */
- goto skip;
- }
- /* Mark that first login occured */
- 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_string(&timestring);
- }
+ time_t cur_time, pw_exp_date;
+ Slapi_Mods smods;
+ double diff_t = 0;
+ char *cur_time_str = NULL;
+ char *passwordExpirationTime = NULL;
+ char *timestring;
+ char *dn;
+ const Slapi_DN *sdn;
+ passwdPolicy *pwpolicy = NULL;
+ int pwdGraceUserTime = 0;
+ char graceUserTime[16] = {0};
+ Connection *pb_conn = NULL;
+ long t;
+
+ if (NULL == e) {
+ return (-1);
+ }
+ slapi_mods_init(&smods, 0);
+ sdn = slapi_entry_get_sdn_const(e);
+ dn = slapi_entry_get_ndn(e);
+ pwpolicy = new_passwdPolicy(pb, dn);
+
+ /* after the user binds with authentication, clear the retry count */
+ if (pwpolicy->pw_lockout == 1) {
+ if (slapi_entry_attr_get_int(e, "passwordRetryCount") > 0) {
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordRetryCount", "0");
+ }
+ }
+
+ cur_time = current_time();
+
+ /* get passwordExpirationTime attribute */
+ passwordExpirationTime = slapi_entry_attr_get_charptr(e, "passwordExpirationTime");
+
+ if (passwordExpirationTime == NULL) {
+ /* password expiration date is not set.
+ * 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);
+
+ timestring = format_genTime(pw_exp_date);
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestring);
+ slapi_ch_free_string(&timestring);
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "0");
+
+ pw_apply_mods(sdn, &smods);
+ } else if (pwpolicy->pw_lockout == 1) {
+ pw_apply_mods(sdn, &smods);
+ }
+ slapi_mods_done(&smods);
+ return (0);
+ }
+
+ pw_exp_date = parse_genTime(passwordExpirationTime);
+
+ slapi_ch_free_string(&passwordExpirationTime);
+
+ slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+
+ /* Check if password has been reset */
+ if (pw_exp_date == NO_TIME) {
+
+ /* check if changing password is required */
+ if (pwpolicy->pw_must_change) {
+ /* set c_needpw for this connection to be true. this client
+ now can only change its own password */
+ pb_conn->c_needpw = 1;
+ t = 0;
+ /* We need to include "changeafterreset" error in
+ * passwordpolicy response control. So, we will not be
+ * done here. We remember this scenario by (c_needpw=1)
+ * and check it before sending the control from various
+ * places. We will also add LDAP_CONTROL_PWEXPIRED control
+ * as the return value used to be (1).
+ */
+ goto skip;
+ }
+ /* Mark that first login occured */
+ 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_string(&timestring);
+ }
skip:
- /* if password never expires, don't need to go on; return 0 */
- if ( pwpolicy->pw_exp == 0 ) {
- /* check for "changeafterreset" condition */
- if (pb->pb_conn->c_needpw == 1) {
- if (pwresponse_req) {
- slapi_pwpolicy_make_response_control ( pb, -1, -1, LDAP_PWPOLICY_CHGAFTERRESET );
- }
- slapi_add_pwd_control ( pb, LDAP_CONTROL_PWEXPIRED, 0);
- }
- pw_apply_mods(sdn, &smods);
- slapi_mods_done(&smods);
- return ( 0 );
- }
-
- /* 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) {
- slapi_ch_free_string(&cur_time_str); /* only need this above */
- /* password has expired. Check the value of
- * passwordGraceUserTime and compare it
- * against the value of passwordGraceLimit */
- pwdGraceUserTime = slapi_entry_attr_get_int( e, "passwordGraceUserTime");
- if ( pwpolicy->pw_gracelimit > pwdGraceUserTime ) {
- pwdGraceUserTime++;
- sprintf ( graceUserTime, "%d", pwdGraceUserTime );
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE,
- "passwordGraceUserTime", graceUserTime);
- pw_apply_mods(sdn, &smods);
- slapi_mods_done(&smods);
- if (pwresponse_req) {
- /* check for "changeafterreset" condition */
- if (pb->pb_conn->c_needpw == 1) {
- slapi_pwpolicy_make_response_control( pb, -1,
- ((pwpolicy->pw_gracelimit) - pwdGraceUserTime),
- LDAP_PWPOLICY_CHGAFTERRESET);
- } else {
- slapi_pwpolicy_make_response_control( pb, -1,
- ((pwpolicy->pw_gracelimit) - pwdGraceUserTime),
- -1);
- }
- }
-
- if (pb->pb_conn->c_needpw == 1) {
- slapi_add_pwd_control ( pb, LDAP_CONTROL_PWEXPIRED, 0);
- }
- return ( 0 );
- }
-
- /* password expired and user exceeded limit of grace attemps.
- * Send result and also the control */
- slapi_add_pwd_control ( pb, LDAP_CONTROL_PWEXPIRED, 0);
- if (pwresponse_req) {
- slapi_pwpolicy_make_response_control ( pb, -1, -1, LDAP_PWPOLICY_PWDEXPIRED );
- }
- slapi_send_ldap_result ( pb, LDAP_INVALID_CREDENTIALS, NULL,
- "password expired!", 0, NULL );
-
- /* abort bind */
- /* pass pb to do_unbind(). pb->pb_op->o_opid and
- pb->pb_op->o_tag are not right but I don't see
- do_unbind() checking for those. We might need to
- create a pb for unbind operation. Also do_unbind calls
- pre and post ops. Maybe we don't want to call them */
- if (pb->pb_conn && (LDAP_VERSION2 == pb->pb_conn->c_ldapversion)) {
- /* We close the connection only with LDAPv2 connections */
- disconnect_server( pb->pb_conn, pb->pb_op->o_connid,
- pb->pb_op->o_opid, SLAPD_DISCONNECT_UNBIND, 0);
- }
- /* Apply current modifications */
- 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");
- 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);
- }
-
- timestring = format_genTime(pw_exp_date);
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestring);
- slapi_ch_free_string(&timestring);
-
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "1");
-
- *t = pwpolicy->pw_warning;
-
- } else {
- *t = (long)diff_t; /* jcm: had to cast double to long */
- }
-
- pw_apply_mods(sdn, &smods);
- slapi_mods_done(&smods);
- if (pwresponse_req) {
- /* check for "changeafterreset" condition */
- if (pb->pb_conn->c_needpw == 1) {
- slapi_pwpolicy_make_response_control( pb, *t, -1,
- LDAP_PWPOLICY_CHGAFTERRESET);
- } else {
- slapi_pwpolicy_make_response_control( pb, *t, -1,
- -1);
- }
- }
-
- if (pb->pb_conn->c_needpw == 1) {
- slapi_add_pwd_control ( pb, LDAP_CONTROL_PWEXPIRED, 0);
- }
- return (2);
- } else {
- if (pwresponse_req && pwpolicy->pw_send_expiring) {
- slapi_pwpolicy_make_response_control( pb, diff_t, -1, -1);
- slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRING, diff_t);
- }
- }
-
- pw_apply_mods(sdn, &smods);
- slapi_mods_done(&smods);
- /* Leftover from "changeafterreset" condition */
- if (pb->pb_conn->c_needpw == 1) {
- slapi_add_pwd_control ( pb, LDAP_CONTROL_PWEXPIRED, 0);
- }
- /* passes checking, return 0 */
- return( 0 );
+ /* if password never expires, don't need to go on; return 0 */
+ if (pwpolicy->pw_exp == 0) {
+ /* check for "changeafterreset" condition */
+ if (pb_conn->c_needpw == 1) {
+ if (pwresponse_req) {
+ slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_CHGAFTERRESET);
+ }
+ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
+ }
+ pw_apply_mods(sdn, &smods);
+ slapi_mods_done(&smods);
+ return (0);
+ }
+
+ /* 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) {
+ slapi_ch_free_string(&cur_time_str); /* only need this above */
+ /* password has expired. Check the value of
+ * passwordGraceUserTime and compare it
+ * against the value of passwordGraceLimit */
+ pwdGraceUserTime = slapi_entry_attr_get_int(e, "passwordGraceUserTime");
+ if (pwpolicy->pw_gracelimit > pwdGraceUserTime) {
+ pwdGraceUserTime++;
+ sprintf(graceUserTime, "%d", pwdGraceUserTime);
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE,
+ "passwordGraceUserTime", graceUserTime);
+ pw_apply_mods(sdn, &smods);
+ slapi_mods_done(&smods);
+ if (pwresponse_req) {
+ /* check for "changeafterreset" condition */
+ if (pb_conn->c_needpw == 1) {
+ slapi_pwpolicy_make_response_control(pb, -1,
+ ((pwpolicy->pw_gracelimit) - pwdGraceUserTime),
+ LDAP_PWPOLICY_CHGAFTERRESET);
+ } else {
+ slapi_pwpolicy_make_response_control(pb, -1,
+ ((pwpolicy->pw_gracelimit) - pwdGraceUserTime),
+ -1);
+ }
+ }
+ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
+ return (0);
+ }
+
+ /* password expired and user exceeded limit of grace attemps.
+ * Send result and also the control */
+ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
+ if (pwresponse_req) {
+ slapi_pwpolicy_make_response_control(pb, -1, -1, LDAP_PWPOLICY_PWDEXPIRED);
+ }
+ slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL,
+ "password expired!", 0, NULL);
+
+ /* abort bind */
+ /* pass pb to do_unbind(). pb->pb_op->o_opid and
+ pb->pb_op->o_tag are not right but I don't see
+ do_unbind() checking for those. We might need to
+ create a pb for unbind operation. Also do_unbind calls
+ pre and post ops. Maybe we don't want to call them */
+ if (pb_conn && (LDAP_VERSION2 == pb_conn->c_ldapversion)) {
+ Operation *pb_op = NULL;
+ slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
+ /* We close the connection only with LDAPv2 connections */
+ disconnect_server(pb_conn, pb_op->o_connid,
+ pb_op->o_opid, SLAPD_DISCONNECT_UNBIND, 0);
+ }
+ /* Apply current modifications */
+ 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");
+ 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_conn->c_needpw != 1) {
+ pw_exp_date = time_plus_sec(cur_time, pwpolicy->pw_warning);
+ }
+
+ timestring = format_genTime(pw_exp_date);
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestring);
+ slapi_ch_free_string(&timestring);
+
+ slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "1");
+
+ t = pwpolicy->pw_warning;
+
+ } else {
+ t = (long)diff_t; /* jcm: had to cast double to long */
+ }
+
+ pw_apply_mods(sdn, &smods);
+ slapi_mods_done(&smods);
+ if (pwresponse_req) {
+ /* check for "changeafterreset" condition */
+ if (pb_conn->c_needpw == 1) {
+ slapi_pwpolicy_make_response_control(pb, t, -1, LDAP_PWPOLICY_CHGAFTERRESET);
+ } else {
+ slapi_pwpolicy_make_response_control(pb, t, -1, -1);
+ }
+ }
+
+ if (pb_conn->c_needpw == 1) {
+ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
+ } else {
+ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRING, t);
+ }
+ return (0);
+ } else {
+ if (pwresponse_req && pwpolicy->pw_send_expiring) {
+ slapi_pwpolicy_make_response_control(pb, diff_t, -1, -1);
+ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRING, diff_t);
+ }
+ }
+
+ pw_apply_mods(sdn, &smods);
+ slapi_mods_done(&smods);
+ /* Leftover from "changeafterreset" condition */
+ if (pb_conn->c_needpw == 1) {
+ slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
+ }
+ /* passes checking, return 0 */
+ return (0);
}
/* Called once from main */
diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c
index dd0c4fb..134f5aa 100644
--- a/ldap/servers/slapd/saslbind.c
+++ b/ldap/servers/slapd/saslbind.c
@@ -859,7 +859,6 @@ ids_sasl_mech_supported(Slapi_PBlock *pb, const char *mech)
void ids_sasl_check_bind(Slapi_PBlock *pb)
{
int rc, isroot;
- long t;
sasl_conn_t *sasl_conn;
struct propctx *propctx;
sasl_ssf_t *ssfp;
@@ -1096,23 +1095,8 @@ sasl_check_result:
set_db_default_result_handlers(pb);
/* check password expiry */
- if (!isroot) {
- int pwrc;
-
- pwrc = need_new_pw(pb, &t, bind_target_entry, pwresponse_requested);
-
- switch (pwrc) {
- case 1:
- slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
- break;
- case 2:
- slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRING, t);
- break;
- case -1:
- goto out;
- default:
- break;
- }
+ if (!isroot && need_new_pw(pb, bind_target_entry, pwresponse_requested) == -1) {
+ goto out;
}
/* attach the sasl data */
--
2.9.5

View file

@ -0,0 +1,439 @@
From 8a7b47602acc910d2f64439b81af3299b60359c8 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 18 Sep 2017 10:35:20 -0400
Subject: [PATCH] Ticket 49379 - Allowed sasl mapping requires restart
Bug Description: If allowed sasl mechanisms are configured, and the server is
restarted, trying to add new sasl mechanisms does not get applied
until the server is restarted again. [1]
We were also overwriting memory when we stripped the commas from
the allowed machanism list. THis lead to the allowed mechanisms
to get truncated,and permanently lose certain mechs. [2]
A crash with PLAIN sasl mechanism was also found. [3]
Fix Description: To address allowed sasl mechs, we no longer explicitly the mechanisms
during the sasl_init at server startup. Instead we check the allowed
list ourselves during a bind. [1]
When setting the allowed sasl mechs, make a copy of the value to
apply the changes to(removing coamms), and do not change the original
value as it's still being used. [2]
The crash when using sasl PLAIN was due to unlocking a rwlock that
was not locked. [3]
https://pagure.io/389-ds-base/issue/49379
Reviewed by: tbordaz(Thanks!)
(cherry picked from commit c78f41db31752a99aadd6abcbf7a1d852a8e7931)
---
dirsrvtests/tests/suites/sasl/allowed_mechs.py | 114 ++++++++++++++++++++++--
dirsrvtests/tests/suites/sasl/plain.py | 10 ++-
ldap/servers/slapd/libglobs.c | 23 ++---
ldap/servers/slapd/saslbind.c | 116 +++++++++++++------------
4 files changed, 187 insertions(+), 76 deletions(-)
diff --git a/dirsrvtests/tests/suites/sasl/allowed_mechs.py b/dirsrvtests/tests/suites/sasl/allowed_mechs.py
index 7958db4..5b1b92c 100644
--- a/dirsrvtests/tests/suites/sasl/allowed_mechs.py
+++ b/dirsrvtests/tests/suites/sasl/allowed_mechs.py
@@ -8,45 +8,141 @@
#
import pytest
-import ldap
-
-import time
-
+import os
from lib389.topologies import topology_st
+
def test_sasl_allowed_mechs(topology_st):
+ """Test the alloweed sasl mechanism feature
+
+ :ID: ab7d9f86-8cfe-48c3-8baa-739e599f006a
+ :feature: Allowed sasl mechanisms
+ :steps: 1. Get the default list of mechanisms
+ 2. Set allowed mechanism PLAIN, and verify it's correctly listed
+ 3. Restart server, and verify list is still correct
+ 4. Test EXTERNAL is properly listed
+ 5. Add GSSAPI to the existing list, and verify it's correctly listed
+ 6. Restart server and verify list is still correct
+ 7. Add ANONYMOUS to the existing list, and veirfy it's correctly listed
+ 8. Restart server and verify list is still correct
+ 9. Remove GSSAPI and verify it's correctly listed
+ 10. Restart server and verify list is still correct
+ 11. Reset allowed list to nothing, verify "all" the mechanisms are returned
+ 12. Restart server and verify list is still correct
+
+ :expectedresults: The supported mechanisms supported what is set for the allowed
+ mechanisms
+ """
standalone = topology_st.standalone
# Get the supported mechs. This should contain PLAIN, GSSAPI, EXTERNAL at least
+ standalone.log.info("Test we have some of the default mechanisms")
orig_mechs = standalone.rootdse.supported_sasl()
print(orig_mechs)
assert('GSSAPI' in orig_mechs)
assert('PLAIN' in orig_mechs)
assert('EXTERNAL' in orig_mechs)
- # Now edit the supported mechs. CHeck them again.
+ # Now edit the supported mechs. Check them again.
+ standalone.log.info("Edit mechanisms to allow just PLAIN")
standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN')
+ limit_mechs = standalone.rootdse.supported_sasl()
+ assert('PLAIN' in limit_mechs)
+ assert('EXTERNAL' in limit_mechs) # Should always be in the allowed list, even if not set.
+ assert('GSSAPI' not in limit_mechs) # Should not be there!
+ # Restart the server a few times and make sure nothing changes
+ standalone.log.info("Restart server and make sure we still have correct allowed mechs")
+ standalone.restart()
+ standalone.restart()
limit_mechs = standalone.rootdse.supported_sasl()
assert('PLAIN' in limit_mechs)
- # Should always be in the allowed list, even if not set.
assert('EXTERNAL' in limit_mechs)
- # Should not be there!
assert('GSSAPI' not in limit_mechs)
+ # Set EXTERNAL, even though its always supported
+ standalone.log.info("Edit mechanisms to allow just PLAIN and EXTERNAL")
standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, EXTERNAL')
+ limit_mechs = standalone.rootdse.supported_sasl()
+ assert('PLAIN' in limit_mechs)
+ assert('EXTERNAL' in limit_mechs)
+ assert('GSSAPI' not in limit_mechs)
+
+ # Now edit the supported mechs. Check them again.
+ standalone.log.info("Edit mechanisms to allow just PLAIN and GSSAPI")
+ standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, GSSAPI')
+ limit_mechs = standalone.rootdse.supported_sasl()
+ assert('PLAIN' in limit_mechs)
+ assert('EXTERNAL' in limit_mechs)
+ assert('GSSAPI' in limit_mechs)
+ assert(len(limit_mechs) == 3)
+
+ # Restart server twice and make sure the allowed list is the same
+ standalone.restart()
+ standalone.restart() # For ticket 49379 (test double restart)
+ limit_mechs = standalone.rootdse.supported_sasl()
+ assert('PLAIN' in limit_mechs)
+ assert('EXTERNAL' in limit_mechs)
+ assert('GSSAPI' in limit_mechs)
+ assert(len(limit_mechs) == 3)
+
+ # Add ANONYMOUS to the supported mechs and test again.
+ standalone.log.info("Edit mechanisms to allow just PLAIN, GSSAPI, and ANONYMOUS")
+ standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, GSSAPI, ANONYMOUS')
+ limit_mechs = standalone.rootdse.supported_sasl()
+ assert('PLAIN' in limit_mechs)
+ assert('EXTERNAL' in limit_mechs)
+ assert('GSSAPI' in limit_mechs)
+ assert('ANONYMOUS' in limit_mechs)
+ assert(len(limit_mechs) == 4)
+
+ # Restart server and make sure the allowed list is the same
+ standalone.restart()
+ standalone.restart() # For ticket 49379 (test double restart)
+ limit_mechs = standalone.rootdse.supported_sasl()
+ assert('PLAIN' in limit_mechs)
+ assert('EXTERNAL' in limit_mechs)
+ assert('GSSAPI' in limit_mechs)
+ assert('ANONYMOUS' in limit_mechs)
+ assert(len(limit_mechs) == 4)
+ # Remove GSSAPI
+ standalone.log.info("Edit mechanisms to allow just PLAIN and ANONYMOUS")
+ standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, ANONYMOUS')
limit_mechs = standalone.rootdse.supported_sasl()
assert('PLAIN' in limit_mechs)
assert('EXTERNAL' in limit_mechs)
- # Should not be there!
assert('GSSAPI' not in limit_mechs)
+ assert('ANONYMOUS' in limit_mechs)
+ assert(len(limit_mechs) == 3)
+
+ # Restart server and make sure the allowed list is the same
+ standalone.restart()
+ limit_mechs = standalone.rootdse.supported_sasl()
+ assert('PLAIN' in limit_mechs)
+ assert('EXTERNAL' in limit_mechs)
+ assert('GSSAPI' not in limit_mechs)
+ assert('ANONYMOUS' in limit_mechs)
+ assert(len(limit_mechs) == 3)
# Do a config reset
+ standalone.log.info("Reset allowed mechaisms")
standalone.config.reset('nsslapd-allowed-sasl-mechanisms')
# check the supported list is the same as our first check.
+ standalone.log.info("Check that we have the original set of mechanisms")
final_mechs = standalone.rootdse.supported_sasl()
- print(final_mechs)
assert(set(final_mechs) == set(orig_mechs))
+ # Check it after a restart
+ standalone.log.info("Check that we have the original set of mechanisms after a restart")
+ standalone.restart()
+ final_mechs = standalone.rootdse.supported_sasl()
+ assert(set(final_mechs) == set(orig_mechs))
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/suites/sasl/plain.py b/dirsrvtests/tests/suites/sasl/plain.py
index 91ccb02..6bf39a8 100644
--- a/dirsrvtests/tests/suites/sasl/plain.py
+++ b/dirsrvtests/tests/suites/sasl/plain.py
@@ -15,9 +15,11 @@ from lib389.topologies import topology_st
from lib389.utils import *
from lib389.sasl import PlainSASL
from lib389.idm.services import ServiceAccounts
+from lib389._constants import (SECUREPORT_STANDALONE1, DEFAULT_SUFFIX)
log = logging.getLogger(__name__)
+
def test_sasl_plain(topology_st):
standalone = topology_st.standalone
@@ -38,7 +40,7 @@ def test_sasl_plain(topology_st):
standalone.rsa.create()
# Set the secure port and nsslapd-security
# Could this fail with selinux?
- standalone.config.set('nsslapd-secureport', '%s' % SECUREPORT_STANDALONE1 )
+ standalone.config.set('nsslapd-secureport', '%s' % SECUREPORT_STANDALONE1)
standalone.config.set('nsslapd-security', 'on')
# Do we need to restart to allow starttls?
standalone.restart()
@@ -65,12 +67,14 @@ def test_sasl_plain(topology_st):
# I can not solve. I think it's leaking state across connections in start_tls_s?
# Check that it works with TLS
- conn = standalone.openConnection(saslmethod='PLAIN', sasltoken=auth_tokens, starttls=True, connOnly=True, certdir=standalone.get_cert_dir(), reqcert=ldap.OPT_X_TLS_NEVER)
+ conn = standalone.openConnection(saslmethod='PLAIN', sasltoken=auth_tokens, starttls=True, connOnly=True,
+ certdir=standalone.get_cert_dir(), reqcert=ldap.OPT_X_TLS_NEVER)
conn.close()
# Check that it correct fails our bind if we don't have the password.
auth_tokens = PlainSASL("dn:%s" % sa.dn, 'password-wrong')
with pytest.raises(ldap.INVALID_CREDENTIALS):
- standalone.openConnection(saslmethod='PLAIN', sasltoken=auth_tokens, starttls=False, connOnly=True, certdir=standalone.get_cert_dir(), reqcert=ldap.OPT_X_TLS_NEVER)
+ standalone.openConnection(saslmethod='PLAIN', sasltoken=auth_tokens, starttls=True, connOnly=True,
+ certdir=standalone.get_cert_dir(), reqcert=ldap.OPT_X_TLS_NEVER)
# Done!
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index bb51827..2fb4bab 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -7137,22 +7137,25 @@ config_set_allowed_sasl_mechs(const char *attrname, char *value, char *errorbuf,
/* During a reset, the value is "", so we have to handle this case. */
if (strcmp(value, "") != 0) {
- /* cyrus sasl doesn't like comma separated lists */
- remove_commas(value);
+ char *nval = slapi_ch_strdup(value);
- if(invalid_sasl_mech(value)){
- slapi_log_err(SLAPI_LOG_ERR,"config_set_allowed_sasl_mechs",
- "Invalid value/character for sasl mechanism (%s). Use ASCII "
- "characters, upto 20 characters, that are upper-case letters, "
- "digits, hyphens, or underscores\n", value);
+ /* cyrus sasl doesn't like comma separated lists */
+ remove_commas(nval);
+
+ if (invalid_sasl_mech(nval)) {
+ slapi_log_err(SLAPI_LOG_ERR, "config_set_allowed_sasl_mechs",
+ "Invalid value/character for sasl mechanism (%s). Use ASCII "
+ "characters, upto 20 characters, that are upper-case letters, "
+ "digits, hyphens, or underscores\n",
+ nval);
+ slapi_ch_free_string(&nval);
return LDAP_UNWILLING_TO_PERFORM;
}
-
CFG_LOCK_WRITE(slapdFrontendConfig);
slapi_ch_free_string(&slapdFrontendConfig->allowed_sasl_mechs);
slapi_ch_array_free(slapdFrontendConfig->allowed_sasl_mechs_array);
- slapdFrontendConfig->allowed_sasl_mechs = slapi_ch_strdup(value);
- slapdFrontendConfig->allowed_sasl_mechs_array = slapi_str2charray_ext(value, " ", 0);
+ slapdFrontendConfig->allowed_sasl_mechs = nval;
+ slapdFrontendConfig->allowed_sasl_mechs_array = slapi_str2charray_ext(nval, " ", 0);
CFG_UNLOCK_WRITE(slapdFrontendConfig);
} else {
/* If this value is "", we need to set the list to *all* possible mechs */
diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c
index 134f5aa..03e2a97 100644
--- a/ldap/servers/slapd/saslbind.c
+++ b/ldap/servers/slapd/saslbind.c
@@ -169,8 +169,6 @@ static int ids_sasl_getopt(
}
} else if (strcasecmp(option, "auxprop_plugin") == 0) {
*result = "iDS";
- } else if (strcasecmp(option, "mech_list") == 0){
- *result = config_get_allowed_sasl_mechs();
}
if (*result) *len = strlen(*result);
@@ -572,12 +570,8 @@ static int ids_sasl_userdb_checkpass(sasl_conn_t *conn, void *context, const cha
slapi_pblock_set(pb, SLAPI_BIND_METHOD, &method);
/* Feed it to pw_verify_be_dn */
bind_result = pw_verify_be_dn(pb, &referral);
- /* Now check the result, and unlock be if needed. */
- if (bind_result == SLAPI_BIND_SUCCESS || bind_result == SLAPI_BIND_ANONYMOUS) {
- Slapi_Backend *be = NULL;
- slapi_pblock_get(pb, SLAPI_BACKEND, &be);
- slapi_be_Unlock(be);
- } else if (bind_result == SLAPI_BIND_REFERRAL) {
+ /* Now check the result. */
+ if (bind_result == SLAPI_BIND_REFERRAL) {
/* If we have a referral do we ignore it for sasl? */
slapi_entry_free(referral);
}
@@ -760,22 +754,25 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
sup_ret = slapi_get_supported_saslmechanisms_copy();
/* If we have a connection, get the provided list from SASL */
- if (pb->pb_conn != NULL) {
- sasl_conn = (sasl_conn_t*)pb->pb_conn->c_sasl_conn;
-
- /* sasl library mechanisms are connection dependent */
- PR_EnterMonitor(pb->pb_conn->c_mutex);
- if (sasl_listmech(sasl_conn,
- NULL, /* username */
- "", ",", "",
- &str, NULL, NULL) == SASL_OK) {
- slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_listmech", "sasl library mechs: %s\n", str);
- /* merge into result set */
- dupstr = slapi_ch_strdup(str);
- others = slapi_str2charray_ext(dupstr, ",", 0 /* don't list duplicate mechanisms */);
- charray_merge(&sup_ret, others, 1);
- charray_free(others);
- slapi_ch_free((void**)&dupstr);
+ if (pb_conn != NULL) {
+ sasl_conn = (sasl_conn_t*)pb_conn->c_sasl_conn;
+ if (sasl_conn != NULL) {
+ /* sasl library mechanisms are connection dependent */
+ PR_EnterMonitor(pb_conn->c_mutex);
+ if (sasl_listmech(sasl_conn,
+ NULL, /* username */
+ "", ",", "",
+ &str, NULL, NULL) == SASL_OK) {
+ slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_listmech", "sasl library mechs: %s\n", str);
+ /* merge into result set */
+ dupstr = slapi_ch_strdup(str);
+ others = slapi_str2charray_ext(dupstr, ",", 0 /* don't list duplicate mechanisms */);
+
+ charray_merge(&sup_ret, others, 1);
+ charray_free(others);
+ slapi_ch_free((void**)&dupstr);
+ }
+ PR_ExitMonitor(pb_conn->c_mutex);
}
PR_ExitMonitor(pb->pb_conn->c_mutex);
}
@@ -785,7 +782,7 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
/* Remove any content that isn't in the allowed list */
if (config_ret != NULL) {
- /* Get the set of supported mechs in the insection of the two */
+ /* Get the set of supported mechs in the intersection of the two */
ret = charray_intersection(sup_ret, config_ret);
charray_free(sup_ret);
charray_free(config_ret);
@@ -816,41 +813,52 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
static int
ids_sasl_mech_supported(Slapi_PBlock *pb, const char *mech)
{
- int i, ret = 0;
- char **mechs;
- char *dupstr;
- const char *str;
- int sasl_result = 0;
- sasl_conn_t *sasl_conn = (sasl_conn_t *)pb->pb_conn->c_sasl_conn;
-
- slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "=>\n");
-
-
- /* sasl_listmech is not thread-safe - caller must lock pb_conn */
- sasl_result = sasl_listmech(sasl_conn,
- NULL, /* username */
- "", ",", "",
- &str, NULL, NULL);
- if (sasl_result != SASL_OK) {
- return 0;
- }
+ int i, ret = 0;
+ char **mechs;
+ char **allowed_mechs = NULL;
+ char *dupstr;
+ const char *str;
+ int sasl_result = 0;
+ Connection *pb_conn = NULL;
+
+ slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+ sasl_conn_t *sasl_conn = (sasl_conn_t *)pb_conn->c_sasl_conn;
+ slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "=>\n");
+
+ /* sasl_listmech is not thread-safe - caller must lock pb_conn */
+ sasl_result = sasl_listmech(sasl_conn,
+ NULL, /* username */
+ "", ",", "",
+ &str, NULL, NULL);
+ if (sasl_result != SASL_OK) {
+ return 0;
+ }
- dupstr = slapi_ch_strdup(str);
- mechs = slapi_str2charray(dupstr, ",");
+ dupstr = slapi_ch_strdup(str);
+ mechs = slapi_str2charray(dupstr, ",");
+ allowed_mechs = config_get_allowed_sasl_mechs_array();
- for (i = 0; mechs[i] != NULL; i++) {
- if (strcasecmp(mech, mechs[i]) == 0) {
- ret = 1;
- break;
+ for (i = 0; mechs[i] != NULL; i++) {
+ if (strcasecmp(mech, mechs[i]) == 0) {
+ if (allowed_mechs) {
+ if (charray_inlist(allowed_mechs, (char *)mech) == 0) {
+ ret = 1;
+ }
+ break;
+ } else {
+ ret = 1;
+ break;
+ }
+ }
}
- }
- charray_free(mechs);
- slapi_ch_free((void**)&dupstr);
+ charray_free(allowed_mechs);
+ charray_free(mechs);
+ slapi_ch_free((void **)&dupstr);
- slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "<=\n");
+ slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "<=\n");
- return ret;
+ return ret;
}
/*
--
2.9.5

View file

@ -0,0 +1,31 @@
From 4a51a17762fb4e7ce1beb0600916fed8b45a5483 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 18 Sep 2017 15:06:06 -0400
Subject: [PATCH] Fix cherry-pick error from sasl mech commit
---
ldap/servers/slapd/saslbind.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c
index 03e2a97..8e94ee6 100644
--- a/ldap/servers/slapd/saslbind.c
+++ b/ldap/servers/slapd/saslbind.c
@@ -745,11 +745,14 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
const char *str;
char *dupstr;
sasl_conn_t *sasl_conn;
+ Connection *pb_conn = NULL;
slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_listmech", "=>\n");
PR_ASSERT(pb);
+ slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
+
/* hard-wired mechanisms and slapi plugin registered mechanisms */
sup_ret = slapi_get_supported_saslmechanisms_copy();
--
2.9.5

View file

@ -0,0 +1,322 @@
From 2741a6db134ad40662cfa0233c4542d2d4148997 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Tue, 3 Oct 2017 17:22:37 -0400
Subject: [PATCH] Ticket 49389 - unable to retrieve specific cosAttribute when
subtree password policy is configured
Bug Description: If indirect cos is being used and a subtree password
policy is added, th orignal COS attributes aren't always
returned. The issue is that when the subtree password
policy attribute was encountered during the virtual
attribute processing it set a flag that said the attribute
was operational (which is correct for the password policy
attr: pwdpolicysubentry).
However, this flag was accidentally carried over to the
following virtual attributes that were being processed.
Which caused those attributes to be seen as operational
which is why it was no longer being returned to the client.
Fix Description: Reset the prop flags before processing the next COS attribute
https://pagure.io/389-ds-base/issue/49389
Reviewed by: firstyear(Thanks!)
(cherry picked from commit 0953e6011368bc29300990e9493ac13e5aba9586)
---
dirsrvtests/tests/suites/cos/__init__.py | 0
dirsrvtests/tests/suites/cos/indirect_cos_test.py | 191 ++++++++++++++++++++++
ldap/servers/plugins/cos/cos_cache.c | 68 ++++----
3 files changed, 223 insertions(+), 36 deletions(-)
create mode 100644 dirsrvtests/tests/suites/cos/__init__.py
create mode 100644 dirsrvtests/tests/suites/cos/indirect_cos_test.py
diff --git a/dirsrvtests/tests/suites/cos/__init__.py b/dirsrvtests/tests/suites/cos/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/dirsrvtests/tests/suites/cos/indirect_cos_test.py b/dirsrvtests/tests/suites/cos/indirect_cos_test.py
new file mode 100644
index 0000000..1aac6b8
--- /dev/null
+++ b/dirsrvtests/tests/suites/cos/indirect_cos_test.py
@@ -0,0 +1,191 @@
+import logging
+import pytest
+import os
+import ldap
+import time
+import subprocess
+
+from lib389 import Entry
+from lib389.idm.user import UserAccounts
+from lib389.topologies import topology_st as topo
+from lib389._constants import (DEFAULT_SUFFIX, DN_DM, PASSWORD, HOST_STANDALONE,
+ SERVERID_STANDALONE, PORT_STANDALONE)
+
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+TEST_USER_DN = "uid=test_user,ou=people,dc=example,dc=com"
+OU_PEOPLE = 'ou=people,{}'.format(DEFAULT_SUFFIX)
+
+PW_POLICY_CONT_PEOPLE = 'cn="cn=nsPwPolicyEntry,' \
+ 'ou=people,dc=example,dc=com",' \
+ 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
+
+PW_POLICY_CONT_PEOPLE2 = 'cn="cn=nsPwPolicyEntry,' \
+ 'dc=example,dc=com",' \
+ 'cn=nsPwPolicyContainerdc=example,dc=com'
+
+
+def check_user(inst):
+ """Search the test user and make sure it has the execpted attrs
+ """
+ try:
+ entries = inst.search_s('dc=example,dc=com', ldap.SCOPE_SUBTREE, "uid=test_user")
+ log.debug('user: \n' + str(entries[0]))
+ assert entries[0].hasAttr('ou'), "Entry is missing ou cos attribute"
+ assert entries[0].hasAttr('x-department'), "Entry is missing description cos attribute"
+ assert entries[0].hasAttr('x-en-ou'), "Entry is missing givenname cos attribute"
+ except ldap.LDAPError as e:
+ log.fatal('Failed to search for user: ' + str(e))
+ raise e
+
+
+def setup_subtree_policy(topo):
+ """Set up subtree password policy
+ """
+ try:
+ topo.standalone.modify_s("cn=config", [(ldap.MOD_REPLACE,
+ 'nsslapd-pwpolicy-local',
+ 'on')])
+ except ldap.LDAPError as e:
+ log.error('Failed to set fine-grained policy: error {}'.format(
+ e.message['desc']))
+ raise e
+
+ log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
+ try:
+ subprocess.call(['%s/ns-newpwpolicy.pl' % topo.standalone.get_sbin_dir(),
+ '-D', DN_DM, '-w', PASSWORD,
+ '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
+ '-S', DEFAULT_SUFFIX, '-Z', SERVERID_STANDALONE])
+ except subprocess.CalledProcessError as e:
+ log.error('Failed to create pw policy policy for {}: error {}'.format(
+ OU_PEOPLE, e.message['desc']))
+ raise e
+
+ log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
+ try:
+ topo.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_REPLACE,
+ 'pwdpolicysubentry',
+ PW_POLICY_CONT_PEOPLE2)])
+ except ldap.LDAPError as e:
+ log.error('Failed to pwdpolicysubentry pw policy '
+ 'policy for {}: error {}'.format(OU_PEOPLE, e.message['desc']))
+ raise e
+ time.sleep(1)
+
+
+def setup_indirect_cos(topo):
+ """Setup indirect COS definition and template
+ """
+ cosDef = Entry(('cn=cosDefinition,dc=example,dc=com',
+ {'objectclass': ['top', 'ldapsubentry',
+ 'cossuperdefinition',
+ 'cosIndirectDefinition'],
+ 'cosAttribute': ['ou merge-schemes',
+ 'x-department merge-schemes',
+ 'x-en-ou merge-schemes'],
+ 'cosIndirectSpecifier': 'seeAlso',
+ 'cn': 'cosDefinition'}))
+
+ cosTemplate = Entry(('cn=cosTemplate,dc=example,dc=com',
+ {'objectclass': ['top',
+ 'extensibleObject',
+ 'cosTemplate'],
+ 'ou': 'My COS Org',
+ 'x-department': 'My COS x-department',
+ 'x-en-ou': 'my COS x-en-ou',
+ 'cn': 'cosTemplate'}))
+ try:
+ topo.standalone.add_s(cosDef)
+ topo.standalone.add_s(cosTemplate)
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add cos: error ' + str(e))
+ raise e
+ time.sleep(1)
+
+
+@pytest.fixture(scope="module")
+def setup(topo, request):
+ """Add schema, and test user
+ """
+ log.info('Add custom schema...')
+ try:
+ ATTR_1 = ("( 1.3.6.1.4.1.409.389.2.189 NAME 'x-department' " +
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
+ ATTR_2 = ("( 1.3.6.1.4.1.409.389.2.187 NAME 'x-en-ou' " +
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )")
+ OC = ("( xPerson-oid NAME 'xPerson' DESC '' SUP person STRUCTURAL MAY " +
+ "( x-department $ x-en-ou ) X-ORIGIN 'user defined' )")
+ topo.standalone.modify_s("cn=schema", [(ldap.MOD_ADD, 'attributeTypes', ATTR_1),
+ (ldap.MOD_ADD, 'attributeTypes', ATTR_2),
+ (ldap.MOD_ADD, 'objectClasses', OC)])
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add custom schema')
+ raise e
+ time.sleep(1)
+
+ log.info('Add test user...')
+ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
+
+ user_properties = {
+ 'uid': 'test_user',
+ 'cn': 'test user',
+ 'sn': 'user',
+ 'uidNumber': '1000',
+ 'gidNumber': '2000',
+ 'homeDirectory': '/home/test_user',
+ 'seeAlso': 'cn=cosTemplate,dc=example,dc=com'
+ }
+ users.create(properties=user_properties)
+ try:
+ topo.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_ADD,
+ 'objectclass',
+ 'xPerson')])
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add objectclass to user')
+ raise e
+
+ # Setup COS
+ log.info("Setup indirect COS...")
+ setup_indirect_cos(topo)
+
+
+def test_indirect_cos(topo, setup):
+ """Test indirect cos
+
+ :id: 890d5929-7d52-4a56-956e-129611b4649a
+ :setup: standalone
+ :steps:
+ 1. Test cos is working for test user
+ 2. Add subtree password policy
+ 3. Test cos is working for test user
+ :expectedresults:
+ 1. User has expected cos attrs
+ 2. Substree password policy setup is successful
+ 3 User still has expected cos attrs
+ """
+
+ # Step 1 - Search user and see if the COS attrs are included
+ log.info('Checking user...')
+ check_user(topo.standalone)
+
+ # Step 2 - Add subtree password policy (Second COS - operational attribute)
+ setup_subtree_policy(topo)
+
+ # Step 3 - Check user again now hat we have a mix of vattrs
+ log.info('Checking user...')
+ check_user(topo.standalone)
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
+
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
index 66c6c7f..87d4890 100644
--- a/ldap/servers/plugins/cos/cos_cache.c
+++ b/ldap/servers/plugins/cos/cos_cache.c
@@ -2190,48 +2190,44 @@ bail:
static int cos_cache_vattr_types(vattr_sp_handle *handle,Slapi_Entry *e,
vattr_type_list_context *type_context,int flags)
{
- int ret = 0;
- int index = 0;
- cosCache *pCache;
- char *lastattr = "thisisfakeforcos";
- int props = 0;
-
- slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_vattr_types\n");
-
- if(cos_cache_getref((cos_cache **)&pCache) < 1)
- {
- /* problems we are hosed */
- slapi_log_err(SLAPI_LOG_PLUGIN, COS_PLUGIN_SUBSYSTEM, "cos_cache_vattr_types - Failed to get class of service reference\n");
- goto bail;
- }
-
- while(index < pCache->attrCount )
- {
- if(slapi_utf8casecmp(
- (unsigned char *)pCache->ppAttrIndex[index]->pAttrName,
- (unsigned char *)lastattr))
- {
- lastattr = pCache->ppAttrIndex[index]->pAttrName;
+ int ret = 0;
+ int index = 0;
+ cosCache *pCache;
+ char *lastattr = "thisisfakeforcos";
- if(1 == cos_cache_query_attr(pCache, NULL, e, lastattr, NULL, NULL,
- NULL, &props, NULL))
- {
- /* entry contains this attr */
- vattr_type_thang thang = {0};
+ slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_vattr_types\n");
- thang.type_name = lastattr;
- thang.type_flags = props;
+ if (cos_cache_getref((cos_cache **)&pCache) < 1) {
+ /* problems we are hosed */
+ slapi_log_err(SLAPI_LOG_PLUGIN, COS_PLUGIN_SUBSYSTEM, "cos_cache_vattr_types - Failed to get class of service reference\n");
+ goto bail;
+ }
- slapi_vattrspi_add_type(type_context,&thang,0);
- }
- }
- index++;
- }
- cos_cache_release(pCache);
+ while (index < pCache->attrCount) {
+ int props = 0;
+ if (slapi_utf8casecmp(
+ (unsigned char *)pCache->ppAttrIndex[index]->pAttrName,
+ (unsigned char *)lastattr)) {
+ lastattr = pCache->ppAttrIndex[index]->pAttrName;
+
+ if (1 == cos_cache_query_attr(pCache, NULL, e, lastattr, NULL, NULL,
+ NULL, &props, NULL)) {
+ /* entry contains this attr */
+ vattr_type_thang thang = {0};
+
+ thang.type_name = lastattr;
+ thang.type_flags = props;
+
+ slapi_vattrspi_add_type(type_context, &thang, 0);
+ }
+ }
+ index++;
+ }
+ cos_cache_release(pCache);
bail:
-slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "<-- cos_cache_vattr_types\n");
+ slapi_log_err(SLAPI_LOG_TRACE, COS_PLUGIN_SUBSYSTEM, "<-- cos_cache_vattr_types\n");
return ret;
}
--
2.9.5

View file

@ -30,7 +30,7 @@
Summary: 389 Directory Server (base)
Name: 389-ds-base
Version: 1.3.6.1
Release: %{?relprefix}19%{?prerel}%{?dist}
Release: %{?relprefix}21%{?prerel}%{?dist}
License: GPLv3+
URL: https://www.port389.org/
Group: System Environment/Daemons
@ -195,7 +195,17 @@ Patch58: 0058-Ticket-49336-SECURITY-Locked-account-provides-differ.patc
Patch59: 0059-Ticket-49298-force-sync-on-shutdown.patch
Patch60: 0060-Ticket-49334-fix-backup-restore-if-changelog-exists.patch
Patch61: 0061-Ticket-49356-mapping-tree-crash-can-occur-during-tot.patch
Patch62: 0062-Ticket-49330-Improve-ndn-cache-performance-1.3.6.patch
Patch63: 0063-Ticket-49330-Add-endian-header-file-check-to-configu.patch
Patch64: 0064-Ticket-49257-only-register-modify-callbacks.patch
Patch65: 0065-Ticket-49291-slapi_search_internal_callback_pb-may-S.patch
Patch66: 0066-Ticket-49370-local-password-policies-should-use-the-.patch
Patch67: 0067-Ticket-49380-Crash-when-adding-invalid-replication.patch
Patch68: 0068-Ticket-49380-Add-CI-test.patch
Patch69: 0069-Ticket-49327-password-expired-control-not-sent-durin.patch
Patch70: 0070-Ticket-49379-Allowed-sasl-mapping-requires-restart.patch
Patch71: 0071-Fix-cherry-pick-error-from-sasl-mech-commit.patch
Patch72: 0072-Ticket-49389-unable-to-retrieve-specific-cosAttribut.patch
%description
389 Directory Server is an LDAPv3 compliant server. The base package includes
@ -327,6 +337,17 @@ cp %{SOURCE2} README.devel
%patch59 -p1
%patch60 -p1
%patch61 -p1
%patch62 -p1
%patch63 -p1
%patch64 -p1
%patch65 -p1
%patch66 -p1
%patch67 -p1
%patch68 -p1
%patch69 -p1
%patch70 -p1
%patch71 -p1
%patch72 -p1
%build
OPENLDAP_FLAG="--with-openldap"
@ -457,9 +478,9 @@ echo remove pid files . . . >> $output 2>&1 || :
echo upgrading instances . . . >> $output 2>&1 || :
DEBUGPOSTSETUPOPT=`/usr/bin/echo $DEBUGPOSTSETUP | /usr/bin/sed -e "s/[^d]//g"`
if [ -n "$DEBUGPOSTSETUPOPT" ] ; then
%{_sbindir}/setup-ds.pl -l $output2 -$DEBUGPOSTSETUPOPT -u -s General.UpdateMode=offline >> $output 2>&1 || :
%{_sbindir}/setup-ds.pl -$DEBUGPOSTSETUPOPT -u -s General.UpdateMode=offline >> $output 2>&1 || :
else
%{_sbindir}/setup-ds.pl -l $output2 -u -s General.UpdateMode=offline >> $output 2>&1 || :
%{_sbindir}/setup-ds.pl -u -s General.UpdateMode=offline >> $output 2>&1 || :
fi
# restart instances that require it
@ -558,8 +579,22 @@ fi
%{_sysconfdir}/%{pkgname}/dirsrvtests
%changelog
* Mon Aug 21 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.19-1
- Bump version to 1.3.6.19-1
* Thu Oct 5 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-21
- Bump verions to 1.3.6.1-21
- Resolves: Bug 1498958 - unable to retrieve specific cosAttribute when subtree password policy is configured
* Mon Sep 18 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-20
- Bump verions to 1.3.6.1-20
- Resolves: Bug 1489693 - PasswordCheckSyntax attribute fails to validate cn, sn, uid
- Resovles: Bug 1492829 - patch should of been applied to 7.4 but got missed
- Resolves: Bug 1486128 - Performance issues with RHDS 10 - NDN cache investigation
- Resolves: Bug 1489694 - crash in send_ldap_result
- Resolves: Bug 1491778 - crash when adding invalid repl agmt
- Resolves: Bug 1492830 - password expired control not sent
- Resolves: Bug 1492833 - sasl-mechanisms removed during upgrade
* Mon Aug 21 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-19
- Bump version to 1.3.6.1-19
- Remove old mozldap and db4 requirements
- Resolves: Bug 1483865 - Crash while binding to a server during replication online init