| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | /* | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  * This file is part of composer/ca-bundle. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  * (c) Composer <https://github.com/composer> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  * For the full copyright and license information, please view | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  * the LICENSE file that was distributed with this source code. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | namespace Composer\CaBundle; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | use Psr\Log\LoggerInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | use Symfony\Component\Process\PhpProcess; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |  * @author Chris Smith <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |  * @author Jordi Boggiano <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | class CaBundle | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |     private static $caPath; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |     private static $caFileValidity = array(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |     private static $useOpensslParse; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |      * Returns the system CA bundle path, or a path to the bundled one | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |      * This method was adapted from Sslurp. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |      * https://github.com/EvanDotPro/Sslurp | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |      * (c) Evan Coury <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |      * For the full copyright and license information, please see below: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |      * Copyright (c) 2013, Evan Coury | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |      * All rights reserved. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |      * Redistribution and use in source and binary forms, with or without modification, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |      * are permitted provided that the following conditions are met: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |      *     * Redistributions of source code must retain the above copyright notice, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |      *       this list of conditions and the following disclaimer. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |      *     * Redistributions in binary form must reproduce the above copyright notice, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |      *       this list of conditions and the following disclaimer in the documentation | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |      *       and/or other materials provided with the distribution. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |      * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |      * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |      * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |      * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |      * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |      * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |      * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |      * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |      * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |      * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |      * @param  LoggerInterface $logger optional logger for information about which CA files were loaded | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |      * @return string          path to a CA bundle file or directory | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 63 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 64 |  |  |     public static function getSystemCaRootBundlePath(LoggerInterface $logger = null) | 
            
                                                                        
                            
            
                                    
            
            
                | 65 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 66 |  |  |         if (self::$caPath !== null) { | 
            
                                                                        
                            
            
                                    
            
            
                | 67 |  |  |             return self::$caPath; | 
            
                                                                        
                            
            
                                    
            
            
                | 68 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 70 |  |  |         // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that. | 
            
                                                                        
                            
            
                                    
            
            
                | 71 |  |  |         // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. | 
            
                                                                        
                            
            
                                    
            
            
                | 72 |  |  |         $envCertFile = getenv('SSL_CERT_FILE'); | 
            
                                                                        
                            
            
                                    
            
            
                | 73 |  |  |         if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 74 |  |  |             return self::$caPath = $envCertFile; | 
            
                                                                        
                            
            
                                    
            
            
                | 75 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 76 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 77 |  |  |         // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that. | 
            
                                                                        
                            
            
                                    
            
            
                | 78 |  |  |         // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. | 
            
                                                                        
                            
            
                                    
            
            
                | 79 |  |  |         $envCertDir = getenv('SSL_CERT_DIR'); | 
            
                                                                        
                            
            
                                    
            
            
                | 80 |  |  |         if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 81 |  |  |             return self::$caPath = $envCertDir; | 
            
                                                                        
                            
            
                                    
            
            
                | 82 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 83 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 84 |  |  |         $configured = ini_get('openssl.cafile'); | 
            
                                                                        
                            
            
                                    
            
            
                | 85 |  |  |         if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 86 |  |  |             return self::$caPath = $configured; | 
            
                                                                        
                            
            
                                    
            
            
                | 87 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 89 |  |  |         $configured = ini_get('openssl.capath'); | 
            
                                                                        
                            
            
                                    
            
            
                | 90 |  |  |         if ($configured && is_dir($configured) && is_readable($configured)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 91 |  |  |             return self::$caPath = $configured; | 
            
                                                                        
                            
            
                                    
            
            
                | 92 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 94 |  |  |         $caBundlePaths = array( | 
            
                                                                        
                            
            
                                    
            
            
                | 95 |  |  |             '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package) | 
            
                                                                        
                            
            
                                    
            
            
                | 96 |  |  |             '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package) | 
            
                                                                        
                            
            
                                    
            
            
                | 97 |  |  |             '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package) | 
            
                                                                        
                            
            
                                    
            
            
                | 98 |  |  |             '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package) | 
            
                                                                        
                            
            
                                    
            
            
                | 99 |  |  |             '/usr/ssl/certs/ca-bundle.crt', // Cygwin | 
            
                                                                        
                            
            
                                    
            
            
                | 100 |  |  |             '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package | 
            
                                                                        
                            
            
                                    
            
            
                | 101 |  |  |             '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option) | 
            
                                                                        
                            
            
                                    
            
            
                | 102 |  |  |             '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat? | 
            
                                                                        
                            
            
                                    
            
            
                | 103 |  |  |             '/etc/ssl/cert.pem', // OpenBSD | 
            
                                                                        
                            
            
                                    
            
            
                | 104 |  |  |             '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x | 
            
                                                                        
                            
            
                                    
            
            
                | 105 |  |  |             '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package | 
            
                                                                        
                            
            
                                    
            
            
                | 106 |  |  |         ); | 
            
                                                                        
                            
            
                                    
            
            
                | 107 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 108 |  |  |         foreach ($caBundlePaths as $caBundle) { | 
            
                                                                        
                            
            
                                    
            
            
                | 109 |  |  |             if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 110 |  |  |                 return self::$caPath = $caBundle; | 
            
                                                                        
                            
            
                                    
            
            
                | 111 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 112 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 113 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 114 |  |  |         foreach ($caBundlePaths as $caBundle) { | 
            
                                                                        
                            
            
                                    
            
            
                | 115 |  |  |             $caBundle = dirname($caBundle); | 
            
                                                                        
                            
            
                                    
            
            
                | 116 |  |  |             if (@is_dir($caBundle) && glob($caBundle.'/*')) { | 
            
                                                                        
                            
            
                                    
            
            
                | 117 |  |  |                 return self::$caPath = $caBundle; | 
            
                                                                        
                            
            
                                    
            
            
                | 118 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 119 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 120 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 121 |  |  |         return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort | 
            
                                                                        
                            
            
                                    
            
            
                | 122 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |      * Returns the path to the bundled CA file | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |      * In case you don't want to trust the user or the system, you can use this directly | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |      * @return string path to a CA bundle file | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |     public static function getBundledCaBundlePath() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |         $caBundleFile = __DIR__.'/../res/cacert.pem'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |         // cURL does not understand 'phar://' paths | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |         // see https://github.com/composer/ca-bundle/issues/10 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |         if (0 === strpos($caBundleFile, 'phar://')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |             file_put_contents( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |                 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |                 file_get_contents($caBundleFile) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |             register_shutdown_function(function() use ($tempCaBundleFile) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |                 @unlink($tempCaBundleFile); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |             }); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |             $caBundleFile = $tempCaBundleFile; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |         return $caBundleFile; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |      * Validates a CA file using opensl_x509_parse only if it is safe to use | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |      * @param string          $filename | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |      * @param LoggerInterface $logger   optional logger for information about which CA files were loaded | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |      * @return bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |     public static function validateCaFile($filename, LoggerInterface $logger = null) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |         static $warned = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |         if (isset(self::$caFileValidity[$filename])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |             return self::$caFileValidity[$filename]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |         $contents = file_get_contents($filename); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |         // assume the CA is valid if php is vulnerable to | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |         // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |         if (!static::isOpensslParseSafe()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |             if (!$warned && $logger) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  |                 $logger->warning(sprintf( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  |                     'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |                     PHP_VERSION | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |                 )); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |                 $warned = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |             $isValid = !empty($contents); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  |             $isValid = (bool) openssl_x509_parse($contents); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |         if ($logger) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  |             $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid')); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  |         return self::$caFileValidity[$filename] = $isValid; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  |      * Test if it is safe to use the PHP function openssl_x509_parse(). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  |      * This checks if OpenSSL extensions is vulnerable to remote code execution | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |      * via the exploit documented as CVE-2013-6420. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |      * @return bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  |     public static function isOpensslParseSafe() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |         if (null !== self::$useOpensslParse) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |             return self::$useOpensslParse; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |         if (PHP_VERSION_ID >= 50600) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  |             return self::$useOpensslParse = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  |         // Vulnerable: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |         // PHP 5.3.0 - PHP 5.3.27 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  |         // PHP 5.4.0 - PHP 5.4.22 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |         // PHP 5.5.0 - PHP 5.5.6 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 |  |  |         if ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 |  |  |                (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 |  |  |             || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 |  |  |             || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 |  |  |         ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  |             // This version of PHP has the fix for CVE-2013-6420 applied. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  |             return self::$useOpensslParse = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 |  |  |         if (defined('PHP_WINDOWS_VERSION_BUILD')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 |  |  |             // Windows is probably insecure in this case. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 |  |  |             return self::$useOpensslParse = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 |  |  |         $compareDistroVersionPrefix = function ($prefix, $fixedVersion) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 |  |  |             $regex = '{^'.preg_quote($prefix).'([0-9]+)$}'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 |  |  |             if (preg_match($regex, PHP_VERSION, $m)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  |                 return ((int) $m[1]) >= $fixedVersion; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 |  |  |             return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 |  |  |         }; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 |  |  |         // Hard coded list of PHP distributions with the fix backported. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  |         if ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 |  |  |             $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  |             || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 |  |  |             || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  |         ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 |  |  |             return self::$useOpensslParse = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  |         // Symfony Process component is missing so we assume it is unsafe at this point | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  |         if (!class_exists('Symfony\Component\Process\PhpProcess')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 |  |  |             return self::$useOpensslParse = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 |  |  |         // This is where things get crazy, because distros backport security | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  |         // fixes the chances are on NIX systems the fix has been applied but | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  |         // it's not possible to verify that from the PHP version. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  |         // | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 |  |  |         // To verify exec a new PHP process and run the issue testcase with | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 |  |  |         // known safe input that replicates the bug. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 |  |  |         // Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  |         // changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 |  |  |         $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 |  |  |         $script = <<<'EOT' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 |  |  | error_reporting(-1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  | $info = openssl_x509_parse(base64_decode('%s')); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 |  |  | var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 |  |  | EOT; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 |  |  |         $script = '<'."?php\n".sprintf($script, $cert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 |  |  |         try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  |             $process = new PhpProcess($script); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  |             $process->mustRun(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 276 |  |  |         } catch (\Exception $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 277 |  |  |             // In the case of any exceptions just accept it is not possible to | 
            
                                                                                                            
                            
            
                                    
            
            
                | 278 |  |  |             // determine the safety of openssl_x509_parse and bail out. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 279 |  |  |             return self::$useOpensslParse = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 280 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 281 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 282 |  |  |         $output = preg_split('{\r?\n}', trim($process->getOutput())); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 283 |  |  |         $errorOutput = trim($process->getErrorOutput()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 284 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 285 |  |  |         if ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 286 |  |  |             count($output) === 3 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 287 |  |  |             && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 288 |  |  |             && $output[1] === 'string(27) "[email protected]"' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 289 |  |  |             && $output[2] === 'int(-1)' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 290 |  |  |             && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 291 |  |  |         ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 292 |  |  |             // This PHP has the fix backported probably by a distro security team. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 293 |  |  |             return self::$useOpensslParse = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 294 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 295 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 296 |  |  |         return self::$useOpensslParse = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 297 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 298 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 299 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 300 |  |  |      * Resets the static caches | 
            
                                                                                                            
                            
            
                                    
            
            
                | 301 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 302 |  |  |     public static function reset() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 303 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 304 |  |  |         self::$caFileValidity = array(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 305 |  |  |         self::$caPath = null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 306 |  |  |         self::$useOpensslParse = null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 307 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 308 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 309 |  |  |  | 
            
                        
If you suppress an error, we recommend checking for the error condition explicitly: