On Fri, 30 Jul 2010 13:55 +0200, "Alan Franzoni" <mail...@franzoni.eu> wrote: > On 7/30/10 12:54 PM, Peter Westlake wrote: > > I'm using LDAP to authenticate users, and when I give it an empty > > password, it appears to succeed! Can anyone see what I'm doing wrong? > > I've added comments by the log messages that appear in the output. > > Please post the full code, including how you're using such class. Also:
The rest of it is below. > - log the entry you've found and that you're using to re-bind. It might > not be what you're expecting. It is, though - it's my directory entry. See the output, below. > - try the very same query using something like ldapsearch or Apache LDAP > Studio, and see whether the result differs. With ldapsearch, it fails as expected. That's a bit different to my code, though, because it only does a bind and a search. It isn't trying to re-bind using the entry it finds. LDAP Studio is a great find, thank you! And thank you for your help. Peter. Here's the test program: ----------------------------------------------------------------------- auth.py: from lda import LDAPAuthenticator import getpass from twisted.internet import reactor import log username = raw_input('Username: ') password = getpass.getpass('Password: ') def _success(entry): log.info('Successful authentication as %r' % username) return username def _failure(f): log.info('Failed authentication as %r' % username, f) raise Exception('Authentication failed') def stop(result): print 'Result', result reactor.stop() authenticator= LDAPAuthenticator( hostname=LDAP_HOST, base_dn=LDAP_ROOT, attr='sAMAccountName', bind_dn=LDAP_BIND_DN, bind_pw=LDAP_BIND_PW ) try: print 'Before authenticate' d = authenticator.authenticate(username, password) print 'Called authenticate' except Exception, e: print 'Exception was:' print e reactor.stop() d.addCallbacks(_success, _failure) d.addBoth(stop) reactor.run() -------------------------------------------------------------------------------- log.py: # Simplified log for test purposes. def info(*message): print message def debug(*message): print message def rep(e, *message): print message print 'Exception is:', e ------------------------------------------------------------------------------- The output of the program: $ python auth.py Username: peterw Password: Before authenticate ('Empty password!!!!',) Called authenticate ('Empty password',) ('Succeeded with an empty password!',) ('user_entry:',) (LDAPEntryWithClient(dn='CN=Peter Westlake,OU=....', attributes={'sAMAccountName': JournaledLDAPAttributeSet('sAMAccountName', ['peterw'])}),) ('Login:', 'peterw') ("Successful authentication as 'peterw'",) Result peterw --------------------------------------------------------------------------------- The file I posted last time, for completeness and ease of reference: lda.py: from twisted.internet import reactor, defer from ldaptor.protocols.ldap import ldapclient, ldapsyntax, ldapconnector, ldaperrors from ldaptor.protocols import pureldap as L import log class LDAPAuthenticator(object): def __init__(self, base_dn, hostname=None, attr='uid', bind_dn='', bind_pw='', filter=L.LDAPFilter_present('cn')): self.hostname = hostname self.base_dn = base_dn self.attr = attr self.bind_dn = bind_dn self.bind_pw = bind_pw self.filter = filter self.cli = None @defer.inlineCallbacks def authenticate(self, username, password): if not password: log.info('Empty password!!!!') else: log.debug('Attempting to login as', username) c = ldapconnector.LDAPClientCreator(reactor, ldapclient.LDAPClient) self.client = yield c.connect(self.base_dn) yield ldapsyntax.LDAPEntry(self.client, self.bind_dn).bind(self.bind_pw) entries = [] base = ldapsyntax.LDAPEntry(self.client, self.base_dn) yield base.search( filterObject=L.LDAPFilter_and( [L.LDAPFilter_equalityMatch( attributeDesc=L.LDAPAttributeDescription(self.attr), assertionValue=L.LDAPAssertionValue(username) ), self.filter, ]), attributes = (self.attr,), # No need to read the whole entry! callback=entries.append ) n_entries = len(entries) if n_entries == 0: self.client.unbind() log.debug('Failed login for %s: no search results' % (username,)) raise Exception('No search results!') elif n_entries > 1: self.client.unbind() log.debug('Failed login as %s: %d search results for unique entry!' % (username, n_entries)) raise Exception('%d search results for unique entry!' % n_entries) else: # The password matches if we can bind as this DN with it. try: if not password: log.info('Empty password') user_entry = yield entries[0].bind(password) if not password: log.info('Succeeded with an empty password!') log.info('user_entry:') log.info(user_entry) log.info('Login:', username) except ldaperrors.LDAPInvalidCredentials: log.info('Failed login for %s: invalid credentials' % username) raise except Exception, e: log.rep(e, 'Error while binding with user password') self.client.unbind() raise self.client.unbind() defer.returnValue(user_entry) --------END----------- _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python