Esempio n. 1
0
def getuserdata(login):
    server = LDAP_SERVER  # getInfo=GET_ALL_INFO
    attributes = ['uid', 'distinguishedName', 'cn',
                  'mail', 'telephoneNumber',
                  'department', 'gidNumber', 'uidNumber']
    # basedn = 'OU=Accounts,DC=nrel,DC=gov'
    basedn = 'DC=nrel,DC=gov'
    search_filter = '(uid=%s)' % login
    # define a synchronous connection with basic authentication

    conn = Connection(server, auto_bind=True,
                      client_strategy=STRATEGY_ASYNC_THREADED,
                      user=LDAP_USER, password=LDAP_PASS,
                      authentication=AUTH_SIMPLE)
    ##client_strategy=STRATEGY_SYNC

    #conn.tls = tls()
    #conn.start_tls()

    result = conn.search(basedn, search_filter=search_filter,
                         search_scope=SEARCH_SCOPE_WHOLE_SUBTREE,
                         attributes=attributes )
    conn.get_response(result, timeout=10)
    data = conn.response

    # Check if a dict was returned,
    # meaning loginID is in LDAP and password works.
    if not data:
        return False

    # User has passed LDAP auth...
    # Finally, return the user's attribs.
    dn = data[0]['attributes']
    return dn
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(test_server, test_port, allowed_referral_hosts=('*', True))
        self.connection = Connection(server, auto_bind=True, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=False, pool_name='pool1')

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    def test_modify(self):
        attribute1 = Attribute()
        vals1 = ValsAtLeast1()
        vals1[0] = AttributeValue('tost')
        attribute1['type'] = AttributeDescription('sn')
        attribute1['vals'] = vals1

        attribute2 = Attribute()
        vals2 = ValsAtLeast1()
        vals2[0] = AttributeValue('tust')
        attribute2['type'] = AttributeDescription('givenName')
        attribute2['vals'] = vals2

        attribute3 = Attribute()
        vals3 = ValsAtLeast1()
        vals3[0] = AttributeValue('inetOrgPerson')
        attribute3['type'] = AttributeDescription('objectClass')
        attribute3['vals'] = vals3

        attributes = AttributeList()
        attributes[0] = attribute1
        attributes[1] = attribute2
        attributes[2] = attribute3

        add_req = AddRequest()
        add_req['entry'] = LDAPDN(dn_for_test(test_base, 'test-modify'))
        add_req['attributes'] = attributes

        result = self.connection.post_send_single_response(self.connection.send('addRequest', add_req))
        if not isinstance(result, bool):
            self.connection.get_response(result)
        vals_mod1 = Vals()
        vals_mod1[0] = 'test-modified'
        part_attr1 = PartialAttribute()
        part_attr1['type'] = AttributeDescription('sn')
        part_attr1['vals'] = vals_mod1
        change1 = Change()
        change1['operation'] = Operation('replace')
        change1['modification'] = part_attr1
        changes = Changes()
        changes[0] = change1
        modify_req = ModifyRequest()
        modify_req['object'] = LDAPDN(dn_for_test(test_base, 'test-modify'))
        modify_req['changes'] = changes
        result = self.connection.post_send_single_response(self.connection.send('modifyRequest', modify_req))
        if not isinstance(result, bool):
            self.connection.get_response(result)
        self.assertTrue(True)
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(test_server, test_port, allowed_referral_hosts=('*', True))
        self.connection = Connection(server, auto_bind=True, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=False, pool_name='pool1')

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()

    def test_compare(self):
        attribute1 = Attribute()
        vals1 = ValsAtLeast1()
        vals1[0] = AttributeValue('tost')
        attribute1['type'] = AttributeDescription('sn')
        attribute1['vals'] = vals1

        attribute2 = Attribute()
        vals2 = ValsAtLeast1()
        vals2[0] = AttributeValue('tust')
        attribute2['type'] = AttributeDescription('givenName')
        attribute2['vals'] = vals2

        attribute3 = Attribute()
        vals3 = ValsAtLeast1()
        vals3[0] = AttributeValue('inetOrgPerson')
        attribute3['type'] = AttributeDescription('objectClass')
        attribute3['vals'] = vals3

        attributes = AttributeList()
        attributes[0] = attribute1
        attributes[1] = attribute2
        attributes[2] = attribute3

        add_req = AddRequest()
        add_req['entry'] = LDAPDN(dn_for_test(test_base, 'test-compare'))
        add_req['attributes'] = attributes

        result = self.connection.post_send_single_response(self.connection.send('addRequest', add_req))
        if not isinstance(result, bool):
            self.connection.get_response(result)

        ava = AttributeValueAssertion()
        ava['attributeDesc'] = AttributeDescription('givenName')
        ava['assertionValue'] = AssertionValue('tust')
        compare_req = CompareRequest()
        compare_req['entry'] = LDAPDN(dn_for_test(test_base, 'test-compare'))
        compare_req['ava'] = ava

        result = self.connection.post_send_single_response(self.connection.send('compareRequest', compare_req))
        if not isinstance(result, bool):
            self.connection.get_response(result)
        self.assertTrue(True)
Esempio n. 4
0
    def test_raise_exceptions(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True), get_info=test_get_info)
        connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1', check_names=test_check_names, raise_exceptions=True)
        ok = False
        try:
            result = connection.search('xxx=xxx', '(cn=*)')
            if not isinstance(result, bool):
                connection.get_response(result)
        except LDAPNoSuchObjectResult:
            ok = True

        self.assertTrue(ok)
