Skip to content

Commit

Permalink
100% code coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
EvanDotPro committed Sep 15, 2012
1 parent f130d5d commit 08dcc3a
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 20 deletions.
12 changes: 6 additions & 6 deletions src/Sslurp/CaRootPemBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ class CaRootPemBundle extends AbstractCaRootData
*/
private $pemContent = null;

/**
* Override for unit testing
*/
public static $overrideDateTime = null;

public function __construct($pemContent = null, MozillaCertData $mozCertData = null)
{
$this->pemContent = $pemContent;
Expand Down Expand Up @@ -47,15 +52,10 @@ public function getUpdatedCaRootBundle()
return $this->buildBundle($this->mozCertData->getContent());
}

public function getMozillaCertData()
{
return $this->mozCertData;
}

protected function buildBundle($rawCertData)
{
$rawCertData = explode("\n", $rawCertData);
$currentDate = defined('SSLURP_OVERRIDE_DATETIME') ? SSLURP_OVERRIDE_DATETIME : date(DATE_RFC822);
$currentDate = static::$overrideDateTime ?: date(DATE_RFC822);
$caBundle = <<<EOT
##
## Bundle of CA Root Certificates
Expand Down
41 changes: 28 additions & 13 deletions src/Sslurp/MozillaCertData.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ class MozillaCertData extends AbstractCaRootData
*/
private $context = null;

/**
* Overrides for unit testing
*/
public static $overrideCertPin = null;
public static $overrideCertExp = null;
public static $forceAltCaBundle = null;

/**
* @param string $certData Used for unit testing
*/
Expand Down Expand Up @@ -77,12 +84,18 @@ protected function fetchLatestCertData()
{
$ctx = $this->getStreamContext();

$fp = stream_socket_client('ssl:https://mxr.mozilla.org:443', $errNo, $errStr, 30, STREAM_CLIENT_CONNECT, $ctx);
set_error_handler(function ($code, $msg) {
throw new \RuntimeException($msg, $code);
});

if (!$fp) {
throw new \RuntimeException($errStr, $errNo);
try {
$fp = stream_socket_client('ssl:https://mxr.mozilla.org:443', $errNo, $errStr, 30, STREAM_CLIENT_CONNECT, $ctx);
} catch (\RuntimeException $e) {
throw new \RuntimeException($errStr, $errNo, $e);
}

restore_error_handler();

$headers = "GET /mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1 HTTP/1.1\r\n";
$headers .= "Host: mxr.mozilla.org\r\n";
$headers .= "Connection: close\r\n";
Expand All @@ -97,18 +110,20 @@ protected function fetchLatestCertData()

$params = stream_context_get_params($ctx);
$cert = new X509Certificate($params['options']['ssl']['peer_certificate']);
$pin = $cert->getPin();
$pin = static::$overrideCertPin ?: $cert->getPin();
// November 1st, 2013 or later (mxr.mozilla.org cert expires Nov 28th, 2013)
$exp = static::$overrideCertExp ?: 1383282000;

if ($pin !== static::MOZILLA_MXR_SSL_PIN) {
if (time() > 1383282000) { // If it's November 1st, 2013 or later (mxr.mozilla.org cert expires Nov 28th, 2013)
echo "WARNING: mxr.mozilla.org certificate pin may be out of date. " .
"If you see this, message, please file an issue at https://github.com/EvanDotPro/Sslurp/issues\n";
} else {
echo "ERROR: Certificate pin for mxr.mozilla.org did NOT match expected value!\n\n";
echo 'Expected: ' . static::MOZILLA_MXR_SSL_PIN . "\n";
echo "Received: {$pin}\n";
exit(1);
if (time() < $exp) {
throw new \RuntimeException(sprintf(
'ERROR: Certificate pin for mxr.mozilla.org did NOT match expected value! ' .
'Expected: %s Received: %s', static::MOZILLA_MXR_SSL_PIN, $pin
));
}
trigger_error('WARNING: mxr.mozilla.org certificate pin may be out of date. ' .
'If you continue to see this message after updating Sslurp, please ' .
'file an issue at https://github.com/EvanDotPro/Sslurp/issues');
}

return $this->getResponseBody($response);
Expand Down Expand Up @@ -154,6 +169,6 @@ protected function getRootCaBundlePath()
}
}

return $caBundle;
return (static::$forceAltCaBundle ?: $caBundle);
}
}
10 changes: 9 additions & 1 deletion test/SslurpTest/CaRootPemBundleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ public function setUp($newVersion = false)
$pemBundle = file_get_contents(__DIR__ . '/_files/ca-bundle.pem');
$certData = file_get_contents(__DIR__ . '/_files/certdata.txt');
if ($newVersion) $certData = str_replace('1.85', '1.86', $certData);
CaRootPemBundle::$overrideDateTime = null;
$this->bundle = new CaRootPemBundle($pemBundle, new MozillaCertData($certData));
}

