0001-WIP-ldap_backend-fix-encoding-errors-during-user-syn.patch
src/authentic2/backends/ldap_backend.py | ||
---|---|---|
319 | 319 |
# First get our configuration into a standard format |
320 | 320 |
for block in blocks: |
321 | 321 |
cls.update_default(block) |
322 |
# python-ldap needs UTF-8 encoded strings |
|
323 |
if isinstance(block.get('base_dn'), unicode): |
|
324 |
block['base_dn'] = block['base_dn'].encode('utf-8') |
|
322 | 325 |
log.debug('got config %r', blocks) |
323 | 326 |
return blocks |
324 | 327 | |
... | ... | |
349 | 352 |
utf8_username = smart_bytes(username) |
350 | 353 |
utf8_password = smart_bytes(password) |
351 | 354 | |
355 |
# python-ldap needs UTF-8 encoded strings |
|
356 |
for dn_subelement in ('basedn', 'user_basedn', 'user_dn_template'): |
|
357 |
if isinstance(block.get(dn_subelement), unicode): |
|
358 |
block[dn_sublement] = block[dn_subelement].encode('utf-8') |
|
359 | ||
352 | 360 |
for conn in self.get_connections(block): |
353 | 361 |
authz_ids = [] |
354 | 362 |
user_basedn = block.get('user_basedn') or block['basedn'] |
... | ... | |
522 | 530 |
'''Retrieve group DNs from the LDAP by attributes (memberOf) or by |
523 | 531 |
filter. |
524 | 532 |
''' |
533 |
# python-ldap needs UTF-8 encoded strings |
|
534 |
if isinstance(block.get('group_base_dn'), unicode): |
|
535 |
block['group_base_dn'] = block['group_base_dn'].encode('utf-8') |
|
525 | 536 |
group_base_dn = block.get('group_basedn', block['basedn']) |
526 | 537 |
member_of_attribute = block['member_of_attribute'] |
527 | 538 |
group_filter = block['group_filter'] |
... | ... | |
840 | 851 |
if conn is None: |
841 | 852 |
logger.warning(u'unable to synchronize with LDAP servers %r', block['url']) |
842 | 853 |
continue |
854 |
# python-ldap needs UTF-8 encoded strings. |
|
855 |
if isinstance(block.get('user_basedn'), unicode): |
|
856 |
block['user_basedn'] = block['user_basedn'].encode('utf-8') |
|
843 | 857 |
user_basedn = block.get('user_basedn') or block['basedn'] |
844 | 858 |
user_filter = block['sync_ldap_users_filter'] or block['user_filter'] |
845 | 859 |
user_filter = user_filter.replace('%s', '*') |
... | ... | |
950 | 964 |
auth = handler_class(*sasl_params) |
951 | 965 |
conn.sasl_interactive_bind_s(who, auth) |
952 | 966 |
elif block['binddn'] and block['bindpw']: |
967 |
# python-ldap needs UTF-8 encoded strings |
|
968 |
if isinstance(block.get('binddn'), unicode): |
|
969 |
block['binddn'] = block['binddn'].encode('utf-8') |
|
953 | 970 |
conn.bind_s(block['binddn'], block['bindpw']) |
954 | 971 |
yield conn |
955 | 972 |
except ldap.INVALID_CREDENTIALS: |
... | ... | |
1072 | 1089 |
results = conn.search_s(dn, ldap.SCOPE_BASE) |
1073 | 1090 |
else: |
1074 | 1091 |
ldap_filter = self.external_id_to_filter(external_id, external_id_tuple) |
1092 |
# python-ldap needs UTF-8 encoded strings |
|
1093 |
if isinstance(block.get('basedn'), unicode): |
|
1094 |
block['basedn'] = block['basedn'].encode('utf-8') |
|
1075 | 1095 |
results = conn.search_s(block['basedn'], |
1076 | 1096 |
ldap.SCOPE_SUBTREE, ldap_filter) |
1077 | 1097 |
if not results: |
tests/test_ldap.py | ||
---|---|---|
23 | 23 |
DN = 'cn=%s,o=orga' % escape_dn_chars(CN) |
24 | 24 |
PASS = 'passé' |
25 | 25 | |
26 |
USERNAME_ACCENTS = u'étienne.michü' |
|
27 |
UID_ACCENTS = 'étienne.michü' |
|
28 |
CN_ACCENTS = 'Étienne Michü' |
|
29 |
DN_ACCENTS = 'cn=%s,o=orga' % (escape_dn_chars(CN_ACCENTS)) |
|
30 | ||
26 | 31 | |
27 | 32 |
@pytest.fixture |
28 | 33 |
def slapd(request): |
... | ... | |
41 | 46 |
member: {dn} |
42 | 47 | |
43 | 48 |
'''.format(dn=DN, uid=UID, password=PASS)) |
49 |
slapd.add_ldif('''dn: {dn} |
|
50 |
objectClass: inetOrgPerson |
|
51 |
userPassword: {password} |
|
52 |
uid: {uid} |
|
53 |
cn: Étienne Michü |
|
54 |
sn: Michü |
|
55 |
gn: Étienne |
|
56 |
mail: etienne.michu@example.net |
|
57 | ||
58 |
dn: cn=group3,o=orga |
|
59 |
objectClass: groupOfNames |
|
60 |
member: {dn} |
|
61 | ||
62 |
'''.format(dn=DN_ACCENTS, uid=UID_ACCENTS, password=PASS)) |
|
44 | 63 |
for i in range(100): |
45 | 64 |
slapd.add_ldif('''dn: uid=michu{i},o=orga |
46 | 65 |
objectClass: inetOrgPerson |
... | ... | |
101 | 120 | |
102 | 121 | |
103 | 122 |
@pytest.mark.django_db |
123 |
def test_accents_in_dn(slapd, settings, client): |
|
124 |
settings.LDAP_AUTH_SETTINGS = [{ |
|
125 |
'url': [slapd.ldap_url], |
|
126 |
'basedn': 'o=entité1', |
|
127 |
'use_tls': False, |
|
128 |
}] |
|
129 |
result = client.post('/login/', {'login-password-submit': '1', |
|
130 |
'username': USERNAME_ACCENTS, |
|
131 |
'password': PASS}, follow=True) |
|
132 |
assert result.status_code == 200 |
|
133 |
assert u'Étienne Michü' in unicode(str(result), 'utf-8') |
|
134 |
User = get_user_model() |
|
135 |
assert User.objects.count() == 1 |
|
136 |
user = User.objects.get() |
|
137 |
assert user.username == u'%s@ldap' % USERNAME_ACCENTS |
|
138 |
assert user.first_name == u'Étienne' |
|
139 |
assert user.last_name == 'Michü' |
|
140 |
assert user.is_active is True |
|
141 |
assert user.is_superuser is False |
|
142 |
assert user.is_staff is False |
|
143 |
assert user.groups.count() == 0 |
|
144 |
assert not user.check_password(PASS) |
|
145 |
assert 'password' not in client.session['ldap-data'] |
|
146 | ||
147 | ||
148 |
@pytest.mark.django_db |
|
104 | 149 |
def test_simple_with_binddn(slapd, settings, client): |
105 | 150 |
settings.LDAP_AUTH_SETTINGS = [{ |
106 | 151 |
'url': [slapd.ldap_url], |
107 |
- |