summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorj0hnsmith <info@whywouldwe.com>2015-08-20 07:33:46 +0100
committerj0hnsmith <info@whywouldwe.com>2015-08-20 07:33:46 +0100
commit21d381f45d278e3049515a82a65608aadf07a289 (patch)
tree0f4c8a688b5cbdf6a4523be9eb77f9b3e8e75663
parent48fe401c78eb1b1048cd20e2d26015585a7986cb (diff)
downloadpython-requests-aws-21d381f45d278e3049515a82a65608aadf07a289.tar.gz
fix invalid signature when params dict used with mp uploadId containing =
-rw-r--r--awsauth.py35
1 files 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