소스 검색

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!!)

Mark Reynolds 10 년 전
부모
커밋
d9f37f1f7a
6개의 변경된 파일157개의 추가작업 그리고 4개의 파일을 삭제
  1. 124 0
      dirsrvtests/tickets/ticket48369_test.py
  2. 1 0
      ldap/schema/02common.ldif
  3. 24 4
      ldap/servers/slapd/libglobs.c
  4. 1 0
      ldap/servers/slapd/proto-slap.h
  5. 5 0
      ldap/servers/slapd/pw_mgmt.c
  6. 2 0
      ldap/servers/slapd/slap.h

+ 124 - 0
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
+
+
[email protected](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)

+ 1 - 0
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' )

+ 24 - 4
ldap/servers/slapd/libglobs.c

@@ -193,6 +193,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;
@@ -661,6 +662,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,
@@ -1506,6 +1511,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;
@@ -3188,14 +3194,28 @@ 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;

+ 1 - 0
ldap/servers/slapd/proto-slap.h

@@ -329,6 +329,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 );

+ 5 - 0
ldap/servers/slapd/pw_mgmt.c

@@ -235,6 +235,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);

+ 2 - 0
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;
@@ -2043,6 +2044,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"