From b9816e222f4f096ac25839a9edb2d501127422d4 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Tue, 4 Dec 2018 15:08:32 +0100 Subject: [PATCH] ldap: fix setting client TLS certificate (fixes #28570) New tests depends upon ldaptools 0.15. --- src/authentic2/backends/ldap_backend.py | 2 +- tests/test_ldap.py | 76 +++++++++++++++++++++++-- tox.ini | 1 + 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/src/authentic2/backends/ldap_backend.py b/src/authentic2/backends/ldap_backend.py index 000f520b..b86ff7e1 100644 --- a/src/authentic2/backends/ldap_backend.py +++ b/src/authentic2/backends/ldap_backend.py @@ -1029,7 +1029,7 @@ class LDAPBackend(object): if block['certfile']: conn.set_option(ldap.OPT_X_TLS_CERTFILE, block['certfile']) if block['keyfile']: - conn.set_option(ldap.OPT_X_TLS_CERTFILE, block['keyfile']) + conn.set_option(ldap.OPT_X_TLS_KEYFILE, block['keyfile']) for key, value in block['ldap_options']: conn.set_option(key, value) conn.set_option(ldap.OPT_REFERRALS, 1 if block['referrals'] else 0) diff --git a/tests/test_ldap.py b/tests/test_ldap.py index 7d9f5076..3ae18175 100644 --- a/tests/test_ldap.py +++ b/tests/test_ldap.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +import os + import pytest import mock @@ -29,10 +31,25 @@ DN = 'cn=%s,o=ôrga' % escape_dn_chars(CN) PASS = 'passé' EMAIL = 'etienne.michu@example.net' +base_dir = os.path.dirname(__file__) +key_file = os.path.join(base_dir, 'key.pem') +cert_file = os.path.join(base_dir, 'cert.pem') + + +@pytest.fixture +def slapd(): + with create_slapd() as s: + yield s + @pytest.fixture -def slapd(request): - slapd = Slapd() +def tls_slapd(): + with Slapd(ldap_url='ldap://localhost:4389', tls=(key_file, cert_file)) as s: + yield create_slapd(s) + + +def create_slapd(slapd=None): + slapd = slapd or Slapd() slapd.add_db('o=ôrga') slapd.add_ldif('''dn: o=ôrga objectClass: organization @@ -72,10 +89,6 @@ memberUid: {uid} group_ldif += 'memberUid: michu{i}\n'.format(i=i) group_ldif += '\n\n' slapd.add_ldif(group_ldif) - - def finalize(): - slapd.clean() - request.addfinalizer(finalize) return slapd @@ -588,3 +601,54 @@ def test_user_cannot_change_password(slapd, settings, app, db): assert 'Password' not in response response = app.get('/accounts/password/change/') assert response['Location'].endswith('/accounts/') + + +def test_tls(db, tls_slapd, settings, client): + conn = tls_slapd.get_connection_admin() + conn.modify_s('cn=config', [ + (ldap.MOD_ADD, 'olcTLSCACertificateFile', cert_file), + (ldap.MOD_ADD, 'olcTLSVerifyClient', 'demand'), + ]) + + # without TLS it does not work + settings.LDAP_AUTH_SETTINGS = [{ + 'url': [tls_slapd.ldap_url], + 'basedn': u'o=ôrga', + 'use_tls': False, + }] + result = client.post('/login/', {'login-password-submit': '1', + 'username': USERNAME, + 'password': PASS}, follow=True) + assert result.status_code == 200 + assert 'Étienne Michu' not in str(result) + assert 'name="username"' in str(result) + + # without TLS client authentication it does not work + settings.LDAP_AUTH_SETTINGS = [{ + 'url': [tls_slapd.ldap_url], + 'basedn': u'o=ôrga', + 'use_tls': True, + 'cacertfile': cert_file, + }] + result = client.post('/login/', {'login-password-submit': '1', + 'username': USERNAME, + 'password': PASS}, follow=True) + assert result.status_code == 200 + assert 'Étienne Michu' not in str(result) + assert 'name="username"' in str(result) + + # now it works ! + settings.LDAP_AUTH_SETTINGS = [{ + 'url': [tls_slapd.ldap_url], + 'basedn': u'o=ôrga', + 'use_tls': True, + 'cacertfile': cert_file, + 'certfile': cert_file, + 'keyfile': key_file, + }] + result = client.post('/login/', {'login-password-submit': '1', + 'username': USERNAME, + 'password': PASS}, follow=True) + assert result.status_code == 200 + assert 'Étienne Michu' in str(result) + assert 'name="username"' not in str(result) diff --git a/tox.ini b/tox.ini index dc233607..d5d7bd2d 100644 --- a/tox.ini +++ b/tox.ini @@ -48,6 +48,7 @@ deps = httmock pytz pytest-freezegun + ldaptools>0.15 commands = ./getlasso.sh authentic: py.test {env:FAST:} {env:REUSEDB:} {env:COVERAGE:} {posargs:tests/ --random} -- 2.18.0