217 protocol, hostport = self.urls[0].split('://') |
217 protocol, hostport = self.urls[0].split('://') |
218 if protocol != 'ldapi' and not ':' in hostport: |
218 if protocol != 'ldapi' and not ':' in hostport: |
219 hostport = '%s:%s' % (hostport, PROTO_PORT[protocol]) |
219 hostport = '%s:%s' % (hostport, PROTO_PORT[protocol]) |
220 return protocol, hostport |
220 return protocol, hostport |
221 |
221 |
222 def authenticate(self, session, login, password=None, **kwargs): |
222 def authenticate(self, cnx, login, password=None, **kwargs): |
223 """return CWUser eid for the given login/password if this account is |
223 """return CWUser eid for the given login/password if this account is |
224 defined in this source, else raise `AuthenticationError` |
224 defined in this source, else raise `AuthenticationError` |
225 |
225 |
226 two queries are needed since passwords are stored crypted, so we have |
226 two queries are needed since passwords are stored crypted, so we have |
227 to fetch the salt first |
227 to fetch the salt first |
235 searchfilter = [filter_format('(%s=%s)', (self.user_login_attr, login))] |
235 searchfilter = [filter_format('(%s=%s)', (self.user_login_attr, login))] |
236 searchfilter.extend(self.base_filters) |
236 searchfilter.extend(self.base_filters) |
237 searchstr = '(&%s)' % ''.join(searchfilter) |
237 searchstr = '(&%s)' % ''.join(searchfilter) |
238 # first search the user |
238 # first search the user |
239 try: |
239 try: |
240 user = self._search(session, self.user_base_dn, |
240 user = self._search(cnx, self.user_base_dn, |
241 self.user_base_scope, searchstr)[0] |
241 self.user_base_scope, searchstr)[0] |
242 except (IndexError, ldap.SERVER_DOWN): |
242 except (IndexError, ldap.SERVER_DOWN): |
243 # no such user |
243 # no such user |
244 raise AuthenticationError() |
244 raise AuthenticationError() |
245 # check password by establishing a (unused) connection |
245 # check password by establishing a (unused) connection |
250 self.info('while trying to authenticate %s: %s', user, ex) |
250 self.info('while trying to authenticate %s: %s', user, ex) |
251 raise AuthenticationError() |
251 raise AuthenticationError() |
252 except Exception: |
252 except Exception: |
253 self.error('while trying to authenticate %s', user, exc_info=True) |
253 self.error('while trying to authenticate %s', user, exc_info=True) |
254 raise AuthenticationError() |
254 raise AuthenticationError() |
255 eid = self.repo.extid2eid(self, user['dn'], 'CWUser', session, {}) |
255 eid = self.repo.extid2eid(self, user['dn'], 'CWUser', session=cnx, insert=False) |
256 if eid < 0: |
256 if eid < 0: |
257 # user has been moved away from this source |
257 # user has been moved away from this source |
258 raise AuthenticationError() |
258 raise AuthenticationError() |
259 return eid |
259 return eid |
260 |
260 |
312 if not kerberos.checkPassword(user[self.user_login_attr], userpwd): |
312 if not kerberos.checkPassword(user[self.user_login_attr], userpwd): |
313 raise Exception('BAD login / mdp') |
313 raise Exception('BAD login / mdp') |
314 #from ldap import sasl |
314 #from ldap import sasl |
315 #conn.sasl_interactive_bind_s('', sasl.gssapi()) |
315 #conn.sasl_interactive_bind_s('', sasl.gssapi()) |
316 |
316 |
317 def _search(self, session, base, scope, |
317 def _search(self, cnx, base, scope, |
318 searchstr='(objectClass=*)', attrs=()): |
318 searchstr='(objectClass=*)', attrs=()): |
319 """make an ldap query""" |
319 """make an ldap query""" |
320 self.debug('ldap search %s %s %s %s %s', self.uri, base, scope, |
320 self.debug('ldap search %s %s %s %s %s', self.uri, base, scope, |
321 searchstr, list(attrs)) |
321 searchstr, list(attrs)) |
322 if self._conn is None: |
322 if self._conn is None: |
323 self._conn = self._connect() |
323 self._conn = self._connect() |
324 cnx = self._conn |
324 ldapcnx = self._conn |
325 try: |
325 try: |
326 res = cnx.search_s(base, scope, searchstr, attrs) |
326 res = ldapcnx.search_s(base, scope, searchstr, attrs) |
327 except ldap.PARTIAL_RESULTS: |
327 except ldap.PARTIAL_RESULTS: |
328 res = cnx.result(all=0)[1] |
328 res = ldapcnx.result(all=0)[1] |
329 except ldap.NO_SUCH_OBJECT: |
329 except ldap.NO_SUCH_OBJECT: |
330 self.info('ldap NO SUCH OBJECT %s %s %s', base, scope, searchstr) |
330 self.info('ldap NO SUCH OBJECT %s %s %s', base, scope, searchstr) |
331 self._process_no_such_object(session, base) |
331 self._process_no_such_object(cnx, base) |
332 return [] |
332 return [] |
333 # except ldap.REFERRAL as e: |
333 # except ldap.REFERRAL as e: |
334 # cnx = self.handle_referral(e) |
334 # ldapcnx = self.handle_referral(e) |
335 # try: |
335 # try: |
336 # res = cnx.search_s(base, scope, searchstr, attrs) |
336 # res = ldapcnx.search_s(base, scope, searchstr, attrs) |
337 # except ldap.PARTIAL_RESULTS: |
337 # except ldap.PARTIAL_RESULTS: |
338 # res_type, res = cnx.result(all=0) |
338 # res_type, res = ldapcnx.result(all=0) |
339 result = [] |
339 result = [] |
340 for rec_dn, rec_dict in res: |
340 for rec_dn, rec_dict in res: |
341 # When used against Active Directory, "rec_dict" may not be |
341 # When used against Active Directory, "rec_dict" may not be |
342 # be a dictionary in some cases (instead, it can be a list) |
342 # be a dictionary in some cases (instead, it can be a list) |
343 # |
343 # |
378 member = self.group_rev_attrs['member'] |
378 member = self.group_rev_attrs['member'] |
379 if isinstance(itemdict.get(member), basestring): |
379 if isinstance(itemdict.get(member), basestring): |
380 itemdict[member] = [itemdict[member]] |
380 itemdict[member] = [itemdict[member]] |
381 return itemdict |
381 return itemdict |
382 |
382 |
383 def _process_no_such_object(self, session, dn): |
383 def _process_no_such_object(self, cnx, dn): |
384 """Some search return NO_SUCH_OBJECT error, handle this (usually because |
384 """Some search return NO_SUCH_OBJECT error, handle this (usually because |
385 an object whose dn is no more existent in ldap as been encountered). |
385 an object whose dn is no more existent in ldap as been encountered). |
386 |
386 |
387 Do nothing by default, let sub-classes handle that. |
387 Do nothing by default, let sub-classes handle that. |
388 """ |
388 """ |