From d18b6d8d5d6ca8c0adf3b98b488042c49394a072 Mon Sep 17 00:00:00 2001 From: Samuel Merritt Date: Thu, 21 Nov 2013 17:39:56 -0800 Subject: [PATCH] Fix HEAD tempurls HEAD-only tempurls didn't work; tempurl only allowed a HEAD request if the tempurl was generated for GET or PUT (that is, the method in the HMAC-signed string was "GET" or "PUT"). The intent of the code was to allow a user with a GET or a PUT tempurl to also perform a HEAD request; I think the breaking of HEAD tempurls is just a bug. Change-Id: I621ddaac03e0d058dd9e7c7c374cb5c4b6386d36 --- swift/common/middleware/tempurl.py | 22 ++++++++++++--------- test/unit/common/middleware/test_tempurl.py | 15 ++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/swift/common/middleware/tempurl.py b/swift/common/middleware/tempurl.py index 59ad206545..2b91ee8815 100644 --- a/swift/common/middleware/tempurl.py +++ b/swift/common/middleware/tempurl.py @@ -267,17 +267,16 @@ class TempURL(object): if not keys: return self._invalid(env, start_response) if env['REQUEST_METHOD'] == 'HEAD': - hmac_vals = self._get_hmacs(env, temp_url_expires, keys, - request_method='GET') - if temp_url_sig not in hmac_vals: - hmac_vals = self._get_hmacs(env, temp_url_expires, keys, - request_method='PUT') - if temp_url_sig not in hmac_vals: - return self._invalid(env, start_response) + hmac_vals = ( + self._get_hmacs(env, temp_url_expires, keys) + + self._get_hmacs(env, temp_url_expires, keys, + request_method='GET') + + self._get_hmacs(env, temp_url_expires, keys, + request_method='PUT')) else: hmac_vals = self._get_hmacs(env, temp_url_expires, keys) - if temp_url_sig not in hmac_vals: - return self._invalid(env, start_response) + if temp_url_sig not in hmac_vals: + return self._invalid(env, start_response) self._clean_incoming_headers(env) env['swift.authorize'] = lambda req: None env['swift.authorize_override'] = True @@ -387,6 +386,11 @@ class TempURL(object): expires. :param keys: Key strings, from the X-Account-Meta-Temp-URL-Key[-2] of the account. + :param request_method: Optional override of the request in + the WSGI env. For example, if a HEAD + does not match, you may wish to + override with GET to still allow the + HEAD. """ if not request_method: request_method = env['REQUEST_METHOD'] diff --git a/test/unit/common/middleware/test_tempurl.py b/test/unit/common/middleware/test_tempurl.py index a462b7a64b..c2a9e1c27a 100644 --- a/test/unit/common/middleware/test_tempurl.py +++ b/test/unit/common/middleware/test_tempurl.py @@ -146,6 +146,21 @@ class TestTempURL(unittest.TestCase): self.assertEquals(req.environ['swift.authorize_override'], True) self.assertEquals(req.environ['REMOTE_USER'], '.wsgi.tempurl') + def test_head_valid(self): + method = 'HEAD' + expires = int(time() + 86400) + path = '/v1/a/c/o' + key = 'abc' + hmac_body = '%s\n%s\n%s' % (method, expires, path) + sig = hmac.new(key, hmac_body, sha1).hexdigest() + req = self._make_request(path, keys=[key], environ={ + 'REQUEST_METHOD': 'HEAD', + 'QUERY_STRING': 'temp_url_sig=%s&temp_url_expires=%s' + % (sig, expires)}) + self.tempurl.app = FakeApp(iter([('200 Ok', (), '123')])) + resp = req.get_response(self.tempurl) + self.assertEquals(resp.status_int, 200) + def test_get_valid_with_filename_and_inline(self): method = 'GET' expires = int(time() + 86400)