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 |