From 21d381f45d278e3049515a82a65608aadf07a289 Mon Sep 17 00:00:00 2001 From: j0hnsmith Date: Thu, 20 Aug 2015 07:33:46 +0100 Subject: fix invalid signature when params dict used with mp uploadId containing = --- awsauth.py | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/awsauth.py b/awsauth.py index c3d5c0a..9414420 100644 --- a/awsauth.py +++ b/awsauth.py @@ -2,6 +2,8 @@ import hmac from hashlib import sha1 as sha +import urllib + py3k = False try: from urlparse import urlparse @@ -115,9 +117,34 @@ class S3Auth(AuthBase): for q in query_args: k = q.split('=')[0] if k in self.special_params: - if params_found: - buf += '&%s' % q - else: - buf += '?%s' % q + buf += '&' if params_found else '?' params_found = True + + try: + k, v = q.split('=', 1) + + except ValueError: + buf += q + + else: + # Riak CS multipart upload ids look like this, `TFDSheOgTxC2Tsh1qVK73A==`, is should be escaped to + # be included as part of a query string. + # + # A requests mp upload part request may look like + # resp = requests.put( + # 'https://url_here', + # params={ + # 'partNumber': 1, + # 'uploadId': 'TFDSheOgTxC2Tsh1qVK73A==' + # }, + # data='some data', + # auth=S3Auth('access_key', 'secret_key') + # ) + # + # Requests automatically escapes the values in the `params` dict, so now our uploadId is + # `TFDSheOgTxC2Tsh1qVK73A%3D%3D`, if we sign the request with the encoded value the signature will + # not be valid, we'll get 403 Access Denied. + # So we unquote, this is no-op if the value isn't encoded. + buf += '{}={}'.format(k, urllib.unquote(v)) + return buf -- cgit v1.2.1