Ejemplo n.º 1
0
 def test_simple_search(self):
     dn = 'uid=hugo,cn=users,dc=test,dc=local'
     server, client = self.create_server_and_client(
         [
             pureldap.LDAPBindResponse(resultCode=0),  # for service account
         ],
         [
             pureldap.LDAPSearchResultEntry(dn,
                                            [('someattr', ['somevalue'])]),
             pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
         ])
     yield client.bind(dn, 'secret')
     # Assert that Proxy<->Backend uses the correct credentials
     server.client.assertSent(
         pureldap.LDAPBindRequest(
             dn='uid=service,cn=users,dc=test,dc=local',
             auth='service-secret'), )
     # Perform a simple search in the context of the service account
     entry = LDAPEntry(client, dn)
     results = yield entry.search('(objectClass=*)',
                                  scope=pureldap.LDAP_SCOPE_baseObject)
     self.assertEqual(len(results), 1)
     self.assertEqual(len(results[0]['someattr']), 1)
     (value, ) = results[0]['someattr']
     self.assertEqual(value, 'somevalue')
Ejemplo n.º 2
0
 def test_realm_mapping_fails_wrong_password(self):
     marker = 'markerSecret'
     realm = 'realmSecret'
     password = '******'  # this is the wrong password!
     service_dn = 'uid=passthrough,cn=users,dc=test,dc=local'
     dn = 'uid=hugo,cn=users,dc=test,dc=local'
     server, client = self.create_server_and_client(
         [
             pureldap.LDAPBindResponse(resultCode=0),  # for service account
         ],
         [
             pureldap.LDAPSearchResultEntry(dn,
                                            [('someattr', ['somevalue'])]),
             pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
         ])
     yield client.bind(service_dn, 'service-secret')
     # Assert that Proxy<->Backend uses the correct credentials
     server.client.assertSent(
         pureldap.LDAPBindRequest(dn=service_dn, auth='service-secret'), )
     # Perform a simple search in the context of the service account
     entry = LDAPEntry(client, dn)
     r = yield entry.search('(|(objectClass=*)(objectclass=App-%s))' %
                            marker,
                            scope=pureldap.LDAP_SCOPE_baseObject)
     # sleep a second and then try to bind as hugo
     time.sleep(0.5)
     server2, client2 = self.create_server_and_client([
         pureldap.LDAPBindResponse(
             resultCode=0),  # for service account (successful hugo bind)
     ])
     d = client2.bind(dn, password)
     yield self.assertFailure(d, ldaperrors.LDAPInvalidCredentials)
     self.assertEqual(self.privacyidea.authentication_requests,
                      [('hugo', realm, password, False)])
     time.sleep(1)  # to clean the reactor
Ejemplo n.º 3
0
 def perform_search(self,
                    dn,
                    filter_object,
                    attributes=(),
                    sizeLimit=0,
                    scope=None):
     """
     Args:
         dn (str): The base DN for the search to start at
         filter_object (LDAPFilterSet): Filter to qualify the search against
         attributes (tuple): Attriutes to get back. Default of empty set means all. `None` gives no attrs
         sizeLimit (int): Number of results to return. 0 means no limit
         scope (int): One of
             LDAP_SCOPE_baseObject = 0
             LDAP_SCOPE_singleLevel = 1
             LDAP_SCOPE_wholeSubtree = 2
     """
     entry = LDAPEntry(self, dn)
     result = yield entry.search(
         filterObject=filter_object,
         attributes=attributes,
         sizeLimit=sizeLimit,
         scope=scope,
     )
     defer.returnValue(result)