Esempio n. 5
0
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True))
        self.connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1')

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    def test_get_replica_list_extension(self):
        result = self.connection.extended('2.16.840.1.113719.1.27.100.19', 'cn=server')
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        print(result['description'])
        self.assertTrue(result['description'] in ['success', 'noSuchObject'])

    def test_who_am_i_extension(self):
        result = self.connection.extended('1.3.6.1.4.1.4203.1.11.3')
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'protocolError'])

    def test_get_bind_dn_extension(self):
        result = self.connection.extended('2.16.840.1.113719.1.27.100.31')
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success'])

    def test_start_tls_extension(self):
        self.connection.server.tls = Tls()
        result = self.connection.extended('1.3.6.1.4.1.1466.20037')
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success'])
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(test_server, test_port)
        self.connection = Connection(server, auto_bind=True, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, pool_name='pool1')

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()

    def test_bind(self):
        bind_req = BindRequest()
        bind_req['version'] = Version(3)
        bind_req['name'] = LDAPDN(test_user)
        bind_req['authentication'] = AuthenticationChoice().setComponentByName('simple', Simple(test_password))
        result = self.connection.post_send_single_response(self.connection.send('bindRequest', bind_req))
        if not isinstance(result, bool):
            self.connection.get_response(result)
        self.assertTrue(True)
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True))
        self.connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1')
        result = self.connection.add(dn_for_test(test_base, 'test-add-for-delete'), [], {'objectClass': 'iNetOrgPerson', 'sn': 'test-add'})
        if not isinstance(result, bool):
            self.connection.get_response(result)

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    def test_delete(self):
        result = self.connection.delete(dn_for_test(test_base, 'test-add-for-delete'))
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'noSuchObject'])
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True), get_info=test_get_info)
        self.connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1', check_names=test_check_names)
        result = self.connection.delete(dn_for_test(test_base, 'test-add-operation'))
        if not isinstance(result, bool):
            self.connection.get_response(result)

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    @pytest.mark.skipif(True,  reason="needs rework")
    def test_add(self):
        result = self.connection.add(dn_for_test(test_base, 'test-add-operation'), 'iNetOrgPerson', {'objectClass': 'iNetOrgPerson', 'sn': 'test-add', test_name_attr: 'test-add-operation'})
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result

        self.assertTrue(result['description'] in ['success', 'entryAlreadyExists'])
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True))
        self.connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1')
        result = self.connection.add(dn_for_test(test_base, 'test-ldif-1'), 'iNetOrgPerson', {'objectClass': 'iNetOrgPerson', 'sn': 'test-ldif-1', test_name_attr: 'test-ldif-1'})
        if not isinstance(result, bool):
            self.connection.get_response(result)
        result = self.connection.add(dn_for_test(test_base, 'test-ldif-2'), 'iNetOrgPerson', {'objectClass': 'iNetOrgPerson', 'sn': 'test-ldif-2', test_name_attr: 'test-ldif-2'})
        if not isinstance(result, bool):
            self.connection.get_response(result)

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    def test_single_search_result_to_ldif(self):
        result = self.connection.search(search_base=test_base, search_filter='(' + test_name_attr + '=test-ldif-1)', attributes=[test_name_attr, 'givenName', 'jpegPhoto', 'sn', 'cn', 'objectClass'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result

        l = self.connection.response_to_ldif(response)
        self.assertTrue('version: 1' in l)
        self.assertTrue('dn: cn=test-ldif-1,o=test' in l)
        self.assertTrue('objectClass: inetOrgPerson' in l)
        self.assertTrue('objectClass: Top' in l)
        self.assertTrue('cn: test-ldif-1' in l)
        self.assertTrue('sn: test-ldif-1' in l)
        self.assertTrue('total number of entries: 1' in l)

    def test_multiple_search_result_to_ldif(self):
        result = self.connection.search(search_base=test_base, search_filter='(sn=test-ldif*)', attributes=[test_name_attr, 'givenName', 'sn', 'objectClass'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        l = self.connection.response_to_ldif(response)
        self.assertTrue('version: 1' in l)
        self.assertTrue('dn: cn=test-ldif-1,o=test' in l)
        self.assertTrue('objectClass: inetOrgPerson' in l)
        self.assertTrue('objectClass: Top' in l)
        self.assertTrue('cn: test-ldif-1' in l)
        self.assertTrue('sn: test-ldif-1' in l)
        self.assertTrue('dn: cn=test-ldif-2,o=test' in l)
        self.assertTrue('cn: test-ldif-2' in l)
        self.assertTrue('sn: test-ldif-2' in l)
        self.assertTrue('total number of entries: 2' in l)
Esempio n. 10
0
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True))
        self.connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1')

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    def test_search_with_controls(self):
        controls = list()
        controls.append(('2.16.840.1.113719.1.27.103.7', True, 'givenName'))
        result = self.connection.search(test_base, '(objectClass=*)', attributes=['sn, givenName'], size_limit=0, controls=controls)
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'operationsError'])
Esempio n. 11
0
class Test(unittest.TestCase):
    def setUp(self):
        self.connection = Connection(server=None, client_strategy=LDIF)
        self.connection.open()

    def tearDown(self):
        self.connection.unbind()
        self.assertFalse(self.connection.bound)

    def test_add_request_to_ldif(self):
        controls = list()
        controls.append(('2.16.840.1.113719.1.27.103.7', True, 'givenName'))
        controls.append(('2.16.840.1.113719.1.27.103.7', False, 'sn'))
        if str != bytes:  # python3
            controls.append(('2.16.840.1.113719.1.27.103.7', False, bytearray('\u00e0\u00e0', encoding='UTF-8')))
        else:
            controls.append(('2.16.840.1.113719.1.27.103.7', False, bytearray(unicode('\xe0\xe0', encoding='latin1'), encoding='UTF-8')))  # for python2 compatability
        controls.append(('2.16.840.1.113719.1.27.103.7', False, 'trailingspace '))
        self.connection.add(generate_dn(test_base, testcase_id, 'ldif-change-1'), 'iNetOrgPerson', {'objectClass': 'iNetOrgPerson', 'sn': 'ldif-change-1', test_name_attr: 'ldif-change-1'}, controls=controls)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-1,' + test_base in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 true: givenName' in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 false: sn' in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 false:: w6DDoA==' in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 false:: dHJhaWxpbmdzcGFjZSA=' in response)
        self.assertTrue('changetype: add' in response)
        self.assertTrue('objectClass: iNetOrgPerson' in response)
        self.assertTrue('sn: ldif-change-1' in response)
        self.assertTrue(test_name_attr + ': ldif-change-1' in response)

    def test_delete_request_to_ldif(self):
        self.connection.strategy.order = dict(delRequest=['dn:', 'changetype', 'vers'])
        self.connection.delete(generate_dn(test_base, testcase_id, 'ldif-change-2'))
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-2,' + test_base in response)
        self.assertTrue('changetype: delete' in response)

    def test_modify_dn_request_to_ldif(self):
        result = self.connection.modify_dn(generate_dn(test_base, testcase_id, 'ldif-change-3'), test_name_attr + '=' + testcase_id + 'ldif-change-4,' + test_base)
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-3,' + test_base in response)
        self.assertTrue('changetype: moddn' in response)
        self.assertTrue('newrdn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-4,' + test_base in response)
        self.assertTrue('deleteoldrdn: 1' in response)

    def test_move_dn_request_to_ldif(self):
        result = self.connection.modify_dn(generate_dn(test_base, testcase_id, 'ldif-change-5'), test_name_attr + '=' + testcase_id + 'ldif-change-5', delete_old_dn=False, new_superior=test_moved)
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-5,' + test_base in response)
        self.assertTrue('changetype: modrdn' in response)
        self.assertTrue('newrdn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-5' in response)
        self.assertTrue('deleteoldrdn: 0' in response)
        self.assertTrue('newsuperior: ' + test_moved in response)

    def test_modify_add_to_ldif(self):
        result = self.connection.modify(generate_dn(test_base, testcase_id, 'ldif-change-6'), {'givenName': (MODIFY_ADD, ['givenname-6-modified'])})
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-6,' + test_base in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('add: givenName' in response)
        self.assertTrue('givenName: givenname-6-modified' in response)
        self.assertEqual('-', response[-1])

    def test_modify_replace_to_ldif(self):
        result = self.connection.modify(generate_dn(test_base, testcase_id, 'ldif-change-7'), {'givenName': (MODIFY_REPLACE, ['givenname-7-replaced'])})
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-7,' + test_base in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('replace: givenName' in response)
        self.assertTrue('givenName: givenname-7-replaced' in response)
        self.assertEqual('-', response[-1])

    def test_modify_delete_to_ldif(self):
        result = self.connection.modify(generate_dn(test_base, testcase_id, 'ldif-change-8'), {'givenName': (MODIFY_DELETE, ['givenname-8-deleted'])})
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id + 'ldif-change-8,' + test_base in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('delete: givenName' in response)
        self.assertTrue('givenName: givenname-8-deleted' in response)
        self.assertEqual('-', response[-1])

    def test_multiple_modify_to_ldif(self):
        # from rfc 2849 example
        result = self.connection.modify('cn=Paula Jensen, ou=Product Development, dc=airius, dc=com',
                                        {'postaladdress': (MODIFY_ADD, ['123 Anystreet $ Sunnyvale, CA $ 94086']),
                                         'description': (MODIFY_DELETE, []),
                                         'telephonenumber': (MODIFY_REPLACE, ['+1 408 555 1234', '+1 408 555 5678']),
                                         'facsimiletelephonenumber': (MODIFY_DELETE, ['+1 408 555 9876'])})
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com' in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('delete: facsimiletelephonenumber' in response)
        self.assertTrue('facsimiletelephonenumber: +1 408 555 9876' in response)
        self.assertTrue('replace: telephonenumber' in response)
        self.assertTrue('telephonenumber: +1 408 555 1234' in response)
        self.assertTrue('telephonenumber: +1 408 555 5678' in response)
        self.assertTrue('add: postaladdress' in response)
        self.assertTrue('postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086' in response)
        self.assertTrue('delete: description' in response)
        self.assertEqual('-', response[-1])
