소스 검색

Use extracted ca-bundle package

Jordi Boggiano 9 년 전
부모
커밋
b1723644e0
4개의 변경된 파일146개의 추가작업 그리고 186개의 파일을 삭제
  1. 4 2
      composer.json
  2. 133 1
      src/Composer/IO/BaseIO.php
  3. 7 128
      src/Composer/Util/RemoteFilesystem.php
  4. 2 55
      src/Composer/Util/TlsHelper.php

+ 4 - 2
composer.json

@@ -24,15 +24,17 @@
     "require": {
         "php": "^5.3.2 || ^7.0",
         "justinrainbow/json-schema": "^1.6",
-        "composer/spdx-licenses": "^1.0",
+        "composer/ca-bundle": "^1.0",
         "composer/semver": "^1.0",
+        "composer/spdx-licenses": "^1.0",
         "seld/jsonlint": "^1.4",
         "symfony/console": "^2.5 || ^3.0",
         "symfony/finder": "^2.2 || ^3.0",
         "symfony/process": "^2.1 || ^3.0",
         "symfony/filesystem": "^2.5 || ^3.0",
         "seld/phar-utils": "^1.0",
-        "seld/cli-prompt": "^1.0"
+        "seld/cli-prompt": "^1.0",
+        "psr/log": "^1.0"
     },
     "require-dev": {
         "phpunit/phpunit": "^4.5 || ^5.0.5",

+ 133 - 1
src/Composer/IO/BaseIO.php

@@ -14,8 +14,10 @@ namespace Composer\IO;
 
 use Composer\Config;
 use Composer\Util\ProcessExecutor;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
 
-abstract class BaseIO implements IOInterface
+abstract class BaseIO implements IOInterface, LoggerInterface
 {
     protected $authentications = array();
 
@@ -115,4 +117,134 @@ abstract class BaseIO implements IOInterface
         // setup process timeout
         ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
     }
+
+    /**
+     * System is unusable.
+     *
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function emergency($message, array $context = array())
+    {
+        return $this->log(LogLevel::EMERGENCY, $message, $context);
+    }
+
+    /**
+     * Action must be taken immediately.
+     *
+     * Example: Entire website down, database unavailable, etc. This should
+     * trigger the SMS alerts and wake you up.
+     *
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function alert($message, array $context = array())
+    {
+        return $this->log(LogLevel::ALERT, $message, $context);
+    }
+
+    /**
+     * Critical conditions.
+     *
+     * Example: Application component unavailable, unexpected exception.
+     *
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function critical($message, array $context = array())
+    {
+        return $this->log(LogLevel::CRITICAL, $message, $context);
+    }
+
+    /**
+     * Runtime errors that do not require immediate action but should typically
+     * be logged and monitored.
+     *
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function error($message, array $context = array())
+    {
+        return $this->log(LogLevel::ERROR, $message, $context);
+    }
+
+    /**
+     * Exceptional occurrences that are not errors.
+     *
+     * Example: Use of deprecated APIs, poor use of an API, undesirable things
+     * that are not necessarily wrong.
+     *
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function warning($message, array $context = array())
+    {
+        return $this->log(LogLevel::WARNING, $message, $context);
+    }
+
+    /**
+     * Normal but significant events.
+     *
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function notice($message, array $context = array())
+    {
+        return $this->log(LogLevel::NOTICE, $message, $context);
+    }
+
+    /**
+     * Interesting events.
+     *
+     * Example: User logs in, SQL logs.
+     *
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function info($message, array $context = array())
+    {
+        return $this->log(LogLevel::INFO, $message, $context);
+    }
+
+    /**
+     * Detailed debug information.
+     *
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function debug($message, array $context = array())
+    {
+        return $this->log(LogLevel::DEBUG, $message, $context);
+    }
+
+    /**
+     * Logs with an arbitrary level.
+     *
+     * @param mixed $level
+     * @param string $message
+     * @param array $context
+     * @return null
+     */
+    public function log($level, $message, array $context = array())
+    {
+        if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
+            $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
+        } elseif ($level === LogLevel::WARNING) {
+            $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
+        } elseif ($level === LogLevel::NOTICE) {
+            $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
+        } elseif ($level === LogLevel::INFO) {
+            $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
+        } else {
+            $this->writeError($message, true, self::DEBUG);
+        }
+    }
 }

+ 7 - 128
src/Composer/Util/RemoteFilesystem.php

@@ -15,6 +15,8 @@ namespace Composer\Util;
 use Composer\Config;
 use Composer\IO\IOInterface;
 use Composer\Downloader\TransportException;
