From 009b029bfc33448fdf4621773bba29fe661361d6 Mon Sep 17 00:00:00 2001 From: Jeremy Lindblom Date: Tue, 16 Jun 2015 11:13:00 -0700 Subject: [PATCH] Fixing an issue with path encoding in SigV4 that affects the Cognito services. --- src/Signature/S3SignatureV4.php | 8 ++++++++ src/Signature/SignatureV4.php | 9 ++++++++- tests/Signature/SignatureV4Test.php | 4 ++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Signature/S3SignatureV4.php b/src/Signature/S3SignatureV4.php index 73f92fbc47..ce7baf1b3b 100644 --- a/src/Signature/S3SignatureV4.php +++ b/src/Signature/S3SignatureV4.php @@ -34,4 +34,12 @@ protected function getPresignedPayload(RequestInterface $request) { return 'UNSIGNED-PAYLOAD'; } + + /** + * Amazon S3 does not double-encode the path component in the canonical request + */ + protected function createCanonicalizedPath($path) + { + return '/' . ltrim($path, '/'); + } } diff --git a/src/Signature/SignatureV4.php b/src/Signature/SignatureV4.php index 95e6324b24..e864e80118 100644 --- a/src/Signature/SignatureV4.php +++ b/src/Signature/SignatureV4.php @@ -154,6 +154,13 @@ protected function getPresignedPayload(RequestInterface $request) return $this->getPayload($request); } + protected function createCanonicalizedPath($path) + { + $doubleEncoded = rawurlencode(ltrim($path, '/')); + + return '/' . str_replace('%2F', '/', $doubleEncoded); + } + private function createStringToSign($longDate, $credentialScope, $creq) { $hash = hash('sha256', $creq); @@ -209,7 +216,7 @@ private function createContext(array $parsedRequest, $payload) // Normalize the path as required by SigV4 $canon = $parsedRequest['method'] . "\n" - . ($parsedRequest['path'] ?: '/') . "\n" + . $this->createCanonicalizedPath($parsedRequest['path']) . "\n" . $this->getCanonicalizedQuery($parsedRequest['query']) . "\n"; // Case-insensitively aggregate all of the headers. diff --git a/tests/Signature/SignatureV4Test.php b/tests/Signature/SignatureV4Test.php index e3bbf65ac4..6fffc64ce7 100644 --- a/tests/Signature/SignatureV4Test.php +++ b/tests/Signature/SignatureV4Test.php @@ -227,8 +227,8 @@ public function testProvider() // Request with space. [ "GET /%20/foo HTTP/1.1\r\nHost: host.foo.com\r\n\r\n", - "GET /%20/foo HTTP/1.1\r\nHost: host.foo.com\r\nX-Amz-Date: 20110909T233600Z\r\nAuthorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=host;x-amz-date, Signature=21c06f2350d850ddc3bb8a463336cb6677214463f29c5354f6678e9efe195712\r\n\r\n", - "GET\n/%20/foo\n\nhost:host.foo.com\n\nhost\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + "GET /%20/foo HTTP/1.1\r\nHost: host.foo.com\r\nX-Amz-Date: 20110909T233600Z\r\nAuthorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=host;x-amz-date, Signature=948b2292a8bcb4510013741d64c5667f75d46dd6c4896ead5d669eb8264ebe1f\r\n\r\n", + "GET\n/%2520/foo\n\nhost:host.foo.com\n\nhost\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ], // Query order key case. [