Ejemplo n.º 4
0
 def test_realm_mapping_succeeds_case_sensitive(self):
     marker = 'markerSecret'
     password = '******'
     service_dn = 'uid=passthrough,cn=users,dc=test,dc=local'
     dn = 'uid=Hugo,cn=users,dc=test,DC=LOCAL'
     server, client = self.create_server_and_client(
         [
             pureldap.LDAPBindResponse(resultCode=0),  # for service account
         ],
         [
             pureldap.LDAPSearchResultEntry(dn,
                                            [('someattr', ['somevalue'])]),
             pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
         ])
     yield client.bind(service_dn, 'service-secret')
     # Assert that Proxy<->Backend uses the correct credentials
     server.client.assertSent(
         pureldap.LDAPBindRequest(dn=service_dn, auth='service-secret'), )
     # Perform a simple search in the context of the service account
     entry = LDAPEntry(client, dn)
     r = yield entry.search('(|(objectClass=*)(objectclass=App-%s))' %
                            marker,
                            scope=pureldap.LDAP_SCOPE_baseObject)
     # sleep half a second and then try to bind as hugo
     time.sleep(0.5)
     server2, client2 = self.create_server_and_client([
         pureldap.LDAPBindResponse(
             resultCode=0),  # for service account (successful hugo bind)
     ])
     yield client2.bind(
         dn.lower(),
         password)  # this will work even though the DN has differing case
     self.assertEqual(self.privacyidea.authentication_requests,
                      [('hugo', 'realmSecret', password, True)])
     time.sleep(1)  # to clean the reactor
Ejemplo n.º 5
0
 def resolve(self, dn):
     """
     Given a distinguished name, return the login name to be used with privacyIDEA
     :param dn: distinguished name as string
     :return: Deferred that fires the login name
     """
     # Perform a LDAP bind, search for an object with the distinguished name *dn*
     client = yield self.factory.connect_service_account()
     entry = LDAPEntry(client, dn)
     try:
         results = yield entry.search('(objectClass=*)',
                                      scope=pureldap.LDAP_SCOPE_baseObject)
         # Assuming we found one, extract the login name attribute
         assert len(results) == 1
         if self.attribute not in results[0]:
             log.warn('Unknown lookup attribute: {attribute}',
                      attribute=self.attribute)
             raise UserMappingError(dn)
         login_name_set = results[0][self.attribute]
         assert len(login_name_set) == 1
         (login_name, ) = login_name_set
         defer.returnValue(login_name)
     except ldaperrors.LDAPNoSuchObject, e:
         # Apparently, the user could not be found. Raise the appropriate exception.
         raise UserMappingError(dn)
Ejemplo n.º 6
0
 def perform_search(self,
                    dn,
                    filter_object,
                    attributes=(),
                    sizeLimit=0,
                    scope=None):
     """
     Args:
         dn (str): The base DN for the search to start at
         filter_object (LDAPFilterSet): Filter to qualify the search against
         attributes (tuple): Attriutes to get back. Default of empty set means all. `None` gives no attrs
         sizeLimit (int): Number of results to return. 0 means no limit
         scope (int): One of
             LDAP_SCOPE_baseObject = 0
             LDAP_SCOPE_singleLevel = 1
             LDAP_SCOPE_wholeSubtree = 2
     """
     entry = LDAPEntry(self, dn)
     try:
         result = yield entry.search(
             filterObject=filter_object,
             attributes=attributes,
             sizeLimit=sizeLimit,
             scope=scope,
         )
     except ldaperrors.LDAPOperationsError as e:
         if e.message.decode().startswith(
                 const.LDAP_SUCCESSFUL_BIND_NEEDED_ERROR):
             log.failure("LDAP search failed")
             raise ConnectionNotProperlyBoundError(
                 "Search failed because either there was no bind on this connection or there were insufficient privileges with the bound user. If you are attempting to use integrated authentication with SSPI please make sure the server running the Authentication Proxy is domain joined."
             )
         else:
             raise e
     defer.returnValue(result)
 def test_passthrough_account_search_fails(self):
     server, client = self.create_server_and_client(
         [pureldap.LDAPBindResponse(resultCode=0)])
     yield client.bind('uid=passthrough,cn=users,dc=test,dc=local',
                       'some-secret')
     entry = LDAPEntry(client, 'cn=users,dc=test,dc=local')
     d = entry.search('(objectClass=*)',
                      scope=pureldap.LDAP_SCOPE_wholeSubtree)
     yield self.assertFailure(d, ldaperrors.LDAPInsufficientAccessRights)
Ejemplo n.º 8
0
    def isAuthenticated(self, result):
        base = LDAPEntry(self.client, self.basedn)
        d = base.search(filterText=self.query, attributes=('*', '+'))

        base_ops = LDAPEntry(self.client, self.basedn_ops)
        d_ops = base.search(filterText=self.query_ops, attributes=('*', '+'))

        d.addCallback(self.gotResults)

        d_ops.addCallback(self.gotResultsOperations)
