|
1 |
# authentic2 - versatile identity manager
|
|
2 |
# Copyright (C) 2010-2018 Entr'ouvert
|
|
3 |
#
|
|
4 |
# This program is free software: you can redistribute it and/or modify it
|
|
5 |
# under the terms of the GNU Affero General Public License as published
|
|
6 |
# by the Free Software Foundation, either version 3 of the License, or
|
|
7 |
# (at your option) any later version.
|
|
8 |
#
|
|
9 |
# This program is distributed in the hope that it will be useful,
|
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 |
# GNU Affero General Public License for more details.
|
|
13 |
#
|
|
14 |
# You should have received a copy of the GNU Affero General Public License
|
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16 |
|
1 |
17 |
try:
|
2 |
18 |
import ldap
|
3 |
19 |
import ldap.modlist
|
... | ... | |
16 |
32 |
import base64
|
17 |
33 |
import os
|
18 |
34 |
|
19 |
|
# code originaly copied from by now merely inspired by
|
20 |
|
# http://www.amherst.k12.oh.us/django-ldap.html
|
21 |
|
|
22 |
|
log = logging.getLogger(__name__)
|
23 |
|
|
24 |
35 |
from django.core.exceptions import ImproperlyConfigured
|
25 |
36 |
from django.conf import settings
|
26 |
37 |
from django.contrib.auth.models import Group
|
27 |
38 |
from django.utils.encoding import force_bytes, force_text
|
28 |
39 |
from django.utils import six
|
29 |
40 |
from django.utils.six.moves.urllib import parse as urlparse
|
30 |
|
from django.utils import six
|
31 |
41 |
|
32 |
42 |
from authentic2.a2_rbac.models import Role
|
33 |
43 |
|
... | ... | |
39 |
49 |
from authentic2.models import UserExternalId
|
40 |
50 |
from authentic2.middleware import StoreRequestMiddleware
|
41 |
51 |
from authentic2.user_login_failure import user_login_failure, user_login_success
|
42 |
|
from django_rbac.utils import get_ou_model
|
43 |
52 |
from authentic2.a2_rbac.utils import get_default_ou
|
44 |
53 |
from authentic2.ldap_utils import FilterFormatter
|
45 |
|
from authentic2.utils import utf8_encode, to_list
|
46 |
|
|
|
54 |
from authentic2.utils import utf8_encode
|
47 |
55 |
from authentic2.backends import is_user_authenticable
|
48 |
56 |
|
|
57 |
from django_rbac.utils import get_ou_model
|
|
58 |
|
|
59 |
# code originaly copied from by now merely inspired by
|
|
60 |
# http://www.amherst.k12.oh.us/django-ldap.html
|
|
61 |
|
|
62 |
log = logging.getLogger(__name__)
|
49 |
63 |
|
50 |
64 |
DEFAULT_CA_BUNDLE = ''
|
51 |
65 |
|
... | ... | |
261 |
275 |
def update_request(self):
|
262 |
276 |
request = StoreRequestMiddleware.get_request()
|
263 |
277 |
if request:
|
264 |
|
assert not request.session is None
|
|
278 |
assert request.session is not None
|
265 |
279 |
self.init_to_session(request.session)
|
266 |
280 |
|
267 |
281 |
def init_from_request(self):
|
268 |
282 |
request = StoreRequestMiddleware.get_request()
|
269 |
|
assert request and not request.session is None
|
|
283 |
assert request and request.session is not None
|
270 |
284 |
self.init_from_session(request.session)
|
271 |
285 |
|
272 |
286 |
def keep_password(self, password):
|
... | ... | |
377 |
391 |
'bindpw': '',
|
378 |
392 |
'bindsasl': (),
|
379 |
393 |
'user_dn_template': '',
|
380 |
|
'user_filter': 'uid=%s', # will be '(|(mail=%s)(uid=%s))' if A2_ACCEPT_EMAIL_AUTHENTICATION is set (see update_default)
|
|
394 |
# user_filter will be '(|(mail=%s)(uid=%s))' if
|
|
395 |
# A2_ACCEPT_EMAIL_AUTHENTICATION is set (see update_default)
|
|
396 |
'user_filter': 'uid=%s',
|
381 |
397 |
'sync_ldap_users_filter': '',
|
382 |
398 |
'user_basedn': '',
|
383 |
399 |
'group_dn_template': '',
|
... | ... | |
587 |
603 |
if not block['connect_with_user_credentials']:
|
588 |
604 |
try:
|
589 |
605 |
self.bind(block, conn)
|
590 |
|
except Exception as e:
|
|
606 |
except Exception:
|
591 |
607 |
log.exception(u'rebind failure after login bind')
|
592 |
608 |
raise ldap.SERVER_DOWN
|
593 |
609 |
break
|
... | ... | |
740 |
756 |
for role_name in role_names:
|
741 |
757 |
role, error = self.get_role(block, role_id=role_name)
|
742 |
758 |
if role is None:
|
743 |
|
log.warning('error %s: couldn\'t retrieve role %r',
|
744 |
|
error, role_name)
|
|
759 |
log.warning(u'error %s: couldn\'t retrieve role "%s"', error, role_name)
|
745 |
760 |
continue
|
746 |
761 |
# Add missing roles
|
747 |
762 |
if dn in role_dns and role not in roles:
|
... | ... | |
843 |
858 |
if group not in groups:
|
844 |
859 |
user.groups.add(group)
|
845 |
860 |
|
846 |
|
|
847 |
861 |
def populate_mandatory_roles(self, user, block):
|
848 |
862 |
mandatory_roles = block.get('set_mandatory_roles')
|
849 |
863 |
if not mandatory_roles:
|
... | ... | |
855 |
869 |
for role_name in mandatory_roles:
|
856 |
870 |
role, error = self.get_role(block, role_id=role_name)
|
857 |
871 |
if role is None:
|
858 |
|
log.warning('error %s: couldn\'t retrieve role %r',
|
859 |
|
error, role_name)
|
|
872 |
log.warning(u'error %s: couldn\'t retrieve role "%s"', error, role_name)
|
860 |
873 |
continue
|
861 |
874 |
if role not in roles:
|
862 |
875 |
user.roles.add(role)
|
... | ... | |
1005 |
1018 |
return
|
1006 |
1019 |
|
1007 |
1020 |
def lookup_by_external_id(self, block, attributes):
|
1008 |
|
User = get_user_model()
|
1009 |
1021 |
for eid_tuple in map_text(block['external_id_tuples']):
|
1010 |
1022 |
external_id = self.build_external_id(eid_tuple, attributes)
|
1011 |
1023 |
if not external_id:
|
... | ... | |
1020 |
1032 |
user = users[0]
|
1021 |
1033 |
if len(users) > 1:
|
1022 |
1034 |
log.info('found %d users, collectings roles into the first one and deleting the other ones.',
|
1023 |
|
len(users))
|
|
1035 |
len(users))
|
1024 |
1036 |
for other in users[1:]:
|
1025 |
1037 |
for r in other.roles.all():
|
1026 |
1038 |
user.roles.add(r)
|
... | ... | |
1313 |
1325 |
if isinstance(cls._DEFAULTS[d], bool) and not isinstance(block[d], bool):
|
1314 |
1326 |
raise ImproperlyConfigured(
|
1315 |
1327 |
'LDAP_AUTH_SETTINGS: attribute %r must be a boolean' % d)
|
1316 |
|
if (isinstance(cls._DEFAULTS[d], (list, tuple)) and
|
1317 |
|
not isinstance(block[d], (list, tuple))):
|
|
1328 |
if (isinstance(cls._DEFAULTS[d], (list, tuple))
|
|
1329 |
and not isinstance(block[d], (list, tuple))):
|
1318 |
1330 |
raise ImproperlyConfigured(
|
1319 |
1331 |
'LDAP_AUTH_SETTINGS: attribute %r must be a list or a tuple' % d)
|
1320 |
1332 |
if isinstance(cls._DEFAULTS[d], dict) and not isinstance(block[d], dict):
|
1321 |
|
-
|