Repository: buildbot/buildbot

Issue:
Uninitialized ASN.1 value when using LdapUserInfo
After updating some Python packages, I got the following exception on login:

```
        Traceback (most recent call last):
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1442, in gotResult
            _inlineCallbacks(r, g, deferred)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1432, in _inlineCallbacks
            deferred.errback()
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 500, in errback
            self._startRunCallbacks(fail)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 567, in _startRunCallbacks
            self._runCallbacks()
        --- <exception caught here> ---
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks
            current.result = callback(current.result, *args, **kw)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/buildbot/www/resource.py", line 91, in failHttpError
            f.trap(Error)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/python/failure.py", line 346, in trap
            self.raiseException()
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks
            current.result = callback(current.result, *args, **kw)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/buildbot/www/resource.py", line 84, in failHttpRedirect
            f.trap(Redirect)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/python/failure.py", line 346, in trap
            self.raiseException()
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1384, in _inlineCallbacks
            result = result.throwExceptionIntoGenerator(g)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/python/failure.py", line 393, in throwExceptionIntoGenerator
            return g.throw(self.type, self.value, self.tb)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/buildbot/www/oauth2.py", line 67, in renderLogin
            infos = yield self.auth.userInfoProvider.getUserInfo(details['username'])
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/python/threadpool.py", line 250, in inContext
            result = inContext.theWork()
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/python/threadpool.py", line 266, in <lambda>
            inContext.theWork = lambda: context.call(ctx, func, *args, **kw)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/python/context.py", line 122, in callWithContext
            return self.currentContext().callWithContext(ctx, func, *args, **kw)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/twisted/python/context.py", line 85, in callWithContext
            return func(*args,**kw)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/buildbot/www/ldapuserinfo.py", line 92, in thd
            c = self.connectLdap()
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/buildbot/www/ldapuserinfo.py", line 82, in connectLdap
            authentication=auth)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/ldap3/core/connection.py", line 278, in __init__
            self.bind(read_server_info=True)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/ldap3/core/connection.py", line 427, in bind
            response = self.post_send_single_response(self.send('bindRequest', request, controls))
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/ldap3/strategy/sync.py", line 122, in post_send_single_response
            responses, result = self.get_response(message_id)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/ldap3/strategy/base.py", line 298, in get_response
            responses = self._get_response(message_id)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/ldap3/strategy/sync.py", line 168, in _get_response
            dict_response = self.decode_response(ldap_resp)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/ldap3/strategy/base.py", line 403, in decode_response
            result = bind_response_to_dict(component)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/ldap3/operation/bind.py", line 119, in bind_response_to_dict
            'saslCreds': bytes(response['serverSaslCreds']) if response['serverSaslCreds'] is not None else None}
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/pyasn1/type/univ.py", line 939, in __str__
            return str(self._value)
          File "/home/buibot00/venv/bb_twisted_test/local/lib/python2.7/site-packages/pyasn1/type/base.py", line 186, in plug
            raise error.PyAsn1Error('Uninitialized ASN.1 value ("%s" attribute looked up)' % name)
        pyasn1.error.PyAsn1Error: Uninitialized ASN.1 value ("__str__" attribute looked up)
```

The problem disappeared after downgrading pyasn1 from 0.3.2 to the version 0.1.9, which I used before.


Discussion:
from the trace, it rather looks like a problem in ldap3 module, which is used by ldapuserinfo. Do you have latest ldap3 module? if not, I think you should post a bug in ldap3 module.

Well it seems like python3-ldap is discontinued and the package ldap3 is the successor. But using ldap3 results in error with Buildbot 0.9.10.
Is there a reason why Buildbot requires python3-ldap?

Btw for some reason I can't access the latest Buildbot documentation under http://docs.buildbot.net/latest/manual
I believe at the time where LdapUserInfo was written, ldap3 module was not there or I couldn't find it.
Would you like to contribute and update the code to use ldap3? There are only 130 lines of code, plus the tests to update. I don't think this will be too hard.
Also, ldap3 looks like much easier to use and well designed than python3-ldap.
I don't know, as much as I would like to help, I'm currently quite busy and don't know if or when I'll find the time to look at it.
I'll see what I can do, but would also be happy if someone else finds the time to do it.
btw thanks for reporting issue with docs. Its now fixed.
> btw thanks for reporting issue with docs. Its now fixed.

You're welcome, but I still get 403 at http://docs.buildbot.net/latest/ and 404 at http://docs.buildbot.net/latest/manual.

Resolving patch:
diff --git a/master/buildbot/www/ldapuserinfo.py b/master/buildbot/www/ldapuserinfo.py
--- a/master/buildbot/www/ldapuserinfo.py
+++ b/master/buildbot/www/ldapuserinfo.py
@@ -71,20 +71,19 @@ def connectLdap(self):
         netloc = server.netloc.split(":")
         # define the server and the connection
         s = ldap3.Server(netloc[0], port=int(netloc[1]), use_ssl=server.scheme == 'ldaps',
-                         get_info=ldap3.GET_ALL_INFO)
+                         get_info=ldap3.ALL)
 
-        auth = ldap3.AUTH_SIMPLE
+        auth = ldap3.SIMPLE
         if self.bindUser is None and self.bindPw is None:
-            auth = ldap3.AUTH_ANONYMOUS
+            auth = ldap3.ANONYMOUS
 
-        c = ldap3.Connection(s, auto_bind=True, client_strategy=ldap3.STRATEGY_SYNC,
+        c = ldap3.Connection(s, auto_bind=True, client_strategy=ldap3.SYNC,
                              user=self.bindUser, password=self.bindPw,
                              authentication=auth)
         return c
 
     def search(self, c, base, filterstr='f', attributes=None):
-        c.search(
-            base, filterstr, ldap3.SEARCH_SCOPE_WHOLE_SUBTREE, attributes=attributes)
+        c.search(base, filterstr, ldap3.SUBTREE, attributes=attributes)
         return c.response
 
     def getUserInfo(self, username):


Test patch:
diff --git a/master/buildbot/test/unit/test_www_ldapuserinfo.py b/master/buildbot/test/unit/test_www_ldapuserinfo.py
--- a/master/buildbot/test/unit/test_www_ldapuserinfo.py
+++ b/master/buildbot/test/unit/test_www_ldapuserinfo.py
@@ -44,7 +44,7 @@ class CommonTestCase(unittest.TestCase):
 
     """Common fixture for all ldapuserinfo tests
 
-    we completely fake the python3-ldap module, so no need to require
+    we completely fake the ldap3 module, so no need to require
     it to run the unit tests
     """