ldaptor icon indicating copy to clipboard operation
ldaptor copied to clipboard

None is neither bytes nor unicode

Open alvaro-gh opened this issue 7 years ago • 4 comments
trafficstars

I'm trying to set up the merger example and I don't know why default bindAddress=None is not working at https://github.com/twisted/ldaptor/blob/4e2b67798b75e0c2b364fc0d9fdf327b0f0ddca4/ldaptor/protocols/ldap/ldapconnector.py#L29

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

alvaro-gh avatar Jan 18 '18 21:01 alvaro-gh

What version of Twisted are you running?

psi29a avatar Jan 19 '18 06:01 psi29a

Hi @psi29a, thanks for replying.

root@7cfc500925db:~# pip list | grep Twisted
Twisted (17.9.0) 

I realized thanks to your reply that I've been looking at master code which obviously differs from my site-package install. So, the error is raised at line 77 of twisted/names/srvconnect.py:

self.domain = nativeString(domain)

In merger.py an LDAPClientCreator is instantiated which uses an LDAPConnector that is a subclass of SRVConnector. My LDAPConnector code is the following:

class LDAPConnector(SRVConnector):
    def __init__(self, reactor, dn, factory,
                 overrides=None, bindAddress=None):
        if not isinstance(dn, distinguishedname.DistinguishedName):
            dn = distinguishedname.DistinguishedName(stringValue=dn)
        if overrides is None:
            overrides={}
        self.override = self._findOverRide(dn, overrides)

        domain = dn.getDomainName()
        SRVConnector.__init__(self, reactor,
                  'ldap', domain, factory,
                  connectFuncKwArgs={'bindAddress': bindAddress})

And master is:

class LDAPConnector(SRVConnector):
    def __init__(self, reactor, dn, factory,
                 overrides=None, bindAddress=None):
        if not isinstance(dn, distinguishedname.DistinguishedName):
            dn = distinguishedname.DistinguishedName(stringValue=dn)
        if overrides is None:
            overrides = {}
        self.override = self._findOverRide(dn, overrides)

        domain = dn.getDomainName() or ''
        SRVConnector.__init__(self, reactor,
                  'ldap', domain, factory,
connectFuncKwArgs={'bindAddress': bindAddress})

As you can see, domain variable in master code gets an empty string default and there's no error. I apologize for creating and issue and overlooking the version I was using. Thanks again for your guidance.

alvaro-gh avatar Jan 19 '18 13:01 alvaro-gh

Hi, I fall on the same problem when I tried to run a code which worked on Ubuntu Xenial 16.04 (twisted 16.0.0) on Ubuntu Bionic 18.04 (twisted 17.9.0). Thanks to this report, I have a workaround. Could Ldaptor maintainers ask Ubuntu for upgrading the packaged version ? Ldaptor 0.0.43 is provided for many years now : https://launchpad.net/ldaptor/+packages ;) Thanks.

jojo2024 avatar Apr 30 '18 15:04 jojo2024

It looks like thats the bug I'm hitting in https://github.com/twisted/ldaptor/issues/113 However, I did not get what the workaround was and why it was broken in the first place (version 18.7.0 for twisted, and 16.0.0 for ldaptor).

Edit: I apologize I did not read carefully enough the diff between both versions, I guess I’ll either patch the released version or just avoid running known failing tests...

nado avatar Oct 09 '18 14:10 nado