summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2016-02-24 00:00:59 (GMT)
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2016-02-24 20:44:57 (GMT)
commitf359d594a58daefe379a6fffb3a697e3374425ce (patch)
treed9105372d2b26e18a5c926ddc6a8c26a6dd0681a
parente3c09e4971fb66bbc62197e46a56da222f381f15 (diff)
downloadauthentic2-auth-kerberos-f359d594a58daefe379a6fffb3a697e3374425ce.zip
authentic2-auth-kerberos-f359d594a58daefe379a6fffb3a697e3374425ce.tar.gz
authentic2-auth-kerberos-f359d594a58daefe379a6fffb3a697e3374425ce.tar.bz2
add LDAP backend for Kerberos login based on authentic2 classic LDAP backend (#10069)
-rw-r--r--src/authentic2_auth_kerberos/app_settings.py1
-rw-r--r--src/authentic2_auth_kerberos/backends.py90
2 files changed, 89 insertions, 2 deletions
diff --git a/src/authentic2_auth_kerberos/app_settings.py b/src/authentic2_auth_kerberos/app_settings.py
index 5f9f63e..7fea6c2 100644
--- a/src/authentic2_auth_kerberos/app_settings.py
+++ b/src/authentic2_auth_kerberos/app_settings.py
@@ -3,6 +3,7 @@ class AppSettings(object):
'ENABLED': True,
'CREATE_USER': True,
'REALM': None,
+ 'LDAP_BACKEND': True,
'DJANGO_BACKEND': False,
}
diff --git a/src/authentic2_auth_kerberos/backends.py b/src/authentic2_auth_kerberos/backends.py
index debb70b..937121e 100644
--- a/src/authentic2_auth_kerberos/backends.py
+++ b/src/authentic2_auth_kerberos/backends.py
@@ -1,9 +1,19 @@
-from django_kerberos.backends import KerberosBackend
-
import logging
+try:
+ import ldap
+except ImportError:
+ ldap = None
+
+from django.core.exceptions import ImproperlyConfigured
+from django_kerberos.backends import KerberosBackend
+from authentic2.backends.ldap_backend import LDAPBackend
+from authentic2.ldap_utils import FilterFormatter
+from authentic2.user_login_failure import user_login_success
+
from . import app_settings
+
class A2KerberosBackend(KerberosBackend):
def __init__(self):
super(A2KerberosBackend, self).__init__()
@@ -31,3 +41,79 @@ class A2KerberosBackend(KerberosBackend):
def get_saml2_authn_context(self):
import lasso
return lasso.SAML2_AUTHN_CONTEXT_KERBEROS
+
+# Allow new parameter
+LDAPBackend._DEFAULTS['principal_filter'] = None
+LDAPBackend._VALID_CONFIG_KEYS.append('principal_filter')
+
+
+class A2LdapKerberosBackend(LDAPBackend):
+ def authenticate(self, principal=None, **kwargs):
+ logger = logging.getLogger(__name__)
+
+ if not app_settings.ENABLED:
+ return
+ if not app_settings.LDAP_BACKEND:
+ return
+ if not principal:
+ return
+ if principal.count('@') != 1:
+ logger.warning(u'maformed principal %r', principal)
+ return
+ username, realm = principal.split('@')
+ config = self.get_config()
+ if not config:
+ return
+ if not ldap:
+ raise ImproperlyConfigured('ldap is not available')
+
+ for block in config:
+ user = self.authenticate_block(block, username, realm, logger)
+ if user:
+ return user
+
+ def authenticate_block(self, block, username, realm, logger):
+ if not block['principal_filter']:
+ return
+ if block['limit_to_realm'] and realm != block['realm']:
+ return
+ if not '{username}' in block['principal_filter']:
+ logger.warning('principal_filter does not contain the {username} pattern: %r',
+ block['principal_filter'])
+ return
+
+ user_basedn = block.get('user_basedn') or block['basedn']
+ principal_filter = FilterFormatter().format(block['principal_filter'], username=username,
+ realm=realm)
+ for conn in self.get_connections(block):
+ try:
+ results = conn.search_s(user_basedn, ldap.SCOPE_SUBTREE, principal_filter,
+ self.get_ldap_attributes_names(block))
+ results = [(dn, attrs) for dn, attrs in results if dn]
+ if not results and block['replicas']:
+ break
+ if len(results) > 1:
+ logger.error('looking up principal %s@%s returned more than 1 user for %s',
+ username, realm, block['url'])
+ return
+ dn, attrs = results[0]
+ attrs['dn'] = dn
+ return self._return_user(dn, None, conn, block, attributes=attrs)
+ except ldap.NO_SUCH_OBJECT:
+ if block['replicas']:
+ logger.warning('principal filter failed with NO_SUCH_OBJECT: %r',
+ principal_filter)
+ return
+ except ldap.CONNECT_ERROR:
+ logger.error('connection to %r failed, did you forget to declare the TLS '
+ 'certificate in /etc/ldap/ldap.conf ?', block['url'])
+ except ldap.TIMEOUT:
+ logger.error('connection to %r timed out', block['url'])
+ except ldap.SERVER_DOWN:
+ logger.error('ldap authentication error: %r is down', block['url'])
+ # Not found
+ logger.info('principal %s@%s not found in %s', username, realm, block['url'])
+
+ def get_saml2_authn_context(self):
+ import lasso
+ return lasso.SAML2_AUTHN_CONTEXT_KERBEROS