Code Monkey home page Code Monkey logo

ldaptor's Introduction

Ldaptor

Codecov

Read the Docs

GitHub Actions

PyPI

Black

Ldaptor is a pure-Python library that implements:

  • LDAP client logic
  • separately-accessible LDAP and BER protocol message generation/parsing
  • ASCII-format LDAP filter generation and parsing
  • LDIF format data generation
  • Samba password changing logic

Also included is a set of LDAP utilities for use from the command line.

Verbose documentation can be found on ReadTheDocs.

Quick Usage Example

from twisted.internet import reactor, defer
from ldaptor.protocols.ldap import ldapclient, ldapsyntax, ldapconnector

@defer.inlineCallbacks
def example():
    # The following arguments may be also specified as unicode strings
    # but it is recommended to use byte strings for ldaptor objects
    serverip = b'192.168.128.21'
    basedn = b'dc=example,dc=com'
    binddn = b'[email protected]'
    bindpw = b'secret'
    query = b'(cn=Babs*)'
    c = ldapconnector.LDAPClientCreator(reactor, ldapclient.LDAPClient)
    overrides = {basedn: (serverip, 389)}
    client = yield c.connect(basedn, overrides=overrides)
    yield client.bind(binddn, bindpw)
    o = ldapsyntax.LDAPEntry(client, basedn)
    results = yield o.search(filterText=query)
    for entry in results:
        print(entry.getLDIF())

if __name__ == '__main__':
    df = example()
    df.addErrback(lambda err: err.printTraceback())
    df.addCallback(lambda _: reactor.stop())
    reactor.run()

Installation

Ldaptor can be installed using the standard command line method:

python setup.py install

or using pip from PyPI:

pip install ldaptor

Linux distributions may also have ready packaged versions of Ldaptor and Twisted. Debian and Ubuntu have quality Ldaptor packages that can be installed e.g., by:

apt-get install python-ldaptor

To run the LDAP server (bind port 38942) from a repo checkout with the project installed:

twistd -n --pidfile=ldapserver.pid --logfile=ldapserver.log \
    -y test-ldapserver.tac

Dependencies:

ldaptor's People

Contributors

adiroiban avatar amirrossert avatar antong avatar aren avatar cl0ne avatar cwaldbieser avatar davidstrauss avatar fossilet avatar fredreichbier avatar glyph avatar graingert avatar grayan avatar hawkowl avatar hynek avatar im-0 avatar jaraco avatar julijane avatar kenmacd avatar ktdreyer avatar mbish avatar mschwager avatar norox avatar pre-commit-ci[bot] avatar psi29a avatar ryangwu82 avatar sile16 avatar tomprince avatar tv42 avatar wiml avatar xdesai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ldaptor's Issues

derefAliases doesn't seem to do anything

As per 

derefAliases=None,
, I'd expect if derefAliases is set to 3 (LDAP_DEREF_derefAlways) then the alias should be resolved instead of returning the alias.

Visual inspection of search()

def search(self,
seems to suggest that the derefAliases is not actually used

I've installed ldaptor from pip with pip install git+https://github.com/twisted/ldaptor.git@42ce8595409a34c97d04eba5598909a3b825bdb8

I'm using ldaptor as an ldap server, based on https://github.com/twisted/ldaptor/blob/42ce8595409a34c97d04eba5598909a3b825bdb8/ldaptor/protocols/ldap/ldapserver.py

Is this a bug? I probably could work around the issue by patching _onSearchGotBase and doing the dereferencing there, do you have any recommendations?

Allow custom escaping functions when generating LDAP filters

Certain LDAP implementations have different escaping requirements for various attributes. For example, in Active Directory the objectGUID attribute must have its value in hexadecimal representation. Here is a concise description of the issue: https://support.pingidentity.com/LDAP-Filter-on-ObjectGUID

In ldaptor it currently looks something like this:

#!/usr/bin/env python

from ldaptor.protocols import pureldap


filt = pureldap.LDAPFilter_equalityMatch(
    attributeDesc=pureldap.LDAPAttributeDescription('objectGUID'),
    assertionValue=pureldap.LDAPAttributeValue('90395F191AB51B4A9E9686C66CB18D11')
)

print filt.asText()

And we get the following result:

$ python escape.py 
(objectGUID=90395F191AB51B4A9E9686C66CB18D11)

Since this value is automatically escaped there's no opportunity to perform the hexadecimal escaping. If we try that beforehand the value will be double escaped. My question is, do you know of any good way to perform some kind of custom escaping of an attribute value? If not, I'd like to purpose a change that would allow for this.

I purpose all LDAPFilter_* classes take an optional argument when initialized that allows for custom escaping. It would look something like this:

#!/usr/bin/env python

from ldaptor.protocols import pureldap


filt = pureldap.LDAPFilter_equalityMatch(
    attributeDesc=pureldap.LDAPAttributeDescription('objectGUID'),
    assertionValue=pureldap.LDAPAttributeValue('90395F191AB51B4A9E9686C66CB18D11'),
    escaper=OBJECTGUID_ESCAPE_FUNCTION
)

print filt.asText()

Which would produce:

$ python escape.py 
(objectGUID=\90\39\5F\19\1A\B5\1B\4A\9E\96\86\C6\6C\B1\8D\11)

But, escaper could be any escaping function. In this scenario we've just defined some OBJECTGUID_ESCAPE_FUNCTION function that does what we need for objectGUID. Finally, if no escaper function is specified we simply fallback on the original behavior.

I was originally planning on simply submitting a PR with the intended changes, but I made the issue first in case you were aware of some way to do this without any changes to the code base. If that's not the case I'll get to work on submitting a PR :)

Let me know if you have any concerns!

Implement LDAPModifyDNRequest with deleteoldrdn=False

LDAPModifyDNRequest(deleteoldrdn=False) needs to be fixed.

There was a test which was always failing for this.

I will remove it in #88 from the code as it was confusing and just creating noise in the test result

    def test_modifyDN_rdnOnly_noDeleteOldRDN_success(self):
        newrdn = 'cn=thingamagic'
        self.server.dataReceived(
            str(
                pureldap.LDAPMessage(
                    pureldap.LDAPModifyDNRequest(
                        entry=self.thingie.dn,
                        newrdn=newrdn,
                        deleteoldrdn=False),
                    id=2)))
        self.assertEqual(
            self.server.transport.value(),
            str(
                pureldap.LDAPMessage(
                    pureldap.LDAPModifyDNResponse(
                        resultCode=ldaperrors.Success.resultCode),
                    id=2)))
        # tree changed
        d = self.stuff.children()
        d.addCallback(
            self.assertItemsEqual,
            {self.another,
                inmemory.ReadOnlyInMemoryLDAPEntry(
                    '%s,ou=stuff,dc=example,dc=com' % newrdn,
                    {
                        'objectClass': ['a', 'b'],
                        'cn': ['thingamagic', 'thingie']
                    })})
        return d

DistinguishedName comparison should only be about hierarchy relation

See this test which now pass, but which I think should raise an exception as you should not compare such elements

I don't have a use case for such a comparison.

I am opening this issue to gather feedback

https://www.ldap.com/ldap-dns-and-rdns

Most LDAP client APIs offer some mechanism for comparing DNs (e.g., to determine whether they are equal, or to determine whether they are hierarchically related)


    def test_parent_unrelated(self):
        """
        Children from different parents should not be compared

        This pass now
        """
        dn1=dn.DistinguishedName('dc=ab,dc=abc,dc=com')
        dn2=dn.DistinguishedName('dc=ba,dc=example,dc=com')

        self.assertLess(dn1, dn2)

Case insensitive attributeType names for bind and LDAPEntry

I am using the sample client and server.

I have this on the server side

dn: cn=bob,ou=people,dc=example,dc=org
cn: bob
gn: Bob
mail: [email protected]
objectclass: top
objectclass: person
objectClass: inetOrgPerson
sn: Roberts
userPassword: secret

If on the client side I try to bind with CN=bob,OU=people,DC=example,DC=org the credentials are rejected.

Also, I bind with cn=bob,ou=people,dc=example,dc=org but then I use as base_dn DC=example,DC=org the operation fails to find the entry.


Maybe the attribute type/name from bind should be case-insensitive, while the attribute value should be case sensitive.

For the base_dn maybe the whole DN should be case insensitive


I am new to LDAP and I have not read the LDAP specification.

My issue report is based of what I have observed with openldap and Windows AD and compare that experience with the ldaptor sample.

Thanks and sorry for the trouble

Fix documentation images such that they work on RTD

Since we’ve discussed this only on IRC so far:

The Dia stuff is causing trouble all around and especially on ReadTheDocs. So before we release anything, we need to sort it out.

I think we kind of agreed to just keeping the SVGs and converting them to PNGs which are also committed into the repo until a better solution comes up.

I can’t do it myself but this ticket should definitely go into the 14.0 milestone.

Binary attributes in parseFilter get serialized incorrectly in python3

Hi all,
We are experiencing an issue when trying to parse an LDAP filter string that contains a binary attribute such as objectguid.

Using python3.7 and the latest ldaptor here is a snippet of code that can produce the error we're seeing.

from ldaptor import ldapfilter
filter_text = '(objectguid=\\be)'
res = ldapfilter.parseFilter(filter_text)
print(repr(res))
print(res.toWire())

Output:

LDAPFilter_equalityMatch(attributeDesc=LDAPAttributeDescription(value='objectguid'), assertionValue=LDAPAssertionValue(value='¾'))
b'\xa3\x10\x04\nobjectguid\x04\x02\xc2\xbe'

The problem is a bit difficult to notice at first, but it's specifically found at the end of that message.
\\be became \xc2\xbe instead of just \xbe. This extra byte is due to the utf-8 encoding. But before we discuss that further let's step back for a second.

As far as we can tell, the way filter parsing works is that it builds up a list of characters in the filter string one at a time. Each byte is run through the _p_escaped function in ldapfilter.py which turns the hex byte into a character. Then it stores this collection of characters as a python3 string on the LDAPFilter object.

The problem manifests itself when we call the toWire() method on the ldapfilter. Each string in the filter has the to_bytes() method from _encoder.py called on it. In this situation to_bytes(value) ends up being value.encode('utf-8'). For a binary data blob this encoding is not the appropriate choice and it actually corrupts the data.

