def bind_search(self, username, password): """ Bind to BIND_DN/BIND_AUTH then search for user to perform lookup. """ log.debug("Performing bind/search") ctx = {'username': username, 'password': password} user = self.config['BIND_DN'] % ctx bind_auth = self.config['BIND_AUTH'] try: log.debug("Binding with the BIND_DN %s" % user) self.conn.simple_bind_s(user, bind_auth) except ldap.INVALID_CREDENTIALS: msg = "Could not connect bind with the BIND_DN=%s" % user log.debug(msg) if self._raise_errors: raise ldap.INVALID_CREDENTIALS(msg) return None user_search = self.config.get('USER_SEARCH') results = None found_user = False for search in user_search: base = search['base'] filt = search['filter'] % ctx scope = search.get('scope', ldap.SCOPE_SUBTREE) log.debug("Search for base=%s filter=%s" % (base, filt)) results = self.conn.search_s(base, scope, filt, attrlist=self.attrlist) if results: found_user = True log.debug("User with DN=%s found" % results[0][0]) try: self.conn.simple_bind_s(results[0][0], password) except ldap.INVALID_CREDENTIALS: self.conn.simple_bind_s(user, bind_auth) log.debug("Username/password mismatch, continue search...") results = None continue else: log.debug("Username/password OK") break if not results and self._raise_errors: msg = "No users found matching search criteria: {}".format( user_search) if found_user: msg = "Username/password mismatch" raise ldap.INVALID_CREDENTIALS(msg) log.debug("Unbind") self.conn.unbind_s() return self.format_results(results)
def test_that_perform_bind_return_false_when_no_wrong_credential(self, ldap_initialize): ldapobj = ldap_initialize.return_value = Mock() xivo_ldap = _XivoLDAP(self.config) ldapobj.simple_bind_s.side_effect = ldap.INVALID_CREDENTIALS() result = xivo_ldap.perform_bind('username', 'password') self.assertEqual(result, False)
def _authenticate_user(self, password): try: conn = ldap.initialize(settings.LDAP_ORIGIN) conn.simple_bind_s(self.dn, password) conn.unbind() except ldap.INVALID_CREDENTIALS as e: raise ldap.INVALID_CREDENTIALS('User ID Passed invalid credentials')
def test_authenticate_with_invalid_credentials(self): """Testing LDAPBackend.authenticate with invalid credentials""" self.spy_on(TestLDAPObject.bind_s, owner=TestLDAPObject, op=kgb.SpyOpRaise(ldap.INVALID_CREDENTIALS())) self.spy_on(TestLDAPObject.search_s, owner=TestLDAPObject, op=kgb.SpyOpReturn([ ('CN=Doc Dwarf,OU=MyOrg,DC=example,DC=COM', {}), ])) user = self.backend.authenticate(request=None, username='******', password='******') self.assertIsNone(user) self.assertSpyCalledWith( TestLDAPObject.bind_s, 'CN=Doc Dwarf,OU=MyOrg,DC=example,DC=COM', 'mypass') self.assertSpyCalledWith( TestLDAPObject.search_s, 'CN=admin,DC=example,DC=com', ldap.SCOPE_SUBTREE, '(uid=doc)')
def test_authenticate_with_invalid_credentials(self): """Testing ActiveDirectoryBackend.authenticate with invalid credentials """ self.spy_on(TestLDAPObject.simple_bind_s, owner=TestLDAPObject, op=kgb.SpyOpRaise(ldap.INVALID_CREDENTIALS())) self.spy_on(TestLDAPObject.search_s, owner=TestLDAPObject, op=kgb.SpyOpReturn([ ('CN=Test User,OU=MyOrg,DC=example,DC=com', { 'givenName': [b'Test'], 'sn': [b'User'], 'mail': [b'*****@*****.**'], }), ])) user = self.backend.authenticate(request=None, username='******', password='******') self.assertIsNone(user) self.assertSpyCalledWith(TestLDAPObject.simple_bind_s, '*****@*****.**', 'test-pass') self.assertSpyNotCalled(TestLDAPObject.search_s)
def _mock_bad_ldap_bind(exception=ldap.INVALID_CREDENTIALS( {'desc': 'Invalid Credentials'})): mock_ldap = ldap mock_initialize = ldap.initialize mock_ldap.initialize = Mock(name='ldap_init', return_value=mock_initialize) # The Python LDAP interface does not distinguish between an invalid DN (the user) and a bad password mock_initialize.simple_bind_s = Mock(name='ldap_bind', side_effect=exception) return mock_ldap, mock_initialize
def test_unsuccessful_authentication(self, mocked_ldap): mocked_ldap.return_value.simple_bind_s.side_effect = ldap.INVALID_CREDENTIALS() user = User.testing_create() authenticator = auth.LdapAuthenticator(app=flask.current_app) success = authenticator.verify_password(user, 'foo') assert mocked_ldap.call_count assert success is False
def simple_bind_s(self, who, passwd): if who not in self.users: raise ldap.NO_SUCH_OBJECT(who) user = self.users[who] pass_ = user['userPassword'][0] if not validate_password(passwd, pass_): raise ldap.INVALID_CREDENTIALS(who, passwd) self.connected = True self.who = who self.cred = passwd
def test_get_connection(self): handler = LDAPHandler() with pytest.raises(LDAPException),\ mock.patch("gosa.backend.utils.ldap.LDAPHandler.connection_usage", new_callable=mock.PropertyMock, return_value=[True]): handler.get_connection() del handler ldap_url = Environment.getInstance().config.get("ldap.url") retry_max = 3 retry_delay = 5 tls = "False" with mock.patch("gosa.backend.utils.ldap.Environment.getInstance") as m_env, \ mock.patch("gosa.backend.utils.ldap.ldap.ldapobject.ReconnectLDAPObject") as m_conn: # ldap.url, bind-user, bind-dn, bind-secret, pool-size, retry-max, retry-delay, tls m_env.return_value.config.get.side_effect = [ ldap_url, 'admin', None, 'secret', 10, retry_max, retry_delay, tls ] handler = LDAPHandler() handler.get_connection() assert m_conn.return_value.sasl_interactive_bind_s.called del handler m_env.return_value.config.get.side_effect = [ ldap_url, None, "bind-dn", 'secret', 10, retry_max, retry_delay, tls ] handler = LDAPHandler() handler.get_connection() m_conn.return_value.simple_bind_s.assert_called_with( "bind-dn", "secret") del handler m_env.return_value.config.get.side_effect = [ ldap_url, None, None, None, 10, retry_max, retry_delay, tls ] handler = LDAPHandler() handler.get_connection() m_conn.return_value.simple_bind_s.assert_called_with() del handler m_conn.reset_mock() m_env.return_value.config.get.side_effect = [ ldap_url, None, None, None, 10, retry_max, retry_delay, tls ] m_conn.return_value.simple_bind_s.side_effect = ldap.INVALID_CREDENTIALS( "test error") handler = LDAPHandler() with mock.patch.object(handler, "log") as m_log: handler.get_connection() assert m_log.error.called del handler
def _simple_bind_s(self, who='', cred=''): success = False if (who == '' and cred == ''): success = True elif self._compare_s(who.lower(), 'userPassword', cred): success = True if success: return (97, [] ) # python-ldap returns this; I don't know what it means else: raise ldap.INVALID_CREDENTIALS('%s:%s' % (who, cred))
def test_ldap_login_auth_invalid(self): user_auth = self._create_user_auth() ldap_object = self.mocker.mock() ldap_object.simple_bind_s(valid_user + '@cdk.deusto.es', invalid_passwd) self.mocker.throw(ldap.INVALID_CREDENTIALS("Invalid user/password")) ldap_module = self.mocker.mock() ldap_module.initialize('ldaps://castor.cdk.deusto.es') self.mocker.result(ldap_object) ldap_auth._ldap_provider.ldap_module = ldap_module self.mocker.replay() self.assertFalse( user_auth.authenticate(valid_user, invalid_passwd) )
def _get_ldap_connection(self, args, allow_machine_connection=False, allow_admin_connection=True): if allow_admin_connection: if ucr_get('server/role') == 'domaincontroller_master' and getuser( ) == 'root': try: return self._get_admin_connection() except ConnectionFailed: if allow_machine_connection or args is not None: # try to get another connection pass else: raise if allow_machine_connection: try: return self._get_machine_connection() except ConnectionFailed: if args is not None: # try to get another connection pass else: raise attempts = 0 if args is not None: args = deepcopy(args) while attempts < 3: attempts += 1 userdn = self._get_userdn(args) password = self._get_password(args) try: if not userdn or not password: raise ldap.INVALID_CREDENTIALS() return get_connection(userdn, password) except ldap.CONNECT_ERROR as exc: raise ConnectionFailedConnectError(exc) except ldap.SERVER_DOWN: raise ConnectionFailedServerDown() except ldap.INVALID_CREDENTIALS: time.sleep(0.1) self.warn('Invalid credentials') args.username = None self._username = None args.pwdfile = None self._password = None raise ConnectionFailedInvalidUserCredentials() raise ConnectionFailed()
async def wrapped_view(**values): if not request.authorization and not app.config['BIND_DN']: return quart.Response('Please log in', 401, UNAUTHORIZED) try: # Set up LDAP connection request.ldap = ldap.initialize(app.config['LDAP_URL']) if app.config['BIND_DN'] and app.config['BIND_PASSWORD']: dn = app.config['BIND_DN'] pw = app.config['BIND_PASSWORD'] elif app.config['BIND_PATTERN']: dn = app.config['BIND_PATTERN'] % ( request.authorization.username) pw = request.authorization.password else: # Search user in HTTP headers pw = request.authorization.password try: dn, _attrs = await unique( request.ldap.search( app.config['BASE_DN'], ldap.SCOPE_SUBTREE, '(%s=%s)' % (app.config['LOGIN_ATTR'], request.authorization.username))) except ValueError: raise ldap.INVALID_CREDENTIALS({ 'desc': 'Invalid user', 'info': "User '%s' unknown" % request.authorization.username }) # Try authenticating await empty(request.ldap.simple_bind(dn, pw)) # On success, call the view function and release connection data = await view(**values) request.ldap.unbind_s() return data except ldap.INVALID_CREDENTIALS: return quart.Response('Please log in', 401, UNAUTHORIZED) except ldap.LDAPError as err: args = err.args[0] raise HTTPException(500, args.get('info', ''), args.get('desc', ''))
def _create_ldap_connection(url, bind_dn, bind_passwd): """ Establish a new connection and do nothing with it. When we initialize this class, we keep A connection object for future reference / querying. That's the primary use. There's a public method for "hey, I'd like to authenticate a user by password" and so we have this available as a staticmethod so we can test that (and then throw away the resulting object). """ ldap.set_option(ldap.OPT_X_TLS_DEMAND, 1) if bind_passwd is None: raise ldap.INVALID_CREDENTIALS(bind_dn, ( 'You need to authenticate via password')) conn = ldap.initialize(url) conn.start_tls_s() conn.simple_bind_s(bind_dn, bind_passwd) return conn
def simple_bind_s(self, who='', cred=''): """ """ success = False try: if (who == '' and cred == ''): success = True elif self._compare_s(who, 'userPassword', cred): success = True except ldap.NO_SUCH_OBJECT: pass if success: self.bound_as = who return (97, []) else: raise ldap.INVALID_CREDENTIALS('%s:%s' % (who, cred))
def direct_bind(self, username, password): """ Bind to username/password directly """ log.debug("Performing direct bind") ctx = {'username': username, 'password': password} scope = self.config.get('SCOPE', ldap.SCOPE_SUBTREE) user = self.config['BIND_DN'] % ctx try: log.debug("Binding with the BIND_DN %s" % user) self.conn.simple_bind_s(user, password) except ldap.INVALID_CREDENTIALS: if self._raise_errors: raise ldap.INVALID_CREDENTIALS("Unable to do a direct bind with BIND_DN %s" % user) return None results = self.conn.search_s(user, scope, attrlist=self.attrlist) self.conn.unbind_s() return self.format_results(results)
def try_login(username, password): ''' Attemps to authenticate the admin with the ldap/active directory server.\n Arguments:\n :param username: Username for the admin <type:str>\n :param password: Password for the admin <type:str> ''' ad_settings = get_ad_settings() pyad.set_defaults(ldap_server=ad_settings['ldap_server'], username=ad_settings['username'], password=ad_settings['password']) u = aduser.ADUser.from_cn(username) if is_web_admin(u) or is_admin(u): dn = u.dn conn = get_ldap_connection() conn.simple_bind_s(dn, password) else: raise ldap.INVALID_CREDENTIALS( "You do not have the required privileges required to access this area." )
def try_admin_login(username, password): ''' Attempts to authenticate the user as an admin with the ldap/active directory server.\n Parameters:\n :username (str): Username for the user\n :password (str): Password for the user\n try_admin_login(`username`, `password`) -> None || Error ''' ad_settings = get_ad_settings() pyad.set_defaults(ldap_server=ad_settings['ldap_server'], username=ad_settings['username'], password=ad_settings['password']) u = aduser.ADUser.from_cn(username) if is_web_admin(u) or is_admin(u): dn = u.dn conn = get_ldap_connection() conn.simple_bind_s(dn, password) else: raise ldap.INVALID_CREDENTIALS( "You do not have the required privileges required to access this area." )
def __init__(self, user_id, password=None): self.user_id = user_id self.dn = None self.first_name = None self.last_name = None self.email = None self.password_last_set = None self.groups = [] self.connection = ldap.initialize(settings.LDAP_ORIGIN) try: self.connection.simple_bind_s(settings.LDAP_MANAGER_DN, settings.LDAP_MANAGER_PASSWORD) except ldap.INVALID_CREDENTIALS as e: raise ldap.INVALID_CREDENTIALS( 'LDAP Manager User Credentials are invalid') self._find_user() if password is not None: self._authenticate_user(password) self._set_user_attributes() self._set_user_groups() self.connection.unbind()
def __init__(self, dcs, username, password=None, basedn=None): '''Method construct. @params: (List)dcs : Domain Controller list. (String)username : username to Active Directory ldap connect (string)password : the username password (string)basedn : minimun dcs to ldap connection must be work. @return: None ''' if type(dcs) is not list: raise Exception("dcs argument is not a valid list") self.controller = None self.domainControllers = dcs self.username = username if password == None: self.password = getpass.getpass("Password: "******"Invalid Username or Password")
def test_check_auth(): ldap_url = Environment.getInstance().config.get("ldap.url") retry_max = 3 retry_delay = 5 tls = "False" with mock.patch("gosa.backend.utils.ldap.Environment.getInstance") as m_env, \ mock.patch("gosa.backend.utils.ldap.ldap.ldapobject.ReconnectLDAPObject") as m_conn: # ldap.url, bind-user, bind-dn, bind-secret, retry-max, retry-delay, tls m_env.return_value.config.get.side_effect = [ ldap_url, 'admin', None, 'secret', retry_max, retry_delay, tls ] m_conn.return_value.search_s.return_value = [('fake-dn', )] assert check_auth("admin", "tester") is True assert m_conn.return_value.sasl_interactive_bind_s.called m_env.return_value.config.get.side_effect = [ ldap_url, None, "bind-dn", 'secret', retry_max, retry_delay, tls ] m_conn.return_value.search_s.return_value = [('fake-dn', ), ('2nd-dn', )] assert check_auth("admin", "tester") is False m_conn.return_value.simple_bind_s.assert_called_with( "bind-dn", "secret") m_env.return_value.config.get.side_effect = [ ldap_url, None, None, None, retry_max, retry_delay, tls ] m_conn.return_value.search_s.return_value = [] assert check_auth("admin", "tester") is False m_conn.return_value.simple_bind_s.assert_called_with() m_env.return_value.config.get.side_effect = [ ldap_url, None, None, None, retry_max, retry_delay, tls ] m_conn.return_value.search_s.side_effect = ldap.INVALID_CREDENTIALS( "test error") assert check_auth("admin", "tester") is False m_conn.return_value.simple_bind_s.assert_called_with()
def __init__(self, ldap_config, who=None, cred=None): """ Initialize an ldap connection object and bind to the configured LDAP server. None if initialization failed. """ ldap_server = ldap_config.get('connection_url') if ldap_server is None: LOG.error('Server address is missing from the configuration') self.connection = None return referals = ldap_config.get('referals', False) ldap.set_option(ldap.OPT_REFERRALS, 1 if referals else 0) deref = ldap_config.get('deref', ldap.DEREF_ALWAYS) if deref == 'never': deref = ldap.DEREF_NEVER else: deref = ldap.DEREF_ALWAYS ldap.set_option(ldap.OPT_DEREF, deref) ldap.protocol_version = ldap.VERSION3 # Check cert if available but do not fail if not. ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW) self.connection = ldap.initialize(ldap_server, bytes_mode=False) LOG.debug('Binding to LDAP server with user: %s', who if who else '') res = None with ldap_error_handler(): if who is None or cred is None: LOG.debug("Anonymous bind with no credentials.") res = self.connection.simple_bind_s() LOG.debug(res) else: LOG.debug("Binding with credential: %s", who) res = self.connection.simple_bind_s(who, cred) whoami = self.connection.whoami_s() LOG.debug(res) LOG.debug(whoami) # mail.python.org/pipermail/python-ldap/2012q4/003180.html if whoami is None: # If LDAP server allows anonymous binds, simple bind # does not throw an exception when the password is # empty and does the binding as anonymous. # This is an expected behaviour as per LDAP RFC. # However, if the bind is successful but no # authentication has been done, it is still to be # considered an error from the user's perspective. LOG.debug("Anonymous bind succeeded but no valid " "password was given.") raise ldap.INVALID_CREDENTIALS() if not res: LOG.debug("Server bind failed.") if self.connection is not None: self.connection.unbind() self.connection = None
def bind_s(ldapo, username, password): self.assertEqual(username, 'CN=Doc Dwarf,OU=MyOrg,DC=example,DC=COM') self.assertEqual(password, 'mypass') raise ldap.INVALID_CREDENTIALS()
def test_returns_none_if_user_password_mismatch(self): self.request.registry.ldap_cm.connection \ .return_value.__enter__.side_effect = ldap.INVALID_CREDENTIALS() self.assertIsNone(self.policy.authenticated_userid(self.request))
def _simple_bind_s(who: str, cred: str) -> Tuple: if who == USER_DN_CN and cred == "jn123": return 97, [], 1, [] elif who == BIND_USER_DN_CN and cred == "bind123": return 97, [], 2, [] raise ldap.INVALID_CREDENTIALS()