2013-11-25 10:03:05 +13:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This tests the password lockout behavior for AD implementations
#
# Copyright Matthias Dieter Wallnoefer 2010
# Copyright Andrew Bartlett 2013
# Copyright Stefan Metzmacher 2014
#
import optparse
import sys
import base64
import time
sys . path . insert ( 0 , " bin/python " )
import samba
2014-11-02 09:30:50 -08:00
from samba . tests . subunitrun import TestProgram , SubunitOptions
2013-11-25 10:03:05 +13:00
import samba . getopt as options
from samba . auth import system_session
from samba . credentials import Credentials , DONT_USE_KERBEROS , MUST_USE_KERBEROS
from ldb import SCOPE_BASE , LdbError
from ldb import ERR_CONSTRAINT_VIOLATION
from ldb import ERR_INVALID_CREDENTIALS
from ldb import Message , MessageElement , Dn
2014-11-02 09:30:50 -08:00
from ldb import FLAG_MOD_REPLACE
2013-11-25 10:03:05 +13:00
from samba import gensec , dsdb
from samba . samdb import SamDB
import samba . tests
from samba . tests import delete_force
from samba . dcerpc import security , samr
from samba . ndr import ndr_unpack
2016-03-11 15:17:43 +13:00
parser = optparse . OptionParser ( " password_lockout.py [options] <host> " )
2013-11-25 10:03:05 +13:00
sambaopts = options . SambaOptions ( parser )
parser . add_option_group ( sambaopts )
parser . add_option_group ( options . VersionOptions ( parser ) )
# use command line creds if available
credopts = options . CredentialsOptions ( parser )
parser . add_option_group ( credopts )
2014-11-02 09:30:50 -08:00
subunitopts = SubunitOptions ( parser )
parser . add_option_group ( subunitopts )
2013-11-25 10:03:05 +13:00
opts , args = parser . parse_args ( )
if len ( args ) < 1 :
parser . print_usage ( )
sys . exit ( 1 )
host = args [ 0 ]
lp = sambaopts . get_loadparm ( )
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
global_creds = credopts . get_credentials ( lp )
2013-11-25 10:03:05 +13:00
# Force an encrypted connection
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
global_creds . set_gensec_features ( global_creds . get_gensec_features ( ) |
gensec . FEATURE_SEAL )
2016-02-05 08:37:53 +01:00
template_creds = Credentials ( )
template_creds . set_username ( " testuser " )
template_creds . set_password ( " thatsAcomplPASS1 " )
template_creds . set_domain ( global_creds . get_domain ( ) )
template_creds . set_realm ( global_creds . get_realm ( ) )
template_creds . set_workstation ( global_creds . get_workstation ( ) )
template_creds . set_gensec_features ( global_creds . get_gensec_features ( ) )
template_creds . set_kerberos_state ( global_creds . get_kerberos_state ( ) )
2013-11-25 10:03:05 +13:00
#
# Tests start here
#
2017-04-05 14:30:28 +12:00
class BasePasswordTestCase ( samba . tests . TestCase ) :
2013-11-25 10:03:05 +13:00
def _open_samr_user ( self , res ) :
self . assertTrue ( " objectSid " in res [ 0 ] )
( domain_sid , rid ) = ndr_unpack ( security . dom_sid , res [ 0 ] [ " objectSid " ] [ 0 ] ) . split ( )
self . assertEquals ( self . domain_sid , domain_sid )
return self . samr . OpenUser ( self . samr_domain , security . SEC_FLAG_MAXIMUM_ALLOWED , rid )
def _reset_samr ( self , res ) :
# Now reset the lockout, by removing ACB_AUTOLOCK (which removes the lock, despite being a generated attribute)
samr_user = self . _open_samr_user ( res )
acb_info = self . samr . QueryUserInfo ( samr_user , 16 )
acb_info . acct_flags & = ~ samr . ACB_AUTOLOCK
self . samr . SetUserInfo ( samr_user , 16 , acb_info )
self . samr . Close ( samr_user )
def _check_attribute ( self , res , name , value ) :
if value is None :
self . assertTrue ( name not in res [ 0 ] ,
msg = " attr[ %s ]= %r on dn[ %s ] " %
( name , res [ 0 ] , res [ 0 ] . dn ) )
return
if isinstance ( value , tuple ) :
( mode , value ) = value
else :
mode = " equal "
if mode == " ignore " :
return
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
if mode == " absent " :
self . assertFalse ( name in res [ 0 ] ,
msg = " attr[ %s ] not missing on dn[ %s ] " %
( name , res [ 0 ] . dn ) )
return
2013-11-25 10:03:05 +13:00
self . assertTrue ( name in res [ 0 ] ,
msg = " attr[ %s ] missing on dn[ %s ] " %
( name , res [ 0 ] . dn ) )
self . assertTrue ( len ( res [ 0 ] [ name ] ) == 1 ,
msg = " attr[ %s ]= %r on dn[ %s ] " %
( name , res [ 0 ] [ name ] , res [ 0 ] . dn ) )
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
print " %s = ' %s ' " % ( name , res [ 0 ] [ name ] [ 0 ] )
2013-11-25 10:03:05 +13:00
if mode == " present " :
return
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
2013-11-25 10:03:05 +13:00
if mode == " equal " :
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
v = int ( res [ 0 ] [ name ] [ 0 ] )
value = int ( value )
msg = ( " attr[ %s ]=[ %s ] != [ %s ] on dn[ %s ] \n "
" (diff %d ; actual value is %s than expected) " %
( name , v , value , res [ 0 ] . dn , v - value ,
( ' less ' if v < value else ' greater ' ) ) )
self . assertTrue ( v == value , msg )
2013-11-25 10:03:05 +13:00
return
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
2013-11-25 10:03:05 +13:00
if mode == " greater " :
v = int ( res [ 0 ] [ name ] [ 0 ] )
self . assertTrue ( v > int ( value ) ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
msg = " attr[ %s ]=[ %s ] <= [ %s ] on dn[ %s ] (diff %d ) " %
( name , v , int ( value ) , res [ 0 ] . dn , v - int ( value ) ) )
2013-11-25 10:03:05 +13:00
return
if mode == " less " :
v = int ( res [ 0 ] [ name ] [ 0 ] )
self . assertTrue ( v < int ( value ) ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
msg = " attr[ %s ]=[ %s ] >= [ %s ] on dn[ %s ] (diff %d ) " %
( name , v , int ( value ) , res [ 0 ] . dn , v - int ( value ) ) )
2013-11-25 10:03:05 +13:00
return
self . assertEqual ( mode , not mode , " Invalid Mode[ %s ] " % mode )
def _check_account ( self , dn ,
badPwdCount = None ,
badPasswordTime = None ,
2016-02-05 08:37:53 +01:00
logonCount = None ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = None ,
lastLogonTimestamp = None ,
2013-11-25 10:03:05 +13:00
lockoutTime = None ,
userAccountControl = None ,
msDSUserAccountControlComputed = None ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
effective_bad_password_count = None ,
msg = None ) :
print ' -= ' * 36
if msg is not None :
print " \033 [01;32m %s \033 [00m \n " % msg
2013-11-25 10:03:05 +13:00
attrs = [
" objectSid " ,
" badPwdCount " ,
" badPasswordTime " ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
" lastLogon " ,
" lastLogonTimestamp " ,
2016-02-05 08:37:53 +01:00
" logonCount " ,
2013-11-25 10:03:05 +13:00
" lockoutTime " ,
" userAccountControl " ,
" msDS-User-Account-Control-Computed "
]
# in order to prevent some time resolution problems we sleep for
# 10 micro second
time . sleep ( 0.01 )
2014-11-02 09:30:50 -08:00
res = self . ldb . search ( dn , scope = SCOPE_BASE , attrs = attrs )
2013-11-25 10:03:05 +13:00
self . assertTrue ( len ( res ) == 1 )
self . _check_attribute ( res , " badPwdCount " , badPwdCount )
self . _check_attribute ( res , " badPasswordTime " , badPasswordTime )
2016-02-05 08:37:53 +01:00
self . _check_attribute ( res , " logonCount " , logonCount )
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
self . _check_attribute ( res , " lastLogon " , lastLogon )
self . _check_attribute ( res , " lastLogonTimestamp " , lastLogonTimestamp )
2013-11-25 10:03:05 +13:00
self . _check_attribute ( res , " lockoutTime " , lockoutTime )
self . _check_attribute ( res , " userAccountControl " , userAccountControl )
self . _check_attribute ( res , " msDS-User-Account-Control-Computed " ,
msDSUserAccountControlComputed )
2016-02-05 08:37:53 +01:00
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
logonCount = int ( res [ 0 ] [ " logonCount " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
2013-11-25 10:03:05 +13:00
samr_user = self . _open_samr_user ( res )
uinfo3 = self . samr . QueryUserInfo ( samr_user , 3 )
uinfo5 = self . samr . QueryUserInfo ( samr_user , 5 )
uinfo16 = self . samr . QueryUserInfo ( samr_user , 16 )
uinfo21 = self . samr . QueryUserInfo ( samr_user , 21 )
self . samr . Close ( samr_user )
expected_acb_info = 0
if userAccountControl & dsdb . UF_NORMAL_ACCOUNT :
expected_acb_info | = samr . ACB_NORMAL
if userAccountControl & dsdb . UF_ACCOUNTDISABLE :
expected_acb_info | = samr . ACB_DISABLED
if userAccountControl & dsdb . UF_PASSWD_NOTREQD :
expected_acb_info | = samr . ACB_PWNOTREQ
if msDSUserAccountControlComputed & dsdb . UF_LOCKOUT :
expected_acb_info | = samr . ACB_AUTOLOCK
if msDSUserAccountControlComputed & dsdb . UF_PASSWORD_EXPIRED :
expected_acb_info | = samr . ACB_PW_EXPIRED
expected_bad_password_count = 0
if badPwdCount is not None :
expected_bad_password_count = badPwdCount
if effective_bad_password_count is None :
effective_bad_password_count = expected_bad_password_count
self . assertEquals ( uinfo3 . acct_flags , expected_acb_info )
self . assertEquals ( uinfo3 . bad_password_count , expected_bad_password_count )
2016-02-05 08:37:53 +01:00
self . assertEquals ( uinfo3 . last_logon , lastLogon )
2016-02-05 08:37:53 +01:00
self . assertEquals ( uinfo3 . logon_count , logonCount )
2013-11-25 10:03:05 +13:00
self . assertEquals ( uinfo5 . acct_flags , expected_acb_info )
self . assertEquals ( uinfo5 . bad_password_count , effective_bad_password_count )
2016-02-05 08:37:53 +01:00
self . assertEquals ( uinfo5 . last_logon , lastLogon )
2016-02-05 08:37:53 +01:00
self . assertEquals ( uinfo5 . logon_count , logonCount )
2013-11-25 10:03:05 +13:00
self . assertEquals ( uinfo16 . acct_flags , expected_acb_info )
self . assertEquals ( uinfo21 . acct_flags , expected_acb_info )
self . assertEquals ( uinfo21 . bad_password_count , effective_bad_password_count )
2016-02-05 08:37:53 +01:00
self . assertEquals ( uinfo21 . last_logon , lastLogon )
2016-02-05 08:37:53 +01:00
self . assertEquals ( uinfo21 . logon_count , logonCount )
2013-11-25 10:03:05 +13:00
# check LDAP again and make sure the samr.QueryUserInfo
# doesn't have any impact.
2014-11-02 09:30:50 -08:00
res2 = self . ldb . search ( dn , scope = SCOPE_BASE , attrs = attrs )
2013-11-25 10:03:05 +13:00
self . assertEquals ( res [ 0 ] , res2 [ 0 ] )
# in order to prevent some time resolution problems we sleep for
# 10 micro second
time . sleep ( 0.01 )
return res
2016-02-05 08:37:53 +01:00
def _readd_user ( self , creds , lockOutObservationWindow = 0 ) :
2016-02-05 08:37:53 +01:00
username = creds . get_username ( )
userpass = creds . get_password ( )
userdn = " cn= %s ,cn=users, %s " % ( username , self . base_dn )
2016-02-05 08:37:53 +01:00
use_kerberos = creds . get_kerberos_state ( )
if use_kerberos == MUST_USE_KERBEROS :
2016-02-05 08:37:53 +01:00
logoncount_relation = ' greater '
2016-02-05 08:37:53 +01:00
lastlogon_relation = ' greater '
else :
2016-02-05 08:37:53 +01:00
logoncount_relation = ' equal '
2016-02-05 08:37:53 +01:00
if lockOutObservationWindow == 0 :
lastlogon_relation = ' greater '
else :
lastlogon_relation = ' equal '
2016-02-05 08:37:53 +01:00
delete_force ( self . ldb , userdn )
2016-02-05 08:37:53 +01:00
self . ldb . add ( {
2016-02-05 08:37:53 +01:00
" dn " : userdn ,
2016-02-05 08:37:53 +01:00
" objectclass " : " user " ,
2016-02-05 08:37:53 +01:00
" sAMAccountName " : username } )
2016-02-05 08:37:53 +01:00
2016-02-05 08:37:53 +01:00
self . addCleanup ( delete_force , self . ldb , userdn )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2016-02-05 08:37:53 +01:00
badPwdCount = 0 ,
badPasswordTime = 0 ,
2016-02-05 08:37:53 +01:00
logonCount = 0 ,
2016-02-05 08:37:53 +01:00
lastLogon = 0 ,
lastLogonTimestamp = ( ' absent ' , None ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT |
dsdb . UF_ACCOUNTDISABLE |
dsdb . UF_PASSWD_NOTREQD ,
msDSUserAccountControlComputed =
dsdb . UF_PASSWORD_EXPIRED )
# SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
# It doesn't create "lockoutTime" = 0.
self . _reset_samr ( res )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2016-02-05 08:37:53 +01:00
badPwdCount = 0 ,
badPasswordTime = 0 ,
2016-02-05 08:37:53 +01:00
logonCount = 0 ,
2016-02-05 08:37:53 +01:00
lastLogon = 0 ,
lastLogonTimestamp = ( ' absent ' , None ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT |
dsdb . UF_ACCOUNTDISABLE |
dsdb . UF_PASSWD_NOTREQD ,
msDSUserAccountControlComputed =
dsdb . UF_PASSWORD_EXPIRED )
# Tests a password change when we don't have any password yet with a
# wrong old password
try :
self . ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2016-02-05 08:37:53 +01:00
changetype : modify
delete : userPassword
userPassword : noPassword
add : userPassword
userPassword : thatsAcomplPASS2
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
# Windows (2008 at least) seems to have some small bug here: it
# returns "0000056A" on longer (always wrong) previous passwords.
self . assertTrue ( ' 00000056 ' in msg , msg )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2016-02-05 08:37:53 +01:00
badPwdCount = 1 ,
badPasswordTime = ( " greater " , 0 ) ,
2016-02-05 08:37:53 +01:00
logonCount = 0 ,
2016-02-05 08:37:53 +01:00
lastLogon = 0 ,
lastLogonTimestamp = ( ' absent ' , None ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT |
dsdb . UF_ACCOUNTDISABLE |
dsdb . UF_PASSWD_NOTREQD ,
msDSUserAccountControlComputed =
dsdb . UF_PASSWORD_EXPIRED )
2016-02-05 08:37:53 +01:00
badPwdCount = int ( res [ 0 ] [ " badPwdCount " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# Sets the initial user password with a "special" password change
# I think that this internally is a password set operation and it can
# only be performed by someone which has password set privileges on the
# account (at least in s4 we do handle it like that).
self . ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2016-02-05 08:37:53 +01:00
changetype : modify
delete : userPassword
add : userPassword
2016-02-05 08:37:53 +01:00
userPassword : """ + userpass + """
2016-02-05 08:37:53 +01:00
""" )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2016-02-05 08:37:53 +01:00
badPwdCount = badPwdCount ,
2016-02-05 08:37:53 +01:00
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = 0 ,
2016-02-05 08:37:53 +01:00
lastLogon = 0 ,
lastLogonTimestamp = ( ' absent ' , None ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT |
dsdb . UF_ACCOUNTDISABLE |
dsdb . UF_PASSWD_NOTREQD ,
msDSUserAccountControlComputed = 0 )
# Enables the user account
2016-02-05 08:37:53 +01:00
self . ldb . enable_account ( " (sAMAccountName= %s ) " % username )
2016-02-05 08:37:53 +01:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2016-02-05 08:37:53 +01:00
badPwdCount = badPwdCount ,
2016-02-05 08:37:53 +01:00
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = 0 ,
2016-02-05 08:37:53 +01:00
lastLogon = 0 ,
lastLogonTimestamp = ( ' absent ' , None ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
2016-02-05 08:37:53 +01:00
if lockOutObservationWindow != 0 :
time . sleep ( lockOutObservationWindow + 1 )
effective_bad_password_count = 0
else :
effective_bad_password_count = badPwdCount
2016-02-05 08:37:53 +01:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
badPwdCount = badPwdCount ,
effective_bad_password_count = effective_bad_password_count ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = 0 ,
2016-02-05 08:37:53 +01:00
lastLogon = 0 ,
lastLogonTimestamp = ( ' absent ' , None ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
2016-02-05 08:37:53 +01:00
2017-04-10 16:08:57 +12:00
ldb = SamDB ( url = self . host_url , credentials = creds , lp = self . lp )
2016-02-05 08:37:53 +01:00
2016-02-05 08:37:53 +01:00
if lockOutObservationWindow == 0 :
badPwdCount = 0
effective_bad_password_count = 0
if use_kerberos == MUST_USE_KERBEROS :
badPwdCount = 0
effective_bad_password_count = 0
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2016-02-05 08:37:53 +01:00
badPwdCount = badPwdCount ,
effective_bad_password_count = effective_bad_password_count ,
2016-02-05 08:37:53 +01:00
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = ( logoncount_relation , 0 ) ,
2016-02-05 08:37:53 +01:00
lastLogon = ( lastlogon_relation , 0 ) ,
lastLogonTimestamp = ( ' greater ' , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
2016-02-05 08:37:53 +01:00
logonCount = int ( res [ 0 ] [ " logonCount " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = int ( res [ 0 ] [ " lastLogonTimestamp " ] [ 0 ] )
if lastlogon_relation == ' greater ' :
self . assertGreater ( lastLogon , badPasswordTime )
self . assertGreaterEqual ( lastLogon , lastLogonTimestamp )
res = self . _check_account ( userdn ,
badPwdCount = badPwdCount ,
effective_bad_password_count = effective_bad_password_count ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
2016-02-05 08:37:53 +01:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
2016-02-05 08:37:53 +01:00
return ldb
2016-02-05 08:37:53 +01:00
2015-10-22 16:54:19 +13:00
def assertLoginFailure ( self , url , creds , lp , errno = ERR_INVALID_CREDENTIALS ) :
try :
ldb = SamDB ( url = url , credentials = creds , lp = lp )
self . fail ( " Login unexpectedly succeeded " )
except LdbError , ( num , msg ) :
if errno is not None :
self . assertEquals ( num , errno , ( " Login failed in the wrong way "
" (got err %d , expected %d ) " %
( num , errno ) ) )
2013-11-25 10:03:05 +13:00
def setUp ( self ) :
2017-04-10 16:08:57 +12:00
self . host = host
self . host_url = host_url
self . lp = lp
2017-04-05 14:30:28 +12:00
super ( BasePasswordTestCase , self ) . setUp ( )
2014-11-02 09:30:50 -08:00
2017-04-10 16:08:57 +12:00
self . ldb = SamDB ( url = self . host_url , session_info = system_session ( lp ) ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
credentials = global_creds , lp = lp )
2014-11-02 09:30:50 -08:00
# Gets back the basedn
base_dn = self . ldb . domain_dn ( )
# Gets back the configuration basedn
configuration_dn = self . ldb . get_config_basedn ( ) . get_linearized ( )
# Get the old "dSHeuristics" if it was set
dsheuristics = self . ldb . get_dsheuristics ( )
# Reset the "dSHeuristics" as they were before
self . addCleanup ( self . ldb . set_dsheuristics , dsheuristics )
res = self . ldb . search ( base_dn ,
scope = SCOPE_BASE , attrs = [ " lockoutDuration " , " lockOutObservationWindow " , " lockoutThreshold " ] )
if " lockoutDuration " in res [ 0 ] :
lockoutDuration = res [ 0 ] [ " lockoutDuration " ] [ 0 ]
else :
lockoutDuration = 0
if " lockoutObservationWindow " in res [ 0 ] :
lockoutObservationWindow = res [ 0 ] [ " lockoutObservationWindow " ] [ 0 ]
else :
lockoutObservationWindow = 0
if " lockoutThreshold " in res [ 0 ] :
lockoutThreshold = res [ 0 ] [ " lockoutThreshold " ] [ 0 ]
else :
lockoutTreshold = 0
self . addCleanup ( self . ldb . modify_ldif , """
dn : """ + base_dn + """
changetype : modify
replace : lockoutDuration
lockoutDuration : """ + str(lockoutDuration) + """
replace : lockoutObservationWindow
lockoutObservationWindow : """ + str(lockoutObservationWindow) + """
replace : lockoutThreshold
lockoutThreshold : """ + str(lockoutThreshold) + """
""" )
m = Message ( )
m . dn = Dn ( self . ldb , base_dn )
2016-02-05 08:37:53 +01:00
self . account_lockout_duration = 2
2014-11-02 09:30:50 -08:00
account_lockout_duration_ticks = - int ( self . account_lockout_duration * ( 1e7 ) )
m [ " lockoutDuration " ] = MessageElement ( str ( account_lockout_duration_ticks ) ,
FLAG_MOD_REPLACE , " lockoutDuration " )
account_lockout_threshold = 3
m [ " lockoutThreshold " ] = MessageElement ( str ( account_lockout_threshold ) ,
FLAG_MOD_REPLACE , " lockoutThreshold " )
2016-02-05 08:37:53 +01:00
self . lockout_observation_window = 2
2014-11-02 09:30:50 -08:00
lockout_observation_window_ticks = - int ( self . lockout_observation_window * ( 1e7 ) )
m [ " lockOutObservationWindow " ] = MessageElement ( str ( lockout_observation_window_ticks ) ,
FLAG_MOD_REPLACE , " lockOutObservationWindow " )
self . ldb . modify ( m )
# Set the "dSHeuristics" to activate the correct "userPassword" behaviour
self . ldb . set_dsheuristics ( " 000000001 " )
# Get the old "minPwdAge"
minPwdAge = self . ldb . get_minPwdAge ( )
# Reset the "minPwdAge" as it was before
self . addCleanup ( self . ldb . set_minPwdAge , minPwdAge )
# Set it temporarely to "0"
self . ldb . set_minPwdAge ( " 0 " )
self . base_dn = self . ldb . domain_dn ( )
2013-11-25 10:03:05 +13:00
self . domain_sid = security . dom_sid ( self . ldb . get_domain_sid ( ) )
2017-04-10 16:08:57 +12:00
self . samr = samr . samr ( " ncacn_ip_tcp: %s [seal] " % self . host , self . lp , global_creds )
2013-11-25 10:03:05 +13:00
self . samr_handle = self . samr . Connect2 ( None , security . SEC_FLAG_MAXIMUM_ALLOWED )
self . samr_domain = self . samr . OpenDomain ( self . samr_handle , security . SEC_FLAG_MAXIMUM_ALLOWED , self . domain_sid )
2016-02-05 08:37:53 +01:00
# (Re)adds the test user accounts
2017-03-16 16:24:20 +13:00
self . lockout1krb5_creds = self . insta_creds ( template_creds ,
username = " lockout1krb5 " ,
userpass = " thatsAcomplPASS0 " ,
kerberos_state = MUST_USE_KERBEROS )
2016-02-05 08:37:53 +01:00
self . lockout1krb5_ldb = self . _readd_user ( self . lockout1krb5_creds )
2017-03-16 16:24:20 +13:00
self . lockout2krb5_creds = self . insta_creds ( template_creds ,
username = " lockout2krb5 " ,
userpass = " thatsAcomplPASS0 " ,
kerberos_state = MUST_USE_KERBEROS )
2016-02-05 08:37:53 +01:00
self . lockout2krb5_ldb = self . _readd_user ( self . lockout2krb5_creds ,
2017-04-10 16:08:57 +12:00
lockOutObservationWindow = self . lockout_observation_window )
2017-03-16 16:24:20 +13:00
self . lockout1ntlm_creds = self . insta_creds ( template_creds ,
username = " lockout1ntlm " ,
userpass = " thatsAcomplPASS0 " ,
kerberos_state = DONT_USE_KERBEROS )
2016-02-05 08:37:53 +01:00
self . lockout1ntlm_ldb = self . _readd_user ( self . lockout1ntlm_creds )
2017-03-16 16:24:20 +13:00
self . lockout2ntlm_creds = self . insta_creds ( template_creds ,
username = " lockout2ntlm " ,
userpass = " thatsAcomplPASS0 " ,
kerberos_state = DONT_USE_KERBEROS )
2016-02-05 08:37:53 +01:00
self . lockout2ntlm_ldb = self . _readd_user ( self . lockout2ntlm_creds ,
2017-04-10 16:08:57 +12:00
lockOutObservationWindow = self . lockout_observation_window )
2013-11-25 10:03:05 +13:00
2017-04-05 14:30:28 +12:00
def tearDown ( self ) :
super ( BasePasswordTestCase , self ) . tearDown ( )
def _test_login_lockout ( self , creds ) :
username = creds . get_username ( )
userpass = creds . get_password ( )
userdn = " cn= %s ,cn=users, %s " % ( username , self . base_dn )
use_kerberos = creds . get_kerberos_state ( )
# This unlocks by waiting for account_lockout_duration
if use_kerberos == MUST_USE_KERBEROS :
logoncount_relation = ' greater '
lastlogon_relation = ' greater '
print " Performs a lockout attempt against LDAP using Kerberos "
else :
logoncount_relation = ' equal '
lastlogon_relation = ' equal '
print " Performs a lockout attempt against LDAP using NTLM "
# Change password on a connection as another user
res = self . _check_account ( userdn ,
badPwdCount = 0 ,
badPasswordTime = ( " greater " , 0 ) ,
logonCount = ( logoncount_relation , 0 ) ,
lastLogon = ( " greater " , 0 ) ,
lastLogonTimestamp = ( " greater " , 0 ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
logonCount = int ( res [ 0 ] [ " logonCount " ] [ 0 ] )
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
firstLogon = lastLogon
lastLogonTimestamp = int ( res [ 0 ] [ " lastLogonTimestamp " ] [ 0 ] )
print firstLogon
print lastLogonTimestamp
self . assertGreater ( lastLogon , badPasswordTime )
self . assertGreaterEqual ( lastLogon , lastLogonTimestamp )
# Open a second LDB connection with the user credentials. Use the
# command line credentials for informations like the domain, the realm
# and the workstation.
creds_lockout = self . insta_creds ( creds )
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
2017-04-10 16:08:57 +12:00
self . assertLoginFailure ( self . host_url , creds_lockout , self . lp )
2017-04-05 14:30:28 +12:00
res = self . _check_account ( userdn ,
badPwdCount = 1 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
logonCount = logonCount ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 ,
msg = ' lastlogontimestamp with wrong password ' )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# Correct old password
creds_lockout . set_password ( userpass )
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
# lastLogonTimestamp should not change
# lastLogon increases if badPwdCount is non-zero (!)
res = self . _check_account ( userdn ,
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
logonCount = ( logoncount_relation , logonCount ) ,
lastLogon = ( ' greater ' , lastLogon ) ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 ,
msg = ' LLTimestamp is updated to lastlogon ' )
logonCount = int ( res [ 0 ] [ " logonCount " ] [ 0 ] )
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
self . assertGreater ( lastLogon , badPasswordTime )
self . assertGreaterEqual ( lastLogon , lastLogonTimestamp )
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
2017-04-10 16:08:57 +12:00
self . assertLoginFailure ( self . host_url , creds_lockout , self . lp )
2017-04-05 14:30:28 +12:00
res = self . _check_account ( userdn ,
badPwdCount = 1 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
logonCount = logonCount ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
try :
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_INVALID_CREDENTIALS )
res = self . _check_account ( userdn ,
badPwdCount = 2 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
logonCount = logonCount ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
print " two failed password change "
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
try :
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_INVALID_CREDENTIALS )
res = self . _check_account ( userdn ,
badPwdCount = 3 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
logonCount = logonCount ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
lockoutTime = ( " greater " , badPasswordTime ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
lockoutTime = int ( res [ 0 ] [ " lockoutTime " ] [ 0 ] )
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
try :
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_INVALID_CREDENTIALS )
res = self . _check_account ( userdn ,
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
logonCount = logonCount ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
try :
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_INVALID_CREDENTIALS )
res = self . _check_account ( userdn ,
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
logonCount = logonCount ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
# The correct password, but we are locked out
creds_lockout . set_password ( userpass )
try :
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_INVALID_CREDENTIALS )
res = self . _check_account ( userdn ,
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
logonCount = logonCount ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
# wait for the lockout to end
time . sleep ( self . account_lockout_duration + 1 )
print self . account_lockout_duration + 1
res = self . _check_account ( userdn ,
badPwdCount = 3 , effective_bad_password_count = 0 ,
badPasswordTime = badPasswordTime ,
logonCount = logonCount ,
lockoutTime = lockoutTime ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# The correct password after letting the timeout expire
creds_lockout . set_password ( userpass )
creds_lockout2 = self . insta_creds ( creds_lockout )
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout2 , lp = self . lp )
2017-04-05 14:30:28 +12:00
time . sleep ( 3 )
res = self . _check_account ( userdn ,
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
logonCount = ( logoncount_relation , logonCount ) ,
lastLogon = ( lastlogon_relation , lastLogon ) ,
lastLogonTimestamp = lastLogonTimestamp ,
lockoutTime = 0 ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 ,
msg = " lastLogon is way off " )
logonCount = int ( res [ 0 ] [ " logonCount " ] [ 0 ] )
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
try :
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_INVALID_CREDENTIALS )
res = self . _check_account ( userdn ,
badPwdCount = 1 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
logonCount = logonCount ,
lockoutTime = 0 ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
try :
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_INVALID_CREDENTIALS )
res = self . _check_account ( userdn ,
badPwdCount = 2 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
logonCount = logonCount ,
lockoutTime = 0 ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
time . sleep ( self . lockout_observation_window + 1 )
res = self . _check_account ( userdn ,
badPwdCount = 2 , effective_bad_password_count = 0 ,
badPasswordTime = badPasswordTime ,
logonCount = logonCount ,
lockoutTime = 0 ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# The wrong password
creds_lockout . set_password ( " thatsAcomplPASS1x " )
try :
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_INVALID_CREDENTIALS )
res = self . _check_account ( userdn ,
badPwdCount = 1 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
logonCount = logonCount ,
lockoutTime = 0 ,
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# The correct password without letting the timeout expire
creds_lockout . set_password ( userpass )
2017-04-10 16:08:57 +12:00
ldb_lockout = SamDB ( url = self . host_url , credentials = creds_lockout , lp = self . lp )
2017-04-05 14:30:28 +12:00
res = self . _check_account ( userdn ,
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
logonCount = ( logoncount_relation , logonCount ) ,
lockoutTime = 0 ,
lastLogon = ( " greater " , lastLogon ) ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
2017-04-10 16:33:03 +12:00
def _test_multiple_logon ( self , creds ) :
# Test the happy case in which a user logs on correctly, then
# logs on correctly again, so that the bad password and
# lockout times are both zero the second time. The lastlogon
# time should increase.
# Open a second LDB connection with the user credentials. Use the
# command line credentials for informations like the domain, the realm
# and the workstation.
username = creds . get_username ( )
userdn = " cn= %s ,cn=users, %s " % ( username , self . base_dn )
use_kerberos = creds . get_kerberos_state ( )
if use_kerberos == MUST_USE_KERBEROS :
print " Testing multiple logon with Kerberos "
logoncount_relation = ' greater '
lastlogon_relation = ' greater '
else :
print " Testing multiple logon with NTLM "
logoncount_relation = ' equal '
lastlogon_relation = ' equal '
2017-04-10 16:08:57 +12:00
SamDB ( url = self . host_url , credentials = self . insta_creds ( creds ) , lp = self . lp )
2017-04-10 16:33:03 +12:00
res = self . _check_account ( userdn ,
badPwdCount = 0 ,
badPasswordTime = ( " greater " , 0 ) ,
logonCount = ( logoncount_relation , 0 ) ,
lastLogon = ( " greater " , 0 ) ,
lastLogonTimestamp = ( " greater " , 0 ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
logonCount = int ( res [ 0 ] [ " logonCount " ] [ 0 ] )
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
lastLogonTimestamp = int ( res [ 0 ] [ " lastLogonTimestamp " ] [ 0 ] )
firstLogon = lastLogon
print " last logon is %d " % lastLogon
self . assertGreater ( lastLogon , badPasswordTime )
self . assertGreaterEqual ( lastLogon , lastLogonTimestamp )
time . sleep ( 1 )
2017-04-10 16:08:57 +12:00
SamDB ( url = self . host_url , credentials = self . insta_creds ( creds ) , lp = self . lp )
2017-04-10 16:33:03 +12:00
res = self . _check_account ( userdn ,
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
logonCount = ( logoncount_relation , logonCount ) ,
lastLogon = ( lastlogon_relation , lastLogon ) ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 ,
msg = ( " second logon, firstlogon was %s " %
firstLogon ) )
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
time . sleep ( 1 )
2017-04-10 16:08:57 +12:00
SamDB ( url = self . host_url , credentials = self . insta_creds ( creds ) , lp = self . lp )
2017-04-10 16:33:03 +12:00
res = self . _check_account ( userdn ,
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
logonCount = ( logoncount_relation , logonCount ) ,
lastLogon = ( lastlogon_relation , lastLogon ) ,
lastLogonTimestamp = lastLogonTimestamp ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
2017-04-05 14:30:28 +12:00
class PasswordTests ( BasePasswordTestCase ) :
def _reset_ldap_lockoutTime ( self , res ) :
self . ldb . modify_ldif ( """
dn : """ + str(res[0].dn) + """
changetype : modify
replace : lockoutTime
lockoutTime : 0
""" )
def _reset_ldap_userAccountControl ( self , res ) :
self . assertTrue ( " userAccountControl " in res [ 0 ] )
self . assertTrue ( " msDS-User-Account-Control-Computed " in res [ 0 ] )
uac = int ( res [ 0 ] [ " userAccountControl " ] [ 0 ] )
uacc = int ( res [ 0 ] [ " msDS-User-Account-Control-Computed " ] [ 0 ] )
uac | = uacc
uac = uac & ~ dsdb . UF_LOCKOUT
self . ldb . modify_ldif ( """
dn : """ + str(res[0].dn) + """
changetype : modify
replace : userAccountControl
userAccountControl : % d
""" % u ac)
def _reset_by_method ( self , res , method ) :
if method is " ldap_userAccountControl " :
self . _reset_ldap_userAccountControl ( res )
elif method is " ldap_lockoutTime " :
self . _reset_ldap_lockoutTime ( res )
elif method is " samr " :
self . _reset_samr ( res )
else :
self . assertTrue ( False , msg = " Invalid reset method[ %s ] " % method )
2016-02-05 08:37:53 +01:00
def _test_userPassword_lockout_with_clear_change ( self , creds , other_ldb , method ,
initial_lastlogon_relation = None ) :
2013-11-25 10:03:05 +13:00
# Notice: This works only against Windows if "dSHeuristics" has been set
# properly
2016-02-05 08:37:53 +01:00
username = creds . get_username ( )
2016-02-05 08:37:53 +01:00
userpass = creds . get_password ( )
2016-02-05 08:37:53 +01:00
userdn = " cn= %s ,cn=users, %s " % ( username , self . base_dn )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
use_kerberos = creds . get_kerberos_state ( )
if use_kerberos == MUST_USE_KERBEROS :
2016-02-05 08:37:53 +01:00
logoncount_relation = ' greater '
2016-02-05 08:37:53 +01:00
lastlogon_relation = ' greater '
print " Performs a password cleartext change operation on ' userPassword ' using Kerberos "
else :
2016-02-05 08:37:53 +01:00
logoncount_relation = ' equal '
2016-02-05 08:37:53 +01:00
lastlogon_relation = ' equal '
print " Performs a password cleartext change operation on ' userPassword ' using NTLMSSP "
if initial_lastlogon_relation is not None :
lastlogon_relation = initial_lastlogon_relation
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 0 ,
badPasswordTime = ( " greater " , 0 ) ,
2016-02-05 08:37:53 +01:00
logonCount = ( logoncount_relation , 0 ) ,
2016-02-05 08:37:53 +01:00
lastLogon = ( lastlogon_relation , 0 ) ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogonTimestamp = ( ' greater ' , 0 ) ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
logonCount = int ( res [ 0 ] [ " logonCount " ] [ 0 ] )
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
lastLogonTimestamp = int ( res [ 0 ] [ " lastLogonTimestamp " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
if lastlogon_relation == ' greater ' :
self . assertGreater ( lastLogon , badPasswordTime )
self . assertGreaterEqual ( lastLogon , lastLogonTimestamp )
2013-11-25 10:03:05 +13:00
# Change password on a connection as another user
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS1x
add : userPassword
userPassword : thatsAcomplPASS2
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 1 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# Correct old password
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
2016-02-05 08:37:53 +01:00
userPassword : """ + userpass + """
2013-11-25 10:03:05 +13:00
add : userPassword
userPassword : thatsAcomplPASS2
""" )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 1 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS1x
add : userPassword
userPassword : thatsAcomplPASS2
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 2 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
print " two failed password change "
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS1x
add : userPassword
userPassword : thatsAcomplPASS2
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = ( " greater " , badPasswordTime ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
lockoutTime = int ( res [ 0 ] [ " lockoutTime " ] [ 0 ] )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS1x
add : userPassword
userPassword : thatsAcomplPASS2
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000775 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS1x
add : userPassword
userPassword : thatsAcomplPASS2
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000775 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
try :
# Correct old password
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS2
add : userPassword
userPassword : thatsAcomplPASS2x
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000775 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
# Now reset the password, which does NOT change the lockout!
self . ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
replace : userPassword
userPassword : thatsAcomplPASS2
""" )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
try :
# Correct old password
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS2
add : userPassword
userPassword : thatsAcomplPASS2x
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000775 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
m = Message ( )
2016-02-05 08:37:53 +01:00
m . dn = Dn ( self . ldb , userdn )
2013-11-25 10:03:05 +13:00
m [ " userAccountControl " ] = MessageElement (
str ( dsdb . UF_LOCKOUT ) ,
FLAG_MOD_REPLACE , " userAccountControl " )
self . ldb . modify ( m )
# This shows that setting the UF_LOCKOUT flag alone makes no difference
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
# This shows that setting the UF_LOCKOUT flag makes no difference
try :
# Correct old password
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
unicodePwd : : """ + base64.b64encode( " \" thatsAcomplPASS2 \" " .encode( ' utf-16-le ' )) + """
add : unicodePwd
unicodePwd : : """ + base64.b64encode( " \" thatsAcomplPASS2x \" " .encode( ' utf-16-le ' )) + """
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000775 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
self . _reset_by_method ( res , method )
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
# Here bad password counts are reset without logon success.
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# The correct password after doing the unlock
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
unicodePwd : : """ + base64.b64encode( " \" thatsAcomplPASS2 \" " .encode( ' utf-16-le ' )) + """
add : unicodePwd
unicodePwd : : """ + base64.b64encode( " \" thatsAcomplPASS2x \" " .encode( ' utf-16-le ' )) + """
""" )
2016-02-05 08:37:53 +01:00
userpass = " thatsAcomplPASS2x "
creds . set_password ( userpass )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS1xyz
add : userPassword
userPassword : thatsAcomplPASS2XYZ
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 1 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : userPassword
userPassword : thatsAcomplPASS1xyz
add : userPassword
userPassword : thatsAcomplPASS2XYZ
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 2 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
self . _reset_ldap_lockoutTime ( res )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
2016-02-05 08:37:53 +01:00
def test_userPassword_lockout_with_clear_change_krb5_ldap_userAccountControl ( self ) :
self . _test_userPassword_lockout_with_clear_change ( self . lockout1krb5_creds ,
self . lockout2krb5_ldb ,
" ldap_userAccountControl " )
def test_userPassword_lockout_with_clear_change_krb5_ldap_lockoutTime ( self ) :
self . _test_userPassword_lockout_with_clear_change ( self . lockout1krb5_creds ,
self . lockout2krb5_ldb ,
" ldap_lockoutTime " )
def test_userPassword_lockout_with_clear_change_krb5_samr ( self ) :
self . _test_userPassword_lockout_with_clear_change ( self . lockout1krb5_creds ,
self . lockout2krb5_ldb ,
" samr " )
def test_userPassword_lockout_with_clear_change_ntlm_ldap_userAccountControl ( self ) :
self . _test_userPassword_lockout_with_clear_change ( self . lockout1ntlm_creds ,
self . lockout2ntlm_ldb ,
2016-02-05 08:37:53 +01:00
" ldap_userAccountControl " ,
initial_lastlogon_relation = ' greater ' )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
def test_userPassword_lockout_with_clear_change_ntlm_ldap_lockoutTime ( self ) :
self . _test_userPassword_lockout_with_clear_change ( self . lockout1ntlm_creds ,
self . lockout2ntlm_ldb ,
2016-02-05 08:37:53 +01:00
" ldap_lockoutTime " ,
initial_lastlogon_relation = ' greater ' )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
def test_userPassword_lockout_with_clear_change_ntlm_samr ( self ) :
self . _test_userPassword_lockout_with_clear_change ( self . lockout1ntlm_creds ,
self . lockout2ntlm_ldb ,
2016-02-05 08:37:53 +01:00
" samr " ,
initial_lastlogon_relation = ' greater ' )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
def _test_unicodePwd_lockout_with_clear_change ( self , creds , other_ldb ,
initial_logoncount_relation = None ) :
2013-11-25 10:03:05 +13:00
print " Performs a password cleartext change operation on ' unicodePwd ' "
2016-02-05 08:37:53 +01:00
username = creds . get_username ( )
2016-02-05 08:37:53 +01:00
userpass = creds . get_password ( )
2016-02-05 08:37:53 +01:00
userdn = " cn= %s ,cn=users, %s " % ( username , self . base_dn )
2016-02-05 08:37:53 +01:00
if initial_logoncount_relation is not None :
logoncount_relation = initial_logoncount_relation
else :
logoncount_relation = " greater "
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 0 ,
badPasswordTime = ( " greater " , 0 ) ,
2016-02-05 08:37:53 +01:00
logonCount = ( logoncount_relation , 0 ) ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = ( " greater " , 0 ) ,
lastLogonTimestamp = ( " greater " , 0 ) ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
logonCount = int ( res [ 0 ] [ " logonCount " ] [ 0 ] )
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = int ( res [ 0 ] [ " lastLogon " ] [ 0 ] )
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = int ( res [ 0 ] [ " lastLogonTimestamp " ] [ 0 ] )
self . assertGreater ( lastLogonTimestamp , badPasswordTime )
self . assertGreaterEqual ( lastLogon , lastLogonTimestamp )
2013-11-25 10:03:05 +13:00
# Change password on a connection as another user
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
unicodePwd : : """ + base64.b64encode( " \" thatsAcomplPASS1x \" " .encode( ' utf-16-le ' )) + """
add : unicodePwd
unicodePwd : : """ + base64.b64encode( " \" thatsAcomplPASS2 \" " .encode( ' utf-16-le ' )) + """
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 1 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# Correct old password
2016-02-05 08:37:53 +01:00
old_utf16 = ( " \" %s \" " % userpass ) . encode ( ' utf-16-le ' )
invalid_utf16 = " \" thatsAcomplPASSX \" " . encode ( ' utf-16-le ' )
userpass = " thatsAcomplPASS2 "
creds . set_password ( userpass )
new_utf16 = ( " \" %s \" " % userpass ) . encode ( ' utf-16-le ' )
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(old_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 1 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(old_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 2 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
# It doesn't create "lockoutTime" = 0 and doesn't
# reset "badPwdCount" = 0.
self . _reset_samr ( res )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 2 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
print " two failed password change "
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(invalid_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
# this is strange, why do we have lockoutTime=badPasswordTime here?
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = ( " greater " , badPasswordTime ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
lockoutTime = int ( res [ 0 ] [ " lockoutTime " ] [ 0 ] )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(invalid_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000775 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(invalid_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000775 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
try :
# Correct old password
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(invalid_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000775 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
# Now reset the lockout, by removing ACB_AUTOLOCK (which removes the lock, despite being a generated attribute)
self . _reset_samr ( res ) ;
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# Correct old password
2016-02-05 08:37:53 +01:00
old_utf16 = ( " \" %s \" " % userpass ) . encode ( ' utf-16-le ' )
invalid_utf16 = " \" thatsAcomplPASSiX \" " . encode ( ' utf-16-le ' )
userpass = " thatsAcomplPASS2x "
creds . set_password ( userpass )
new_utf16 = ( " \" %s \" " % userpass ) . encode ( ' utf-16-le ' )
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(old_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 0 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(invalid_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 1 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(invalid_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 2 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
# SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
# It doesn't reset "badPwdCount" = 0.
self . _reset_samr ( res )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 2 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = 0 ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# Wrong old password
try :
2016-02-05 08:37:53 +01:00
other_ldb . modify_ldif ( """
2016-02-05 08:37:53 +01:00
dn : """ + userdn + """
2013-11-25 10:03:05 +13:00
changetype : modify
delete : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(invalid_utf16) + """
2013-11-25 10:03:05 +13:00
add : unicodePwd
2016-02-05 08:37:53 +01:00
unicodePwd : : """ + base64.b64encode(new_utf16) + """
2013-11-25 10:03:05 +13:00
""" )
self . fail ( )
except LdbError , ( num , msg ) :
self . assertEquals ( num , ERR_CONSTRAINT_VIOLATION )
2016-02-05 08:37:53 +01:00
self . assertTrue ( ' 00000056 ' in msg , msg )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 ,
badPasswordTime = ( " greater " , badPasswordTime ) ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = ( " greater " , badPasswordTime ) ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = dsdb . UF_LOCKOUT )
badPasswordTime = int ( res [ 0 ] [ " badPasswordTime " ] [ 0 ] )
lockoutTime = int ( res [ 0 ] [ " lockoutTime " ] [ 0 ] )
2014-11-02 09:30:50 -08:00
time . sleep ( self . account_lockout_duration + 1 )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 , effective_bad_password_count = 0 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
# SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
# It doesn't reset "lockoutTime" = 0 and doesn't
# reset "badPwdCount" = 0.
self . _reset_samr ( res )
2016-02-05 08:37:53 +01:00
res = self . _check_account ( userdn ,
2013-11-25 10:03:05 +13:00
badPwdCount = 3 , effective_bad_password_count = 0 ,
badPasswordTime = badPasswordTime ,
2016-02-05 08:37:53 +01:00
logonCount = logonCount ,
2013-11-25 10:03:05 +13:00
lockoutTime = lockoutTime ,
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
lastLogon = lastLogon ,
2016-02-05 08:37:53 +01:00
lastLogonTimestamp = lastLogonTimestamp ,
2013-11-25 10:03:05 +13:00
userAccountControl =
dsdb . UF_NORMAL_ACCOUNT ,
msDSUserAccountControlComputed = 0 )
2016-02-05 08:37:53 +01:00
def test_unicodePwd_lockout_with_clear_change_krb5 ( self ) :
self . _test_unicodePwd_lockout_with_clear_change ( self . lockout1krb5_creds ,
self . lockout2krb5_ldb )
2016-02-05 08:37:53 +01:00
2016-02-05 08:37:53 +01:00
def test_unicodePwd_lockout_with_clear_change_ntlm ( self ) :
self . _test_unicodePwd_lockout_with_clear_change ( self . lockout1ntlm_creds ,
2016-02-05 08:37:53 +01:00
self . lockout2ntlm_ldb ,
initial_logoncount_relation = " equal " )
2016-02-05 08:37:53 +01:00
def test_login_lockout_krb5 ( self ) :
self . _test_login_lockout ( self . lockout1krb5_creds )
2013-11-25 10:03:05 +13:00
2016-02-05 08:37:53 +01:00
def test_login_lockout_ntlm ( self ) :
self . _test_login_lockout ( self . lockout1ntlm_creds )
def test_multiple_logon_krb5 ( self ) :
self . _test_multiple_logon ( self . lockout1krb5_creds )
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
def test_multiple_logon_ntlm ( self ) :
2016-02-05 08:37:53 +01:00
self . _test_multiple_logon ( self . lockout1ntlm_creds )
auth: keep track of lastLogon and lastLogonTimestamp
lastLogon is supposed to be updated for every interactive or kerberos
login, and (according to testing against Windows2012r2) when the bad
password count is non-zero but the lockout time is zero. It is not
replicated.
lastLogonTimestamp is updated if the old value is more than 14 -
random.choice([0, 1, 2, 3, 4, 5]) days old, and it is replicated. The
14 in this calculation is the default, stored as
"msDS-LogonTimeSyncInterval", which we offer no interface for
changing.
The authsam_zero_bad_pwd_count() function is a convenient place to
update these values, as it is called upon a successful logon however
that logon is performed. That makes the function's name inaccurate, so
we rename it authsam_logon_success_accounting(). It also needs to be
told whet5her the login is interactive.
The password_lockout tests are extended to test lastLogon and
lasLogonTimestamp.
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Ralph Boehme <slow@samba.org>
2015-10-23 16:57:56 +13:00
2013-11-25 10:03:05 +13:00
host_url = " ldap:// %s " % host
2014-11-02 09:30:50 -08:00
TestProgram ( module = __name__ , opts = subunitopts )