a quick stab at adding capath

main
Rob Bast 9 years ago
parent 395d115d9b
commit c1488f65bf

@ -55,9 +55,15 @@ php_openssl extension in php.ini.
## cafile ## cafile
A way to set the path to the openssl CA file. In PHP 5.6+ you should rather Location of Certificate Authority file on local filesystem. In PHP 5.6+ you
set this via openssl.cafile in php.ini, although PHP 5.6+ should be able to should rather set this via openssl.cafile in php.ini, although PHP 5.6+ should
detect your system CA file automatically. be able to detect your system CA file automatically.
## capath
If cafile is not specified or if the certificate is not found there, the
directory pointed to by capath is searched for a suitable certificate.
capath must be a correctly hashed certificate directory.
## http-basic ## http-basic

@ -333,6 +333,10 @@ EOT
function ($val) { return file_exists($val) && is_readable($val); }, function ($val) { return file_exists($val) && is_readable($val); },
function ($val) { return $val === 'null' ? null : $val; } function ($val) { return $val === 'null' ? null : $val; }
), ),
'capath' => array(
function ($val) { return is_dir($val) && is_readable($val); },
function ($val) { return $val === 'null' ? null : $val; }
),
'github-expose-hostname' => array($booleanValidator, $booleanNormalizer), 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
); );
$multiConfigValues = array( $multiConfigValues = array(

@ -47,6 +47,7 @@ class Config
'github-domains' => array('github.com'), 'github-domains' => array('github.com'),
'disable-tls' => false, 'disable-tls' => false,
'cafile' => null, 'cafile' => null,
'capath' => null,
'github-expose-hostname' => true, 'github-expose-hostname' => true,
'gitlab-domains' => array('gitlab.com'), 'gitlab-domains' => array('gitlab.com'),
'store-auths' => 'prompt', 'store-auths' => 'prompt',
@ -179,6 +180,7 @@ class Config
case 'cache-repo-dir': case 'cache-repo-dir':
case 'cache-vcs-dir': case 'cache-vcs-dir':
case 'cafile': case 'cafile':
case 'capath':
// convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config
$env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_')); $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));

@ -590,9 +590,17 @@ class Factory
$remoteFilesystemOptions = array(); $remoteFilesystemOptions = array();
if ($disableTls === false) { if ($disableTls === false) {
if ($config && $config->get('cafile')) { if ($config && $config->get('cafile')) {
$remoteFilesystemOptions = array('ssl' => array('cafile' => $config->get('cafile'))); $remoteFilesystemOptions = array_merge_recursive(
$remoteFilesystemOptions,
array('ssl' => array('cafile' => $config->get('cafile')))
);
}
if ($config && $config->get('capath')) {
$remoteFilesystemOptions = array_merge_recursive(
$remoteFilesystemOptions,
array('ssl' => array('capath' => $config->get('capath')))
);
} }
$remoteFilesystemOptions = array_merge_recursive($remoteFilesystemOptions, $options);
} }
try { try {
$remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls); $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);

@ -54,15 +54,7 @@ class RemoteFilesystem
// Setup TLS options // Setup TLS options
// The cafile option can be set via config.json // The cafile option can be set via config.json
if ($disableTls === false) { if ($disableTls === false) {
$this->options = $this->getTlsDefaults(); $this->options = $this->getTlsDefaults($options);
if (isset($options['ssl']['cafile'])
&& (
!is_readable($options['ssl']['cafile'])
|| !$this->validateCaFile($options['ssl']['cafile'])
)
) {
throw new TransportException('The configured cafile was not valid or could not be read.');
}
} else { } else {
$this->disableTls = true; $this->disableTls = true;
} }
@ -575,7 +567,7 @@ class RemoteFilesystem
return $options; return $options;
} }
private function getTlsDefaults() private function getTlsDefaults(array $options)
{ {
$ciphers = implode(':', array( $ciphers = implode(':', array(
'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES128-GCM-SHA256',
@ -622,7 +614,7 @@ class RemoteFilesystem
* *
* cafile or capath can be overridden by passing in those options to constructor. * cafile or capath can be overridden by passing in those options to constructor.
*/ */
$options = array( $defaults = array(
'ssl' => array( 'ssl' => array(
'ciphers' => $ciphers, 'ciphers' => $ciphers,
'verify_peer' => true, 'verify_peer' => true,
@ -635,7 +627,7 @@ class RemoteFilesystem
* Attempt to find a local cafile or throw an exception if none pre-set * Attempt to find a local cafile or throw an exception if none pre-set
* The user may go download one if this occurs. * The user may go download one if this occurs.
*/ */
if (!isset($this->options['ssl']['cafile'])) { if (!isset($options['ssl']['cafile']) && !isset($options['ssl']['capath'])) {
$result = $this->getSystemCaRootBundlePath(); $result = $this->getSystemCaRootBundlePath();
if ($result) { if ($result) {
if (preg_match('{^phar://}', $result)) { if (preg_match('{^phar://}', $result)) {
@ -659,7 +651,7 @@ class RemoteFilesystem
} }
} }
} else { } else {
throw new TransportException('A valid cafile could not be located automatically.'); throw new TransportException('A valid cafile or capath could not be located automatically.');
} }
} }
@ -667,10 +659,10 @@ class RemoteFilesystem
* Disable TLS compression to prevent CRIME attacks where supported. * Disable TLS compression to prevent CRIME attacks where supported.
*/ */
if (PHP_VERSION_ID >= 50413) { if (PHP_VERSION_ID >= 50413) {
$options['ssl']['disable_compression'] = true; $defaults['ssl']['disable_compression'] = true;
} }
return $options; return $defaults;
} }
/** /**
@ -721,6 +713,11 @@ class RemoteFilesystem
return $caPath = $envCertFile; return $caPath = $envCertFile;
} }
$configured = ini_get('openssl.cafile');
if ($configured && strlen($configured) > 0 && is_readable($configured) && $this->validateCaFile($configured)) {
return $caPath = $configured;
}
$caBundlePaths = array( $caBundlePaths = array(
'/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package) '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
'/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package) '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
@ -732,14 +729,8 @@ class RemoteFilesystem
'/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat? '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
'/etc/ssl/cert.pem', // OpenBSD '/etc/ssl/cert.pem', // OpenBSD
'/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
__DIR__.'/../../../res/cacert.pem', // Bundled with Composer
); );
$configured = ini_get('openssl.cafile');
if ($configured && strlen($configured) > 0 && is_readable($configured) && $this->validateCaFile($configured)) {
return $caPath = $configured;
}
foreach ($caBundlePaths as $caBundle) { foreach ($caBundlePaths as $caBundle) {
if (@is_readable($caBundle) && $this->validateCaFile($caBundle)) { if (@is_readable($caBundle) && $this->validateCaFile($caBundle)) {
return $caPath = $caBundle; return $caPath = $caBundle;
@ -753,7 +744,7 @@ class RemoteFilesystem
} }
} }
return $caPath = false; return $caPath = __DIR__.'/../../../res/cacert.pem'; // Bundled with Composer, last resort
} }
private function validateCaFile($filename) private function validateCaFile($filename)

Loading…
Cancel
Save