Beispiel #1
0
    def search(self,
               search_filter,
               attributes=None,
               search_scope=ldap3.SUBTREE,
               raise_exc=True):
        """
        Search Active Directory using an LDAP filter.

        :param str search_filter: the LDAP search filter to use
        :kwarg list attributes: a list of LDAP attributes to search for
        :kwarg str search_scope: the LDAP search scope to use
        :kwarg bool raise_exc: raise an exception if the search yields no results
        :return: the ldap3 formatted response from Active Directory
        :rtype: list
        """
        if not self.connection.bound:
            raise ADError('You must be logged into LDAP to search')
        msg = (
            'Searching Active Directory with "{0}" and the following attributes: {1}'
            .format(search_filter, ', '.join(attributes or [])))
        self.log('debug', msg)

        try:
            search_succeeded = self.connection.search(
                self.base_dn,
                search_filter,
                search_scope=search_scope,
                attributes=attributes)
        except ldap3.core.exceptions.LDAPAttributeError:
            msg = (
                'An invalid LDAP attribute was requested when searching for "{0}" with '
                'attributes: {1}').format(search_filter, ', '.join(attributes))
            self.log('error', msg, exc_info=True)
            raise ADError(self.failed_search_error)

        if search_succeeded and self.connection.response:
            return self.connection.response

        self.log(
            'error', 'The search for "{0}" did not yield any results'.format(
                search_filter))
        if raise_exc:
            raise ADError(self.failed_search_error)
Beispiel #2
0
    def get_sam_account_name(self, guid):
        """
        Get a user's distinguished name from their GUID.

        :param str guid: the GUID of the user to search for
        :return: the user's sAMAccountNmae
        :rtype: str
        """
        search_filter = '(&(objectClass=user)(objectGUID={0}))'.format(guid)
        results = self.search(search_filter, ['sAMAccountName'])

        if 'attributes' in results[0]:
            return results[0]['attributes']['sAMAccountName']
        else:
            self.log(
                'error',
                'The user with the GUID {0} couldn\'t be found in Active Directory'
                .format(guid))
            raise ADError('The user couldn\'t be found in Active Directory')
Beispiel #3
0
    def login(self, username, password):
        """
        Login to Active Directory.

        :param str username: the Active Directory username
        :param str password: the Active Directory password
        """
        if self.connection.bound:
            msg = 'The login method was called but the connection is already bound. Will reconnect.'
            self.log('debug', msg)
            self.connection.unbind()
            self.connection.open()

        domain = self._get_config('AD_DOMAIN')
        if '@' in username or '\\' in username or 'CN=' in username:
            self.connection.user = username
        else:
            if self.connection.authentication == ldap3.NTLM:
                self.connection.user = '******'.format(domain, username)
            else:
                self.connection.user = '******'.format(username, domain)
        self.connection.password = password

        svc_account = self._get_config('AD_SERVICE_USERNAME') == username
        if not self.connection.bind():
            if svc_account:
                self.log('error', 'The service account failed to login')
                raise ADError(self.unknown_error_msg)
            else:
                self.log(
                    'info', 'The user "{0}" failed to login'.format(
                        self.connection.user))
                raise Unauthorized(
                    'The username or password is incorrect. Please try again.')
        else:
            if svc_account:
                self.log('info', 'The service account logged in successfully')
            else:
                self.log('info', 'The user logged in successfully')
Beispiel #4
0
    def connection(self):
        """
        Return an unauthenticated LDAP connection to Active Directory.

        :return: an LDAP connection to Active Directory
        :rtype: ldap3.Connection
        """
        if self._connection:
            return self._connection

        ldap_url = self._get_config('AD_LDAP_URI')
        server = ldap3.Server(ldap_url,
                              allowed_referral_hosts=[('*', False)],
                              connect_timeout=3)
        self._connection = ldap3.Connection(server)

        if self._get_config('AD_USE_NTLM', raise_exc=False):
            msg = 'Configuring the Active Directory connection to use NTLM authentication'
            self.log('debug', msg)
            self._connection.authentication = ldap3.NTLM
        else:
            msg = 'Configuring the Active Directory connection to use SIMPLE authentication'
            self.log('debug', msg)
            self._connection.authentication = ldap3.SIMPLE

        try:
            msg = 'Connecting to Active Directory with the URL "{0}"'.format(
                ldap_url)
            self.log('debug', msg)
            self._connection.open()
        except LDAPSocketOpenError:
            msg = 'The connection to Active Directory with the URL "{0}" failed'.format(
                ldap_url)
            self.log('error', msg, exc_info=True)
            raise ADError(
                'The connection to Active Directory failed. Please try again.')

        return self._connection
Beispiel #5
0
    def get_loggedin_user(self, raise_exc=True):
        """
        Get the logged in user's username.

        :kwarg bool raise_exc: raise an exception if the connection isn't bound
        :return: a the logged in user's user name
        :rtype: str
        """
        if self.connection.bound:
            user = self.connection.extend.standard.who_am_i()
            if not self._get_config('TESTING', raise_exc=False):
                # AD returns the username as DOMAIN\username, so this gets the sAMAccountName
                return user.split('\\')[-1]
            else:
                # We are using ldap3's mocking, which returns the distinguished name, so derive the
                # sAMAccountName from that
                return user.split('CN=')[-1].split(',')[0]

        elif raise_exc:
            self.log(
                'error',
                'You must be logged in to get the logged in user\'s username')
            raise ADError(self.unknown_error_msg)