Show More
@@ -69,6 +69,12 b' class LdapAuthnResource(AuthnPluginResou' | |||||
69 | class AuthLdap(AuthLdapBase): |
|
69 | class AuthLdap(AuthLdapBase): | |
70 | default_tls_cert_dir = '/etc/openldap/cacerts' |
|
70 | default_tls_cert_dir = '/etc/openldap/cacerts' | |
71 |
|
71 | |||
|
72 | scope_labels = { | |||
|
73 | ldap.SCOPE_BASE: 'SCOPE_BASE', | |||
|
74 | ldap.SCOPE_ONELEVEL: 'SCOPE_ONELEVEL', | |||
|
75 | ldap.SCOPE_SUBTREE: 'SCOPE_SUBTREE', | |||
|
76 | } | |||
|
77 | ||||
72 | def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='', |
|
78 | def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='', | |
73 | tls_kind='PLAIN', tls_reqcert='DEMAND', tls_cert_file=None, |
|
79 | tls_kind='PLAIN', tls_reqcert='DEMAND', tls_cert_file=None, | |
74 | tls_cert_dir=None, ldap_version=3, |
|
80 | tls_cert_dir=None, ldap_version=3, | |
@@ -148,19 +154,27 b' class AuthLdap(AuthLdapBase):' | |||||
148 | log.debug('simple_bind successful') |
|
154 | log.debug('simple_bind successful') | |
149 | return ldap_conn |
|
155 | return ldap_conn | |
150 |
|
156 | |||
151 |
def fetch_attrs_from_simple_bind(self, |
|
157 | def fetch_attrs_from_simple_bind(self, ldap_conn, dn, username, password): | |
|
158 | scope = ldap.SCOPE_BASE | |||
|
159 | scope_label = self.scope_labels.get(scope) | |||
|
160 | ldap_filter = '(objectClass=*)' | |||
|
161 | ||||
152 | try: |
|
162 | try: | |
153 |
log.debug('Trying |
|
163 | log.debug('Trying authenticated search bind with dn: %r SCOPE: %s (and filter: %s)', | |
154 | server.simple_bind_s(dn, safe_str(password)) |
|
164 | dn, scope_label, ldap_filter) | |
155 | _dn, attrs = server.search_ext_s( |
|
165 | ldap_conn.simple_bind_s(dn, safe_str(password)) | |
156 | dn, ldap.SCOPE_BASE, '(objectClass=*)', )[0] |
|
166 | response = ldap_conn.search_ext_s(dn, scope, ldap_filter, attrlist=['*', '+']) | |
157 |
|
167 | |||
158 |
|
|
168 | if not response: | |
|
169 | log.error('search bind returned empty results: %r', response) | |||
|
170 | return {} | |||
|
171 | else: | |||
|
172 | _dn, attrs = response[0] | |||
|
173 | return attrs | |||
159 |
|
174 | |||
160 | except ldap.INVALID_CREDENTIALS: |
|
175 | except ldap.INVALID_CREDENTIALS: | |
161 | log.debug( |
|
176 | log.debug("LDAP rejected password for user '%s': %s, org_exc:", | |
162 | "LDAP rejected password for user '%s': %s, org_exc:", |
|
177 | username, dn, exc_info=True) | |
163 | username, dn, exc_info=True) |
|
|||
164 |
|
178 | |||
165 | def authenticate_ldap(self, username, password): |
|
179 | def authenticate_ldap(self, username, password): | |
166 | """ |
|
180 | """ | |
@@ -179,35 +193,38 b' class AuthLdap(AuthLdapBase):' | |||||
179 |
|
193 | |||
180 | self.validate_password(username, password) |
|
194 | self.validate_password(username, password) | |
181 | self.validate_username(username) |
|
195 | self.validate_username(username) | |
|
196 | scope_label = self.scope_labels.get(self.SEARCH_SCOPE) | |||
182 |
|
197 | |||
183 | ldap_conn = None |
|
198 | ldap_conn = None | |
184 | try: |
|
199 | try: | |
185 | ldap_conn = self._get_ldap_conn() |
|
200 | ldap_conn = self._get_ldap_conn() | |
186 | filter_ = '(&%s(%s=%s))' % ( |
|
201 | filter_ = '(&%s(%s=%s))' % ( | |
187 | self.LDAP_FILTER, self.attr_login, username) |
|
202 | self.LDAP_FILTER, self.attr_login, username) | |
188 |
log.debug("Authenticating %r filter %s", |
|
203 | log.debug("Authenticating %r filter %s and scope: %s", | |
|
204 | self.BASE_DN, filter_, scope_label) | |||
189 |
|
205 | |||
190 | lobjects = ldap_conn.search_ext_s( |
|
206 | ldap_objects = ldap_conn.search_ext_s( | |
191 | self.BASE_DN, self.SEARCH_SCOPE, filter_) |
|
207 | self.BASE_DN, self.SEARCH_SCOPE, filter_, attrlist=['*', '+']) | |
192 |
|
208 | |||
193 | if not lobjects: |
|
209 | if not ldap_objects: | |
194 | log.debug("No matching LDAP objects for authentication " |
|
210 | log.debug("No matching LDAP objects for authentication " | |
195 | "of UID:'%s' username:(%s)", uid, username) |
|
211 | "of UID:'%s' username:(%s)", uid, username) | |
196 | raise ldap.NO_SUCH_OBJECT() |
|
212 | raise ldap.NO_SUCH_OBJECT() | |
197 |
|
213 | |||
198 | log.debug('Found matching ldap object, trying to authenticate') |
|
214 | log.debug('Found %s matching ldap object[s], trying to authenticate on each one now...', len(ldap_objects)) | |
199 | for (dn, _attrs) in lobjects: |
|
215 | for (dn, _attrs) in ldap_objects: | |
200 | if dn is None: |
|
216 | if dn is None: | |
201 | continue |
|
217 | continue | |
202 |
|
218 | |||
203 | user_attrs = self.fetch_attrs_from_simple_bind( |
|
219 | user_attrs = self.fetch_attrs_from_simple_bind( | |
204 | ldap_conn, dn, username, password) |
|
220 | ldap_conn, dn, username, password) | |
|
221 | ||||
205 | if user_attrs: |
|
222 | if user_attrs: | |
|
223 | log.debug('Got authenticated user attributes from DN:%s', dn) | |||
206 | break |
|
224 | break | |
207 | else: |
|
225 | else: | |
208 | raise LdapPasswordError( |
|
226 | raise LdapPasswordError( | |
209 | 'Failed to authenticate user `{}` ' |
|
227 | 'Failed to authenticate user `{}` with given password'.format(username)) | |
210 | 'with given password'.format(username)) |
|
|||
211 |
|
228 | |||
212 | except ldap.NO_SUCH_OBJECT: |
|
229 | except ldap.NO_SUCH_OBJECT: | |
213 | log.debug("LDAP says no such user '%s' (%s), org_exc:", |
|
230 | log.debug("LDAP says no such user '%s' (%s), org_exc:", | |
@@ -216,8 +233,7 b' class AuthLdap(AuthLdapBase):' | |||||
216 | except ldap.SERVER_DOWN: |
|
233 | except ldap.SERVER_DOWN: | |
217 | org_exc = traceback.format_exc() |
|
234 | org_exc = traceback.format_exc() | |
218 | raise LdapConnectionError( |
|
235 | raise LdapConnectionError( | |
219 | "LDAP can't access authentication " |
|
236 | "LDAP can't access authentication server, org_exc:%s" % org_exc) | |
220 | "server, org_exc:%s" % org_exc) |
|
|||
221 | finally: |
|
237 | finally: | |
222 | if ldap_conn: |
|
238 | if ldap_conn: | |
223 | log.debug('ldap: connection release') |
|
239 | log.debug('ldap: connection release') |
General Comments 0
You need to be logged in to leave comments.
Login now