Changeset View
Changeset View
Standalone View
Standalone View
src/applications/files/storage/PhabricatorFile.php
| Show First 20 Lines • Show All 465 Lines • ▼ Show 20 Lines | public static function newFromFileDownload($uri, array $params = array()) { | ||||
| $current = $uri; | $current = $uri; | ||||
| while (true) { | while (true) { | ||||
| try { | try { | ||||
| if (count($redirects) > 10) { | if (count($redirects) > 10) { | ||||
| throw new Exception( | throw new Exception( | ||||
| pht('Too many redirects trying to fetch remote URI.')); | pht('Too many redirects trying to fetch remote URI.')); | ||||
| } | } | ||||
| PhabricatorEnv::requireValidRemoteURIForFetch( | $resolved = PhabricatorEnv::requireValidRemoteURIForFetch( | ||||
| $current, | $current, | ||||
| array( | array( | ||||
| 'http', | 'http', | ||||
| 'https', | 'https', | ||||
| )); | )); | ||||
| list($status, $body, $headers) = id(new HTTPSFuture($current)) | list($resolved_uri, $resolved_domain) = $resolved; | ||||
| $current = new PhutilURI($current); | |||||
| if ($current->getProtocol() == 'http') { | |||||
| // For HTTP, we can use a pre-resolved URI to defuse DNS rebinding. | |||||
| $fetch_uri = $resolved_uri; | |||||
| $fetch_host = $resolved_domain; | |||||
| } else { | |||||
| // For HTTPS, we can't: cURL won't verify the SSL certificate if | |||||
| // the domain has been replaced with an IP. But internal services | |||||
| // presumably will not have valid certificates for rebindable | |||||
| // domain names on attacker-controlled domains, so the DNS rebinding | |||||
| // attack should generally not be possible anyway. | |||||
| $fetch_uri = $current; | |||||
| $fetch_host = null; | |||||
| } | |||||
| $future = id(new HTTPSFuture($fetch_uri)) | |||||
| ->setFollowLocation(false) | ->setFollowLocation(false) | ||||
| ->setTimeout($timeout) | ->setTimeout($timeout); | ||||
| ->resolve(); | |||||
| if ($fetch_host !== null) { | |||||
| $future->addHeader('Host', $fetch_host); | |||||
| } | |||||
| list($status, $body, $headers) = $future->resolve(); | |||||
| if ($status->isRedirect()) { | if ($status->isRedirect()) { | ||||
| // This is an HTTP 3XX status, so look for a "Location" header. | // This is an HTTP 3XX status, so look for a "Location" header. | ||||
| $location = null; | $location = null; | ||||
| foreach ($headers as $header) { | foreach ($headers as $header) { | ||||
| list($name, $value) = $header; | list($name, $value) = $header; | ||||
| if (phutil_utf8_strtolower($name) == 'location') { | if (phutil_utf8_strtolower($name) == 'location') { | ||||
| $location = $value; | $location = $value; | ||||
| ▲ Show 20 Lines • Show All 878 Lines • Show Last 20 Lines | |||||