dirsrvtests/tickets/ticket48369_test.py | 124 ++++++++++++++++++++++++++++++++
ldap/schema/02common.ldif | 1
ldap/servers/slapd/libglobs.c | 28 ++++++-
ldap/servers/slapd/proto-slap.h | 1
ldap/servers/slapd/pw_mgmt.c | 5 +
ldap/servers/slapd/slap.h | 2
6 files changed, 157 insertions(+), 4 deletions(-)
New commits:
commit ed1ad6cd818c4db4472ffe43189651f8d3abce12
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Dec 4 15:55:46 2015 -0500
Ticket 48369 - RFE - Add config setting to always send the
password expiring time
Description: If password expiration time is set, and the password is not within
the warning period, then the expiring time is not returned. A new
config setting was added that will force the expiring time to always
be returned when the password expiring request control is sent.
https://fedorahosted.org/389/ticket/48369
Reviewed by: wibrown & spichugi(Thanks!!)
(cherry picked from commit d9f37f1f7aa718d2d9465d89051d28b4e1db5050)
diff --git a/dirsrvtests/tickets/ticket48369_test.py
b/dirsrvtests/tickets/ticket48369_test.py
new file mode 100644
index 0000000..0b65fa2
--- /dev/null
+++ b/dirsrvtests/tickets/ticket48369_test.py
@@ -0,0 +1,124 @@
+import os
+import time
+import ldap
+import logging
+import pytest
+from lib389 import DirSrv, Entry
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from lib389.utils import *
+from ldap.controls.ppolicy import PasswordPolicyControl
+
+
+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_ticket48369(topology):
+ """
+ Test RFE 48369 - return password policy controls by default without needing
+ to be requested.
+ """
+
+ DN = 'uid=test,' + DEFAULT_SUFFIX
+
+ #
+ # Setup password policy
+ #
+ try:
+ topology.standalone.modify_s('cn=config', [(ldap.MOD_REPLACE,
+ 'passwordExp',
+ 'on'),
+ (ldap.MOD_REPLACE,
+ 'passwordMaxAge',
+ '864000'),
+ (ldap.MOD_REPLACE,
+ 'passwordSendExpiringTime',
+ 'on')])
+ except ldap.LDAPError as e:
+ log.fatal('Failed to set config: %s' % str(e))
+ assert False
+
+ #
+ # Add entry
+ #
+ try:
+ topology.standalone.add_s(Entry((DN,
+ {'objectclass': 'top extensibleObject'.split(),
+ 'uid': 'test',
+ 'userpassword': 'password'})))
+ except ldap.LDAPError as e:
+ log.fatal('Failed to add user entry: %s' % str(e))
+ assert False
+ time.sleep(1)
+
+ #
+ # Bind as the new user, and request the control
+ #
+ try:
+ msgid = topology.standalone.simple_bind(DN, "password",
+ serverctrls=[PasswordPolicyControl()])
+ res_type, res_data, res_msgid, res_ctrls = \
+ topology.standalone.result3(msgid)
+ except ldap.LDAPError as e:
+ log.fatal('Failed to bind: %s: Error %s' % (ctl_resp, str(e)))
+ assert False
+
+ if res_ctrls[0].controlType == PasswordPolicyControl.controlType:
+ ppolicy_ctrl = res_ctrls[0]
+ else:
+ log.fatal('Control not found')
+ assert False
+
+ log.info('Time until expiration (%s)' %
+ repr(ppolicy_ctrl.timeBeforeExpiration))
+
+ 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/schema/02common.ldif b/ldap/schema/02common.ldif
index 5d91628..dda75e7 100644
--- a/ldap/schema/02common.ldif
+++ b/ldap/schema/02common.ldif
@@ -67,6 +67,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2082 NAME (
'passwordMinCategories' 'pwd
attributeTypes: ( 2.16.840.1.113730.3.1.2083 NAME ( 'passwordMinTokenLength'
'pwdMinTokenLength' ) DESC 'Netscape defined password policy attribute
type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape
Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2153 NAME ( 'passwordAdminDN'
'pwdAdminDN' ) DESC 'Netscape defined password policy attribute type'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'Netscape Directory
Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2140 NAME ( 'passwordTrackUpdateTime' )
DESC 'Netscape defined password policy attribute type' SYNTAX
1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2329 NAME ( 'passwordSendExpiringTime'
'pwdSendExpiringTime' ) DESC 'Netscape defined password policy attribute
type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape
Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.198 NAME 'memberURL' DESC 'Netscape
defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape
Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.199 NAME 'memberCertificateDescription'
DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.207 NAME 'vlvBase' DESC 'Netscape
defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape
Directory Server' )
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index a3c4243..d58e4c2 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -187,6 +187,7 @@ slapi_onoff_t init_pw_is_legacy;
slapi_onoff_t init_pw_track_update_time;
slapi_onoff_t init_pw_change;
slapi_onoff_t init_pw_exp;
+slapi_onoff_t init_pw_send_expiring;
slapi_onoff_t init_allow_hashed_pw;
slapi_onoff_t init_pw_syntax;
slapi_onoff_t init_schemacheck;
@@ -655,6 +656,10 @@ static struct config_get_and_set {
NULL, 0,
(void**)&global_slapdFrontendConfig.pw_policy.pw_exp,
CONFIG_ON_OFF, NULL, &init_pw_exp},
+ {CONFIG_PW_SEND_EXPIRING, config_set_pw_send_expiring,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.pw_policy.pw_send_expiring,
+ CONFIG_ON_OFF, NULL, &init_pw_send_expiring},
{CONFIG_ACCESSCONTROL_ATTRIBUTE, config_set_accesscontrol,
NULL, 0,
(void**)&global_slapdFrontendConfig.accesscontrol,
@@ -1435,6 +1440,7 @@ FrontendConfig_init () {
init_allow_hashed_pw = cfg->allow_hashed_pw = LDAP_OFF;
init_pw_syntax = cfg->pw_policy.pw_syntax = LDAP_OFF;
init_pw_exp = cfg->pw_policy.pw_exp = LDAP_OFF;
+ init_pw_send_expiring = cfg->pw_policy.pw_send_expiring = LDAP_OFF;
cfg->pw_policy.pw_minlength = 8;
cfg->pw_policy.pw_mindigits = 0;
cfg->pw_policy.pw_minalphas = 0;
@@ -3084,15 +3090,29 @@ config_set_pw_exp( const char *attrname, char *value, char
*errorbuf, int apply
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
retVal = config_set_onoff ( attrname,
- value,
- &(slapdFrontendConfig->pw_policy.pw_exp),
- errorbuf,
- apply);
+ value,
+ &(slapdFrontendConfig->pw_policy.pw_exp),
+ errorbuf,
+ apply);
return retVal;
}
int
+config_set_pw_send_expiring( const char *attrname, char *value, char *errorbuf, int apply
) {
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff ( attrname,
+ value,
+
&(slapdFrontendConfig->pw_policy.pw_send_expiring),
+ errorbuf,
+ apply);
+
+ return retVal;
+}
+
+int
config_set_pw_unlock( const char *attrname, char *value, char *errorbuf, int apply ) {
int retVal = LDAP_SUCCESS;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index e1cb53e..8fcebb8 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -328,6 +328,7 @@ int config_set_pw_is_legacy_policy(const char *attrname, char *value,
char *err
int config_set_pw_track_last_update_time(const char *attrname, char *value, char
*errorbuf, int apply );
int config_set_pw_gracelimit(const char *attrname, char *value, char *errorbuf, int
apply );
int config_set_pw_admin_dn( const char *attrname, char *value, char *errorbuf, int apply
);
+int config_set_pw_send_expiring( const char *attrname, char *value, char *errorbuf, int
apply );
int config_set_useroc(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_return_exact_case(const char *attrname, char *value, char *errorbuf, int
apply );
int config_set_result_tweak(const char *attrname, char *value, char *errorbuf, int apply
);
diff --git a/ldap/servers/slapd/pw_mgmt.c b/ldap/servers/slapd/pw_mgmt.c
index 8f33751..5ebbc2b 100644
--- a/ldap/servers/slapd/pw_mgmt.c
+++ b/ldap/servers/slapd/pw_mgmt.c
@@ -250,6 +250,11 @@ skip:
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);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 823568d..38895c6 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1551,6 +1551,7 @@ typedef struct passwordpolicyarray {
int pw_mincategories;
int pw_mintokenlength;
slapi_onoff_t pw_exp;
+ slapi_onoff_t pw_send_expiring;
long pw_maxage;
long pw_minage;
long pw_warning;
@@ -2027,6 +2028,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_PW_IS_LEGACY "passwordLegacyPolicy"
#define CONFIG_PW_TRACK_LAST_UPDATE_TIME "passwordTrackUpdateTime"
#define CONFIG_PW_ADMIN_DN_ATTRIBUTE "passwordAdminDN"
+#define CONFIG_PW_SEND_EXPIRING "passwordSendExpiringTime"
#define CONFIG_ACCESSLOG_BUFFERING_ATTRIBUTE "nsslapd-accesslog-logbuffering"
#define CONFIG_CSNLOGGING_ATTRIBUTE "nsslapd-csnlogging"
#define CONFIG_RETURN_EXACT_CASE_ATTRIBUTE "nsslapd-return-exact-case"