Skip to content

Commit

Permalink
refactor pr
Browse files Browse the repository at this point in the history
  • Loading branch information
freekmurze committed Aug 10, 2017
1 parent 7c460d1 commit d25add1
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 41 deletions.
93 changes: 52 additions & 41 deletions src/Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ class Downloader
protected $timeout = 30;

/** @var bool */
protected $sni = true;
protected $enableSni = true;

/** @var bool */
protected $ca_chain = false;
protected $capturePeerChain = false;

/**
* @param int $port
Expand All @@ -38,7 +38,7 @@ public function usingPort(int $port)
*/
public function usingSni(bool $sni)
{
$this->sni = $sni;
$this->enableSni = $sni;

return $this;
}
Expand All @@ -50,7 +50,7 @@ public function usingSni(bool $sni)
*/
public function withFullChain(bool $ca_chain)
{
$this->ca_chain = $ca_chain;
$this->capturePeerChain = $ca_chain;

return $this;
}
Expand All @@ -68,17 +68,50 @@ public function setTimeout(int $timeOutInSeconds)
}

public function getCertificates(string $hostName): array
{
$response = $this->fetchCertificates($hostName);

$peerCertificate = $response['options']['ssl']['peer_certificate'];

$peerCertificateChain = $response['options']['ssl']['peer_certificate_chain'] ?? [];

$fullCertificateChain = array_merge([$peerCertificate], $peerCertificateChain);

return array_map(function($certificate) {
$certificateFields = openssl_x509_parse($certificate);

return new SslCertificate($certificateFields);
}, $fullCertificateChain);
}

public function forHost(string $hostName): SslCertificate
{
$hostName = (new Url($hostName))->getHostName();

$ssl_options = [
$certificates = $this->getCertificates($hostName);

return $certificates[0] ?? false;
}

public static function downloadCertificateFromUrl(string $url, int $timeout = 30): SslCertificate
{
return (new static())
->setTimeout($timeout)
->forHost($url);
}

protected function fetchCertificates(string $hostName): array
{
$hostName = (new Url($hostName))->getHostName();

$sslOptions = [
'capture_peer_cert' => true,
'capture_peer_cert_chain' => $this->ca_chain,
'SNI_enabled' => $this->sni,
'capture_peer_cert_chain' => $this->capturePeerChain,
'SNI_enabled' => $this->enableSni,
];

$streamContext = stream_context_create([
'ssl' => $ssl_options,
'ssl' => $sslOptions,
]);

try {
Expand All @@ -91,49 +124,27 @@ public function getCertificates(string $hostName): array
$streamContext
);
} catch (Throwable $thrown) {
if (str_contains($thrown->getMessage(), 'getaddrinfo failed')) {
throw CouldNotDownloadCertificate::hostDoesNotExist($hostName);
}

if (str_contains($thrown->getMessage(), 'error:14090086')) {
throw CouldNotDownloadCertificate::noCertificateInstalled($hostName);
}

throw CouldNotDownloadCertificate::unknownError($hostName, $thrown->getMessage());
$this->handleRequestFailure($hostName, $thrown);
}

if (! $client) {
if (!$client) {
throw CouldNotDownloadCertificate::unknownError($hostName, "Could not connect to `{$hostName}`.");
}

$response = stream_context_get_params($client);

$peer_certificate = $response['options']['ssl']['peer_certificate'];
$peer_certificate_chain = $response['options']['ssl']['peer_certificate_chain'] ?? [];
$certificates = array_merge([$peer_certificate], $peer_certificate_chain);

$return = [];
foreach ($certificates as $certificate) {
$certificateFields = openssl_x509_parse($certificate);
$return[] = new SslCertificate($certificateFields);
}

return $return;
return $response;
}

public function forHost(string $hostName): SslCertificate
protected function handleRequestFailure(string $hostName, Throwable $thrown)
{
$hostName = (new Url($hostName))->getHostName();

$certificates = $this->getCertificates($hostName);
if (str_contains($thrown->getMessage(), 'getaddrinfo failed')) {
throw CouldNotDownloadCertificate::hostDoesNotExist($hostName);
}

return $certificates[0] ?? false;
}
if (str_contains($thrown->getMessage(), 'error:14090086')) {
throw CouldNotDownloadCertificate::noCertificateInstalled($hostName);
}

public static function downloadCertificateFromUrl(string $url, int $timeout = 30): SslCertificate
{
return (new static())
->setTimeout($timeout)
->forHost($url);
throw CouldNotDownloadCertificate::unknownError($hostName, $thrown->getMessage());
}
}
8 changes: 8 additions & 0 deletions tests/DownloaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ public function it_can_download_a_certificate_from_a_host_name()
$this->assertInstanceOf(SslCertificate::class, $sslCertificate);
}

/** @test */
public function it_can_download_all_certificates_from_a_host_name()
{
$sslCertificates = (new Downloader)->getCertificates('spatie.be');

$this->assertCount(1, $sslCertificates);
}

/** @test */
public function it_throws_an_exception_for_non_existing_host()
{
Expand Down

0 comments on commit d25add1

Please sign in to comment.