Esempio n. 12
0
class Test(unittest.TestCase):
    def setUp(self):
        self.connection = Connection(server=None, client_strategy=LDIF)
        self.connection.open()

    def tearDown(self):
        self.connection.unbind()
        self.assertFalse(self.connection.bound)

    def test_add_request_to_ldif(self):
        controls = list()
        controls.append(('2.16.840.1.113719.1.27.103.7', True, 'givenName'))
        controls.append(('2.16.840.1.113719.1.27.103.7', False, 'sn'))
        if str != bytes:  # python3
            controls.append(('2.16.840.1.113719.1.27.103.7', False,
                             bytearray('\u00e0\u00e0', encoding='UTF-8')))
        else:
            controls.append(
                ('2.16.840.1.113719.1.27.103.7', False,
                 bytearray(unicode('\xe0\xe0', encoding='latin1'),
                           encoding='UTF-8')))  # for python2 compatability
        controls.append(
            ('2.16.840.1.113719.1.27.103.7', False, 'trailingspace '))
        self.connection.add(generate_dn(test_base, testcase_id,
                                        'ldif-change-1'),
                            'inetOrgPerson', {
                                'objectClass': 'inetOrgPerson',
                                'sn': 'ldif-change-1',
                                test_name_attr: 'ldif-change-1'
                            },
                            controls=controls)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-1,' + test_base in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 true: givenName'
                        in response)
        self.assertTrue(
            'control: 2.16.840.1.113719.1.27.103.7 false: sn' in response)
        self.assertTrue(
            'control: 2.16.840.1.113719.1.27.103.7 false:: w6DDoA==' in
            response)
        self.assertTrue(
            'control: 2.16.840.1.113719.1.27.103.7 false:: dHJhaWxpbmdzcGFjZSA='
            in response)
        self.assertTrue('changetype: add' in response)
        self.assertTrue('objectClass: inetOrgPerson' in response)
        self.assertTrue('sn: ldif-change-1' in response)
        self.assertTrue(test_name_attr + ': ldif-change-1' in response)

    def test_delete_request_to_ldif(self):
        self.connection.strategy.order = dict(
            delRequest=['dn:', 'changetype', 'vers'])
        self.connection.delete(
            generate_dn(test_base, testcase_id, 'ldif-change-2'))
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-2,' + test_base in response)
        self.assertTrue('changetype: delete' in response)

    def test_modify_dn_request_to_ldif(self):
        result = self.connection.modify_dn(
            generate_dn(test_base, testcase_id, 'ldif-change-3'),
            test_name_attr + '=' + testcase_id + 'ldif-change-4,' + test_base)
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-3,' + test_base in response)
        self.assertTrue('changetype: moddn' in response)
        self.assertTrue('newrdn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-4,' + test_base in response)
        self.assertTrue('deleteoldrdn: 1' in response)

    def test_move_dn_request_to_ldif(self):
        result = self.connection.modify_dn(
            generate_dn(test_base, testcase_id, 'ldif-change-5'),
            test_name_attr + '=' + testcase_id + 'ldif-change-5',
            delete_old_dn=False,
            new_superior=test_moved)
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-5,' + test_base in response)
        self.assertTrue('changetype: modrdn' in response)
        self.assertTrue('newrdn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-5' in response)
        self.assertTrue('deleteoldrdn: 0' in response)
        self.assertTrue('newsuperior: ' + test_moved in response)

    def test_modify_add_to_ldif(self):
        result = self.connection.modify(
            generate_dn(test_base, testcase_id, 'ldif-change-6'),
            {'givenName': (MODIFY_ADD, ['givenname-6-modified'])})
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-6,' + test_base in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('add: givenName' in response)
        self.assertTrue('givenName: givenname-6-modified' in response)
        self.assertEqual('-', response[-1])

    def test_modify_replace_to_ldif(self):
        result = self.connection.modify(
            generate_dn(test_base, testcase_id, 'ldif-change-7'),
            {'givenName': (MODIFY_REPLACE, ['givenname-7-replaced'])})
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-7,' + test_base in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('replace: givenName' in response)
        self.assertTrue('givenName: givenname-7-replaced' in response)
        self.assertEqual('-', response[-1])

    def test_modify_delete_to_ldif(self):
        result = self.connection.modify(
            generate_dn(test_base, testcase_id, 'ldif-change-8'),
            {'givenName': (MODIFY_DELETE, ['givenname-8-deleted'])})
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: ' + test_name_attr + '=' + testcase_id +
                        'ldif-change-8,' + test_base in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('delete: givenName' in response)
        self.assertTrue('givenName: givenname-8-deleted' in response)
        self.assertEqual('-', response[-1])

    def test_multiple_modify_to_ldif(self):
        # from rfc 2849 example
        result = self.connection.modify(
            'cn=Paula Jensen,ou=Product Development,dc=airius,dc=com', {
                'postaladdress':
                (MODIFY_ADD, ['123 Anystreet $ Sunnyvale, CA $ 94086']),
                'description': (MODIFY_DELETE, []),
                'telephonenumber':
                (MODIFY_REPLACE, ['+1 408 555 1234', '+1 408 555 5678']),
                'facsimiletelephonenumber':
                (MODIFY_DELETE, ['+1 408 555 9876'])
            })
        if isinstance(result, int):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue(
            'dn: cn=Paula Jensen,ou=Product Development,dc=airius,dc=com' in
            response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('delete: facsimiletelephonenumber' in response)
        self.assertTrue(
            'facsimiletelephonenumber: +1 408 555 9876' in response)
        self.assertTrue('replace: telephonenumber' in response)
        self.assertTrue('telephonenumber: +1 408 555 1234' in response)
        self.assertTrue('telephonenumber: +1 408 555 5678' in response)
        self.assertTrue('add: postaladdress' in response)
        self.assertTrue(
            'postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086' in response)
        self.assertTrue('delete: description' in response)
        self.assertEqual('-', response[-1])
Esempio n. 13
0
def get_connection(bind=None,
                   use_ssl=None,
                   check_names=None,
                   lazy_connection=None,
                   authentication=None,
                   sasl_mechanism=None,
                   sasl_credentials=None,
                   ntlm_credentials=(None, None),
                   get_info=None,
                   usage=None,
                   internal_decoder=None,
                   simple_credentials=(None, None),
                   receive_timeout=None,
                   auto_escape=None,
                   auto_encode=None):

    if bind is None:
        bind = True
    if check_names is None:
        check_names = test_check_names
    if lazy_connection is None:
        lazy_connection = test_lazy_connection
    if authentication is None:
        authentication = test_authentication
    if get_info is None:
        get_info = test_get_info
    if usage is None:
        usage = test_usage
    if internal_decoder is None:
        internal_decoder = test_internal_decoder
    if receive_timeout is None:
        receive_timeout = test_receive_timeout
    if auto_escape is None:
        auto_escape = test_auto_escape
    if auto_encode is None:
        auto_encode = test_auto_encode

    if test_server_type == 'AD' and use_ssl is None:
        use_ssl = True  # Active directory forbids Add operations in cleartext

    if test_strategy not in [MOCK_SYNC, MOCK_ASYNC]:
        # define real server
        if isinstance(test_server, (list, tuple)):
            server = ServerPool(pool_strategy=test_pooling_strategy,
                                active=test_pooling_active,
                                exhaust=test_pooling_exhaust)
            for host in test_server:
                server.add(
                    Server(host=host,
                           use_ssl=use_ssl,
                           port=test_port_ssl if use_ssl else test_port,
                           allowed_referral_hosts=('*', True),
                           get_info=get_info,
                           mode=test_server_mode))
        else:
            server = Server(host=test_server,
                            use_ssl=use_ssl,
                            port=test_port_ssl if use_ssl else test_port,
                            allowed_referral_hosts=('*', True),
                            get_info=get_info,
                            mode=test_server_mode)
    else:
        if test_server_type == 'EDIR':
            schema = SchemaInfo.from_json(edir_9_1_4_schema)
            info = DsaInfo.from_json(edir_9_1_4_dsa_info, schema)
            server = Server.from_definition('MockSyncServer', info, schema)
        elif test_server_type == 'AD':
            schema = SchemaInfo.from_json(ad_2012_r2_schema)
            info = DsaInfo.from_json(ad_2012_r2_dsa_info, schema)
            server = Server.from_definition('MockSyncServer', info, schema)
        elif test_server_type == 'SLAPD':
            schema = SchemaInfo.from_json(slapd_2_4_schema)
            info = DsaInfo.from_json(slapd_2_4_dsa_info, schema)
            server = Server.from_definition('MockSyncServer', info, schema)

    if authentication == SASL:
        connection = Connection(server,
                                auto_bind=bind,
                                version=3,
                                client_strategy=test_strategy,
                                authentication=SASL,
                                sasl_mechanism=sasl_mechanism,
                                sasl_credentials=sasl_credentials,
                                lazy=lazy_connection,
                                pool_name='pool1',
                                pool_size=test_pool_size,
                                check_names=check_names,
                                collect_usage=usage,
                                fast_decoder=internal_decoder,
                                receive_timeout=receive_timeout,
                                auto_escape=auto_escape,
                                auto_encode=auto_encode)
    elif authentication == NTLM:
        connection = Connection(server,
                                auto_bind=bind,
                                version=3,
                                client_strategy=test_strategy,
                                user=ntlm_credentials[0],
                                password=ntlm_credentials[1],
                                authentication=NTLM,
                                lazy=lazy_connection,
                                pool_name='pool1',
                                pool_size=test_pool_size,
                                check_names=check_names,
                                collect_usage=usage,
                                fast_decoder=internal_decoder,
                                receive_timeout=receive_timeout,
                                auto_escape=auto_escape,
                                auto_encode=auto_encode)
    elif authentication == ANONYMOUS:
        connection = Connection(server,
                                auto_bind=bind,
                                version=3,
                                client_strategy=test_strategy,
                                user=None,
                                password=None,
                                authentication=ANONYMOUS,
                                lazy=lazy_connection,
                                pool_name='pool1',
                                pool_size=test_pool_size,
                                check_names=check_names,
                                collect_usage=usage,
                                fast_decoder=internal_decoder,
                                receive_timeout=receive_timeout,
                                auto_escape=auto_escape,
                                auto_encode=auto_encode)
    else:
        connection = Connection(server,
                                auto_bind=bind,
                                version=3,
                                client_strategy=test_strategy,
                                user=simple_credentials[0] or test_user,
                                password=simple_credentials[1]
                                or test_password,
                                authentication=authentication,
                                lazy=lazy_connection,
                                pool_name='pool1',
                                pool_size=test_pool_size,
                                check_names=check_names,
                                collect_usage=usage,
                                fast_decoder=internal_decoder,
                                receive_timeout=receive_timeout,
                                auto_escape=auto_escape,
                                auto_encode=auto_encode)

    if test_strategy in [MOCK_SYNC, MOCK_ASYNC]:
        # create authentication identities for testing mock strategies
        connection.strategy.add_entry(test_user, {
            'objectClass': 'inetOrgPerson',
            'userPassword': test_password
        })
        connection.strategy.add_entry(
            test_secondary_user, {
                'objectClass': 'inetOrgPerson',
                'userPassword': test_secondary_password
            })
        connection.strategy.add_entry(test_sasl_user_dn, {
            'objectClass': 'inetOrgPerson',
            'userPassword': test_sasl_password
        })
        connection.strategy.add_entry(
            test_sasl_secondary_user_dn, {
                'objectClass': 'inetOrgPerson',
                'userPassword': test_sasl_secondary_password
            })
        # connection.strategy.add_entry(test_ntlm_user, {'objectClass': 'inetOrgPerson', 'userPassword': test_ntlm_password})
        if bind:
            connection.bind()

    if 'TRAVIS,' in location and test_server_type == 'SLAPD' and not connection.closed:  # try to create the contexts for fixtures
        result1 = connection.add(test_base, 'organizationalUnit')
        result2 = connection.add(test_moved, 'organizationalUnit')

        if not connection.strategy.sync:
            connection.get_response(result1)
            connection.get_response(result2)

    return connection
Esempio n. 14
0
class Test(unittest.TestCase):
    def setUp(self):
        # server = Server(host = test_server, port = test_port, allowed_referral_hosts = ('*', True))
        self.connection = Connection(server=None, client_strategy=STRATEGY_LDIF_PRODUCER)
        self.connection.open()

    def tearDown(self):
        self.connection.unbind()
        self.assertFalse(self.connection.bound)

    def test_add_request_to_ldif(self):
        controls = list()
        controls.append(('2.16.840.1.113719.1.27.103.7', True, 'givenName'))
        controls.append(('2.16.840.1.113719.1.27.103.7', False, 'sn'))
        if str != bytes:  # python3
            controls.append(('2.16.840.1.113719.1.27.103.7', False, bytearray('\u00e0\u00e0', encoding='UTF-8')))
        else:
            controls.append(('2.16.840.1.113719.1.27.103.7', False, bytearray(unicode('\xe0\xe0', encoding='latin1'), encoding='UTF-8')))  # for python2 compatability
        controls.append(('2.16.840.1.113719.1.27.103.7', False, 'trailingspace '))
        self.connection.add(dn_for_test(test_base, 'test-add-operation'), 'iNetOrgPerson', {'objectClass': 'iNetOrgPerson', 'sn': 'test-add', test_name_attr: 'test-add-operation'}, controls=controls)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=test-add-operation,o=test' in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 true: givenName' in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 false: sn' in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 false:: w6DDoA==' in response)
        self.assertTrue('control: 2.16.840.1.113719.1.27.103.7 false:: dHJhaWxpbmdzcGFjZSA=' in response)
        self.assertTrue('changetype: add' in response)
        self.assertTrue('objectClass: inetorgperson' in response)
        self.assertTrue('sn: test-add' in response)
        self.assertTrue('cn: test-add-operation' in response)

    def test_delete_request_to_ldif(self):
        self.connection.strategy.order = dict(delRequest=['dn:', 'changetype', 'vers'])
        self.connection.delete(dn_for_test(test_base, 'test-del-operation'))
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=test-del-operation,o=test' in response)
        self.assertTrue('changetype: delete' in response)

    def test_modify_dn_request_to_ldif(self):
        result = self.connection.modify_dn(dn_for_test(test_base, 'test-modify-dn-operation'), test_name_attr + '=test-modified-dn-operation')
        if not isinstance(result, bool):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=test-modify-dn-operation,o=test' in response)
        self.assertTrue('changetype: moddn' in response)
        self.assertTrue('newrdn: cn=test-modified-dn-operation' in response)
        self.assertTrue('deleteoldrdn: 1' in response)

    def test_move_dn_request_to_ldif(self):
        result = self.connection.modify_dn(dn_for_test(test_base, 'test-move-dn-operation'), test_name_attr + '=test-move-dn-operation', delete_old_dn=False, new_superior=test_moved)
        if not isinstance(result, bool):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=test-move-dn-operation,o=test' in response)
        self.assertTrue('changetype: modrdn' in response)
        self.assertTrue('newrdn: cn=test-move-dn-operation' in response)
        self.assertTrue('deleteoldrdn: 0' in response)
        self.assertTrue('newsuperior: ou=moved,o=test' in response)

    def test_modify_add_to_ldif(self):
        result = self.connection.modify(dn_for_test(test_base, 'test-add-for-modify'), {'givenName': (MODIFY_ADD, ['test-modified-added'])})
        if not isinstance(result, bool):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=test-add-for-modify,o=test' in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('add: givenName' in response)
        self.assertTrue('givenName: test-modified-added' in response)
        self.assertEqual('-', response[-1])

    def test_modify_replace_to_ldif(self):
        result = self.connection.modify(dn_for_test(test_base, 'test-add-for-modify'), {'givenName': (MODIFY_REPLACE, ['test-modified-replace'])})
        if not isinstance(result, bool):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=test-add-for-modify,o=test' in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('replace: givenName' in response)
        self.assertTrue('givenName: test-modified-replace' in response)
        self.assertEqual('-', response[-1])

    def test_modify_delete_to_ldif(self):
        result = self.connection.modify(dn_for_test(test_base, 'test-add-for-modify'), {'givenName': (MODIFY_DELETE, ['test-modified-added2'])})
        if not isinstance(result, bool):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=test-add-for-modify,o=test' in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('delete: givenName' in response)
        self.assertTrue('givenName: test-modified-added2' in response)
        self.assertEqual('-', response[-1])

    def test_multiple_modify_to_ldif(self):
        # from rfc 2849 example
        result = self.connection.modify('cn=Paula Jensen, ou=Product Development, dc=airius, dc=com',
                                        {'postaladdress': (MODIFY_ADD, ['123 Anystreet $ Sunnyvale, CA $ 94086']), 'description': (MODIFY_DELETE, []), 'telephonenumber': (MODIFY_REPLACE, ['+1 408 555 1234', '+1 408 555 5678']),
                                         'facsimiletelephonenumber': (MODIFY_DELETE, ['+1 408 555 9876'])})
        if not isinstance(result, bool):
            self.connection.get_response(result)
        response = self.connection.response
        self.assertTrue('version: 1' in response)
        self.assertTrue('dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com' in response)
        self.assertTrue('changetype: modify' in response)
        self.assertTrue('delete: facsimiletelephonenumber' in response)
        self.assertTrue('facsimiletelephonenumber: +1 408 555 9876' in response)
        self.assertTrue('replace: telephonenumber' in response)
        self.assertTrue('telephonenumber: +1 408 555 1234' in response)
        self.assertTrue('telephonenumber: +1 408 555 5678' in response)
        self.assertTrue('add: postaladdress' in response)
        self.assertTrue('postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086' in response)
        self.assertTrue('delete: description' in response)
        self.assertEqual('-', response[-1])
