AWSTest.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <?php
  2. declare(strict_types=1);
  3. namespace Sabre\HTTP\Auth;
  4. use Sabre\HTTP\Request;
  5. use Sabre\HTTP\Response;
  6. class AWSTest extends \PHPUnit\Framework\TestCase
  7. {
  8. /**
  9. * @var Sabre\HTTP\Response
  10. */
  11. private $response;
  12. /**
  13. * @var Sabre\HTTP\Request
  14. */
  15. private $request;
  16. /**
  17. * @var Sabre\HTTP\Auth\AWS
  18. */
  19. private $auth;
  20. public const REALM = 'SabreDAV unittest';
  21. public function setUp(): void
  22. {
  23. $this->response = new Response();
  24. $this->request = new Request('GET', '/');
  25. $this->auth = new AWS(self::REALM, $this->request, $this->response);
  26. }
  27. public function testNoHeader()
  28. {
  29. $this->request->setMethod('GET');
  30. $result = $this->auth->init();
  31. $this->assertFalse($result, 'No AWS Authorization header was supplied, so we should have gotten false');
  32. $this->assertEquals(AWS::ERR_NOAWSHEADER, $this->auth->errorCode);
  33. }
  34. public function testInvalidAuthorizationHeader()
  35. {
  36. $this->request->setMethod('GET');
  37. $this->request->setHeader('Authorization', 'Invalid Auth Header');
  38. $this->assertFalse($this->auth->init(), 'The Invalid AWS authorization header');
  39. }
  40. public function testIncorrectContentMD5()
  41. {
  42. $accessKey = 'accessKey';
  43. $secretKey = 'secretKey';
  44. $this->request->setMethod('GET');
  45. $this->request->setHeaders([
  46. 'Authorization' => "AWS $accessKey:sig",
  47. 'Content-MD5' => 'garbage',
  48. ]);
  49. $this->request->setUrl('/');
  50. $this->auth->init();
  51. $result = $this->auth->validate($secretKey);
  52. $this->assertFalse($result);
  53. $this->assertEquals(AWS::ERR_MD5CHECKSUMWRONG, $this->auth->errorCode);
  54. }
  55. public function testNoDate()
  56. {
  57. $accessKey = 'accessKey';
  58. $secretKey = 'secretKey';
  59. $content = 'thisisthebody';
  60. $contentMD5 = base64_encode(md5($content, true));
  61. $this->request->setMethod('POST');
  62. $this->request->setHeaders([
  63. 'Authorization' => "AWS $accessKey:sig",
  64. 'Content-MD5' => $contentMD5,
  65. ]);
  66. $this->request->setUrl('/');
  67. $this->request->setBody($content);
  68. $this->auth->init();
  69. $result = $this->auth->validate($secretKey);
  70. $this->assertFalse($result);
  71. $this->assertEquals(AWS::ERR_INVALIDDATEFORMAT, $this->auth->errorCode);
  72. }
  73. public function testFutureDate()
  74. {
  75. $accessKey = 'accessKey';
  76. $secretKey = 'secretKey';
  77. $content = 'thisisthebody';
  78. $contentMD5 = base64_encode(md5($content, true));
  79. $date = new \DateTime('@'.(time() + (60 * 20)));
  80. $date->setTimeZone(new \DateTimeZone('GMT'));
  81. $date = $date->format('D, d M Y H:i:s \\G\\M\\T');
  82. $this->request->setMethod('POST');
  83. $this->request->setHeaders([
  84. 'Authorization' => "AWS $accessKey:sig",
  85. 'Content-MD5' => $contentMD5,
  86. 'Date' => $date,
  87. ]);
  88. $this->request->setBody($content);
  89. $this->auth->init();
  90. $result = $this->auth->validate($secretKey);
  91. $this->assertFalse($result);
  92. $this->assertEquals(AWS::ERR_REQUESTTIMESKEWED, $this->auth->errorCode);
  93. }
  94. public function testPastDate()
  95. {
  96. $accessKey = 'accessKey';
  97. $secretKey = 'secretKey';
  98. $content = 'thisisthebody';
  99. $contentMD5 = base64_encode(md5($content, true));
  100. $date = new \DateTime('@'.(time() - (60 * 20)));
  101. $date->setTimeZone(new \DateTimeZone('GMT'));
  102. $date = $date->format('D, d M Y H:i:s \\G\\M\\T');
  103. $this->request->setMethod('POST');
  104. $this->request->setHeaders([
  105. 'Authorization' => "AWS $accessKey:sig",
  106. 'Content-MD5' => $contentMD5,
  107. 'Date' => $date,
  108. ]);
  109. $this->request->setBody($content);
  110. $this->auth->init();
  111. $result = $this->auth->validate($secretKey);
  112. $this->assertFalse($result);
  113. $this->assertEquals(AWS::ERR_REQUESTTIMESKEWED, $this->auth->errorCode);
  114. }
  115. public function testIncorrectSignature()
  116. {
  117. $accessKey = 'accessKey';
  118. $secretKey = 'secretKey';
  119. $content = 'thisisthebody';
  120. $contentMD5 = base64_encode(md5($content, true));
  121. $date = new \DateTime('now');
  122. $date->setTimeZone(new \DateTimeZone('GMT'));
  123. $date = $date->format('D, d M Y H:i:s \\G\\M\\T');
  124. $this->request->setUrl('/');
  125. $this->request->setMethod('POST');
  126. $this->request->setHeaders([
  127. 'Authorization' => "AWS $accessKey:sig",
  128. 'Content-MD5' => $contentMD5,
  129. 'X-amz-date' => $date,
  130. ]);
  131. $this->request->setBody($content);
  132. $this->auth->init();
  133. $result = $this->auth->validate($secretKey);
  134. $this->assertFalse($result);
  135. $this->assertEquals(AWS::ERR_INVALIDSIGNATURE, $this->auth->errorCode);
  136. }
  137. public function testValidRequest()
  138. {
  139. $accessKey = 'accessKey';
  140. $secretKey = 'secretKey';
  141. $content = 'thisisthebody';
  142. $contentMD5 = base64_encode(md5($content, true));
  143. $date = new \DateTime('now');
  144. $date->setTimeZone(new \DateTimeZone('GMT'));
  145. $date = $date->format('D, d M Y H:i:s \\G\\M\\T');
  146. $sig = base64_encode($this->hmacsha1($secretKey,
  147. "POST\n$contentMD5\n\n$date\nx-amz-date:$date\n/evert"
  148. ));
  149. $this->request->setUrl('/evert');
  150. $this->request->setMethod('POST');
  151. $this->request->setHeaders([
  152. 'Authorization' => "AWS $accessKey:$sig",
  153. 'Content-MD5' => $contentMD5,
  154. 'X-amz-date' => $date,
  155. ]);
  156. $this->request->setBody($content);
  157. $this->auth->init();
  158. $result = $this->auth->validate($secretKey);
  159. $this->assertTrue($result, 'Signature did not validate, got errorcode '.$this->auth->errorCode);
  160. $this->assertEquals($accessKey, $this->auth->getAccessKey());
  161. }
  162. public function test401()
  163. {
  164. $this->auth->requireLogin();
  165. $test = preg_match('/^AWS$/', $this->response->getHeader('WWW-Authenticate'), $matches);
  166. $this->assertTrue(true == $test, 'The WWW-Authenticate response didn\'t match our pattern');
  167. }
  168. /**
  169. * Generates an HMAC-SHA1 signature.
  170. *
  171. * @param string $key
  172. * @param string $message
  173. *
  174. * @return string
  175. */
  176. private function hmacsha1($key, $message)
  177. {
  178. $blocksize = 64;
  179. if (strlen($key) > $blocksize) {
  180. $key = pack('H*', sha1($key));
  181. }
  182. $key = str_pad($key, $blocksize, chr(0x00));
  183. $ipad = str_repeat(chr(0x36), $blocksize);
  184. $opad = str_repeat(chr(0x5C), $blocksize);
  185. $hmac = pack('H*', sha1(($key ^ $opad).pack('H*', sha1(($key ^ $ipad).$message))));
  186. return $hmac;
  187. }
  188. }