diff --git a/swift/common/swob.py b/swift/common/swob.py index 26e0bf912e..69f4f2f694 100644 --- a/swift/common/swob.py +++ b/swift/common/swob.py @@ -1215,7 +1215,7 @@ class Response(object): realm = 'unknown' except (AttributeError, ValueError): realm = 'unknown' - return 'Swift realm="%s"' % realm + return 'Swift realm="%s"' % urllib2.quote(realm) @property def is_success(self): diff --git a/test/functional/tests.py b/test/functional/tests.py index 250efe2717..b6dbce377b 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -268,6 +268,19 @@ class TestAccount(Base): self.assertEqual(sorted(containers, cmp=locale.strcoll), containers) + def testQuotedWWWAuthenticateHeader(self): + conn = Connection(tf.config) + conn.authenticate() + inserted_html = 'Hello World' + hax = 'AUTH_haxx"\nContent-Length: %d\n\n%s' % (len(inserted_html), + inserted_html) + quoted_hax = urllib.quote(hax) + conn.connection.request('GET', '/v1/' + quoted_hax, None, {}) + resp = conn.connection.getresponse() + resp_headers = resp.getheaders() + expected = ('www-authenticate', 'Swift realm="%s"' % quoted_hax) + self.assert_(expected in resp_headers) + class TestAccountUTF8(Base2, TestAccount): set_up = False diff --git a/test/unit/common/test_swob.py b/test/unit/common/test_swob.py index b3a0a9329b..5ced5b68d9 100644 --- a/test/unit/common/test_swob.py +++ b/test/unit/common/test_swob.py @@ -601,6 +601,28 @@ class TestRequest(unittest.TestCase): self.assertEquals('Me realm="whatever"', resp.headers['Www-Authenticate']) + def test_401_www_authenticate_is_quoted(self): + + def test_app(environ, start_response): + start_response('401 Unauthorized', []) + return ['hi'] + + hacker = 'account-name\n\nfoo
' # url injection test + quoted_hacker = quote(hacker) + req = swift.common.swob.Request.blank('/v1/' + hacker) + resp = req.get_response(test_app) + self.assertEquals(resp.status_int, 401) + self.assert_('Www-Authenticate' in resp.headers) + self.assertEquals('Swift realm="%s"' % quoted_hacker, + resp.headers['Www-Authenticate']) + + req = swift.common.swob.Request.blank('/v1/' + quoted_hacker) + resp = req.get_response(test_app) + self.assertEquals(resp.status_int, 401) + self.assert_('Www-Authenticate' in resp.headers) + self.assertEquals('Swift realm="%s"' % quoted_hacker, + resp.headers['Www-Authenticate']) + def test_not_401(self): # Other status codes should not have WWW-Authenticate in response