utf-8 was designed to use just 1 byte when encoding anything in the range of 0-128. However in the range 128-256 it requires 2 bytes to encode a single character. Which is why a value like \xbe (190 in decimal) can only be stored as \xc2\xbe. Storing a literal ‘\xbe` would be invalid for the encoding.

While utf-8 is actually the correct encoding for most LDAP fields this does not work for fields that contain binary data like objectguid. The extra bytes added by the utf-8 encoding essentially corrupt the field we are trying to search on and the LDAP Server will return 0 results for your search.

We have some egregious hacks in place today to make it so that objectguid filters use a latin-1 encoding. This encoding uses only 1 byte for the range 0-256 so the toWire() method returns data that the LDAPServer likes. However, we hate this and would love to see a broader and better solution adopted by ldaptor. Unfortunately we were not able to identify a proper solution ourselves. The main difficulty we ran up against when trying to develop a real solution was that at the time of encoding for the wire the LDAPAttributeValueAssertion /BerSequence has no context and we are not able to tell whether this data is binary or not. So in lieu of a PR I wanted to create this issue so that the ldaptor team was at least aware and maybe a real solution could be found.

Thanks!
Xander

Implement ldapsyntax.DNNotPresentError

This was removed in #88 from ldaptor.test.test_ldapsyntax as this tests is broken and there is no point to be in the code... we have code revision and issues to track broken stuff :)

    def TODOtestDNKeyExistenceFailure(self):
        client = LDAPClientTestDriver()
        self.failUnlessRaises(ldapsyntax.DNNotPresentError,
                              ldapsyntax.LDAPEntry,
                              client=client,
                              dn='cn=foo,dc=example,dc=com',
                              attributes={
            'foo': ['bar'],
            })

Cannot install ldaptor via .pip

As the title suggested, cannot install ldaptor via pip install ldaptor. Looks like it is not on pypi.

(venv)shhuang-mn1:~ shhuang$ pip install ldaptor -v
Downloading/unpacking ldaptor
Could not fetch URL http://pypi.python.org/simple/ldaptor: HTTP Error 404: Not Found
Will skip URL http://pypi.python.org/simple/ldaptor when looking for download links for ldaptor
Real name of requirement ldaptor is ldaptor
Could not fetch URL http://pypi.python.org/simple/ldaptor/: HTTP Error 404: Not Found
Will skip URL http://pypi.python.org/simple/ldaptor/ when looking for download links for ldaptor
Could not find any downloads that satisfy the requirement ldaptor
No distributions at all found for ldaptor
Exception information:
Traceback (most recent call last):
File "/Users/shhuang/.virtualenvs/venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/basecommand.py", line 107, in main
status = self.run(options, args)
File "/Users/shhuang/.virtualenvs/venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/commands/install.py", line 256, in run
requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
File "/Users/shhuang/.virtualenvs/venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/req.py", line 1011, in prepare_files
url = finder.find_requirement(req_to_install, upgrade=self.upgrade)
File "/Users/shhuang/.virtualenvs/venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/index.py", line 157, in find_requirement
raise DistributionNotFound('No distributions at all found for %s' % req)
DistributionNotFound: No distributions at all found for ldaptor

Storing complete log in /Users/shhuang/.pip/pip.log

Fail to run test suite on Gentoo

Hi,
I’m in the process of packaging this for gentoo, while running tests to verify I integrate them correctly in the ebuild, I hit some failures.
Could you give me some suggestion in order to make them pass (assuming I did a mistake), or help fix whats causing them (if its a legit failure)?

Gentoo uses a sandbox system to prevent packages to access internet or write in inappropriate directories during compilation/tests.

Edit: I realised that ldaptor doesnt support python3 yet, I updated the log and ebuild to python2.7 only to reduce the noise.

ebuild (mostly to give you the python_test() phase)

EAPI=7
PYTHON_COMPAT=( python2_7 )
inherit distutils-r1
DESCRIPTION="LDAP server, client and utilities, using Twisted Python"
HOMEPAGE="https://github.com/twisted/ldaptor"
SRC_URI="https://github.com/twisted/ldaptor/archive/${PV}.tar.gz"
S="${WORKDIR}/ldaptor-${PV}"

LICENSE="MIT BSD"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="test"
RESTRICT="!test? ( test )"

DEPEND="${PYTHON_DEPS}
	dev-python/pycrypto
	dev-python/twisted
	dev-python/pyopenssl
	dev-python/pyparsing
	dev-python/six
	dev-python/zope-interface"
DEPEND="${RDEPEND}
	test? ( dev-python/service_identity )"

python_test() {
	"${EPYTHON}" -m twisted.trial ldaptor || die "Failed tests with ${EPYTHON}"
}

Build.log

�[32;01m * �[39;49;00mPackage:    dev-python/twisted-ldaptor-16.0.0
�[32;01m * �[39;49;00mRepository: nado
�[32;01m * �[39;49;00mMaintainer: [email protected]
�[32;01m * �[39;49;00mUSE:        abi_x86_64 amd64 elibc_glibc kernel_linux python_targets_python2_7 test userland_GNU
�[32;01m * �[39;49;00mFEATURES:   preserve-libs sandbox test userpriv usersandbox
>>> Unpacking source...
>>> Unpacking 16.0.0.tar.gz to /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work
>>> Source unpacked in /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work
>>> Preparing source in /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0 ...
>>> Source prepared.
>>> Configuring source in /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0 ...
>>> Source configured.
>>> Compiling source in /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0 ...
 �[32;01m*�[0m python2_7: running distutils-r1_run_phase distutils-r1_python_compile
python2.7 setup.py build
running build
running build_py
creating /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/usage.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/testutil.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/schema.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/numberalloc.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/md4.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/ldiftree.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/ldapfilter.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/interfaces.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/insensitive.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/inmemory.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/generate_password.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/entryhelpers.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/entry.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/dns.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/delta.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/config.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/compat.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/checkers.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/attributeset.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
copying ldaptor/__init__.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor
creating /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols
copying ldaptor/protocols/pureldap.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols
copying ldaptor/protocols/pureber.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols
copying ldaptor/protocols/__init__.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols
creating /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/svcbindproxy.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/proxybase.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/proxy.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/merger.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/ldifprotocol.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/ldifdelta.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/ldif.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/ldapsyntax.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/ldapserver.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/ldaperrors.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/ldapconnector.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/ldapclient.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/fetchschema.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/distinguishedname.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
copying ldaptor/protocols/ldap/__init__.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap
creating /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap/autofill
copying ldaptor/protocols/ldap/autofill/sambaSamAccount.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap/autofill
copying ldaptor/protocols/ldap/autofill/sambaAccount.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap/autofill
copying ldaptor/protocols/ldap/autofill/posixAccount.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap/autofill
copying ldaptor/protocols/ldap/autofill/__init__.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/protocols/ldap/autofill
creating /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/samba
copying ldaptor/samba/smbpassword.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/samba
copying ldaptor/samba/__init__.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/samba
creating /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/util.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_svcbindproxy.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_smbpassword.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_server.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_schema.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_pureldap.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_pureber.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_proxybase.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_proxy.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_merger.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_match.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_ldiftree.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_ldifprotocol.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_ldifdelta.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_ldapsyntax.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_ldapfilter.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_ldapclient.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_inmemory.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_fetchschema.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_entry_diff.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_dns.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_distinguishedname.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_delta.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_connector.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_config.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_autofill_samba.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_autofill_posix.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_autofill.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/test_attributeset.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
copying ldaptor/test/__init__.py -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/lib/ldaptor/test
warning: build_py: byte-compiling is disabled, skipping.

running build_scripts
creating /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-ldap2dhcpconf -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-ldap2maradns -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-ldap2dnszones -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-search -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-namingcontexts -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-passwd -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-ldap2passwd -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-getfreenumber -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-ldap2pdns -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-find-server -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-rename -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-fetchschema -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-ldifdiff -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
copying and adjusting bin/ldaptor-ldifpatch -> /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-ldap2dhcpconf from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-ldap2maradns from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-ldap2dnszones from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-search from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-namingcontexts from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-passwd from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-ldap2passwd from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-getfreenumber from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-ldap2pdns from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-find-server from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-rename from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-fetchschema from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-ldifdiff from 644 to 755
changing mode of /var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0-python2_7/scripts/ldaptor-ldifpatch from 644 to 755
>>> Source compiled.
>>> Test phase: dev-python/twisted-ldaptor-16.0.0
 �[32;01m*�[0m python2_7: running distutils-r1_run_phase python_test
ldaptor.test.test_attributeset
  TestComparison
    testEquality_False_Key ...                                             [OK]
    testEquality_False_Value ...                                           [OK]
    testEquality_True_List ...                                             [OK]
    testEquality_True_List_Ordering ...                                    [OK]
    testEquality_True_Set ...                                              [OK]
    testEquality_True_Set_Ordering ...                                     [OK]
  TestSetOperations
    testCopy ...                                                           [OK]
    testDeepCopy ...                                                       [OK]
    testDifference ...                                                     [OK]
    testIntersection ...                                                   [OK]
    testSymmetricDifference ...                                            [OK]
    testUnion ...                                                          [OK]
ldaptor.test.test_autofill
  LDAPAutoFill_Simple
    testSimpleSum ...                                                      [OK]
ldaptor.test.test_autofill_posix
  LDAPAutoFill_Posix
    testDefaultSetting ...                                                 [OK]
    testMustHaveObjectClass ...                                            [OK]
ldaptor.test.test_autofill_samba
  LDAPAutoFill_sambaAccount
    testDefaultSetting ...                                                 [OK]
    testMustHaveObjectClass ...                                            [OK]
    testPrimaryGroupId ...                                                 [OK]
    testRid ...                                                            [OK]
  LDAPAutoFill_sambaSamAccount
    testDefaultSetting ...                                                 [OK]
    testDefaultSetting_fixedPrimaryGroupSID ...                            [OK]
    testMustHaveObjectClass ...                                            [OK]
    testSambaPrimaryGroupSID ...                                           [OK]
    testSambaPrimaryGroupSID_notUpdatedWhenFixed ...                       [OK]
    testSambaPrimaryGroupSID_preExisting ...                               [OK]
    testSambaSID ...                                                       [OK]
    testSambaSID_preExisting ...                                           [OK]
ldaptor.test.test_config
  IdentitySearch
    testConfig ...                                                         [OK]
    testCopy ...                                                           [OK]
    testInitArg ...                                                        [OK]
  TestConfig
    testSomething ...                                                      [OK]
ldaptor.test.test_connector
  TestCallableOverride
    testFindOverride_plainString ...                                       [OK]
    testFindOverride_root ...                                              [OK]
    testSimple ...                                                         [OK]
ldaptor.test.test_delta
  TestAddOpLDIF
    testSimple ...                                                         [OK]
  TestDeleteOpLDIF
    testSimple ...                                                         [OK]
  TestModificationComparison
    testEquality_AddVsDelete_False ...                                     [OK]
    testEquality_Add_True ...                                              [OK]
    testEquality_AttributeSet_False ...                                    [OK]
    testEquality_List_False ...                                            [OK]
  TestModificationOpLDIF
    testAdd ...                                                            [OK]
    testDelete ...                                                         [OK]
    testDeleteAll ...                                                      [OK]
    testReplace ...                                                        [OK]
    testReplaceAll ...                                                     [OK]
  TestModifications
    testAddNew ...                                                         [OK]
    testAddOld ...                                                         [OK]
    testDelete ...                                                         [OK]
    testDeleteAll ...                                                      [OK]
    testDelete_FailOnNonExistingAttributeType_All ...                      [OK]
    testDelete_FailOnNonExistingAttributeType_OneValue ...                 [OK]
    testDelete_FailOnNonExistingAttributeValue ...                         [OK]
    testReplace_Add ...                                                    [OK]
    testReplace_Delete_Existing ...                                        [OK]
    testReplace_Delete_NonExisting ...                                     [OK]
    testReplace_Modify ...                                                 [OK]
  TestOperationLDIF
    testModify ...                                                         [OK]
  TestOperations
    testAddOp_DNExists ...                                                 [OK]
    testDeleteOp_DNNotFound ...                                            [OK]
    testModifyOp_DNNotFound ...                                            [OK]
ldaptor.test.test_distinguishedname
  DistinguishedName_Comparison
    testGT ...                                                             [OK]
  DistinguishedName_Init
    testDN ...                                                             [OK]
    testString ...                                                         [OK]
  LDAPDistinguishedName_DomainName
    testInterleaved_SubHostSubExampleCom ...                               [OK]
    testNonDc ...                                                          [OK]
    testNonTrailingDc ...                                                  [OK]
    testSimple_ExampleCom ...                                              [OK]
    testSimple_HostSubExampleCom ...                                       [OK]
    testSimple_SubExampleCom ...                                           [OK]
  LDAPDistinguishedName_Escaping
    testKnownValues ...                                                    [OK]
    testOpenLDAPEqualsEscape ...                                           [OK]
  LDAPDistinguishedName_InitialSpaces
    testKnownValues ...                                                    [OK]
  LDAPDistinguishedName_Malformed
    testMalformed ...                                                      [OK]
  LDAPDistinguishedName_Prettify
    testPrettifySpaces ...                                                 [OK]
  LDAPDistinguishedName_RFC2253_Examples
    testKnownValues ...                                                    [OK]
  LDAPDistinguishedName_contains
    test_nonContainment_nonParents ...                                     [OK]
    test_nonContainment_parents ...                                        [OK]
    test_realContainment ...                                               [OK]
    test_selfContainment ...                                               [OK]
  RelativeDistinguishedName_Init
    testRDN ...                                                            [OK]
    testString ...                                                         [OK]
  TestCaseWithKnownValues
    testKnownValues ...                                                    [OK]
ldaptor.test.test_dns
  NetmaskToNumbits
    test_CIDR ...                                                          [OK]
    test_classA ...                                                        [OK]
    test_classB ...                                                        [OK]
    test_classC ...                                                        [OK]
    test_host ...                                                          [OK]
    test_numbits ...                                                       [OK]
  PtrSoaName
    test_CIDR_12 ...                                                       [OK]
    test_CIDR_13 ...                                                       [OK]
    test_CIDR_15 ...                                                       [OK]
    test_CIDR_29 ...                                                       [OK]
    test_CIDR_30 ...                                                       [OK]
    test_CIDR_9 ...                                                        [OK]
    test_classA ...                                                        [OK]
    test_classB ...                                                        [OK]
    test_classC ...                                                        [OK]
ldaptor.test.test_entry_diff
  TestDiffEntry
    testAdd_Existing_OneType_ManyValues ...                                [OK]
    testAdd_Existing_OneType_OneValue ...                                  [OK]
    testAdd_NewAndExisting_ManyTypes ...                                   [OK]
    testAdd_New_ManyTypes ...                                              [OK]
    testAdd_New_OneType_ManyValues ...                                     [OK]
    testAdd_New_OneType_OneValue ...                                       [OK]
    testComplex ...                                                        [OK]
    testDelete_All_OneType ...                                             [OK]
    testDelete_Some_OneType ...                                            [OK]
    testEqual ...                                                          [OK]
ldaptor.test.test_fetchschema
  OnWire
    testSimple ...                                                         [OK]
ldaptor.test.test_inmemory
  FromLDIF
    test_missingNode ...                                                   [OK]
    test_single ...                                                        [OK]
    test_two ...                                                           [OK]
  TestDiff
    testAddChild ...                                                       [OK]
    testAddSubtree ...                                                     [OK]
    testChildChange_Add ...                                                [OK]
    testDeleteChild ...                                                    [OK]
    testDeleteSubtree ...                                                  [OK]
    testNoChange ...                                                       [OK]
    testRootChange_Add ...                                                 [OK]
  TestInMemoryDatabase
    testSearch_withCallback ...                                            [OK]
    testSearch_withoutCallback ...                                         [OK]
    test_addChild ...                                                      [OK]
    test_addChild_Exists ...                                               [OK]
    test_children_empty ...                                                [OK]
    test_children_oneChild ...                                             [OK]
    test_children_repeat ...                                               [OK]
    test_children_twoChildren ...                                          [OK]
    test_commit ...                                                        [OK]
    test_delete ...                                                        [OK]
    test_deleteChild ...                                                   [OK]
    test_deleteChild_NonExisting ...                                       [OK]
    test_delete_nonLeaf ...                                                [OK]
    test_delete_root ...                                                   [OK]
    test_lookup_deep ...                                                   [OK]
    test_lookup_fail ...                                                   [OK]
    test_lookup_fail_outOfTree ...                                         [OK]
    test_move_children_newSuperior ...                                     [OK]
    test_move_children_sameSuperior ...                                    [OK]
    test_move_noChildren_newSuperior ...                                   [OK]
    test_move_noChildren_sameSuperior ...                                  [OK]
    test_parent ...                                                        [OK]
    test_setPassword ...                                                   [OK]
    test_setPassword_noSalt ...                                            [OK]
    test_subtree_empty ...                                                 [OK]
    test_subtree_many ...                                                  [OK]
    test_subtree_many_cb ...                                               [OK]
    test_subtree_oneChild ...                                              [OK]
    test_subtree_oneChild_cb ...                                           [OK]
ldaptor.test.test_ldapclient
  ConnectionLost
    test_simple ...                                                        [OK]
ldaptor.test.test_ldapfilter
  RFC2254Examples
    test_and_or ...                                                        [OK]
    test_cn ...                                                            [OK]
    test_escape_asterisk ...                                               [OK]
    test_escape_backslash ...                                              [OK]
    test_escape_binary ...                                                 [OK]
    test_escape_parens ...                                                 [OK]
    test_escape_utf8 ...                                                   [OK]
    test_extensible_1 ...                                                  [OK]
    test_extensible_2 ...                                                  [OK]
    test_extensible_3 ...                                                  [OK]
    test_extensible_4 ...                                                  [OK]
    test_not_cn ...                                                        [OK]
    test_substrings ...                                                    [OK]
  TestInvalid
    test_closeParen_1 ...                                                  [OK]
    test_closeParen_2 ...                                                  [OK]
    test_closeParen_3 ...                                                  [OK]
    test_closeParen_4 ...                                                  [OK]
    test_openParen_1 ...                                                   [OK]
    test_openParen_2 ...                                                   [OK]
    test_openParen_3 ...                                                   [OK]
    test_openParen_4 ...                                                   [OK]
    test_whitespace_afterOpenParen ...                                     [OK]
    test_whitespace_beforeEq ...                                           [OK]
    test_whitespace_leading ...                                            [OK]
    test_whitespace_trailing ...                                           [OK]
  TestMaybeSubstring
    test_escape_simple ...                                                 [OK]
    test_item_present ...                                                  [OK]
    test_item_simple ...                                                   [OK]
    test_item_substring_aa ...                                             [OK]
    test_item_substring_aaf ...                                            [OK]
    test_item_substring_af ...                                             [OK]
    test_item_substring_any ...                                            [OK]
    test_item_substring_final ...                                          [OK]
    test_item_substring_ia ...                                             [OK]
    test_item_substring_iaa ...                                            [OK]
    test_item_substring_iaaf ...                                           [OK]
    test_item_substring_iaf ...                                            [OK]
    test_item_substring_if ...                                             [OK]
    test_item_substring_init ...                                           [OK]
  TestValid
    test_and_item ...                                                      [OK]
    test_andornot ...                                                      [OK]
    test_item_present ...                                                  [OK]
    test_item_simple ...                                                   [OK]
    test_item_substring_aa ...                                             [OK]
    test_item_substring_aaf ...                                            [OK]
    test_item_substring_af ...                                             [OK]
    test_item_substring_any ...                                            [OK]
    test_item_substring_final ...                                          [OK]
    test_item_substring_ia ...                                             [OK]
    test_item_substring_iaa ...                                            [OK]
    test_item_substring_iaaf ...                                           [OK]
    test_item_substring_iaf ...                                            [OK]
    test_item_substring_if ...                                             [OK]
    test_item_substring_init ...                                           [OK]
    test_not_item ...                                                      [OK]
    test_or_item ...                                                       [OK]
    test_whitespace_afterEq ...                                            [OK]
    test_whitespace_beforeCloseParen ...                                   [OK]
  TestWhitespace
    test_escape ...                                                        [OK]
ldaptor.test.test_ldapsyntax
  Bind
    test_err ...                                                           [OK]
    test_fail ...                                                          [OK]
    test_ok ...                                                            [OK]
  LDAPSyntaxAddChild
    testAddChildOnWire ...                                                 [OK]
  LDAPSyntaxAttributes
    testAttributeAdd ...                                                   [OK]
    testAttributeDelete ...                                                [OK]
    testAttributeItemDelete ...                                            [OK]
    testAttributeSetting ...                                               [OK]
    testUndo ...                                                           [OK]
    testUndoAfterCommit ...                                                [OK]
    testUndoJournaling ...                                                 [OK]
  LDAPSyntaxAttributesModificationOnWire
    testAdd ...                                                            [OK]
    testAddSeparate ...                                                    [OK]
    testDeleteAllAttribute ...                                             [OK]
    testDeleteAttribute ...                                                [OK]
    testReplaceAttributes ...                                              [OK]
  LDAPSyntaxBasics
    testCreation ...                                                       [OK]
    testIn ...                                                             [OK]
    testItems ...                                                          [OK]
    testKeys ...                                                           [OK]
  LDAPSyntaxContainingNamingContext
    testNamingContext ...                                                  [OK]
  LDAPSyntaxDNs
    testDNKeyExistenceSuccess ...                                          [OK]
  LDAPSyntaxDelete
    testDeleteInvalidates ...                                              [OK]
    testDeleteOnWire ...                                                   [OK]
    testErrorHandling ...                                                  [OK]
    testErrorHandling_extended ...                                         [OK]
  LDAPSyntaxFetch
    testCommitAndFetch ...                                                 [OK]
    testFetch_Empty ...                                                    [OK]
    testFetch_Partial ...                                                  [OK]
    testFetch_Prefilled ...                                                [OK]
    testFetch_WithDirtyJournal ...                                         [OK]
  LDAPSyntaxLDIF
    testLDIFConversion ...                                                 [OK]
  LDAPSyntaxMove
    test_move ...                                                          [OK]
  LDAPSyntaxPasswords
    testPasswordSettingAll_hasSamba ...                                    [OK]
    testPasswordSettingAll_hasSambaSam ...                                 [OK]
    testPasswordSettingAll_hasSambaSam_differentCase ...                   [OK]
    testPasswordSettingAll_hasSamba_differentCase ...                      [OK]
    testPasswordSettingAll_maybeSamba_WillFind ...                         [OK]
    testPasswordSettingAll_maybeSamba_WillNotFind ...                      [OK]
    testPasswordSettingAll_maybeSamba_WillNotFindAnything ...              [OK]
    testPasswordSettingAll_noSamba ...                                     [OK]
    testPasswordSetting_ExtendedOperation ...                              [OK]
    testPasswordSetting_Samba_badStyle ...                                 [OK]
    testPasswordSetting_Samba_defaultStyle ...                             [OK]
    testPasswordSetting_Samba_sambaAccount ...                             [OK]
    testPasswordSetting_Samba_sambaSamAccount ...                          [OK]
    testPasswordSetting_abortsOnFirstError ...                             [OK]
  LDAPSyntaxRDNHandling
    testRemovingRDNFails ...                                               [OK]
  LDAPSyntaxSearch
    testSearch ...                                                         [OK]
    testSearch_ImmediateProcessing ...                                     [OK]
    testSearch_defaultAttributes ...                                       [OK]
    testSearch_err ...                                                     [OK]
    testSearch_fail ...                                                    [OK]
    testSearch_noAttributes ...                                            [OK]
ldaptor.test.test_ldifdelta
  TestLDIFDeltaParsing
    testAdd ...                                                            [OK]
    testAdd_fail_noAttrvals ...                                            [OK]
    testDelete ...                                                         [OK]
    testModification_complex ...                                           [OK]
    testModification_empty ...                                             [OK]
    testModification_fail_differentKey ...                                 [OK]
    testModification_fail_noDash_1 ...                                     [OK]
    testModification_fail_noDash_2 ...                                     [OK]
    testModification_fail_unknownModSpec ...                               [OK]
    testModification_oneAdd ...                                            [OK]
    testModification_twoAdds ...                                           [OK]
    testNoChangeType ...                                                   [OK]
ldaptor.test.test_ldifprotocol
  RFC2849_Examples
    testExamples ...                                                       [OK]
  TestLDIFParsing
    testCaseInsensitiveAttributeTypes ...                                  [OK]
    testFromLDIF ...                                                       [OK]
    testNoSpaces ...                                                       [OK]
    testSplitLines ...                                                     [OK]
    testTruncatedFailure ...                                               [OK]
    testVersion1 ...                                                       [OK]
    testVersion2 ...                                                       [OK]
    testVersionInvalid ...                                                 [OK]
ldaptor.test.test_ldiftree
  Dir2LDIF
    testEmptyError ...                                                     [OK]
    testMissingEndError ...                                                [OK]
    testMultipleError ...                                                  [OK]
    testNoAccess ...                                                       [OK]
    testOnlyNewlineError ...                                               [OK]
    testSimpleRead ...                                                     [OK]
    testTreeBranches ...                                                   [OK]
  LDIF2Dir
    testAddTopLevel ...                                                    [OK]
    testDirCreation ...                                                    [OK]
    testDirExists ...                                                      [OK]
    testMissingLinkError ...                                               [OK]
    testSimpleWrite ...                                                    [OK]
  Tree
    test_addChild ...                                                      [OK]
    test_addChild_Exists ...                                               [OK]
    test_children_empty ...                                                [OK]
    test_children_noAccess_dir_noExec ...                                  [OK]
    test_children_noAccess_dir_noRead ...                                  [OK]
    test_children_noAccess_file ...                                        [OK]
    test_children_oneChild ...                                             [OK]
    test_children_repeat ...                                               [OK]
    test_children_twoChildren ...                                          [OK]
    test_children_twoChildren_callback ...                                 [OK]
    test_delete ...                                                        [OK]
    test_deleteChild ...                                                   [OK]
    test_deleteChild_NonExisting ...                                       [OK]
    test_delete_nonLeaf ...                                                [OK]
    test_delete_root ...                                                   [OK]
    test_diffTree_addChild ...                                             [OK]
    test_diffTree_copy ...                                                 [OK]
    test_diffTree_delChild ...                                             [OK]
    test_diffTree_edit ...                                                 [OK]
    test_diffTree_self ...                                                 [OK]
    test_lookup_deep ...                                                   [OK]
    test_lookup_fail ...                                                   [OK]
    test_lookup_fail_emptyError ...                                        [OK]
    test_lookup_fail_multipleError ...                                     [OK]
    test_lookup_fail_outOfTree ...                                         [OK]
    test_lookup_fail_outOfTree_2 ...                                       [OK]
    test_move_children_newSuperior ...                                     [OK]
    test_move_children_sameSuperior ...                                    [OK]
    test_move_noChildren_newSuperior ...                                   [OK]
    test_move_noChildren_sameSuperior ...                                  [OK]
    test_parent ...                                                        [OK]
    test_setPassword ...                                                   [OK]
    test_setPassword_noSalt ...                                            [OK]
    test_subtree_empty ...                                                 [OK]
    test_subtree_many ...                                                  [OK]
    test_subtree_many_cb ...                                               [OK]
    test_subtree_oneChild ...                                              [OK]
    test_subtree_oneChild_cb ...                                           [OK]
ldaptor.test.test_match
  TestEntryMatch
    test_and_match ...                                                     [OK]
    test_and_noMatch ...                                                   [OK]
    test_equality_match ...                                                [OK]
    test_equality_match_caseInsensitive ...                                [OK]
    test_equality_noMatch ...                                              [OK]
    test_extensibleMatch4 ...                                              [OK]
    test_extensibleMatch4_noMatch ...                                      [OK]
    test_greaterOrEqual_match_equal ...                                    [OK]
    test_greaterOrEqual_match_greater ...                                  [OK]
    test_greaterOrEqual_noMatch ...                                        [OK]
    test_greaterOrEqual_noMatch_nosuchattr ...                             [OK]
    test_lessOrEqual_match_equal ...                                       [OK]
    test_lessOrEqual_match_less ...                                        [OK]
    test_lessOrEqual_noMatch ...                                           [OK]
    test_lessOrEqual_noMatch_nosuchattr ...                                [OK]
    test_matchAll ...                                                      [OK]
    test_not ...                                                           [OK]
    test_notImplemented ...                                                [OK]
    test_or_match ...                                                      [OK]
    test_or_noMatch ...                                                    [OK]
    test_present_match ...                                                 [OK]
    test_present_noMatch ...                                               [OK]
    test_substrings_match ...                                              [OK]
    test_substrings_match2 ...                                             [OK]
    test_substrings_match3 ...                                             [OK]
    test_substrings_match4 ...                                             [OK]
    test_substrings_match5 ...                                             [OK]
    test_substrings_match6 ...                                             [OK]
    test_substrings_match7 ...                                             [OK]
    test_substrings_noMatch ...                                            [OK]
    test_substrings_noMatch2 ...                                           [OK]
ldaptor.test.test_merger
  MergedLDAPServerTest
    test_bind_both_invalid ...                                          [ERROR]
    test_bind_both_success ...                                          [ERROR]
    test_bind_one_invalid ...                                           [ERROR]
    test_search_merged ...                                              [ERROR]
    test_search_one_invalid ...                                         [ERROR]
    test_unbind_clientEOF ...                                           [ERROR]
    test_unbind_clientUnbinds ...                                       [ERROR]
    test_unwilling_to_perform ...                                       [ERROR]
ldaptor.test.test_proxy
  Proxy
    test_bind ...                                                       [ERROR]
    test_search ...                                                     [ERROR]
    test_unbind_clientEOF ...                                           [ERROR]
    test_unbind_clientUnbinds ...                                       [ERROR]
ldaptor.test.test_proxybase
  ProxyBase
    test_bind ...                                                          [OK]
    test_cannot_connect_to_proxied_server_no_pending_requests ...          [OK]
    test_cannot_connect_to_proxied_server_pending_requests ...             [OK]
    test_intercepted_search_request ...                                    [OK]
    test_intercepted_search_response ...                                   [OK]
    test_search ...                                                        [OK]
    test_unbind_clientEOF ...                                              [OK]
    test_unbind_clientUnbinds ...                                          [OK]
ldaptor.test.test_pureber
  BERBaseEquality
    testBERBaseEquality ...                                                [OK]
    testBERBaseInEquality ...                                              [OK]
  BERBooleanKnownValues
    testFromBERBooleanKnownValues ...                                      [OK]
    testPartialBERBooleanEncodings ...                                     [OK]
    testToBERBooleanKnownValues ...                                        [OK]
  BEREnumeratedKnownValues
    testFromBEREnumeratedKnownValues ...                                   [OK]
    testPartialBEREnumeratedEncodings ...                                  [OK]
    testToBEREnumeratedKnownValues ...                                     [OK]
  BEREnumeratedSanityCheck
    testSanity ...                                                         [OK]
  BERIntegerKnownValues
    testFromBERIntegerKnownValues ...                                      [OK]
    testPartialBERIntegerEncodings ...                                     [OK]
    testToBERIntegerKnownValues ...                                        [OK]
  BERIntegerSanityCheck
    testSanity ...                                                         [OK]
  BERNullKnownValues
    testFromBERNullKnownValues ...                                         [OK]
    testPartialBERNullEncodings ...                                        [OK]
    testToBERNullKnownValues ...                                           [OK]
  BEROctetStringKnownValues
    testFromBEROctetStringKnownValues ...                                  [OK]
    testPartialBEROctetStringEncodings ...                                 [OK]
    testToBEROctetStringKnownValues ...                                    [OK]
  BEROctetStringSanityCheck
    testSanity ...                                                         [OK]
  BERSequenceKnownValues
    testFromBERSequenceKnownValues ...                                     [OK]
    testPartialBERSequenceEncodings ...                                    [OK]
    testToBERSequenceKnownValues ...                                       [OK]
  BerLengths
    testFromBER ...                                                        [OK]
    testPartialBER ...                                                     [OK]
    testToBER ...                                                          [OK]
ldaptor.test.test_pureldap
  KnownValues
    testFromLDAP ...                                                       [OK]
    testPartial ...                                                        [OK]
    testToLDAP ...                                                         [OK]
  Substrings
    test_length ...                                                        [OK]
  TestEquality
    testEquality ...                                                       [OK]
    testInEquality ...                                                     [OK]
ldaptor.test.test_schema
  AttributeType_KnownValues
    testParse ...                                                          [OK]
    testStringification ...                                                [OK]
  ObjectClass_KnownValues
    testParse ...                                                          [OK]
    testStringification ...                                                [OK]
  TestComparison
    test_eq ...                                                            [OK]
    test_ne ...                                                            [OK]
    test_order ...                                                         [OK]
ldaptor.test.test_server
  LDAPServerTest
    test_add_fail_existsAlready ...                                        [OK]
    test_add_success ...                                                   [OK]
    test_bind ...                                                          [OK]
    test_bind_badVersion_1_anonymous ...                                   [OK]
    test_bind_badVersion_2_anonymous ...                                   [OK]
    test_bind_badVersion_4_anonymous ...                                   [OK]
    test_bind_badVersion_4_nonExisting ...                                 [OK]
    test_bind_invalidCredentials_badPassword ...                           [OK]
    test_bind_invalidCredentials_nonExisting ...                           [OK]
    test_bind_success ...                                                  [OK]
    test_control_unknown_critical ...                                      [OK]
    test_control_unknown_nonCritical ...                                   [OK]
    test_delete ...                                                        [OK]
    test_extendedRequest_unknown ...                                       [OK]
    test_modify ...                                                        [OK]
    test_modifyDN_rdnOnly_deleteOldRDN_success ...                         [OK]
    test_modifyDN_rdnOnly_noDeleteOldRDN_success ...                     [TODO]
    test_passwordModify_notBound ...                                       [OK]
    test_passwordModify_simple ...                                         [OK]
    test_rootDSE ...                                                       [OK]
    test_search_matchAll_manyResults ...                                   [OK]
    test_search_matchAll_oneResult ...                                     [OK]
    test_search_matchAll_oneResult_filtered ...                            [OK]
    test_search_matchAll_oneResult_filteredNoAttribsRemaining ...          [OK]
    test_search_outOfTree ...                                              [OK]
    test_search_scope_baseObject ...                                       [OK]
    test_search_scope_oneLevel ...                                         [OK]
    test_search_scope_wholeSubtree ...                                     [OK]
    test_unbind ...                                                        [OK]
    test_unknownRequest ...                                                [OK]
  TestSchema
    testSimple ...                                                 [SUCCESS!?!]
ldaptor.test.test_smbpassword
  TestLMHash
    testKnownValues ...                                                    [OK]
  TestNTHash
    testKnownValues ...                                                    [OK]
ldaptor.test.test_svcbindproxy
  ServiceBindingProxy
    test_bind_match_badAuth ...                                         [ERROR]
    test_bind_match_success ...                                         [ERROR]
    test_bind_match_success_later ...                                   [ERROR]
    test_bind_noMatchingServicesFound_fallback_badAuth ...              [ERROR]
    test_bind_noMatchingServicesFound_fallback_success ...              [ERROR]
    test_bind_noMatchingServicesFound_noFallback ...                    [ERROR]

===============================================================================
[TODO]
Reason: 'Not supported yet.'
Traceback (most recent call last):
  File "ldaptor/test/test_server.py", line 552, in test_modifyDN_rdnOnly_noDeleteOldRDN_success
    id=2)))
  File "/usr/lib64/python2.7/site-packages/twisted/trial/_synctest.py", line 432, in assertEqual
    super(_Assertions, self).assertEqual(first, second, msg)
  File "/usr/lib64/python2.7/unittest/case.py", line 513, in assertEqual
    assertion_func(first, second, msg=msg)
  File "/usr/lib64/python2.7/unittest/case.py", line 506, in _baseAssertEqual
    raise self.failureException(msg)
twisted.trial.unittest.FailTest: '01\x02\x01\x02m,\n\x015\x04\x00\x04%Cannot handle preserving old RDN yet.' != '0\x0c\x02\x01\x02m\x07\n\x01\x00\x04\x00\x04\x00'

ldaptor.test.test_server.LDAPServerTest.test_modifyDN_rdnOnly_noDeleteOldRDN_success
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_merger.py", line 75, in test_bind_both_invalid
    [[LDAPBindResponse(resultCode=ldaperrors.LDAPInvalidCredentials.resultCode)]])
  File "ldaptor/test/test_merger.py", line 43, in createMergedServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
    overrides=c.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_merger.MergedLDAPServerTest.test_bind_both_invalid
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_merger.py", line 50, in test_bind_both_success
    [[LDAPBindResponse(resultCode=0)]])
  File "ldaptor/test/test_merger.py", line 43, in createMergedServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
    overrides=c.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_merger.MergedLDAPServerTest.test_bind_both_success
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_merger.py", line 64, in test_bind_one_invalid
    [[LDAPBindResponse(resultCode=0)]])
  File "ldaptor/test/test_merger.py", line 43, in createMergedServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
    overrides=c.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_merger.MergedLDAPServerTest.test_bind_one_invalid
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_merger.py", line 91, in test_search_merged
    LDAPSearchResultDone(ldaperrors.Success.resultCode)]])
  File "ldaptor/test/test_merger.py", line 43, in createMergedServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
    overrides=c.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_merger.MergedLDAPServerTest.test_search_merged
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_merger.py", line 110, in test_search_one_invalid
    LDAPSearchResultDone(ldaperrors.Success.resultCode),
  File "ldaptor/test/test_merger.py", line 43, in createMergedServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
    overrides=c.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_merger.MergedLDAPServerTest.test_search_one_invalid
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_merger.py", line 138, in test_unbind_clientEOF
    d = self.createMergedServer([[]], [[]])
  File "ldaptor/test/test_merger.py", line 43, in createMergedServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
    overrides=c.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_merger.MergedLDAPServerTest.test_unbind_clientEOF
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_merger.py", line 125, in test_unbind_clientUnbinds
    d = self.createMergedServer([[]], [[]])
  File "ldaptor/test/test_merger.py", line 43, in createMergedServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
    overrides=c.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_merger.MergedLDAPServerTest.test_unbind_clientUnbinds
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_merger.py", line 151, in test_unwilling_to_perform
    d = self.createMergedServer([[]], [[]])
  File "ldaptor/test/test_merger.py", line 43, in createMergedServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
    overrides=c.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_merger.MergedLDAPServerTest.test_unwilling_to_perform
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_proxy.py", line 16, in test_bind
    server = self.createServer([ pureldap.LDAPBindResponse(resultCode=0),
  File "ldaptor/test/test_proxy.py", line 13, in createServer
    return testutil.createServer(proxy.Proxy, *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_proxy.Proxy.test_bind
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_proxy.py", line 28, in test_search
    pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode),
  File "ldaptor/test/test_proxy.py", line 13, in createServer
    return testutil.createServer(proxy.Proxy, *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_proxy.Proxy.test_search
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_proxy.py", line 62, in test_unbind_clientEOF
    [],
  File "ldaptor/test/test_proxy.py", line 13, in createServer
    return testutil.createServer(proxy.Proxy, *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_proxy.Proxy.test_unbind_clientEOF
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_proxy.py", line 43, in test_unbind_clientUnbinds
    [],
  File "ldaptor/test/test_proxy.py", line 13, in createServer
    return testutil.createServer(proxy.Proxy, *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_proxy.Proxy.test_unbind_clientUnbinds
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_svcbindproxy.py", line 352, in test_bind_match_badAuth
    [ pureldap.LDAPBindResponse(resultCode=ldaperrors.LDAPInvalidCredentials.resultCode) ],
  File "ldaptor/test/test_svcbindproxy.py", line 24, in createServer
    *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_svcbindproxy.ServiceBindingProxy.test_bind_match_badAuth
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_svcbindproxy.py", line 226, in test_bind_match_success
    [ pureldap.LDAPBindResponse(resultCode=ldaperrors.Success.resultCode) ],
  File "ldaptor/test/test_svcbindproxy.py", line 24, in createServer
    *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_svcbindproxy.ServiceBindingProxy.test_bind_match_success
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_svcbindproxy.py", line 275, in test_bind_match_success_later
    [ pureldap.LDAPBindResponse(resultCode=ldaperrors.Success.resultCode) ],
  File "ldaptor/test/test_svcbindproxy.py", line 24, in createServer
    *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_svcbindproxy.ServiceBindingProxy.test_bind_match_success_later
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_svcbindproxy.py", line 161, in test_bind_noMatchingServicesFound_fallback_badAuth
    [ pureldap.LDAPBindResponse(resultCode=ldaperrors.LDAPInvalidCredentials.resultCode),
  File "ldaptor/test/test_svcbindproxy.py", line 24, in createServer
    *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_svcbindproxy.ServiceBindingProxy.test_bind_noMatchingServicesFound_fallback_badAuth
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_svcbindproxy.py", line 100, in test_bind_noMatchingServicesFound_fallback_success
    [ pureldap.LDAPBindResponse(resultCode=ldaperrors.Success.resultCode) ],
  File "ldaptor/test/test_svcbindproxy.py", line 24, in createServer
    *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_svcbindproxy.ServiceBindingProxy.test_bind_noMatchingServicesFound_fallback_success
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "ldaptor/test/test_svcbindproxy.py", line 39, in test_bind_noMatchingServicesFound_noFallback
    [ pureldap.LDAPSearchResultDone(ldaperrors.Success.resultCode) ],
  File "ldaptor/test/test_svcbindproxy.py", line 24, in createServer
    *responses)
  File "ldaptor/testutil.py", line 160, in createServer
    server.connectionMade()
  File "ldaptor/protocols/ldap/proxy.py", line 65, in connectionMade
    overrides=self.config.getServiceLocationOverrides())
  File "ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
    bindAddress=bindAddress)
  File "ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
    connectFuncKwArgs={'bindAddress': bindAddress})
  File "/usr/lib64/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
    self.domain = nativeString(domain)
  File "/usr/lib64/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
    raise TypeError("%r is neither bytes nor unicode" % s)
exceptions.TypeError: None is neither bytes nor unicode

ldaptor.test.test_svcbindproxy.ServiceBindingProxy.test_bind_noMatchingServicesFound_noFallback
===============================================================================
[SUCCESS!?!]
Reason: 'Not supported yet.'

ldaptor.test.test_server.TestSchema.testSimple
-------------------------------------------------------------------------------
Ran 461 tests in 2.203s

FAILED (expectedFailures=1, errors=18, unexpectedSuccesses=1, successes=441)
 �[31;01m*�[0m ERROR: dev-python/twisted-ldaptor-16.0.0::nado failed (test phase):
 �[31;01m*�[0m   Failed tests with python2.7
 �[31;01m*�[0m 
 �[31;01m*�[0m Call stack:
 �[31;01m*�[0m     ebuild.sh, line  124:  Called src_test
 �[31;01m*�[0m   environment, line 2723:  Called distutils-r1_src_test
 �[31;01m*�[0m   environment, line  974:  Called _distutils-r1_run_foreach_impl 'python_test'
 �[31;01m*�[0m   environment, line  425:  Called python_foreach_impl 'distutils-r1_run_phase' 'python_test'
 �[31;01m*�[0m   environment, line 2256:  Called multibuild_foreach_variant '_python_multibuild_wrapper' 'distutils-r1_run_phase' 'python_test'
 �[31;01m*�[0m   environment, line 1628:  Called _multibuild_run '_python_multibuild_wrapper' 'distutils-r1_run_phase' 'python_test'
 �[31;01m*�[0m   environment, line 1626:  Called _python_multibuild_wrapper 'distutils-r1_run_phase' 'python_test'
 �[31;01m*�[0m   environment, line  637:  Called distutils-r1_run_phase 'python_test'
 �[31;01m*�[0m   environment, line  905:  Called python_test
 �[31;01m*�[0m   environment, line 2625:  Called die
 �[31;01m*�[0m The specific snippet of code:
 �[31;01m*�[0m       "${EPYTHON}" -m twisted.trial ldaptor || die "Failed tests with ${EPYTHON}"
 �[31;01m*�[0m 
 �[31;01m*�[0m If you need support, post the output of `emerge --info '=dev-python/twisted-ldaptor-16.0.0::nado'`,
 �[31;01m*�[0m the complete build log and the output of `emerge -pqv '=dev-python/twisted-ldaptor-16.0.0::nado'`.
 �[31;01m*�[0m The complete build log is located at '/var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/temp/build.log'.
 �[31;01m*�[0m The ebuild environment file is located at '/var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/temp/environment'.
 �[31;01m*�[0m Working directory: '/var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0'
 �[31;01m*�[0m S: '/var/tmp/portage/dev-python/twisted-ldaptor-16.0.0/work/ldaptor-16.0.0'

Add comparison to BER objects

The BER base had a naive implementation turning everything to string and the comparing this... but I think that this is wrong

At least for Integer, we should compare them as numbers.

    def __lt__(self, other):
        if not isinstance(other, BERBase):
            return NotImplemented

        return str(self) < str(other)

pluggable password storage format for ldiftree back end

The base classes for LDAP DIT entries found in :file:ldaptor/entry.py are hard-coded to store password hashes for simple BINDs in salted SHA1 format. The entry is prefixed with "{SSHA}". This is similar to one of the schemes that OpenLDAP uses, but allowing alternate schemes may be a good idea.

If the entry has no prefix, it can indicate the password itself is stored in plain text. This is useful to developing and debugging. Different hash formats could have different prefixes. For example {SHA} for unsalted SHA or maybe {PBKDF2} for Password-Based Key Derivation Function 2.

There would need to be a default storage format that is configurable. That would indicate the format used when the LDAP modify password extended request is used.

Also, it may be nice to allow configuration of the attribute in which the password/hash is stored. OpenLDAP allows this, but defaults to userPassword.

does not work integrating with Jenkins (plugin)

I run the ldap server
$twistd -n --pidfile=ldapserver.pid --logfile=ldapserver.log -y test-ldapserver.tac

when configure it as ldap server in Jenkins, it does not work
I add some logs and ldap server give below logs.
Can you give some hint? thanks

2019-06-04T18:23:05+0800 [stdout#info] BERDecoderContext has no tag 0x16: <LDAPBERDecoderContext_TopLevel identities={0x10: LDAPMessage} fallback=None inherit=<LDAPBERDecoderContext_LDAPMessage identities={0x80: LDAPControls, 0x53: LDAPSearchResultReference} fallback=<LDAPBERDecoderContext identities={0x40: LDAPBindRequest, 0x41: LDAPBindResponse, 0x42: LDAPUnbindRequest, 0x43: LDAPSearchRequest, 0x44: LDAPSearchResultEntry, 0x45: LDAPSearchResultDone, 0x46: LDAPModifyRequest, 0x47: LDAPModifyResponse, 0x48: LDAPAddRequest, 0x49: LDAPAddResponse, 0x4a: LDAPDelRequest, 0x4b: LDAPDelResponse, 0x4c: LDAPModifyDNRequest, 0x4d: LDAPModifyDNResponse, 0x4e: LDAPCompareRequest, 0x4f: LDAPCompareResponse, 0x50: LDAPAbandonRequest, 0x53: LDAPSearchResultReference, 0x83: LDAPReferral, 0x57: LDAPExtendedRequest, 0x58: LDAPExtendedResponse} fallback=<BERDecoderContext identities={0x10: BERSequence, 0x01: BERBoolean, 0x02: BERInteger, 0x04: BEROctetString, 0x05: BERNull, 0x16: BERIA5String, 0x11: BERSet, 0x0a: BEREnumerated} fallback=None inherit=None> inherit=None> inherit=<LDAPBERDecoderContext identities={0x40: LDAPBindRequest, 0x41: LDAPBindResponse, 0x42: LDAPUnbindRequest, 0x43: LDAPSearchRequest, 0x44: LDAPSearchResultEntry, 0x45: LDAPSearchResultDone, 0x46: LDAPModifyRequest, 0x47: LDAPModifyResponse, 0x48: LDAPAddRequest, 0x49: LDAPAddResponse, 0x4a: LDAPDelRequest, 0x4b: LDAPDelResponse, 0x4c: LDAPModifyDNRequest, 0x4d: LDAPModifyDNResponse, 0x4e: LDAPCompareRequest, 0x4f: LDAPCompareResponse, 0x50: LDAPAbandonRequest, 0x53: LDAPSearchResultReference, 0x83: LDAPReferral, 0x57: LDAPExtendedRequest, 0x58: LDAPExtendedResponse} fallback=<BERDecoderContext identities={0x10: BERSequence, 0x01: BERBoolean, 0x02: BERInteger, 0x04: BEROctetString, 0x05: BERNull, 0x16: BERIA5String, 0x11: BERSet, 0x0a: BEREnumerated} fallback=None inherit=None> inherit=None>>>

Basic Sphinx framework

The idea here is to create a basic framework for document generation based on reading the doctypes in the source. In additional to this, we can also create a basic usage documentation so a developer can get to work and 'use' the library right away instead spending a few days to see what is possible.

Steps:

  • Sphinx autodoc framework
  • Convert existing documents to RST
  • Automate conversion of DIAs (diagrams) to PNGs.
  • Have a starting point for additional information

How to query/load contact from SQL database?

I searched for sample code of ldaptor and found this website:
https://ldaptor.readthedocs.io/en/latest/cookbook/servers.html .It only provides with an emample of pre-load DIT from the python code. I think very few people would hard code contact information in script, since there are often hundreds or more employees in a company , and guys enter and leave frequently.
Could anybody offer me some help how to conduct a SQL query when receiving a LDAP query?

Python3 support

Hi, could you please support Python3? Many distributions are shifting to Python3 very soon and Python 2.7 will be supported only until 2020.

TCP Connection not closed if non SSL ldaptor LDAPServer accessed via SSL

I'm using ldaptor for testing the ldap login routines of my code. The ldaptor LDAPServer acts as server in this usecase. One of the testcases is accessing a non SSL server (ldaptor) via SSL configured client (my code).

The server reacts with a log output:

ldaptor.protocols.pureber.UnknownBERTag: BERDecoderContext has no tag 0x16: <LDAPBERDecoderContext_TopLevel identities={0x10: LDAPMessage} fallback=None inherit=<LDAPBERDecoderContext_LDAPMessage identities={0x80: LDAPControls, 0x53: LDAPSearchResultReference} fallback=<LDAPBERDecoderContext identities={0x41: LDAPBindResponse, 0x40: LDAPBindRequest, 0x42: LDAPUnbindRequest, 0x43: LDAPSearchRequest, 0x44: LDAPSearchResultEntry, 0x45: LDAPSearchResultDone, 0x53: LDAPSearchResultReference, 0x83: LDAPReferral, 0x46: LDAPModifyRequest, 0x47: LDAPModifyResponse, 0x48: LDAPAddRequest, 0x49: LDAPAddResponse, 0x4a: LDAPDelRequest, 0x4b: LDAPDelResponse, 0x57: LDAPExtendedRequest, 0x58: LDAPExtendedResponse, 0x4c: LDAPModifyDNRequest, 0x4d: LDAPModifyDNResponse, 0x50: LDAPAbandonRequest, 0x4e: LDAPCompareRequest, 0x4f: LDAPCompareResponse} fallback=<BERDecoderContext identities={0x02: BERInteger, 0x04: BEROctetString, 0x05: BERNull, 0x01: BERBoolean, 0x0a: BEREnumerated, 0x10: BERSequence, 0x11: BERSet} fallback=None inherit=None> inherit=None> inherit=<LDAPBERDecoderContext identities={0x41: LDAPBindResponse, 0x40: LDAPBindRequest, 0x42: LDAPUnbindRequest, 0x43: LDAPSearchRequest, 0x44: LDAPSearchResultEntry, 0x45: LDAPSearchResultDone, 0x53: LDAPSearchResultReference, 0x83: LDAPReferral, 0x46: LDAPModifyRequest, 0x47: LDAPModifyResponse, 0x48: LDAPAddRequest, 0x49: LDAPAddResponse, 0x4a: LDAPDelRequest, 0x4b: LDAPDelResponse, 0x57: LDAPExtendedRequest, 0x58: LDAPExtendedResponse, 0x4c: LDAPModifyDNRequest, 0x4d: LDAPModifyDNResponse, 0x50: LDAPAbandonRequest, 0x4e: LDAPCompareRequest, 0x4f: LDAPCompareResponse} fallback=<BERDecoderContext identities={0x02: BERInteger, 0x04: BEROctetString, 0x05: BERNull, 0x01: BERBoolean, 0x0a: BEREnumerated, 0x10: BERSequence, 0x11: BERSet} fallback=None inherit=None> inherit=None>>>

and the TCP connection doesn't get closed, which causes the client to never return. (This looks similar to #137).
I tried to debug the code a little bit, it hits the following line in pureber.py:
print(str(UnknownBERTag(i, context))) # TODO
If I add an line afterwards
raise UnknownBERTag(i, context)
the code closes the connection via the general exception handler with a traceback in twisted (not the best solution, but better than now).

Steps to reproduce (tested with Linux Mint 19.3 python 3.6, using ldaptor 19.1.0):

  • start ldapserver.py
  • On commandline start ldapsearch -H ldaps://127.0.0.1:10389 -x
  • The server outputs the line and the command never returns.
    Excecuting the same command (with 'ldaps' address) on an openldap server (also configured nonSSL) it returns immediately with ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1) (My hack leads to the same result).

Would be great if you could find a proper solution for this.

Thanks a lot

Unknown command test-ldapserver.tac when running readme

I tried to run the ldap server according to the docs in the readme, but got an "Unknown command" error response:

$ python -m venv ~/.envs/ldaptor
$ ~/.envs/ldaptor/bin/pip install ldaptor
Collecting ldaptor
  Using cached ldaptor-16.0.1-py2.py3-none-any.whl
Collecting PyCrypto (from ldaptor)
Collecting Twisted (from ldaptor)
Collecting pyOpenSSL (from ldaptor)
  Using cached pyOpenSSL-17.5.0-py2.py3-none-any.whl
Collecting pyparsing (from ldaptor)
  Using cached pyparsing-2.2.0-py2.py3-none-any.whl
Collecting zope.interface (from ldaptor)
Collecting hyperlink>=17.1.1 (from Twisted->ldaptor)
  Using cached hyperlink-18.0.0-py2.py3-none-any.whl
Collecting constantly>=15.1 (from Twisted->ldaptor)
  Using cached constantly-15.1.0-py2.py3-none-any.whl
Collecting incremental>=16.10.1 (from Twisted->ldaptor)
  Using cached incremental-17.5.0-py2.py3-none-any.whl
Collecting Automat>=0.3.0 (from Twisted->ldaptor)
  Using cached Automat-0.6.0-py2.py3-none-any.whl
Collecting cryptography>=2.1.4 (from pyOpenSSL->ldaptor)
  Using cached cryptography-2.2.2-cp34-abi3-macosx_10_6_intel.whl
Collecting six>=1.5.2 (from pyOpenSSL->ldaptor)
  Using cached six-1.11.0-py2.py3-none-any.whl
Requirement already satisfied: setuptools in ./.envs/ldaptor/lib/python3.7/site-packages (from zope.interface->ldaptor)
Collecting idna>=2.5 (from hyperlink>=17.1.1->Twisted->ldaptor)
  Using cached idna-2.6-py2.py3-none-any.whl
Collecting attrs (from Automat>=0.3.0->Twisted->ldaptor)
  Using cached attrs-17.4.0-py2.py3-none-any.whl
Collecting asn1crypto>=0.21.0 (from cryptography>=2.1.4->pyOpenSSL->ldaptor)
  Using cached asn1crypto-0.24.0-py2.py3-none-any.whl
Collecting cffi>=1.7; platform_python_implementation != "PyPy" (from cryptography>=2.1.4->pyOpenSSL->ldaptor)
Collecting pycparser (from cffi>=1.7; platform_python_implementation != "PyPy"->cryptography>=2.1.4->pyOpenSSL->ldaptor)
Installing collected packages: PyCrypto, idna, hyperlink, constantly, incremental, six, attrs, Automat, zope.interface, Twisted, asn1crypto, pycparser, cffi, cryptography, pyOpenSSL, pyparsing, ldaptor
Successfully installed Automat-0.6.0 PyCrypto-2.6.1 Twisted-17.9.0 asn1crypto-0.24.0 attrs-17.4.0 cffi-1.11.5 constantly-15.1.0 cryptography-2.2.2 hyperlink-18.0.0 idna-2.6 incremental-17.5.0 ldaptor-16.0.1 pyOpenSSL-17.5.0 pycparser-2.18 pyparsing-2.2.0 six-1.11.0 zope.interface-4.4.3
$ ~/.envs/ldaptor/bin/twistd -ny --pidfile=ldapserver.pid --logfile=ldapserver.log test-ldapserver.tac
:0: UserWarning: You do not have a working installation of the service_identity module: 'No module named 'service_identity''.  Please install it from <https://pypi.python.org/pypi/service_identity> and make sure all of its dependencies are satisfied.  Without the service_identity module, Twisted can perform only rudimentary TLS client hostname verification.  Many valid certificate/hostname mappings may be rejected.
Usage: twistd [options]
Options:
  -b, --debug          Run the application in the Python Debugger (implies
                       nodaemon),         sending SIGUSR2 will drop into
                       debugger
      --chroot=        Chroot to a supplied directory before running
  -d, --rundir=        Change to a supplied directory before running [default:
                       .]
  -e, --encrypted      The specified tap/aos file is encrypted.
      --euid           Set only effective user-id rather than real user-id.
                       (This option has no effect unless the server is running
                       as root, in which case it means not to shed all
                       privileges after binding ports, retaining the option to
                       regain privileges in cases such as spawning processes.
                       Use with caution.)
  -f, --file=          read the given .tap file [default: twistd.tap]
  -g, --gid=           The gid to run as.
      --help           Display this help and exit.
      --help-reactors  Display a list of possibly available reactor names.
  -l, --logfile=       log to a specified file, - for stdout
      --logger=        A fully-qualified name to a log observer factory to use
                       for the initial log observer.  Takes precedence over
                       --logfile and --syslog (when available).
  -n, --nodaemon       don't daemonize, don't use default umask of 0077
  -o, --no_save        do not save state on shutdown
      --originalname   Don't try to change the process name
  -p, --profile=       Run in profile mode, dumping results to specified file.
      --pidfile=       Name of the pidfile [default: twistd.pid]
      --prefix=        use the given prefix when syslogging [default: twisted]
      --profiler=      Name of the profiler to use (profile, cprofile).
                       [default: cprofile]
  -r, --reactor=       Which reactor to use (see --help-reactors for a list of
                       possibilities)
  -s, --source=        Read an application from a .tas file (AOT format).
      --savestats      save the Stats object rather than the text output of the
                       profiler.
      --spew           Print an insanely verbose log of everything that happens.
                       Useful when debugging freezes or locks in complex code.
      --syslog         Log to syslog, not to file
  -u, --uid=           The uid to run as.
      --umask=         The (octal) file creation mask to apply.
      --version        Print version information and exit.
  -y, --python=        read an application from within a Python file (implies
                       -o)

twistd reads a twisted.application.service.Application out of a file and runs
it.
Commands:
    conch            A Conch SSH service.
    dns              A domain name server.
    ftp              An FTP server.
    inetd            An inetd(8) replacement.
    manhole          An interactive remote debugger service accessible via
                     telnet and ssh and providing syntax coloring and basic line
                     editing functionality.
    portforward      A simple port-forwarder.
    procmon          A process watchdog / supervisor
    socks            A SOCKSv4 proxy service.
    web              A general-purpose web server which can serve from a
                     filesystem or application resource.
    words            A modern words server
    xmpp-router      An XMPP Router server

/Users/jaraco/.envs/ldaptor/bin/twistd: Unknown command: test-ldapserver.tac

None is neither bytes nor unicode

I'm trying to set up the merger example and I don't know why default bindAddress=None is not working at

class LDAPConnector(SRVConnector):

My code is (Python 2.7.14):

from twisted.internet import defer, reactor, protocol
from twisted.python import log
from ldaptor.config import LDAPConfig
from ldaptor.protocols.ldap.merger import MergedLDAPServer
from six.moves.queue import Queue
import sys

log.startLogging(sys.stderr)

configs = [LDAPConfig(serviceLocationOverrides={'dc=example,dc=com': ('some_host', 389)}),
           LDAPConfig(serviceLocationOverrides={'dc=example.dc=org': ('other_host', 636)})]
use_tls = [False,True]
factory = protocol.ServerFactory()
factory.protocol = lambda: MergedLDAPServer(configs, use_tls)
reactor.listenTCP(8389, factory)
    
reactor.run()

And trace:

2018-01-18 21:36:59+0000 [-] Log opened.
2018-01-18 21:36:59+0000 [-] ServerFactory starting on 8389
2018-01-18 21:36:59+0000 [-] Starting factory <twisted.internet.protocol.ServerFactory instance at 0x7f991a0e7320>
2018-01-18 21:37:03+0000 [twisted.internet.protocol.ServerFactory] Unhandled Error
	Traceback (most recent call last):
	  File "/usr/local/lib/python2.7/site-packages/twisted/python/log.py", line 86, in callWithContext
	    return context.call({ILogContext: newCtx}, func, *args, **kw)
	  File "/usr/local/lib/python2.7/site-packages/twisted/python/context.py", line 122, in callWithContext
	    return self.currentContext().callWithContext(ctx, func, *args, **kw)
	  File "/usr/local/lib/python2.7/site-packages/twisted/python/context.py", line 85, in callWithContext
	    return func(*args,**kw)
	  File "/usr/local/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
	    why = selectable.doRead()
	--- <exception caught here> ---
	  File "/usr/local/lib/python2.7/site-packages/twisted/internet/tcp.py", line 1073, in doRead
	    protocol.makeConnection(transport)
	  File "/usr/local/lib/python2.7/site-packages/twisted/internet/protocol.py", line 510, in makeConnection
	    self.connectionMade()
	  File "/usr/local/lib/python2.7/site-packages/ldaptor/protocols/ldap/merger.py", line 88, in connectionMade
	    overrides=c.getServiceLocationOverrides())
	  File "/usr/local/lib/python2.7/site-packages/ldaptor/protocols/ldap/ldapconnector.py", line 113, in connect
	    bindAddress=bindAddress)
	  File "/usr/local/lib/python2.7/site-packages/ldaptor/protocols/ldap/ldapconnector.py", line 39, in __init__
	    connectFuncKwArgs={'bindAddress': bindAddress})
	  File "/usr/local/lib/python2.7/site-packages/twisted/names/srvconnect.py", line 77, in __init__
	    self.domain = nativeString(domain)
	  File "/usr/local/lib/python2.7/site-packages/twisted/python/compat.py", line 412, in nativeString
	    raise TypeError("%r is neither bytes nor unicode" % s)
	exceptions.TypeError: None is neither bytes nor unicode

Add additional tests

We need to improve our code/test coverage. We're currently around 75%.

@hynek You did work with Coverage, can you explain what you did?

ldapsearch against ldaptor always returns all attributes

Hi,
if i do an ldapsearch agains ldaptor which requests just one (or some) attributes ldaptor seems to always return the complete ldif of the found object. Using the same seach against openldap only the "dn" and the requested attributes are returned.

You should be able to reproduce with the following steps:

Try ldapsearch which requests only specific attribute(s) with ldaptor:

  1. run ldaptest.py
  2. on second console run ldapsearch command that requests only "uid" attribute: ldapsearch -H ldap://localhost:8080 -b "dc=de" -w afdg -x uid
  3. the ldif returned from ldapsearch contains all object attributes!

Try ldapsearch which requests only specific attribute(s) with openldap:

  1. copy slapd.conf to /etc/openldap (or whatever directory your distribution uses)
  2. import ldap tree from ldaptor: ldapsearch -H ldap://localhost:8080 -b "dc=de" -w afdg -x | slapadd -l /dev/stdin
  3. start slapd (e.g. /etc/init.d/slapd start)
  4. run ldapsearch command that requests only "uid" attribute: ldapsearch -H ldap://localhost -b "dc=de" -D 'cn=manager,dc=example,dc=de' -w root -x uid
  5. the ldif returned from ldapsearch contains only "dn" and "uid" attributes

ldaptor.py: https://bpaste.net/show/3f5174d8ec15
slapd.conf: https://bpaste.net/show/c334ec415850

reference: http://twistedmatrix.com/pipermail/twisted-python/2015-May/029447.html

LDAP Proxy - Bind SASL GSS-SPNEGO - List index out of range

A network device is sending the attached bind request to our LDAP proxy that is built on top of Proxy Base. We get a list out of range Exception.

See the attached screenshot from wireshark and the bytes exported into the bin file, also attached.

ldap_bind_gss_wireshark_screenshot

This can be reproduced by doing:

nc 10.228.112.141 389 < ldap_bind_sasl.bin
ldap_bind_sasl.bin.zip

2019-12-14 11:36:55-0600 [LoggingProxy,0,172.16.231.167] Unhandled Error
        Traceback (most recent call last):
          File "/usr/lib64/python2.7/site-packages/twisted/python/log.py", line 103, in callWithLogger
            return callWithContext({"system": lp}, func, *args, **kw)
          File "/usr/lib64/python2.7/site-packages/twisted/python/log.py", line 86, in callWithContext
            return context.call({ILogContext: newCtx}, func, *args, **kw)
          File "/usr/lib64/python2.7/site-packages/twisted/python/context.py", line 122, in callWithContext
            return self.currentContext().callWithContext(ctx, func, *args, **kw)
          File "/usr/lib64/python2.7/site-packages/twisted/python/context.py", line 85, in callWithContext
            return func(*args,**kw)
        --- <exception caught here> ---
          File "/usr/lib64/python2.7/site-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
            why = selectable.doRead()
          File "/usr/lib64/python2.7/site-packages/twisted/internet/tcp.py", line 243, in doRead
            return self._dataReceived(data)
          File "/usr/lib64/python2.7/site-packages/twisted/internet/tcp.py", line 249, in _dataReceived
            rval = self.protocol.dataReceived(data)
          File "/root/pureldap/ldapter_proxy/ldaptor/protocols/ldap/ldapserver.py", line 49, in dataReceived
            self.berdecoder, self.buffer)
          File "/root/pureldap/ldapter_proxy/ldaptor/protocols/pureber.py", line 390, in berDecodeObject
            berdecoder=inh)
          File "/root/pureldap/ldapter_proxy/ldaptor/protocols/pureldap.py", line 84, in fromBER
            l = berDecodeMultiple(content, berdecoder)
          File "/root/pureldap/ldapter_proxy/ldaptor/protocols/pureber.py", line 409, in berDecodeMultiple
            n, bytes = berDecodeObject(berdecoder, content)
          File "/root/pureldap/ldapter_proxy/ldaptor/protocols/pureber.py", line 390, in berDecodeObject
            berdecoder=inh)
          File "/root/pureldap/ldapter_proxy/ldaptor/protocols/pureldap.py", line 172, in fromBER
            auth = (l[2][0].value, l[2][1].value)
          File "/usr/lib64/python2.7/UserList.py", line 31, in __getitem__
            def __getitem__(self, i): return self.data[i]
        exceptions.IndexError: list index out of range

Environment:

# cat /etc/centos-release
CentOS Linux release 7.7.1908 (Core)
# python --version
Python 2.7.5

ldaptor, had pulled form pip install ldaptor, but now pulled directly from github and seeing the same.  

Package                      Version    
---------------------------- -----------
attrs                        19.3.0     
Automat                      0.8.0      
backports.ssl-match-hostname 3.5.0.1    
cffi                         1.13.2     
chardet                      2.2.1      
configobj                    4.7.2      
configparser                 4.0.2      
constantly                   15.1.0     
cryptography                 2.8        
decorator                    3.4.0      
entrypoints                  0.3        
enum34                       1.1.6      
flake8                       3.7.9      
functools32                  3.2.3.post2
hyperlink                    19.0.0     
idna                         2.8        
incremental                  17.5.0     
iniparse                     0.4        
ipaddress                    1.0.16     
kitchen                      1.1.1      
mccabe                       0.6.1      
passlib                      1.7.2      
perf                         0.1        
pip                          19.3.1     
pyasn1                       0.4.8      
pyasn1-modules               0.2.7      
pycodestyle                  2.5.0      
pycparser                    2.19       
pycurl                       7.19.0     
pyflakes                     2.1.1      
pygobject                    3.22.0     
pygpgme                      0.3        
PyHamcrest                   1.9.0      
pyliblzma                    0.5.3      
pyOpenSSL                    19.1.0     
pyparsing                    2.4.5      
python-linux-procfs          0.4.9      
pyudev                       0.15       
pyxattr                      0.5.1      
schedutils                   0.4        
service-identity             18.1.0     
setuptools                   0.9.8      
six                          1.13.0     
slip                         0.4.0      
slip.dbus                    0.4.0      
Twisted                      19.10.0    
typing                       3.7.4.1    
urlgrabber                   3.10       
yum-metadata-parser          1.1.4      
zope.interface               4.7.1      

Review server tests

Some tests, on the server side, require an ordered response but this is not guaranteed. We do some manual re-ordering on the server side to meet the requirements of the test case. LDAP doesn't care what order the 'bag of attributes' comes in so we shouldn't care either. We'll have to re-write our tests do checking of elements them selves instead of getting the str representation and comparing those.

value.toWire raises NotImplementedError

The 'quick usage example' on ldaptor's github homepage works for me (with minimal obvious modifications) on version 16 of ldaptor on Python 2.7

For version 19 of ldaptor, I get this error with python 3.6.5

Unhandled Error
Traceback (most recent call last):
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/twisted/python/log.py", line 103, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/twisted/python/log.py", line 86, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/twisted/python/context.py", line 122, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/twisted/python/context.py", line 85, in callWithContext
    return func(*args,**kw)
--- <exception caught here> ---
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
    why = selectable.doRead()
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/twisted/internet/tcp.py", line 243, in doRead
    return self._dataReceived(data)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/twisted/internet/tcp.py", line 249, in _dataReceived
    rval = self.protocol.dataReceived(data)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/ldaptor/protocols/ldap/ldapclient.py", line 70, in dataReceived
    if not o:
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/ldaptor/protocols/pureber.py", line 132, in __len__
    return len(self.toWire())
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/ldaptor/protocols/pureldap.py", line 122, in toWire
    return BERSequence(l).toWire()
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/ldaptor/protocols/pureber.py", line 312, in toWire
    r = b''.join(to_bytes(x) for x in self.data)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/ldaptor/protocols/pureber.py", line 312, in <genexpr>
    r = b''.join(to_bytes(x) for x in self.data)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/ldaptor/_encoder.py", line 19, in to_bytes
    return value.toWire()
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-3.6/lib/python3.6/site-packages/ldaptor/protocols/pureldap.py", line 139, in toWire
    raise NotImplementedError()
builtins.NotImplementedError: 

And the same error with version 19 of ldaptor on Python 2.7.14:

Unhandled Error
Traceback (most recent call last):
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/twisted/python/log.py", line 103, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/twisted/python/log.py", line 86, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/twisted/python/context.py", line 122, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/twisted/python/context.py", line 85, in callWithContext
    return func(*args,**kw)
--- <exception caught here> ---
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
    why = selectable.doRead()
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/twisted/internet/tcp.py", line 243, in doRead
    return self._dataReceived(data)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/twisted/internet/tcp.py", line 249, in _dataReceived
    rval = self.protocol.dataReceived(data)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/ldaptor/protocols/ldap/ldapclient.py", line 70, in dataReceived
    if not o:
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/ldaptor/protocols/pureber.py", line 132, in __len__
    return len(self.toWire())
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/ldaptor/protocols/pureldap.py", line 122, in toWire
    return BERSequence(l).toWire()
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/ldaptor/protocols/pureber.py", line 312, in toWire
    r = b''.join(to_bytes(x) for x in self.data)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/ldaptor/protocols/pureber.py", line 312, in <genexpr>
    r = b''.join(to_bytes(x) for x in self.data)
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/ldaptor/_encoder.py", line 19, in to_bytes
    return value.toWire()
  File "/mnt/software/external/python_extras/0.8.0/platform-linux/python-2.7/lib/python2.7/site-packages/ldaptor/protocols/pureldap.py", line 139, in toWire
    raise NotImplementedError()
exceptions.NotImplementedError:

Tweaking the master branch ( d3c1919 ), I was able to suppress the error (in both Python interpreters) by modifying LDAPSearchResultReference in ldaptor/protocols/pureldap.py:

    def toWire(self):                                                           
        return b''

So I guess that's what the code is trying to convert to bytes. I'm not sure why I seem to be the first person to run into this. I don't think I'm doing anything unexpected.

Thanks!

Proxy may keep connection to proxied server open if client disconnects immediately

Hello! We're developing an LDAP proxy application based on ldaptor which has worked pretty well so far, so thanks for the great library! We recently stumbled upon a small bug which can be reproduced as follows:

  • Use the current ldaptor master (7a51037)
  • Run the exemplary logging proxy code from the docs, proxying any LDAP server (AD at 10.0.1.161:7389 in our case)
  • Use netcat to perform a simple "health check": netcat -z localhost 10389. The -z flag is described as follows: In connect mode it means that as soon as the port is open it is immediately shutdown and closed.
  • Even though netcat has disconnected, netstat -nto reports a connection from the LDAP proxy to the proxied server in the ESTABLISHED state:
tcp        0      0 10.1.0.4:60478          10.0.1.161:7389         ESTABLISHED off (0.00/0/0)

This socket is only closed when the LDAP proxy is shut down. This is unfortunate because some appliances may perform periodical "health checks" against the LDAP proxy, similar to the netcat call above (see here). If every such health check persists one connection to the proxied server, the LDAP proxy will eventually run out of open files.

I believe this is due to a race condition:

  • When netcat connects to the proxy, connectionMade is called, which initiates a connection to the proxied server. It uses a deferred to invoke _connectedToProxiedServer once the connection has been established:
    d = self.clientConnector()
  • netcat closes the connection to the proxy, so connectionLost is called. However, as netcat does so immediately, the above deferred's callback has not been called yet, so self.client is still None.
  • After that, _connectedToProxiedServer is finally called. Because of that, the connection to the proxied server is never closed.

I'll come up with a small PR to fix this, though it may not be the optimal solution as I'm not that familiar with the ldaptor codebase :)

Implement DistinguishedName comparison with text

16.0.1 used to allow comparing a DistinguishedName with a text... but the implementation was broken as it relies on simple string comparison... and had no test coverage

The 16.0.1 implementation converting the DistinguishedName to a text and then compare it, instead of converting the text to a DistinguishedName and then do the comparison.

See the end of https://www.ldap.com/ldap-dns-and-rdns

Two DistinguishedName can still be compared. This is only about things like

dn.DistinguishedName('dc=example,dc=com') > 'dc = example, dc = dc`

