You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
3.9 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <?php
  2. namespace p3k\HTTP\Tests;
  3. use p3k\HTTP;
  4. use PHPUnit\Framework\TestCase;
  5. class SafeModeTest extends TestCase {
  6. const DNS = [
  7. 'a.example' => ['93.184.216.34'],
  8. 'b.example' => ['93.184.216.35', '2606:2800:220:1::'],
  9. 'internal.example' => ['10.0.0.5'],
  10. ];
  11. private function http(array $responses, &$transport) {
  12. $transport = new RecordingTransport($responses);
  13. $http = new HTTP('test', $transport);
  14. $http->set_safe_mode(true, [], function($host) { return self::DNS[$host] ?? []; });
  15. return $http;
  16. }
  17. public function testBlockedUrlMakesNoRequest() {
  18. $http = $this->http([], $transport);
  19. foreach(['gopher://127.0.0.1:6379/_FLUSHALL', 'file:///etc/passwd', 'http://127.0.0.1/', 'https://internal.example/'] as $url) {
  20. $response = $http->post($url, 'x');
  21. $this->assertSame('blocked_url', $response['error'], $url);
  22. $this->assertSame(0, $response['code']);
  23. }
  24. $this->assertSame([], $transport->requests);
  25. }
  26. public function testRequestIsPinnedToCheckedAddresses() {
  27. $http = $this->http(['https://b.example/' => [200, '', 'ok']], $transport);
  28. $response = $http->get('https://b.example/');
  29. $this->assertSame(200, $response['code']);
  30. $this->assertSame(['b.example:443:93.184.216.35,[2606:2800:220:1::]'], $transport->requests[0]['pinned']);
  31. $this->assertSame(0, $transport->max_redirects);
  32. }
  33. public function testRedirectToPrivateAddressIsRefused() {
  34. $http = $this->http([
  35. 'https://a.example/' => [302, "Location: http://169.254.169.254/latest/meta-data/\r\n", ''],
  36. ], $transport);
  37. $response = $http->get('https://a.example/');
  38. $this->assertSame('blocked_url', $response['error']);
  39. $this->assertCount(1, $transport->requests);
  40. }
  41. public function testRedirectToOtherSchemeIsRefused() {
  42. $http = $this->http([
  43. 'https://a.example/token' => [307, "Location: gopher://a.example:6379/_x\r\n", ''],
  44. ], $transport);
  45. $this->assertSame('blocked_url', $http->post('https://a.example/token', 'code=1')['error']);
  46. $this->assertCount(1, $transport->requests);
  47. }
  48. public function testRedirectsAreFollowedKeepingMethodAndBody() {
  49. $http = $this->http([
  50. 'https://a.example/one' => [301, "Location: /two\r\n", ''],
  51. 'https://a.example/two' => [200, "Content-Type: text/plain\r\n", 'done'],
  52. ], $transport);
  53. $response = $http->post('https://a.example/one', 'body', ['Authorization: Bearer secret']);
  54. $this->assertSame(200, $response['code']);
  55. $this->assertSame('done', $response['body']);
  56. $this->assertSame('https://a.example/two', $response['url']);
  57. $this->assertSame('POST', $transport->requests[1]['method']);
  58. $this->assertSame('body', $transport->requests[1]['body']);
  59. $this->assertContains('Authorization: Bearer secret', $transport->requests[1]['headers']);
  60. }
  61. public function testCredentialsAreDroppedWhenARedirectLeavesTheOrigin() {
  62. $http = $this->http([
  63. 'https://a.example/' => [302, "Location: https://b.example/\r\n", ''],
  64. 'https://b.example/' => [200, '', 'ok'],
  65. ], $transport);
  66. $http->get('https://a.example/', ['Authorization: Bearer secret', 'Cookie: a=b', 'Accept: text/html']);
  67. $this->assertSame(['Accept: text/html', 'User-Agent: test'], $transport->requests[1]['headers']);
  68. }
  69. public function testTooManyRedirects() {
  70. $http = $this->http([
  71. 'https://a.example/loop' => [302, "Location: /loop\r\n", ''],
  72. ], $transport);
  73. $http->set_max_redirects(3);
  74. $response = $http->get('https://a.example/loop');
  75. $this->assertSame('too_many_redirects', $response['error']);
  76. $this->assertCount(4, $transport->requests);
  77. }
  78. public function testOffByDefault() {
  79. $transport = new RecordingTransport([]);
  80. $http = new HTTP('test', $transport);
  81. $this->assertFalse($http->safe_mode());
  82. $http->get('http://127.0.0.1/');
  83. $this->assertCount(1, $transport->requests);
  84. $this->assertNull($transport->requests[0]['pinned']);
  85. $this->assertSame(8, $transport->max_redirects);
  86. }
  87. }