Esempio n. 15
0
class LDAPUserManager(object):

    def __init__(
            self,
            ldap_server,
            user_filter,
            base_dn=None,
            root_dn=None,
            passwd_dn=None,
            user_profile=[],
            read_only=True,
            cache_users=None,
            cache_groups=None):
        self.ldap_server = ldap_server
        self.root_dn = root_dn
        self.passwd_dn = passwd_dn
        self.base_dn = base_dn
        self.user_filter = user_filter
        self.user_profile = user_profile
        self.read_only = read_only
        self.cache_users = cache_users
        self.cache_groups = cache_groups
        self.ttl_users = 3660
        self.bind()


    def scopes_filter(self):
        f = 'ou=scopes,' + self.base_dn
        return f

    def scope_filter(self, scope):
        f = 'ou={scope},' + self.scopes_filter()
        return f.format(scope=scope)

    def groups_filter(self, scope):
        return 'ou=groups,' + self.scope_filter(scope=scope)

    def group_filter(self, scope, group):
        f = 'cn={group},' + self.groups_filter(scope=scope)
        return f.format(group=group)

    def roles_filter(self, scope):
        return 'ou=roles,' + self.scope_filter(scope=scope)

    def role_filter(self, scope, role):
        f = 'cn={role},' + self.roles_filter(scope)
        return f.format(role=role)

    def users_filter(self):
        f = 'ou=users,' + self.base_dn
        return f

    def userdn2id(self, user_dn):
        """
        :param user_dn: can be a user or a group dn
        :type user_dn: str
        """
        parse_dn = None
        if user_dn.startswith('mail='):
            parse_dn = 'mail='
        elif user_dn.startswith('cn='):
            parse_dn = 'cn='

        if parse_dn:
            return user_dn[len(parse_dn):user_dn.find(',')]

    def bind(self):
        if self.root_dn is None:
            raise Exception('No LDAP Admin Configuration')

        authentication_method = SIMPLE
        bind_type = ASYNC

        self.ldap_conn_mng = Connection(
            self.ldap_server,
            authentication=authentication_method,
            client_strategy=bind_type,
            user=self.root_dn,
            password=self.passwd_dn,
            read_only=self.read_only)
        self.ldap_conn_mng.bind()

    def bind_root_readonly(self):
        """
        A root connection to LDAP server only read_only
        """
        if self.root_dn is None:
            raise Exception('No LDAP Admin Configuration')

        authentication_method = SIMPLE
        bind_type = ASYNC

        ldap_conn_mng = Connection(
            self.ldap_server,
            authentication=authentication_method,
            client_strategy=bind_type,
            user=self.root_dn,
            password=self.passwd_dn,
            read_only=True)

        ldap_conn_mng.bind()
        return ldap_conn_mng

    def unbind(self):
        self.ldap_conn_mng.unbind()

    def checkUserName(self, username):
        if ',' in username:
            raise TypeError('No , in username')

    def parse_async_add(self, return_code):
        """
        Parser the response for an LDAP async ADD
        """
        result = 'Not done'
        if return_code:
            result = self.ldap_conn_mng.get_response(return_code)
            result = result[1].get('description', 'Error no description')
        return result

    async def addScope(self, scope):
        """
        !!!Admin add: must be protected when calling
        """
        # Needs admin
        if self.read_only:
            raise Exception('LDAP in Read only mode')

        self.bind()

        scope_dn = self.scope_filter(scope=scope)
        done = self.ldap_conn_mng.add(scope_dn, 'organizationalUnit')

        result = self.parse_async_add(done)

        if result == 'success':
            #add subelements for scope
            roles_dn = self.roles_filter(scope=scope)
            done = self.ldap_conn_mng.add(roles_dn, 'organizationalUnit')
            if self.parse_async_add(done) != 'success':
                result = 'Failed creating roles'

            groups_dn = self.groups_filter(scope=scope)
            done = self.ldap_conn_mng.add(groups_dn, 'organizationalUnit')
            if self.parse_async_add(done) != 'success':
                result = 'Failed creating groups'

        self.unbind()
        return result

    def addUser(self, username, password):
        """
        !!!Admin add: must be protected when calling
        """
        # Needs admin
        if self.read_only:
            raise Exception('LDAP in Read only mode')

        self.bind()

        self.checkUserName(username)
        user_dn = self.user_filter.format(username=username)
        if '@' in username:
            sn = username.split('@')[0]
        else:
            sn = username

        done = self.ldap_conn_mng.add(
            user_dn,
            self.user_profile,
            {
            'cn': username,
            'sn': sn,
            'mail': username,
            'userPassword': password,
            })

        result = self.parse_async_add(done)
        self.unbind()
        return result

    async def addGroup(self, scope, group):
        """
        !!!Admin add: must be protected when calling
        """
        # Needs admin
        if self.read_only:
            raise Exception('LDAP in Read only mode')

        self.bind()

        self.checkUserName(group)
        group_dn = self.group_filter(scope=scope, group=group)

        done = self.ldap_conn_mng.add(
            group_dn,
            'groupOfUniqueNames',
            {
            'cn': group,
            'uniqueMember': group_dn #  group itself as an empty members list
            })

        result = self.parse_async_add(done)
        self.unbind()
        return result

    async def setPassword(self, username, password):
        """
        !!!Admin add: must be protected when calling
        """
        # Needs admin
        if self.read_only:
            raise Exception('LDAP in Read only mode')
        self.bind()
        user_dn = self.user_filter.format(username=username)
        hashed_password = hashed(HASHED_SHA512, password)
        done = self.ldap_conn_mng.modify(
            user_dn,
            {'userPassword': [(MODIFY_REPLACE, [hashed_password])]}
            )
        result = self.parse_async_add(done)
        if result == 'success':
            return True
        else:
            return False

    async def addScopeRole(self, scope, user_dn, role):
        """
        !!!Admin add: must be protected when calling

        `user_dn` can be a user or a group dn.
        """
        # Needs admin
        if self.read_only:
            raise Exception('LDAP in Read only mode')

        self.bind()

        role_dn = self.role_filter(scope=scope, role=role.lower())

        #Create role for first time
        done = self.ldap_conn_mng.add(
            role_dn,
            'groupOfUniqueNames',
            {'cn': role, 'uniqueMember': user_dn}
            )
        result = self.parse_async_add(done)
        if  result == 'entryAlreadyExists':
            #Extend role with new user
            done = self.ldap_conn_mng.modify(
                role_dn,
                {'uniqueMember': [(MODIFY_ADD, [user_dn])]}
                )
            result = self.parse_async_add(done)

        self.unbind()
        return result

    async def addScopeRoleUser(self, scope, username, role):
        user_dn = self.user_filter.format(username=username)
        return await self.addScopeRole(scope, user_dn, role)

    async def addScopeRoleGroup(self, scope, groupname, role):
        group_dn = self.group_filter(scope, groupname)
        return await self.addScopeRole(scope, group_dn, role)

    async def delScopeRole(self, scope, username, role):
        """
        !!!Admin del: must be protected when calling
        """
        # Needs admin
        if self.read_only:
            raise Exception('LDAP in Read only mode')

        self.bind()

        role_dn = self.role_filter(scope=scope, role=role.lower())
        user_dn = self.user_filter.format(username=username)

        #Find role for first time
        done = self.ldap_conn_mng.modify(
            role_dn,
            {'uniqueMember': [(MODIFY_DELETE, [user_dn])]}
            )
        result = self.parse_async_add(done)

        if result == 'objectClassViolation':
            # member was the last remaining
            done = self.ldap_conn_mng.delete(role_dn)
            result = self.parse_async_add(done)

        self.unbind()
        return result

    async def searchUser(self, scope, criteria, exact_match, attrs, page=None, num_x_page=0):
        """ !!!Admin search: must be protected when calling
        """
        total = 0
        result = []
        paged_size = num_x_page
        paged_cookie = page

        if exact_match is False and any(criteria.values()):
            for k in criteria.keys():
                criteria[k] = "*" + criteria[k] + "*"

        for objclass in self.user_profile:
            criteria['objectClass'] = objclass

        filter_ldap = ""
        for j, v in criteria.items():
            filter_ldap += "(%s=%s)" % (j, v)
        filter_ldap = "(&%s)" % filter_ldap

        self.ldap_conn_mng.bind()
        done = self.ldap_conn_mng.search(
            self.base_dn,
            filter_ldap,
            search_scope=SUBTREE,
            dereference_aliases=DEREF_ALWAYS,
            attributes=USER_ATTRIBUTES,
            size_limit=0,
            time_limit=0,
            types_only=False,
            get_operational_attributes=False,
            controls=None,
            paged_size=paged_size,
            paged_criticality=False,
            paged_cookie=paged_cookie)

        if done:
            result = self.ldap_conn_mng.get_response(done)[0]
            total = len(result)
        self.ldap_conn_mng.unbind()
        return [dict(r['attributes']) for r in result], total

    async def getUser(self, dn, ldap_conn):
        # We should be logged in with the user
        with (await self.cache_users) as redis:
            user = await redis.get(dn)
            if user and user != b'{}':
                return ujson.loads(user)
        r = ldap_conn.search(
            dn,
            '(objectClass=*)',
            search_scope=BASE,
            attributes=USER_ATTRIBUTES)
        if r:
            res = ldap_conn.response[0]
            with (await self.cache_users) as redis:
                redis.set(res['dn'], ujson.dumps(dict(res['attributes'])))
                redis.expire(res['dn'], self.ttl_users)
            return res['attributes']

    async def loginUser(self, username, password):
        user_dn = self.user_filter.format(username=username)
        bind_type = SYNC
        authentication_method = SIMPLE
        ldap_conn = Connection(
            self.ldap_server,
            authentication=authentication_method,
            client_strategy=bind_type,
            user=user_dn,
            password=password,
            read_only=True)
        try:
            result = ldap_conn.bind()
            if result:
                user = await self.getUser(user_dn, ldap_conn)
                ldap_conn.unbind()
                return user
            else:
                return None
        except LDAPException:
            return None

    async def getUserName(self, username):
        dn = self.user_filter.format(username=username)
        with (await self.cache_users) as redis:
            user = await redis.get(dn)
            if user and user != b'{}':
                return ujson.loads(user)
        ldap_conn = self.bind_root_readonly()
        r = ldap_conn.search(
            dn,
            '(objectClass=*)',
            search_scope=BASE,
            attributes=USER_ATTRIBUTES)
        if r:
            names = ldap_conn.get_response(r)[0]
            res = [res['attributes']['cn'][0] for res in names]
        else:
            res = []
        ldap_conn.unbind()
        return ' '.join(res)

    async def get_user_groups(self, ldap_conn, scope, user_dn):
        """
        Return all groups cn that `user_dn` has in `scope`

        :param user_dn: can be a user or a group dn
        :type user_dn: str
        """
        groups_dn = self.groups_filter(scope=scope)

        search_filter = '(uniqueMember={0})'.format(user_dn)

        r = ldap_conn.search(
            groups_dn,
            search_filter,
            search_scope=SUBTREE,
            attributes=['cn']
        )
        if r:
            groups = ldap_conn.get_response(r)[0]
            groups = filter(lambda x: x['dn'] != user_dn, groups) # filter self
            return [res['attributes']['cn'][0] for res in groups]

    async def get_user_roles(self, ldap_conn, scope, user_dn, groups=None):
        """
        Return all roles cn that `user_dn` has in `scope`.
        Return all roles cn that each of `groups` has in `scope`.

        :param user_dn: can be a user or a group dn
        :type user_dn: str
        :param groups: (Optionally)
        :type groups: list
        """
        roles_dn = self.roles_filter(scope=scope)
        search_filter = '(uniqueMember={0})'.format(user_dn)

        if groups is not None:
            search_filter = '(|' + search_filter
            for group_cn in groups:
                group_dn = self.group_filter(scope=scope, group=group_cn)
                search_filter += '(uniqueMember={0})'.format(group_dn)
            search_filter += ')'


        r = ldap_conn.search(
            roles_dn,
            search_filter,
            search_scope=SUBTREE,
            attributes=['cn']
            )
        if r:
            roles = ldap_conn.get_response(r)[0]
            return [res['attributes']['cn'][0] for res in roles]

    async def get_info_user_or_group(self, user_dn, scope):
        """
        !!!Admin search: must be protected when calling

        :returns:
            {
                'groups': {
                    'group1': 1,
                },
                'roles': {
                    'plone.Manager': 1,
                }
            }
        """
        ldap_conn = self.bind_root_readonly()
        groups = await self.get_user_groups(ldap_conn, scope, user_dn)
        roles = await self.get_user_roles(
            ldap_conn,
            scope,
            user_dn,
            groups=groups,
        )
        ldap_conn.unbind()

        return {
            'roles': {e: 1 for e in roles},
            'groups': {e: 1 for e in groups},
        }

    async def getUserInfo(self, username, scope):
        """
        !!!Admin search: must be protected when calling

        :returns:
            {
                'groups': {
                    'group1': 1,
                },
                'roles': {
                    'plone.Manager': 1,
                }
                'name': 'Name'
            }
        """
        user_dn = self.user_filter.format(username=username)
        info = await self.get_info_user_or_group(user_dn, scope)
        info['name'] = username
        return info

    async def getGroupInfo(self, scope, group=None):
        """
        !!!Admin search: must be protected when calling

        :rtype: dict or list of dict or None
        :returns:
            {
                'members': [
                    member1,
                ],
                'name': 'Name'
            }

            or list of groups if group is None
            or None if group is not found

        """
        ldap_conn = self.bind_root_readonly()

        groups_dn = self.groups_filter(scope=scope)

        if group is None:
            search_filter = '(objectClass=groupOfUniqueNames)'
        else:
            search_filter = '(cn={0})'.format(group)

        r = ldap_conn.search(
            groups_dn,
            search_filter,
            search_scope=SUBTREE,
            attributes=['cn', 'uniqueMember']
            )

        if not r:
            raise Exception('LDAP Group search bad formed')

        groups = ldap_conn.get_response(r)[0]
        ldap_conn.unbind()

        async def ldap2json(entry):
            group_dn = entry['dn']
            group_name = entry['attributes']['cn'][0]
            members_ldap = entry['attributes']['uniqueMember']
            members_ldap = filter(lambda x: x != group_dn, members_ldap) # filter self
            info = await self.get_info_user_or_group(group_dn, scope)
            info.update({
                'name': group_name,
                'members': list(map(self.userdn2id, members_ldap)),
                })
            return info

        groups = await asyncio.gather(*map(ldap2json, groups))

        if group is None:
            return groups
        try:
            return groups[0]
        except IndexError:
            return None

    async def get_all_scopes(self, ldap_conn):
        """
        """
        r = ldap_conn.search(
            self.scopes_filter(),
            "(objectClass=organizationalUnit)",
            search_scope=LEVEL,
            attributes=['ou']
            )
        if r:
            scopes = ldap_conn.get_response(r)[0]
            return [scope['attributes']['ou'][0] for scope in scopes]

    async def getUserScopes(self, username):
        """
        Aquesta crida retorna tots els scopes als quals pertany un usuari

        Nota: es pot millorar. Recorre dos cops tots els scopes. Un cop per
        obtenir-los tots i un altre per filtrar segons si l'usuari pertany o no
        """
        ldap_conn = self.bind_root_readonly()

        all_scopes = await self.get_all_scopes(ldap_conn)

        if plone.oauth.is_superuser(username):
            scopes = all_scopes
        else:
            user_dn = self.user_filter.format(username=username)
            scopes = []
            for scope in all_scopes:
                roles = await self.get_user_roles(ldap_conn, scope, user_dn)
                if roles:
                    scopes.append(scope)

        ldap_conn.unbind()

        return {
            'scopes': scopes
        }

    async def get_all_users(self, ldap_conn):
        """
        Return all users cn that `username` has in `scope`.
        Optionally also search by `groups`.
        """
        r = ldap_conn.search(
            self.users_filter(),
            "(objectClass=organizationalPerson)",
            search_scope=LEVEL,
            attributes=['mail']
            )
        if r:
            users = ldap_conn.get_response(r)[0]
            return [user['attributes']['mail'][0] for user in users]

    async def getScopeUsers(self, scope):
        """
        Retorna tots els usuaris que pertanyen a un scope

        Nota: es pot millorar. Recorre dos cops tots els usuaris. Un cop per
        obtenir-los tots i un altre per filtrar segons si l'usuari pertany o no
        """
        ldap_conn = self.bind_root_readonly()

        all_users_ids = await self.get_all_users(ldap_conn)

        users = []
        for user_id in all_users_ids:
            user_dn = self.user_filter.format(username=user_id)
            roles = await self.get_user_roles(ldap_conn, scope, user_dn)
            if roles:
                user = {
                    'id': user_id,
                    'roles': roles
                }
                users.append(user)

        ldap_conn.unbind()

        return {
            'users': users
        }