+use Composer\CaBundle\CaBundle;
+use Psr\Log\LoggerInterface;
 
 /**
  * @author François Pluchino <francois.pluchino@opendisplay.com>
@@ -418,7 +420,7 @@ class RemoteFilesystem
             // 4. To prevent any attempt at being hoodwinked by switching the
             //    certificate between steps 2 and 3 the fingerprint of the certificate
             //    presented in step 3 is compared against the one recorded in step 2.
-            if (TlsHelper::isOpensslParseSafe()) {
+            if (CaBundle::isOpensslParseSafe()) {
                 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
 
                 if ($certDetails) {
@@ -786,12 +788,14 @@ class RemoteFilesystem
             $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
         }
 
+        $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
+
         /**
          * Attempt to find a local cafile or throw an exception if none pre-set
          * The user may go download one if this occurs.
          */
         if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
-            $result = $this->getSystemCaRootBundlePath();
+            $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
 
             if (preg_match('{^phar://}', $result)) {
                 $hash = hash_file('sha256', $result);
@@ -810,7 +814,7 @@ class RemoteFilesystem
             }
         }
 
-        if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !$this->validateCaFile($defaults['ssl']['cafile']))) {
+        if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
             throw new TransportException('The configured cafile was not valid or could not be read.');
         }
 
@@ -828,131 +832,6 @@ class RemoteFilesystem
         return $defaults;
     }
 
-    /**
-     * This method was adapted from Sslurp.
-     * https://github.com/EvanDotPro/Sslurp
-     *
-     * (c) Evan Coury <me@evancoury.com>
-     *
-     * For the full copyright and license information, please see below:
-     *
-     * Copyright (c) 2013, Evan Coury
-     * All rights reserved.
-     *
-     * Redistribution and use in source and binary forms, with or without modification,
-     * are permitted provided that the following conditions are met:
-     *
-     *     * Redistributions of source code must retain the above copyright notice,
-     *       this list of conditions and the following disclaimer.
-     *
-     *     * Redistributions in binary form must reproduce the above copyright notice,
-     *       this list of conditions and the following disclaimer in the documentation
-     *       and/or other materials provided with the distribution.
-     *
-     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-     * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-     * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-     *
-     * @return string
-     */
-    private function getSystemCaRootBundlePath()
-    {
-        static $caPath = null;
-
-        if ($caPath !== null) {
-            return $caPath;
-        }
-
-        // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
-        // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
-        $envCertFile = getenv('SSL_CERT_FILE');
-        if ($envCertFile && is_readable($envCertFile) && $this->validateCaFile($envCertFile)) {
-            return $caPath = $envCertFile;
-        }
-
-        // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that.
-        // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
-        $envCertDir = getenv('SSL_CERT_DIR');
-        if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
-            return $caPath = $envCertDir;
-        }
-
-        $configured = ini_get('openssl.cafile');
-        if ($configured && strlen($configured) > 0 && is_readable($configured) && $this->validateCaFile($configured)) {
-            return $caPath = $configured;
-        }
-
-        $configured = ini_get('openssl.capath');
-        if ($configured && is_dir($configured) && is_readable($configured)) {
-            return $caPath = $configured;
-        }
-
-        $caBundlePaths = array(
-            '/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/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
-            '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
-            '/usr/ssl/certs/ca-bundle.crt', // Cygwin
-            '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
-            '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
-            '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
-            '/etc/ssl/cert.pem', // OpenBSD
-            '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x
-        );
-
-        foreach ($caBundlePaths as $caBundle) {
-            if (Silencer::call('is_readable', $caBundle) && $this->validateCaFile($caBundle)) {
-                return $caPath = $caBundle;
-            }
-        }
-
-        foreach ($caBundlePaths as $caBundle) {
-            $caBundle = dirname($caBundle);
-            if (Silencer::call('is_dir', $caBundle) && glob($caBundle.'/*')) {
-                return $caPath = $caBundle;
-            }
-        }
-
-        return $caPath = __DIR__.'/../../../res/cacert.pem'; // Bundled with Composer, last resort
-    }
-
-    /**
-     * @param string $filename
-     *
-     * @return bool
-     */
-    private function validateCaFile($filename)
-    {
-        static $files = array();
-
-        if (isset($files[$filename])) {
-            return $files[$filename];
-        }
-
-        $this->io->writeError('Checking CA file '.realpath($filename), true, IOInterface::DEBUG);
-        $contents = file_get_contents($filename);
-
-        // assume the CA is valid if php is vulnerable to
-        // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html
-        if (!TlsHelper::isOpensslParseSafe()) {
-            $this->io->writeError(sprintf(
-                '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
-                PHP_VERSION
-            ));
-
-            return $files[$filename] = !empty($contents);
-        }
-
-        return $files[$filename] = (bool) openssl_x509_parse($contents);
-    }
-
     /**
      * Uses stream_copy_to_stream instead of copy to work around https://bugs.php.net/bug.php?id=64634
      *

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2 - 55
src/Composer/Util/TlsHelper.php


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.