Changeset - 18c9eb22c29c
[Not reviewed]
stable
0 1 0
Robert James Dennington - 10 years ago 2016-01-15 15:38:27
tinytimrob@googlemail.com
auth: Fix tomcat throwing '505 HTTP Version Not Supported' when trying to log in to Atlassian Crowd with usernames that contain spaces

If you try to log in to Kallithea via the Crowd auth module, and the username
contains a space, it fails. Tomcat on the Crowd server gives error '505 HTTP
Version Not Supported'.

Further investigation showed that the username was not being quoted. E.g. for
the user 'test account', the REST URL should contain 'test%20account' but
actually was containing 'test account'. When Tomcat received this HTTP request
it interprets the word 'account' as the HTTP version because of the space. This
obviously isn't a valid HTTP version.

This bug is fixed by using urllib2.quote on the username to ensure that special
characters are correctly quoted. After making that change on my local install,
the user 'test account' was able to log in successfully.
1 file changed with 2 insertions and 2 deletions:
0 comments (0 inline, 0 general)
kallithea/lib/auth_modules/auth_crowd.py
Show inline comments
 
@@ -74,104 +74,104 @@ class CrowdServer(object):
 
        mgr.add_password(None, self._uri, self.user, self.passwd)
 
        handler = urllib2.HTTPBasicAuthHandler(mgr)
 
        self.opener = urllib2.build_opener(handler)
 

	
 
    def _request(self, url, body=None, headers=None,
 
                 method=None, noformat=False,
 
                 empty_response_ok=False):
 
        _headers = {"Content-type": "application/json",
 
                    "Accept": "application/json"}
 
        if self.user and self.passwd:
 
            authstring = base64.b64encode("%s:%s" % (self.user, self.passwd))
 
            _headers["Authorization"] = "Basic %s" % authstring
 
        if headers:
 
            _headers.update(headers)
 
        log.debug("Sent crowd: \n%s",
 
                  formatted_json({"url": url, "body": body,
 
                                           "headers": _headers}))
 
        request = urllib2.Request(url, body, _headers)
 
        if method:
 
            request.get_method = lambda: method
 

	
 
        global msg
 
        msg = ""
 
        try:
 
            rdoc = self.opener.open(request)
 
            msg = "".join(rdoc.readlines())
 
            if not msg and empty_response_ok:
 
                rval = {}
 
                rval["status"] = True
 
                rval["error"] = "Response body was empty"
 
            elif not noformat:
 
                rval = json.loads(msg)
 
                rval["status"] = True
 
            else:
 
                rval = "".join(rdoc.readlines())
 
        except Exception as e:
 
            if not noformat:
 
                rval = {"status": False,
 
                        "body": body,
 
                        "error": str(e) + "\n" + msg}
 
            else:
 
                rval = None
 
        return rval
 

	
 
    def user_auth(self, username, password):
 
        """Authenticate a user against crowd. Returns brief information about
 
        the user."""
 
        url = ("%s/rest/usermanagement/%s/authentication?username=%s"
 
               % (self._uri, self._version, username))
 
               % (self._uri, self._version, urllib2.quote(username)))
 
        body = json.dumps({"value": password})
 
        return self._request(url, body)
 

	
 
    def user_groups(self, username):
 
        """Retrieve a list of groups to which this user belongs."""
 
        url = ("%s/rest/usermanagement/%s/user/group/nested?username=%s"
 
               % (self._uri, self._version, username))
 
               % (self._uri, self._version, urllib2.quote(username)))
 
        return self._request(url)
 

	
 

	
 
class KallitheaAuthPlugin(auth_modules.KallitheaExternalAuthPlugin):
 

	
 
    @hybrid_property
 
    def name(self):
 
        return "crowd"
 

	
 
    def settings(self):
 
        settings = [
 
            {
 
                "name": "host",
 
                "validator": self.validators.UnicodeString(strip=True),
 
                "type": "string",
 
                "description": "The FQDN or IP of the Atlassian CROWD Server",
 
                "default": "127.0.0.1",
 
                "formname": "Host"
 
            },
 
            {
 
                "name": "port",
 
                "validator": self.validators.Number(strip=True),
 
                "type": "int",
 
                "description": "The Port in use by the Atlassian CROWD Server",
 
                "default": 8095,
 
                "formname": "Port"
 
            },
 
            {
 
                "name": "app_name",
 
                "validator": self.validators.UnicodeString(strip=True),
 
                "type": "string",
 
                "description": "The Application Name to authenticate to CROWD",
 
                "default": "",
 
                "formname": "Application Name"
 
            },
 
            {
 
                "name": "app_password",
 
                "validator": self.validators.UnicodeString(strip=True),
 
                "type": "string",
 
                "description": "The password to authenticate to CROWD",
 
                "default": "",
 
                "formname": "Application Password"
 
            },
 
            {
 
                "name": "admin_groups",
 
                "validator": self.validators.UnicodeString(strip=True),
 
                "type": "string",
 
                "description": "A comma separated list of group names that identify users as Kallithea Administrators",
0 comments (0 inline, 0 general)