Bug #58823
closed4.5 t3lib_div::getUrl() till 6.2 \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl() with open_basedir and CURLOPT_FOLLOWLOCATION
0%
Description
Hello,
i've read several other issues before writing my own including:
#17479 and #16600
The first one claims to have the issue fixed however the warning message was just suppressed by "@" and nothing really was fixed. The second one just suggest to note this somewhere but doesn't fix any. The only non helpful info is:
// may fail (PHP 5.2.0+ and 5.1.5+) when open_basedir or safe_mode are enabled
This was later even removed.
Why it doesn't work Back to the Future
I am not sure why they never implemented a external URI switch CURLOPT_FOLLOWEXTERNAL :sad:
Anyway i think the problem can be solved:
getUrl() only uses curl if the requested $url is a external resource.
// Use cURL for: http, https, ftp, ftps, sftp and scp
if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['curlUse'] == '1' && preg_match('/^(?:http|ftp)s?|s(?:ftp|cp):/', $url)) {
There are 2 ways to fix this issue:
Modify open_basedir at runtime in PHP gte 5.3:
http://www.php.net/manual/en/ini.core.php#ini.sect.path-directory
http://www.php.net/manual/en/ini.core.php#ini.open-basedir
if (version_compare(phpversion(), '5.3.0', '>=')) {
$openBasedir = @ini_get('open_basedir');
ini_set('open_basedir', NULL);
}
$followLocation = @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
if (version_compare(phpversion(), '5.3.0', '>=')) {
if ($openBasedir) {
ini_set('open_basedir', $openBasedir);
}
}
Sounds good but is almost as bad as disabling open_basedir
Why? This may break open_basedir as a redirect could point to /etc/passwd :gosh:
Implement a own redirector which doesn't rely on CURLOPT_FOLLOWLOCATION:
function curl_redirect_exec($ch, &$redirects, $curlopt_header = false) {
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 301 || $http_code == 302) {
list($header) = explode("\r\n\r\n", $data, 2);
$matches = array();
preg_match("/(Location:|URI:)[^(\n)]*/", $header, $matches);
$url = trim(str_replace($matches[1], "", $matches[0]));
$url_parsed = parse_url($url);
if (isset($url_parsed)) {
curl_setopt($ch, CURLOPT_URL, $url);
$redirects++;
return curl_redirect_exec($ch, $redirects, $curlopt_header);
}
}
if ($curlopt_header) {
return $data;
} else {
list(, $body) = explode("\r\n\r\n", $data, 2);
return $body;
}
}
Source: http://stackoverflow.com/a/3890902/999205
I think this could be implemented with "relatively" little effort?
if $http_code = 3xx call getUrl() again which only allows external resources anyway.
Other notes:
You could use file_get_contents() with stream_context to bypass proxies too but this neither wouldn't fix the open_basedir dilemma.
But i still think a implementation should be considered? This could be useful for others (not wanting to use cURL).
Disabling open_basedir is imho not an option.
Why are we even requiring cURL? Because we are sitting behind a proxy and guess what open_basedir is activated :meh:
But hey we can XCLASS t3lib_div! No you can't! awww
Holy Moly TYPO3 Core Team to the rescue!