public function testBuildsCaRootBundleProperly()
{
define('SSLURP_OVERRIDE_DATETIME', 'for testing');
CaRootPemBundle::$overrideDateTime = 'for testing';
$result = $this->bundle->getUpdatedCaRootBundle();
$this->assertStringEqualsFile(__DIR__ . '/_files/ca-bundle.pem', $result);
}
Expand All @@ -37,4 +38,11 @@ public function testIsLatestMethodWorks()
$this->setUp(true);
$this->assertFalse($this->bundle->isLatest());
}

public function testCanFetchContentFromLiveServer()
{
require_once __DIR__ . '/TestAsset/MockMozillaCertData.php';
$bundle = new CaRootPemBundle(null, new TestAsset\MockMozillaCertData);
$this->assertNotNull($bundle->getContent());
}
}
49 changes: 49 additions & 0 deletions test/SslurpTest/MozillaCertDataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class MozillaCertDataTest extends TestCase
{
public function setUp()
{
MozillaCertData::$overrideCertPin = null;
MozillaCertData::$overrideCertExp = null;
MozillaCertData::$forceAltCaBundle = null;
$this->mozCertData = new MozillaCertData();
}

Expand All @@ -18,6 +21,14 @@ public function certData()
return file_get_contents(__DIR__ . '/_files/certdata.txt');
}

public function canDoOnlineTest()
{
if (!($fp = @stream_socket_client('tcp:https://mxr.mozilla.org:80', $errNo, $errStr, 1))) {
$this->markTestSkipped('Could not reach mxr.mozilla.org for online test.');
}
fclose($fp);
}

public function testContextOptionsAreSecureDefaults()
{
$context = $this->mozCertData->getStreamContext();
Expand Down Expand Up @@ -51,4 +62,42 @@ public function testExceptionThrownIfCertDataIsInvalid()
$this->mozCertData->getVersion();
}

public function testMozillaCertDataOnlineCheck()
{
$this->canDoOnlineTest();
$this->assertRegExp('/^\d+\.\d+$/', $this->mozCertData->getVersion());
}

public function testMozillaCertDataOnlineCheckWithInvalidPinThrowsException()
{
$this->canDoOnlineTest();
MozillaCertData::$overrideCertPin = 'invalid';
$this->setExpectedException('RuntimeException');
$this->mozCertData->getVersion();
}

public function testMozillaCertDataOnlineCheckWithNewCertificateShowsWarningMessage()
{
$this->canDoOnlineTest();
MozillaCertData::$overrideCertPin = 'invalid';
MozillaCertData::$overrideCertExp = time() - 100;
$this->setExpectedException('PHPUnit_Framework_Error_Notice');
$this->mozCertData->getVersion();
}

public function testMozillaCertDataOnlineCheckWithNewCertificateStillReturnsVersion()
{
$this->canDoOnlineTest();
MozillaCertData::$overrideCertPin = 'invalid';
MozillaCertData::$overrideCertExp = time() - 100;
$this->assertRegExp('/^\d+\.\d+$/', @$this->mozCertData->getVersion());
}

public function testMozillaCertDataOnlineFailsIfNoCaRootBundleFound()
{
$this->canDoOnlineTest();
MozillaCertData::$forceAltCaBundle = __DIR__ . '/_files/mxr.mozilla.org.pem';
$this->setExpectedException('RuntimeException');
$this->mozCertData->getVersion();
}
}
13 changes: 13 additions & 0 deletions test/SslurpTest/TestAsset/MockMozillaCertData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace SslurpTest\TestAsset;

use Sslurp\MozillaCertData;

class MockMozillaCertData extends MozillaCertData
{
public function getContent()
{
return 'foo';
}
}

0 comments on commit 08dcc3a

Please sign in to comment.