def request_page_(client, basedn, page_size=100, cookie='', **search_kwds):
    control_value = pureber.BERSequence([
        pureber.BERInteger(page_size),
        pureber.BEROctetString(cookie),
    ])
    controls = [('1.2.840.113556.1.4.319', None, control_value)]
    search_kwds['controls'] = controls
    search_kwds['return_controls'] = True
    o = LDAPEntry(client, basedn)
    results, resp_controls = yield o.search(**search_kwds)
    cookie = get_paged_search_cookie_(resp_controls)
    defer.returnValue((results, cookie))
Ejemplo n.º 10
0
    def dn_to_username(self, dn_str: str, client_factory):
        """
        Return a username usable for Duo auth.

        The return value may include a domain. If necessary, that must
        be handled with a domain username normalization policy on the
        Duo integration.
        Args:
            dn_str: (str)
            client_factory (ADClientFactory)
        Returns:
            str: The username we want to send to Duo
            None: If we could not determine the username to send
        """
        try:
            dn = DistinguishedName(dn_str)
        except Exception:
            # At this point we think the DN is actually in a username format
            # but we'll need some extra searches to verify for sure.
            # This is technically not legal LDAP to do this, but Active Directory
            # supports it so we must as well.
            possible_username = utilities.LdapUsername(
                dn_str, LdapUsernameOrigin.BIND_DN)
            try:
                _ = yield self.validate_ldap_username_for_auth(
                    possible_username, client_factory.search_dn)
            except NoUserFound as e:
                log.msg(str(e))
                defer.returnValue(None)
            else:
                # If our validate call didn't throw an exception that means our "DN" was a valid username
                # and we can just return that for usage with our call to Duo
                defer.returnValue(dn_str)

        entry = LDAPEntry(self, dn)
        user_filter = yield self.user_filter_object()
        result = yield entry.search(
            filterObject=user_filter,
            attributes=(self.factory.username_attribute, ),
        )

        if len(result) != 1:
            defer.returnValue(None)

        attr_set = result[0].get(self.factory.username_attribute)

        if not attr_set:
            defer.returnValue(None)

        defer.returnValue(list(attr_set)[0].decode())
Ejemplo n.º 11
0
def process_entry(client, args, search_filter, page_size=100, cookie=''):
    basedn = args.base_dn
    control_value = pureber.BERSequence([
        pureber.BERInteger(page_size),
        pureber.BEROctetString(cookie),
    ])
    controls = [('1.2.840.113556.1.4.319', None, control_value)]
    o = LDAPEntry(client, basedn)
    results, resp_controls = yield o.search(filterText=search_filter,
                                            attributes=['dn'],
                                            controls=controls,
                                            return_controls=True)
    cookie = get_paged_search_cookie(resp_controls)
    defer.returnValue((results, cookie))
Ejemplo n.º 12
0
def process_entry(client, args, search_filter, page_size=100, cookie=''):
    basedn = args.base_dn
    control_value = pureber.BERSequence([
        pureber.BERInteger(page_size),
        pureber.BEROctetString(cookie),
    ])
    controls = [('1.2.840.113556.1.4.319', None, control_value)]
    o = LDAPEntry(client, basedn)
    results, resp_controls  = yield o.search(
        filterText=search_filter,
        attributes=['dn'],
        controls=controls,
        return_controls=True)
    cookie = get_paged_search_cookie(resp_controls)
    defer.returnValue((results, cookie))
Ejemplo n.º 13
0
 def test_user_search_fails(self):
     dn = 'uid=hugo,cn=users,dc=test,dc=local'
     server, client = self.create_server_and_client([
         # TODO: Would the backend actually answer like that?
         pureldap.LDAPSearchResultDone(
             ldaperrors.LDAPInsufficientAccessRights.resultCode),
     ])
     yield client.bind(dn, 'secret')
     # Assert that there was no traffic between Proxy<->Backend
     server.client.assertNothingSent()
     # Try to perform a simple search in the context of the service account
     entry = LDAPEntry(client, dn)
     d = entry.search('(objectClass=*)',
                      scope=pureldap.LDAP_SCOPE_baseObject)
     yield self.assertFailure(d, ldaperrors.LDAPInsufficientAccessRights)