Esempio n. 16
0
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True), get_info=3)
        self.connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1', check_names=True)

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    def test_wrong_assertion(self):
        ok = False
        try:
            result = self.connection.search(search_base=test_base, search_filter='(xxx=yyy)', attributes=[test_name_attr])
        except LDAPException:
            ok = True

        self.assertTrue(ok)

    def test_wrong_attribute(self):
        ok = False
        try:
            result = self.connection.search(search_base=test_base, search_filter='(cn=yyy)', attributes=[test_name_attr, 'xxx'])
        except LDAPException:
            ok = True

        self.assertTrue(ok)

    def test_wrong_object_class_add(self):
        ok = False
        try:
            result = self.connection.add(dn_for_test(test_base, 'test-add-operation-wrong'), 'iNetOrgPerson', {'objectClass': ['iNetOrgPerson', 'xxx'], 'sn': 'test-add', test_name_attr: 'test-add-operation'})
        except LDAPException:
            ok = True
        self.assertTrue(ok)

    def test_valid_assertion(self):
        result = self.connection.search(search_base=test_base, search_filter='(cn=test*)', attributes=[test_name_attr])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertTrue(len(response) > 1)

    def test_valid_attribute(self):
        result = self.connection.search(search_base=test_base, search_filter='(cn=test*)', attributes=[test_name_attr, 'givenName'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertTrue(len(response) > 1)

    def test_valid_object_class_add(self):
        result = self.connection.add(dn_for_test(test_base, 'test-add-operation-check-names'), 'iNetOrgPerson', {'objectClass': ['iNetOrgPerson', 'Person'], 'sn': 'test-add', test_name_attr: 'test-add-operation-check-names'})
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'entryAlreadyExists'])
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True))
        self.connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1')

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    def test_modify_dn_operation(self):
        result = self.connection.delete(dn_for_test(test_base, 'test-add-modified-dn'))
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'noSuchObject'])

        result = self.connection.delete(dn_for_test(test_base, 'test-add-for-modify-dn'))
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'noSuchObject'])

        result = self.connection.add(dn_for_test(test_base, 'test-add-for-modify-dn'), [], {'objectClass': 'iNetOrgPerson', 'sn': 'test-compare', 'givenName': 'modify-dn'})
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'entryAlreadyExists'])

        result = self.connection.modify_dn(dn_for_test(test_base, 'test-add-for-modify-dn'), test_name_attr + '=test-add-modified-dn')
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'noSuchObject'])

    def test_move_dn(self):
        result = self.connection.delete(dn_for_test(test_base, 'test-add-for-move-dn'))
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'noSuchObject'])

        result = self.connection.add(dn_for_test(test_base, 'test-add-for-move-dn'), [], {'objectClass': 'iNetOrgPerson', 'sn': 'test-add-for-move-dn', 'givenName': 'move-dn'})
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'entryAlreadyExists'])

        result = self.connection.delete(dn_for_test(test_moved, 'test-add-for-move-dn'))
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['success', 'noSuchObject', 'busy'])

        result = self.connection.modify_dn(dn_for_test(test_base, 'test-add-for-move-dn'), test_name_attr + '=test-add-for-move-dn', new_superior=test_moved)
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertTrue(result['description'] in ['other', 'success', 'entryAlreadyExists', 'noSuchObject'])
class Test(unittest.TestCase):
    def setUp(self):
        server = Server(host=test_server, port=test_port, allowed_referral_hosts=('*', True), get_info=test_get_info)
        self.connection = Connection(server, auto_bind=True, version=3, client_strategy=test_strategy, user=test_user, password=test_password, authentication=test_authentication, lazy=test_lazy_connection, pool_name='pool1', check_names=test_check_names)
        result = self.connection.add(dn_for_test(test_base, 'test-search-(parentheses)'), [], {'objectClass': 'iNetOrgPerson', 'sn': 'test-search-(parentheses)', 'loginGraceLimit': 10})
        if not isinstance(result, bool):
            self.connection.get_response(result)

    def tearDown(self):
        self.connection.unbind()
        if self.connection.strategy_type == STRATEGY_REUSABLE_THREADED:
            self.connection.strategy.terminate()
        self.assertFalse(self.connection.bound)

    def test_search_exact_match(self):
        result = self.connection.search(search_base=test_base, search_filter='(' + test_name_attr + '=test-add-operation)', attributes=[test_name_attr, 'givenName', 'jpegPhoto'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertEqual(len(response), 1)

    def test_search_extensible_match(self):
        result = self.connection.search(search_base=test_base, search_filter='(&(o:dn:=test)(objectclass=inetOrgPerson))', attributes=[test_name_attr, 'givenName', 'sn'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertTrue(len(response) > 8)

    def test_search_present(self):
        result = self.connection.search(search_base=test_base, search_filter='(objectClass=*)', search_scope=SEARCH_SCOPE_WHOLE_SUBTREE, attributes=[test_name_attr, 'givenName', 'jpegPhoto'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertTrue(len(response) > 9)

    def test_search_substring_many(self):
        result = self.connection.search(search_base=test_base, search_filter='(sn=t*)', attributes=[test_name_attr, 'givenName', 'sn'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')

        self.assertTrue(len(response) > 8)

    def test_search_substring_one(self):
        result = self.connection.search(search_base=test_base, search_filter='(' + test_name_attr + '=*y)', attributes=[test_name_attr, 'givenName', 'sn'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')

        self.assertTrue(len(response) > 1)

    def test_search_raw(self):
        result = self.connection.search(search_base=test_base, search_filter='(' + test_name_attr + '=*)', search_scope=SEARCH_SCOPE_WHOLE_SUBTREE, attributes=[test_name_attr, 'givenName', 'photo'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')

        self.assertTrue(len(response) > 8)

    def test_search_with_operational_attributes(self):
        result = self.connection.search(search_base=test_base, search_filter='(' + test_name_attr + '=test-add-operation)', search_scope=SEARCH_SCOPE_WHOLE_SUBTREE, attributes=[test_name_attr, 'givenName', 'photo'], get_operational_attributes=True)
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertEqual(response[0]['attributes']['entryDN'][0], dn_for_test(test_base, 'test-add-operation'))

    def test_search_simple_paged(self):
        paged_size = 1
        total_entries = 0
        result = self.connection.search(search_base=test_base, search_filter='(objectClass=*)', search_scope=SEARCH_SCOPE_WHOLE_SUBTREE, attributes=[test_name_attr, 'givenName'], paged_size=paged_size)
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertEqual(len(response), paged_size)
        total_entries += len(response)
        cookie = result['controls']['1.2.840.113556.1.4.319']['value']['cookie']
        while cookie:
            paged_size += 1
            result = self.connection.search(search_base=test_base, search_filter='(objectClass=*)', search_scope=SEARCH_SCOPE_WHOLE_SUBTREE, attributes=[test_name_attr, 'givenName'], paged_size=paged_size, paged_cookie=cookie)
            if not isinstance(result, bool):
                response, result = self.connection.get_response(result)
            else:
                response = self.connection.response
                result = self.connection.result
            self.assertEqual(result['description'], 'success')
            total_entries += len(response)
            self.assertTrue(len(response) <= paged_size)
            cookie = result['controls']['1.2.840.113556.1.4.319']['value']['cookie']
        self.assertTrue(total_entries > 9)

    def test_search_exact_match_with_parentheses_in_filter(self):
        result = self.connection.search(search_base=test_base, search_filter='(' + test_name_attr + '=*' + escape_bytes(')') + '*)', attributes=[test_name_attr, 'sn'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertEqual(len(response), 1)
        self.assertEqual(response[0]['attributes']['cn'][0], 'test-search-(parentheses)')

    def test_search_integer_exact_match(self):
        result = self.connection.search(search_base=test_base, search_filter='(loginGraceLimit=10)', attributes=[test_name_attr, 'loginGraceLimit'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertEqual(len(response), 2)

    def test_search_integer_less_than(self):
        result = self.connection.search(search_base=test_base, search_filter='(loginGraceLimit<=11)', attributes=[test_name_attr, 'loginGraceLimit'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertEqual(len(response), 2)

    def test_search_integer_greater_than(self):
        result = self.connection.search(search_base=test_base, search_filter='(loginGraceLimit>=9)', attributes=[test_name_attr, 'loginGraceLimit'])
        if not isinstance(result, bool):
            response, result = self.connection.get_response(result)
        else:
            response = self.connection.response
            result = self.connection.result
        self.assertEqual(result['description'], 'success')
        self.assertEqual(len(response), 2)