Refactor out deprecated code

Not just tests, but ldaptor code itself to bring it more in-line with Python 2.7

We should also keep an eye on Python 3 compatibility.

(TLS negotiation failure) when connecting to ldaps://fqdn:636 server

Using ldap-merger.tac I cannot connect to ldaps port 636.
No problem to port 389 with or without start TLS.
Tracelog here:

2019-07-19T01:27:42+0200 [twisted.internet.defer#critical] Unhandled error in Deferred:
2019-07-19T01:27:42+0200 [twisted.internet.defer#critical] 
	Traceback (most recent call last):
	  File "/home/wert/ldaptor/env/lib/python3.5/site-packages/twisted/internet/tcp.py", line 327, in connectionLost
	    protocol.connectionLost(reason)
	  File "/home/wert/ldaptor/env/lib/python3.5/site-packages/ldaptor/protocols/ldap/ldapclient.py", line 85, in connectionLost
	    d.errback(reason)
	  File "/home/wert/ldaptor/env/lib/python3.5/site-packages/twisted/internet/defer.py", line 501, in errback
	    self._startRunCallbacks(fail)
	  File "/home/wert/ldaptor/env/lib/python3.5/site-packages/twisted/internet/defer.py", line 568, in _startRunCallbacks
	    self._runCallbacks()
	--- <exception caught here> ---
	  File "/home/wert/ldaptor/env/lib/python3.5/site-packages/twisted/internet/defer.py", line 654, in _runCallbacks
	    current.result = callback(current.result, *args, **kw)
	  File "/home/wert/ldaptor/env/lib/python3.5/site-packages/ldaptor/protocols/ldap/merger.py", line 40, in _failConnection
	    raise ldaperrors.LDAPOther("Cannot connect to server.{}".format(reason))
	ldaptor.protocols.ldap.ldaperrors.LDAPOther: other: Cannot connect to server.[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.

These server are usable with ldapsearch and/or python ldap3.
Any hints?

BERDecoderContext has no tag 0x0d

Am using a third party proxy for my LDAP client and seeing this error. What does this tag: 0x0d mean?If possible, I'd like to work around it.

BERDecoderContext has no tag 0x0d: <LDAPBERDecoderContext_TopLevel identities={0x10: LDAPMessage} fallback=None inherit=<LDAPBERDecoderContext_LDAPMessage identities={0x80: LDAPControls, 0x53: LDAPSearchResultReference} fallback=<LDAPBERDecoderContext identities={0x40: LDAPBindRequest, 0x41: LDAPBindResponse, 0x42: LDAPUnbindRequest, 0x43: LDAPSearchRequest, 0x44: LDAPSearchResultEntry, 0x45: LDAPSearchResultDone, 0x46: LDAPModifyRequest, 0x47: LDAPModifyResponse, 0x48: LDAPAddRequest, 0x49: LDAPAddResponse, 0x4a: LDAPDelRequest, 0x4b: LDAPDelResponse, 0x4c: LDAPModifyDNRequest, 0x4d: LDAPModifyDNResponse, 0x50: LDAPAbandonRequest, 0x83: LDAPReferral, 0x57: LDAPExtendedRequest, 0x58: LDAPExtendedResponse} fallback=<BERDecoderContext identities={0x01: BERBoolean, 0x02: BERInteger, 0x04: BEROctetString, 0x05: BERNull, 0x0a: BEREnumerated, 0x10: BERSequence, 0x11: BERSet} fallback=None inherit=None> inherit=None> inherit=<LDAPBERDecoderContext identities={0x40: LDAPBindRequest, 0x41: LDAPBindResponse, 0x42: LDAPUnbindRequest, 0x43: LDAPSearchRequest, 0x44: LDAPSearchResultEntry, 0x45: LDAPSearchResultDone, 0x46: LDAPModifyRequest, 0x47: LDAPModifyResponse, 0x48: LDAPAddRequest, 0x49: LDAPAddResponse, 0x4a: LDAPDelRequest, 0x4b: LDAPDelResponse, 0x4c: LDAPModifyDNRequest, 0x4d: LDAPModifyDNResponse, 0x50: LDAPAbandonRequest, 0x83: LDAPReferral, 0x57: LDAPExtendedRequest, 0x58: LDAPExtendedResponse} fallback=<BERDecoderContext identities={0x01: BERBoolean, 0x02: BERInteger, 0x04: BEROctetString, 0x05: BERNull, 0x0a: BEREnumerated, 0x10: BERSequence, 0x11: BERSet} fallback=None inherit=None> inherit=None>>>

Malformed LDAP packets due to missing LDAPSearchResultReference implementation

The missing __str__() implementation of LDAPSearchResultReference can lead to malformed LDAP packets.

I tried running proxybase.py as a transparent LDAP proxy for (GitLab-)user authentication against a Microsoft Active Directory server and ended up with "Unsupported object type: id=60" failures originating somewere deep in GitLab's BER parser.

Investigating the Proxy -> Client communication with Wireshark showed several [Malformed Packet: LDAP] errors where the byte stream contained stuff like <instance object at 0x7fba757ed2d8> (with < as ASCII char 60 apparently being the cause for the "Unsupported object type: id=60" message).

On the Server -> Proxy stream, Wireshark showed searchResRef LDAP messages instead.
Since I don't need those for my use case, I created a workaround by ignoring them:

    def handleProxiedResponse(self, response, request, controls):
        if isinstance(response, pureldap.LDAPSearchResultReference):
            return
        ...

But strictly speaking this is not a transparent proxy anymore.

BerOctetString Repr

Hey ldaptor team we got another one for ya!

As is seen in PR #164, calling repr() on a BEROctetString results in an exception when the value of the BEROctetString is not utf-8 encoded bytes. In practice, LDAPBindResponse_serverSaslCreds has non-utf-8 bytes as demonstrated by the PR, and it turns out that LDAPMessages may have non-utf-8 bytes as well. One specific example is the controls used during a paged search. The cookie part of the controls is not utf-8 and therefore also leads to the same type of exception when an LDAPMessage with one of these cookies is being repr()’d.

The root of both of this issue and that PR is that repr_converter can’t handle bytes that aren’t utf-8 encoded so BEROctetString.__repr__ can often lead to an exception in real-world application.

from ldaptor.protocols.pureber import BEROctetString
# A real cookie from a search against AD
cookie = b'\xa3\x02\x00\x00'
octet_string = BEROctetString(cookie)

# results in an exception being raised
repr(octet_string)

It seems that either:
BEROctetString.__repr__ should be updated to not use repr_converter to account for its value not necessarily being utf-8 encoded bytes.
OR repr_converter should not assume that it can always decode bytes as utf-8 and should fail gracefully if it can’t.

Additionally, if one the above changes were to be implemented (or something similar) then the changes in the PR listed above wouldn’t be necessary.

Do you all have any preference on where the change for this should occur? On our fork personally we're rolling with a change to repr_converter to basically catch a UnicodeError and then not raise if the bytes can't be decoded but instead just letting the bytes get repr()'d and printed.

Whichever one sounds better to you all let us know and we'll likely be able to get a PR up for it.

get twisted trial working again

for the matrix of environments in travis-ci

at least 2.6 and 2.7 should be supported.

pypy is a bonus

and we're still not sure on py-flakes

Decide if we need both ldaptor.testutil and ldaptor.test.util

I guess that ldaptor.testutil should be moved to ldaptor.test.util so that we have it only in test and not used it outside of ldaptor.

While working on this check if we can get 100% coverage for ldaptor.test.util and enable codecov.io reporting for whole tests

in codecov.yml now we have

      tests:
        target: 100%
        paths:
          - "ldaptor/test/test_*"

It would be nice to have

      tests:
        target: 100%
        paths:
          - "ldaptor/test/*"

builtins.TypeError: startswith first arg must be str or a tuple of str, not bytes

I read the tutorial https://ldaptor.readthedocs.io/en/latest/quickstart.html and learned how to load LDAP entries from a static LDIF. Since I want to load contact from SQL database, I raised a question and get help from a kind response here #154

I tried the code below, and sent a query from Microsoft Outlook, but my program raised an error

import sys

from ldaptor.inmemory import ReadOnlyInMemoryLDAPEntry
from ldaptor.inmemory import fromLDIFFile
from ldaptor.interfaces import IConnectedLDAPEntry
from ldaptor.protocols.ldap.ldapserver import LDAPServer


from twisted.application import service
from twisted.internet.endpoints import serverFromString
from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
from twisted.python.components import registerAdapter
from twisted.python import log

class LDAPServerFactory(ServerFactory):
    protocol = LDAPServer

    def __init__(self, db_engine= None):
        self.root = None
        self.reload_tree()

    def reload_tree(self):
        """
        Building LDAP tree.
        Call this method if you need to reload data from the database.
        """
        com_tree = ReadOnlyInMemoryLDAPEntry('dc=org')
        example_tree = com_tree.addChild('dc=example', {})
        people_tree = example_tree.addChild('ou=people', {})
        sales_tree = people_tree.addChild('ou=sales', {})



        sales_tree.addChild('cn=bob', {
            'cn': 'bob',
            'gn': 'Bob',
            'mail': '[email protected]',
            'sn': 'Roberts'
        })



        self.root = com_tree

    def buildProtocol(self, addr):
        proto = self.protocol()
        proto.debug = self.debug
        proto.factory = self
        return proto

        

if __name__ == '__main__':

    log.startLogging(sys.stderr)

    registerAdapter(lambda x: x.root, LDAPServerFactory, IConnectedLDAPEntry)
    factory = LDAPServerFactory()
    factory.debug = True
    application = service.Application("ldaptor-server")
    myService = service.IServiceCollection(application)
    serverEndpointStr = "tcp:{0}".format(389)
    e = serverFromString(reactor, serverEndpointStr)
    d = e.listen(factory)
    reactor.run()

The error information is

          File "d:\code_python\LDAP\ldaptor\entryhelpers.py", line 172, in <listcomp>
            if x.lower().startswith(filter.substrings[0].value.lower())
        builtins.TypeError: startswith first arg must be str or a tuple of str, not bytes

here x is a plain string while the filter values are byte.

Malformed packet for LDAPFilter_extensibleMatch

from ldaptor.ldapfilter import parseFilter
from pyasn1.codec.ber import decoder

l = parseFilter('(ou:=test)')
print repr(l)

print decoder.decode(str(l))

result:

LDAPFilter_extensibleMatch(matchingRule=None, type='ou', matchValue='test', dnAttributes=None)
Traceback (most recent call last):
  File "test_ber.py", line 10, in <module>
    print decoder.decode(str(l))
  File "/usr/lib64/python2.7/site-packages/pyasn1/codec/ber/decoder.py", line 825, in __call__
    stGetValueDecoder, self, substrateFun
  File "/usr/lib64/python2.7/site-packages/pyasn1/codec/ber/decoder.py", line 50, in valueDecoder
    value, _ = decodeFun(head, asn1Spec, tagSet, length)
  File "/usr/lib64/python2.7/site-packages/pyasn1/codec/ber/decoder.py", line 706, in __call__
    '%d-octet short' % (length - len(substrate))
pyasn1.error.SubstrateUnderrunError: 113-octet short

Connection lost in proxy server

I set up an LDAP proxy using this code http://ldaptor.readthedocs.io/en/latest/cookbook/ldap-proxy.html#code, but I constantly get connection lost errors as in the end. I enabled TCP keepalive for both LoggingProxy.connectionMade and LDAPClient.connectionMade, and I can confirm with ss that all the connection from my clients to the proxy and from the proxy to the Active Directory server have keepalive timers. However, the error persists. Hope I can get some hints here.

2016-12-08 15:30:26+0800 [-] Unhandled error in Deferred:
2016-12-08 15:30:26+0800 [-] Unhandled Error
        Traceback (most recent call last):
          File "/usr/lib64/python2.7/site-packages/twisted/internet/defer.py", line 651, in _runCallb
acks
            current.result = callback(current.result, *args, **kw)
          File "/usr/lib/python2.7/site-packages/ldaptor/protocols/ldap/proxybase.py", line 132, in _
forwardRequestToProxiedServer
            d.addCallback(forwardit, reply)
          File "/usr/lib64/python2.7/site-packages/twisted/internet/defer.py", line 319, in addCallback
            callbackKeywords=kw)
          File "/usr/lib64/python2.7/site-packages/twisted/internet/defer.py", line 308, in addCallbacks
            self._runCallbacks()
        --- <exception caught here> ---
          File "/usr/lib64/python2.7/site-packages/twisted/internet/defer.py", line 651, in _runCallbacks
            current.result = callback(current.result, *args, **kw)
          File "/usr/lib/python2.7/site-packages/ldaptor/protocols/ldap/proxybase.py", line 129, in forwardit
            self.client.send_noResponse(request)
          File "/usr/lib/python2.7/site-packages/ldaptor/protocols/ldap/ldapclient.py", line 144, in send_noResponse
            msg = self._send(op)
          File "/usr/lib/python2.7/site-packages/ldaptor/protocols/ldap/ldapclient.py", line 77, in _send
            raise LDAPClientConnectionLostException()
        ldaptor.protocols.ldap.ldapclient.LDAPClientConnectionLostException: Connection lost

`entryhelpers.SearchByTreeWalkingMixin.search()` Deferred never called if scope iterator is actually asynchronous.

entryhelpers.SearchByTreeWalkingMixin.search() creates a node iterator function based on the scope of the LDAP search request. This function returns a defer.Deferred in each case. Unfortunately, the code assumes that this Deferred will automatically be called, because later when the iterator function is called, the returned Deferred is just discarded.

The reason that this issue has not led to noticeable failures up to this point is that the entryhelpers.SubtreeFromChildrenMixin.subtree() method calls the children() method on existing underlying implementations (inmemory or ldifftree). In each case, while these functions are written to return a Deferred, it has already succeeded-- i.e. the callbacks have already been run.

A hypothetical implementation based on a database back end that actually did require asynchonous calls to retrieve the nodes would mysteriously fail to return all the results.

Allow for logical comparisons in LDAPFilterSet

Hey again!

I'm back with some more LDAP filter requests. The basic jist of this request is, I'd like to be able to perform logical comparisons on LDAP filter AND and OR statements. For example, consider the following:

(&(foo=1)(bar=2)) == (&(bar=2)(foo=1))

I would expect to be true. Note that this may not be an identical comparison in terms of performance. E.g.

if long_comparison_operation() and short_comparison_operation():
    ...

This would be logically equivalent to the following statement, but not necessarily the same in terms of performance:

if short_comparison_operation() and long_comparison_operation():
    ...

We can avoid making the second comparison operation if the first one is false, and thus avoid the long comparison operation.

In terms of actual behavior within this codebase, I'd like to see something like the following work:

from ldaptor.protocols import pureldap

filter1 = pureldap.LDAPFilter_and([
    pureldap.LDAPFilter_equalityMatch(
        attributeDesc=pureldap.LDAPAttributeDescription('foo'),
        assertionValue=pureldap.LDAPAttributeValue('1')
    ),
    pureldap.LDAPFilter_equalityMatch(
        attributeDesc=pureldap.LDAPAttributeDescription('bar'),
        assertionValue=pureldap.LDAPAttributeValue('2')
    ),
])
filter2 = pureldap.LDAPFilter_and([
    pureldap.LDAPFilter_equalityMatch(
        attributeDesc=pureldap.LDAPAttributeDescription('bar'),
        assertionValue=pureldap.LDAPAttributeValue('2')
    ),
    pureldap.LDAPFilter_equalityMatch(
        attributeDesc=pureldap.LDAPAttributeDescription('foo'),
        assertionValue=pureldap.LDAPAttributeValue('1')
    ),
])
                                                                
assert filter1 == filter2

Why would we want to perform comparisons like this? We could imagine some unordered LDAP filter generation strategy where we'd like to confirm two filters are equivalent. For example, consider a Python dict (unordered key: value pairs) that is eventually converted to an LDAP filter. We may want to confirm that LDAP filters are logically equivalent, but not necessarily the exact same string or LDAPFilter_* object. E.g.

filter1 = {
    'attribute1': 'value1',
    'attribute2': 'value2',
}

filter2 = {
    'attribute1': 'value1',
    'attribute2': 'value2',
}

We're not guaranteed an ordering if we do something like filter1.items(), but it's conceivable an LDAP filter could be generated from this dict. Further, it's conceivable we'd like to confirm two of these LDAP filters generated from unordered dicts are equivalent.

I have a PR in mind for implementing this behavior, but I opened this issue to A.) ensure this is something we should be considering and B.) open the door for other options than my PR implementation.

Let me know what you think!

Fix equality and hash for BaseLDAPEntry

Equality is implemented as

    def __eq__(self, other):
        if not isinstance(other, BaseLDAPEntry):
            return NotImplemented
        if self.dn != other.dn:
            return 0

        my = self.keys()
        my.sort()
        its = other.keys()
        its.sort()
        if my != its:
            return 0
        for key in my:
            myAttr = self[key]
            itsAttr = other[key]
            if myAttr != itsAttr:
                return 0
        return 1

while hash as

    def __hash__(self):
        return hash(self.dn)

I think that this is wrong is it can lead to objects with same hash but which are not equal.

Allow BIND using UPN to fake a AD LDAP server.

Not sure if someone can find it useful.

Active Directory LDAP implementation allows to bind using UPN ([email protected]) or down-level logon name (user\domain)

I am using ldaptor to support the testing for an ldap client code.

For some unit / integration tests for me is easier to use ldaptor, so I have created this modified server which allows to bind using something similar to an UPN

Code is here

https://gist.github.com/adiroiban/cc60a78e0275e07869e3ed1fb0114621

If there is interest, I can look at pushing a PR... but the code is not designed for production :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.