0001-ldap-log-controls-on-authenticate-and-enable-ppolicy.patch
src/authentic2/backends/ldap_backend.py | ||
---|---|---|
23 | 23 |
from ldap.filter import filter_format |
24 | 24 |
from ldap.dn import escape_dn_chars |
25 | 25 |
from ldap.ldapobject import ReconnectLDAPObject as NativeLDAPObject |
26 |
from ldap.controls import SimplePagedResultsControl |
|
26 |
from ldap.controls import SimplePagedResultsControl, DecodeControlTuples |
|
27 |
from ldap.controls.ppolicy import PasswordPolicyControl |
|
27 | 28 |
PYTHON_LDAP3 = [int(x) for x in ldap.__version__.split('.')] >= [3] |
28 | 29 |
LDAPObject = NativeLDAPObject |
29 | 30 |
except ImportError: |
... | ... | |
628 | 629 |
if failed: |
629 | 630 |
continue |
630 | 631 |
try: |
631 |
conn.simple_bind_s(authz_id, password) |
|
632 |
conn.simple_bind_s(authz_id, password, serverctrls=[PasswordPolicyControl()])
|
|
632 | 633 |
user_login_success(authz_id) |
633 | 634 |
if not block['connect_with_user_credentials']: |
634 | 635 |
try: |
... | ... | |
637 | 638 |
log.exception(u'rebind failure after login bind') |
638 | 639 |
raise ldap.SERVER_DOWN |
639 | 640 |
break |
640 |
except ldap.INVALID_CREDENTIALS: |
|
641 |
except ldap.INVALID_CREDENTIALS as e: |
|
642 |
if len(e.args) > 0 and 'ctrls' in e.args[0]: |
|
643 |
log.info('ctrls=%s' % DecodeControlTuples(e.args[0]['ctrls'])) |
|
641 | 644 |
user_login_failure(authz_id) |
642 | 645 |
pass |
643 | 646 |
else: |
tests/test_ldap.py | ||
---|---|---|
78 | 78 |
yield s |
79 | 79 | |
80 | 80 | |
81 |
@pytest.fixture |
|
82 |
def slapd_ppolicy(): |
|
83 |
with create_slapd() as slapd: |
|
84 |
conn = slapd.get_connection_admin() |
|
85 |
conn.modify_s( |
|
86 |
'cn=module{0},cn=config', |
|
87 |
[ |
|
88 |
(ldap.MOD_ADD, 'olcModuleLoad', [ |
|
89 |
force_bytes('ppolicy') |
|
90 |
]) |
|
91 |
]) |
|
92 |
slapd.add_ldif(open('/etc/ldap/schema/ppolicy.ldif').read()) |
|
93 |
slapd.add_ldif(''' |
|
94 |
dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config |
|
95 |
objectclass: olcOverlayConfig |
|
96 |
objectclass: olcPPolicyConfig |
|
97 |
olcoverlay: {0}ppolicy |
|
98 |
olcppolicydefault: cn=default,ou=ppolicies,o=ôrga |
|
99 |
olcppolicyforwardupdates: FALSE |
|
100 |
olcppolicyhashcleartext: TRUE |
|
101 |
olcppolicyuselockout: FALSE |
|
102 |
''') |
|
103 | ||
104 |
slapd.add_ldif(''' |
|
105 |
dn: ou=ppolicies,o=ôrga |
|
106 |
objectclass: organizationalUnit |
|
107 |
ou: ppolicies |
|
108 |
''') |
|
109 | ||
110 |
slapd.add_ldif(''' |
|
111 |
dn: cn=default,ou=ppolicies,o=ôrga |
|
112 |
cn: default |
|
113 |
objectclass: top |
|
114 |
objectclass: device |
|
115 |
objectclass: pwdPolicy |
|
116 |
objectclass: pwdPolicyChecker |
|
117 |
pwdAttribute: userPassword |
|
118 |
pwdMinAge: 0 |
|
119 |
pwdMaxAge: 0 |
|
120 |
pwdInHistory: 0 |
|
121 |
pwdCheckQuality: 1 |
|
122 |
pwdMinLength: 8 |
|
123 |
pwdExpireWarning: 0 |
|
124 |
pwdGraceAuthnLimit: 0 |
|
125 |
pwdLockout: FALSE |
|
126 |
pwdLockoutDuration: 0 |
|
127 |
pwdMaxFailure: 0 |
|
128 |
pwdMaxRecordedFailure: 0 |
|
129 |
pwdFailureCountInterval: 0 |
|
130 |
pwdMustChange: FALSE |
|
131 |
pwdAllowUserChange: FALSE |
|
132 |
pwdSafeModify: FALSE |
|
133 |
''') |
|
134 |
yield slapd |
|
135 | ||
136 | ||
81 | 137 |
@pytest.fixture |
82 | 138 |
def tls_slapd(): |
83 | 139 |
tcp_port = utils.find_free_tcp_port() |
... | ... | |
872 | 928 |
assert user.pk == user2.pk |
873 | 929 | |
874 | 930 | |
931 |
def test_authenticate_ppolicy(slapd_ppolicy, settings, db, caplog): |
|
932 |
settings.LDAP_AUTH_SETTINGS = [{ |
|
933 |
'url': [slapd_ppolicy.ldap_url], |
|
934 |
'basedn': u'o=ôrga', |
|
935 |
'use_tls': False, |
|
936 |
}] |
|
937 |
assert authenticate(username=u'etienne.michu', password='incorrect') is None |
|
938 |
assert "failed to login" in caplog.text |
|
939 | ||
940 | ||
875 | 941 |
def test_ou_selector(slapd, settings, app, ou1): |
876 | 942 |
settings.LDAP_AUTH_SETTINGS = [{ |
877 | 943 |
'url': [slapd.ldap_url], |
878 |
- |