/** @dataProvider dataCheckCertificateHost */ public function testCheckCertificateHost($expectedResult, $hostname, $certNames) { $certificate['subject']['commonName'] = $expectedCn = array_shift($certNames); $certificate['extensions']['subjectAltName'] = $certNames ? 'DNS:' . implode(',DNS:', $certNames) : ''; $result = TlsHelper::checkCertificateHost($certificate, $hostname, $foundCn); if (true === $expectedResult) { $this->assertTrue($result); $this->assertSame($expectedCn, $foundCn); } else { $this->assertFalse($result); $this->assertNull($foundCn); } }
/** * Fetch certificate common name and fingerprint for validation of SAN. * * @todo Remove when PHP 5.6 is minimum supported version. */ private function getCertificateCnAndFp($url, $options) { if (PHP_VERSION_ID >= 50600) { throw new \BadMethodCallException(sprintf('%s must not be used on PHP >= 5.6', __METHOD__)); } $context = StreamContextFactory::getContext($url, $options, array('options' => array('ssl' => array('capture_peer_cert' => true, 'verify_peer' => false)))); // Ideally this would just use stream_socket_client() to avoid sending a // HTTP request but that does not capture the certificate. if (false === ($handle = @fopen($url, 'rb', false, $context))) { return; } // Close non authenticated connection without reading any content. fclose($handle); $handle = null; $params = stream_context_get_params($context); if (!empty($params['options']['ssl']['peer_certificate'])) { $peerCertificate = $params['options']['ssl']['peer_certificate']; if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) { return array('cn' => $commonName, 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate)); } } }