Ejemplo n.º 14
0
def onConnect(client):
    # The following arguments may be also specified as unicode strings
    # but it is recommended to use byte strings for ldaptor objects
    basedn = b"dc=ldap,dc=com"
    binddn = b"cn=ldap,ou=user,dc=ldap,dc=com"
    bindpw = b"123456"
    query = b"(cn=test)"
    try:
        yield client.bind(binddn, bindpw)
    except Exception as ex:
        print(ex)
        raise
    o = LDAPEntry(client, basedn)
    results = yield o.search(filterText=query)
    for entry in results:
        print(entry.getLDIF())
def onConnect(client):
    # The following arguments may be also specified as unicode strings
    # but it is recommended to use byte strings for ldaptor objects
    basedn = b'dc=example,dc=org'
    binddn = b'cn=bob,ou=people,dc=example,dc=org'
    bindpw = b'secret'
    query = b'(cn=bob)'
    try:
        yield client.bind(binddn, bindpw)
    except Exception as ex:
        print(ex)
        raise
    o = LDAPEntry(client, basedn)
    results = yield o.search(filterText=query)
    for entry in results:
        print(entry.getLDIF())
Ejemplo n.º 16
0
def transform_result(
    result: LDAPEntry,
    desired_attributes: List[str],
    value_transform: Callable[[LDAPAttribute], str] = encoding_transform,
):
    """
    Turn an LDAPEntry result into a dictionary of attribute values.

    Args:
        result (LDAPEntry): an LDAPEntry
        desired_attributes (list): The desired attributes
        value_transform (func): a per-value transform function to apply

    Returns:
        A dict of {attribute name: [list of attribute values]} for the requested attributes
    """
    result_dict = {}
    for att in desired_attributes:
        attset = result.get(att, [])
        transformed_values = set()
        for val in list(attset):
            transformed_values.add(value_transform(val))
        result_dict[att] = list(transformed_values)

    result_dict.pop("userpassword", None)

    return result_dict
 def test_ignores_search_result_reference(self):
     dn = 'uid=hugo,cn=users,dc=test,dc=local'
     server, client = self.create_server_and_client(
         [pureldap.LDAPBindResponse(resultCode=0)],
         [
             pureldap.LDAPSearchResultEntry(dn,
                                            [('someattr', ['somevalue'])]),
             pureldap.LDAPSearchResultReference(
             ),  # NOTE: ldaptor does not really support these
             pureldap.LDAPSearchResultReference(),
             pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
         ])
     yield client.bind('uid=passthrough,cn=users,dc=test,dc=local',
                       'some-secret')
     entry = LDAPEntry(client, 'cn=users,dc=test,dc=local')
     r = yield entry.search('(objectClass=*)',
                            scope=pureldap.LDAP_SCOPE_wholeSubtree)
     self.assertEqual(len(r), 1)
     self.assertEqual(r[0].dn, dn)
 def test_state_reset(self):
     # Passthrough Bind, User Bind
     dn = 'uid=hugo,cn=users,dc=test,dc=local'
     search_response = pureldap.LDAPSearchResultEntry(
         dn, [('someattr', ['somevalue'])])
     server, client = self.create_server_and_client(
         [pureldap.LDAPBindResponse(resultCode=0)], [
             search_response,
             pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
         ], [pureldap.LDAPBindResponse(resultCode=0)])
     yield client.bind('uid=passthrough,cn=users,dc=test,dc=local',
                       'some-secret')
     server.client.assertSent(
         pureldap.LDAPBindRequest(
             dn='uid=passthrough,cn=users,dc=test,dc=local',
             auth='some-secret'), )
     # perform a search
     entry = LDAPEntry(client, dn)
     r = yield entry.search(
         '(|(objectClass=*)(objectcLAsS=App-markerSecret))',
         scope=pureldap.LDAP_SCOPE_baseObject)
     # check that the state is correct
     self.assertTrue(server.received_bind_request)
     self.assertTrue(server.forwarded_passthrough_bind)
     self.assertEqual(server.search_response_entries, 0)
     self.assertIsNone(server.last_search_response_entry)
     yield client.bind(dn, 'secret')
     self.assertEqual(len(server.client.sent), 2)
     # Check that the bind requests was sent properly
     self.assertEqual(
         server.client.sent[0],
         pureldap.LDAPBindRequest(
             dn='uid=passthrough,cn=users,dc=test,dc=local',
             auth='some-secret'))
     # check that state is properly reset
     self.assertTrue(server.received_bind_request)
     self.assertFalse(server.forwarded_passthrough_bind)
     self.assertEqual(server.search_response_entries, 0)
     self.assertIsNone(server.last_search_response_entry)
Ejemplo n.º 19
0
 def test_user_search_fails(self):
     dn = 'uid=hugo,cn=users,dc=test,dc=local'
     server, client = self.create_server_and_client(
         [
             pureldap.LDAPBindResponse(resultCode=0),  # for service account
         ],
         [
             pureldap.LDAPSearchResultEntry(dn,
                                            [('someattr', ['somevalue'])]),
             pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
         ])
     yield client.bind(dn, 'secret')
     # Assert that Proxy<->Backend uses the correct credentials
     server.client.assertSent(
         pureldap.LDAPBindRequest(
             dn='uid=service,cn=users,dc=test,dc=local',
             auth='service-secret'), )
     # Try to perform a simple search in the context of the service account
     entry = LDAPEntry(client, dn)
     d = entry.search('(objectClass=*)',
                      scope=pureldap.LDAP_SCOPE_baseObject)
     yield self.assertFailure(d, ldaperrors.LDAPInsufficientAccessRights)
Ejemplo n.º 20
0
 def test_realm_mapping_fails_fake_search_by_user(self):
     service_dn = 'uid=passthrough,cn=users,dc=test,dc=local'
     dn = 'uid=hugo,cn=users,dc=test,dc=local'
     server, client = self.create_server_and_client(
         [
             pureldap.LDAPBindResponse(resultCode=0),  # for service account
         ],
         [
             pureldap.LDAPSearchResultEntry(dn,
                                            [('someattr', ['somevalue'])]),
             pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
         ])
     yield client.bind(service_dn, 'service-secret')
     # Assert that Proxy<->Backend uses the correct credentials
     server.client.assertSent(
         pureldap.LDAPBindRequest(dn=service_dn, auth='service-secret'), )
     # Perform a simple search in the context of the service account
     entry = LDAPEntry(client, dn)
     r = yield entry.search(
         '(|(objectClass=*)(objectcLAsS=App-markerSecret))',
         scope=pureldap.LDAP_SCOPE_baseObject)
     # sleep half a second and then try to bind as hugo
     time.sleep(0.5)
     server2, client2 = self.create_server_and_client(
         [
             pureldap.LDAPBindResponse(
                 resultCode=0
             ),  # for service account (successful hugo bind)
         ],
         [
             pureldap.LDAPSearchResultEntry(
                 dn, [('someattr', ['somevalue'])]),  # hugo's search
             pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
         ])
     yield client2.bind(dn, 'secret')
     self.assertEqual(self.privacyidea.authentication_requests,
                      [('hugo', 'realmSecret', 'secret', True)])
     # Perform another search in hugo's context
     entry2 = LDAPEntry(client2, dn)
     r = yield entry2.search(
         '(|(objectClass=*)(objectcLAsS=App-markerOfficial))',
         scope=pureldap.LDAP_SCOPE_baseObject)
     self.assertTrue(
         server.factory.app_cache.get_cached_marker(dn) in ('markerSecret',
                                                            None))
     time.sleep(1)  # to clean the reactor
Ejemplo n.º 21
0
def onConnect(clientProtocol):
    o = LDAPEntry(clientProtocol, "dc=fr")
    results = yield o.search()
    data = "".join([result.getLDIF() for result in results])
    log.msg(f"LDIF formatted results:\n{data}")
Ejemplo n.º 22
0
 def _cb(client, baseDN):
     e = LDAPEntry(client=client, dn=baseDN)
     return e
Ejemplo n.º 23
0
def onConnect(clientProtocol):
    o = LDAPEntry(clientProtocol, "dc=fr")
    results = yield o.search()
    data = u"".join([result.getLDIF() for result in results])
    log.msg(u"LDIF formatted results:\n{}".format(data))