Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactor API to prepare for bundle-update feature

- Updated / improved README
- Added Sslurp::VERSION / Sslurp::getSystemCaRootBundlePath()
- Improved system bundle path detection
- Changed private properties to protected (helps with unit testing)
- Removed public static properties in userland classes in favor of mock
  classes that extend the userland classes for testing.
- Loosened regex for version/date match to allow checking some distro
  bundle file versions.
- CaRootPemBundle now wraps an SplFileObject instead of just the bundle
  string.
- Updated unit tests
  • Loading branch information...
commit 497ea163d0f4e0cad9e8933a3732e7ccf0622a6a 1 parent 846b88f
@EvanDotPro authored
View
116 README.md
@@ -6,67 +6,29 @@ v1.0 by Evan Coury
## Introduction
-Dealing with SSL properly in PHP is a pain in the ass. Sslurp aims to make it
-suck less. Sslurp can be used as a stand-alone library or a ZF2 module.
+Dealing with SSL properly in PHP is a pain in the ass and completely insecure by default. Sslurp aims to make it easier to use SSL in PHP safely and securely. Sslurp can be used as a stand-alone library, CLI tool, or a ZF2 module.
-**Note:** This library requires PHP with OpenSSL support. This is standard in
-most Linux distributions' PHP packages, else you need to ensure you compile
-using --with-openssl[=DIR].
+**Note:** Sslurp requires PHP with OpenSSL support. This is standard in most Linux distributions' PHP packages, otherwise you need to compile PHP using --with-openssl[=DIR].
-## Installation
-
-### Composer / Packagist
-
-```
-./composer.phar require evandotpro/sslurp
-```
-
-### Normal
-
-The `./bin/update-ca-bundle` CLI tool will "just work" out of the box.
-
-Sslurp can _easily_ be used in any existing project, framework, or library.
-
-To use Sslurp as a library in your project, the easiest method is to simply
-include the `autoload_register.php` file:
-
-```php
-require_once 'vendor/Sslurp/autoload_register.php';
-```
+## Features / Usage
-Alternatively, if you project supports loading classmap arrays, you may fetch
-the classmap without registering an additional SPL autoloader:
+### Root CA bundle management
-```php
-$classmap = include 'vendor/Sslurp/autoload_classmap.php';
-// Register $classmap with your project's existing classmap autoloader
-```
+Sslurp provides CLI and OOP interfaces for generating a trusted root Certificate Authority (CA) bundle using [certdata.txt](http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1) from the source tree of Mozilla's [Network Security Services (NSS) libraries](https://www.mozilla.org/projects/security/pki/nss/) and keeping it up-to-date. The resulting root CA bundle includes the certificates vetted according to the [Mozilla Root Certificate Program](http://www.mozilla.org/projects/security/certs/policy/) — the same root CA bundle trusted by cURL, Firefox, Chrome, and many other applications, libraries, languages, and operating systems.
-If you have an existing SPL autoloader that allows adding a callable to a stack
-instead of directly registering the classmap array, you have the option of
-simply getting a closure which can autoload the Sslurp classes:
+Sslurp takes additional steps to protect against MITM attacks while fetching certdata.txt from Mozilla's source tree, ensuring that the generated bundle is truly authentic. When connecting to Mozilla's mxr.mozilla.org domain to fetch the updated certdata.txt, Sslurp forces the use of verified SSL. Sslurp uses the following process to establish the initial trust of the SSL certificate on mxr.mozilla.org:
-```php
-$sslurpLoader = include 'vendor/Sslurp/autoload_function.php';
-// $sslurpLoader is a closure that can be registered with an existing autoloader
-```
+* Check the SSL\_CERT\_FILE environment variable (used by OpenSSL). If the value is the path to a readable file and valid certificate bundle, Sslurp will use it.
+* If the SSL\_CERT\_FILE is not set or points to a non-existent / invalid certificate bundle, Sslurp will search several known/expected locations for the root CA bundle and use the first valid bundle found.
+* If a valid bundle is not found in any of the expected paths, Sslurp will finally fall back to using a bundled, pre-verified copy of the root CA's public key which established trust for the mxr.mozilla.org certificate (Equifax Secure Certificate Authority at least until November 2013).
-## Usage
+As if that's not enough, Sslurp _additionally_ makes use of [public key pinning](http://tools.ietf.org/html/draft-ietf-websec-key-pinning-02) to further authenticate the authenticity of communications with Mozilla's mxr.mozilla.org domain. If the public key pin for mxr.mozilla.org changes before the expiration date of the current certificate, Sslurp will being to throw an exception, and refuse to update the root CA bundle. If the public key pin changes within the final month or after the expiration date of their current certificate (November, 2013), Sslurp will begin throwing a PHP notice encouraging you to update your copy of Sslurp to get the latest pin.
+**You are STRONGLY ENCOURAGED to be using the latest version of Sslurp at all times.**
### CLI root CA bundle updater
-[update-ca-bundle](https://github.com/EvanDotPro/Sslurp/blob/master/bin/update-ca-bundle)
-is a handy command-line tool for fetching and building a PEM certificate bundle
-from the latest trusted CAs in the [Mozilla source
-tree](https://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt).
-It bootstraps the initial trust of the mxr.mozilla.org SSL certificate using
-[key pinning](http://tools.ietf.org/html/draft-ietf-websec-key-pinning-02) in
-addition to verifying the key with either the system's trusted CA root bundle
-or, as a fallback, the included Equifax\_Secure\_CA.pem public key. This
-approach minimizes the possibility of MITM attacks at any point during the
-process so that you can have a very high certainty that the CA bundle built is
-authentic and has not been tampered with.
+[./bin/update-ca-bundle](https://github.com/EvanDotPro/Sslurp/blob/master/bin/update-ca-bundle) is a handy command-line tool for fetching, building, and subsequently updating a root CA bundle in PEM format for use with PHP's OpenSSL support, curl, libcurl, php\_curl, etc. The output generated is fully compatible with the [mk-ca-bundle.pl](https://github.com/bagder/curl/blob/master/lib/mk-ca-bundle.pl) which is used to [generate cURL's trusted bundle](http://curl.haxx.se/docs/caextract.html).
```
Sslurp Root CA Bundle Updater
@@ -81,15 +43,13 @@ Options
### Using Sslurp as a library
In addition to the CLI tool, Sslurp can be used as a library through the OOP
-interface. The
-[source](https://github.com/EvanDotPro/Sslurp/tree/master/src/Sslurp) _is_ the
-API documentation.
+interface. The [source](https://github.com/EvanDotPro/Sslurp/tree/master/src/Sslurp) _is_ the API documentation.
```php
<?php
-require_once 'autoload_register.php';
+require_once 'vendor/Sslurp/autoload_register.php';
-$bundle = new \Sslurp\CaRootPemBundle(file_get_contents('ca-bundle.pem'));
+$bundle = new \Sslurp\CaRootPemBundle('ca-bundle.pem');
if ($bundle->isLatest()) {
echo 'Your CA root bundle is up to date!' . PHP_EOL;
@@ -99,11 +59,55 @@ if ($bundle->isLatest()) {
. 'Latest version available from Mozilla is ' . $bundle->getMozillaCertData()->getVersion() . '.' . PHP_EOL;
echo 'Updating...';
- file_put_contents('ca-bundle.pem', $bundle->getUpdatedCaRootBundle());
+ $bundle->update();
echo "\tDone!" . PHP_EOL;
}
```
+## Installation
+
+### Composer / Packagist
+
+```
+./composer.phar require evandotpro/sslurp
+```
+
+### Normal
+
+The `./bin/update-ca-bundle` CLI tool will "just work" out of the box.
+
+Sslurp can _easily_ be used in any existing project, framework, or library.
+
+To use Sslurp as a library in your project, the easiest method is to simply
+include the `autoload_register.php` file:
+
+```php
+require_once 'vendor/Sslurp/autoload_register.php';
+```
+
+Alternatively, if you project supports loading classmap arrays, you may fetch
+the classmap without registering an additional SPL autoloader:
+
+```php
+$classmap = include 'vendor/Sslurp/autoload_classmap.php';
+// Register $classmap with your project's existing classmap autoloader
+```
+
+If you have an existing SPL autoloader that allows adding a callable to a stack
+instead of directly registering the classmap array, you have the option of
+simply getting a closure which can autoload the Sslurp classes:
+
+```php
+$sslurpLoader = include 'vendor/Sslurp/autoload_function.php';
+// $sslurpLoader is a closure that can be registered with an existing autoloader
+```
+
+## To-Do
+
+* **Paranoia level 1000** - Test environment for the ability to call the OpenSSL executable, and if possible, make use of OCSP to _further_ verify the validity of the mxr.mozilla.org domain.
+
## License
Sslurp is released under the BSD license. See the included LICENSE file.
+
+The generated root CA bundle file is simply a converted version of the original and as such, it is licensed under the same licenses as the Mozilla source: MPL v2.0, GPL v2.0 or LGPL 2.1. See [nss/COPYING](http://mxr.mozilla.org/mozilla/source/security/nss/COPYING?raw=1) for details.
View
10 autoload_classmap.php
@@ -1,8 +1,10 @@
<?php
// Generated by ZF2's ./bin/classmap_generator.php
return array(
- 'Sslurp\AbstractCaRootData' => __DIR__ . '/src/Sslurp/AbstractCaRootData.php',
- 'Sslurp\MozillaCertData' => __DIR__ . '/src/Sslurp/MozillaCertData.php',
- 'Sslurp\CaRootPemBundle' => __DIR__ . '/src/Sslurp/CaRootPemBundle.php',
- 'Sslurp\X509Certificate' => __DIR__ . '/src/Sslurp/X509Certificate.php',
+ 'Sslurp\Module' => __DIR__ . '/Module.php',
+ 'Sslurp\Sslurp' => __DIR__ . '/src/Sslurp/Sslurp.php',
+ 'Sslurp\AbstractCaRootData' => __DIR__ . '/src/Sslurp/AbstractCaRootData.php',
+ 'Sslurp\MozillaCertData' => __DIR__ . '/src/Sslurp/MozillaCertData.php',
+ 'Sslurp\CaRootPemBundle' => __DIR__ . '/src/Sslurp/CaRootPemBundle.php',
+ 'Sslurp\X509Certificate' => __DIR__ . '/src/Sslurp/X509Certificate.php',
);
View
24 src/Sslurp/AbstractCaRootData.php
@@ -20,29 +20,27 @@
*
* @var string
*/
- private $version = null;
+ protected $version = null;
/**
- * The date/time of the version commit
+ * The date/time of the certdataversion
*
* @var DateTime
*/
- private $dateTime = null;
+ protected $dateTime = null;
/**
- * Get the version number
+ * Get the version number according to CVS.
*
* @return string
*/
public function getVersion()
{
if ($this->version === null) {
- if (preg_match('/^#?\s?(CVS_ID\s+\".*\")/m', $this->getContent('CVS_ID'), $match)) {
- $parts = explode(' ', $match[1]);
- $this->version = $parts[6];
- $this->dateTime = new DateTime($parts[9] . ' ' . $parts[10], new DateTimeZone('UTC'));
+ if (preg_match('/^.*\$Revision: ([\d\.]+)/m', $this->getContent('Revision:'), $match)) {
+ $this->version = $match[1];
} else {
- throw new \RuntimeException('Unable to detect CVS version ID.');
+ throw new \RuntimeException('Unable to detect revesion ID.');
}
}
@@ -50,14 +48,18 @@ public function getVersion()
}
/**
- * Get the date/time of the last update
+ * Get the date/time the certdata was modified by Mozilla according to CVS.
*
* @return DateTime
*/
public function getDateTime()
{
if ($this->dateTime === null) {
- $this->getVersion();
+ if (preg_match('/^.*\$Date: ([\d\/-]+\s+[\d:]+)/m', $this->getContent('Date:'), $match)) {
+ $this->dateTime = new DateTime($match[1], new DateTimeZone('UTC'));
+ } else {
+ throw new \RuntimeException('Unable to detect revision date.');
+ }
}
return $this->dateTime;
View
44 src/Sslurp/CaRootPemBundle.php
@@ -10,30 +10,28 @@
*/
namespace Sslurp;
+use SplFileObject;
+
class CaRootPemBundle extends AbstractCaRootData
{
/**
- * The content of the PEM bundle
- *
- * @var string
+ * @var SplFileObject
*/
- private $pemContent = null;
+ protected $fileObject = null;
/**
- * @var MozillaCertData
+ * @var string
*/
- private $mozCertData = null;
+ protected $pemContent = null;
/**
- * Override for unit testing
- *
- * @var string
+ * @var MozillaCertData
*/
- public static $overrideDateTime = null;
+ protected $mozCertData = null;
- public function __construct($pemContent = null, MozillaCertData $mozCertData = null)
+ public function __construct($filename = null, MozillaCertData $mozCertData = null)
{
- $this->pemContent = $pemContent;
+ $this->fileObject = new SplFileObject($filename, 'r+');
$this->mozCertData = $mozCertData ?: new MozillaCertData();
}
@@ -43,7 +41,9 @@ public function __construct($pemContent = null, MozillaCertData $mozCertData = n
public function getContent($until = false)
{
if ($this->pemContent === null) {
- $this->pemContent = $this->getUpdatedCaRootBundle();
+ $this->pemContent = '';
+ while (!$this->fileObject->eof()) $this->pemContent .= $this->fileObject->fgets();
+ //$this->pemContent = $this->fileObject->getUpdatedCaRootBundle();
}
if ($until) {
@@ -71,20 +71,22 @@ public function getUpdatedCaRootBundle()
protected function buildBundle($rawCertData)
{
$rawCertData = explode("\n", $rawCertData);
- $currentDate = static::$overrideDateTime ?: date(DATE_RFC822);
+ $currentDate = date(DATE_ISO8601);
$caBundle = <<<EOT
##
## Bundle of CA Root Certificates
##
-## Generated $currentDate
## Generated with Sslurp (https://github.com/EvanDotPro/Sslurp)
##
-## This is a bundle of X.509 certificates of public Certificate Authorities
-## (CA). These were automatically extracted from Mozilla's root certificates
-## file (certdata.txt). This file can be found in the mozilla source tree:
-## '/mozilla/security/nss/lib/ckfw/builtins/certdata.txt'
+## This is a bundle of X.509 certificates of public Certificate Authorities.
+## These were automatically extracted from Mozilla's root certificates
+## file (certdata.txt). This file can be found in the Mozilla source tree:
+## /mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt
+##
+## http://www.mozilla.org/projects/security/certs/policy/
+## http://www.mozilla.org/projects/security/pki/nss/
##
-## It contains the certificates in PEM format and therefore
+## This file contains the certificates in PEM format and therefore
## can be directly used with curl / libcurl / php_curl, or with
## an Apache+mod_ssl webserver for SSL client authentication.
## Just configure this file as the SSLCACertificateFile.
@@ -99,7 +101,7 @@ protected function buildBundle($rawCertData)
$line = rtrim($line);
- if (preg_match('/^(CVS_ID\s+\".*\")/', $line, $match)) {
+ if (preg_match('/^CVS_ID\s+\"(.*)\"/', $line, $match)) {
$caBundle .= "# {$match[1]}\n";
}
View
44 src/Sslurp/MozillaCertData.php
@@ -14,35 +14,21 @@ class MozillaCertData extends AbstractCaRootData
{
// mxr.mozilla.org cert expires Nov 28th, 2013
const MOZILLA_MXR_SSL_PIN = '47cac6d8f2c2363675e6f433970f27523824d0ec';
+ const MOZILLA_MXR_SSL_EXP = 1383282000; // Nov 1st, 2013
/**
* certdata.txt contents
*
* @var string
*/
- private $certData = null;
+ protected $certData = null;
/**
* Stream context
*
* @var resource
*/
- 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
- */
- public function __construct($certData = null)
- {
- $this->certData = $certData;
- }
+ protected $context = null;
/**
* Get the raw certdata.txt contents from mxr.mozilla.org
@@ -53,7 +39,7 @@ public function getContent($until = false)
{
if ($until) {
// don't cache the partial fetch for version check
- if ($this->certData) {
+ if ($this->certData !== null) {
return substr($this->certData, 0, strpos($this->certData, "\n", strpos($this->certData, $until)));
}
@@ -122,12 +108,10 @@ protected function fetchLatestCertData($until = false)
$params = stream_context_get_params($ctx);
$cert = new X509Certificate($params['options']['ssl']['peer_certificate']);
- $pin = static::$overrideCertPin ?: $cert->getPin();
- // November 1st, 2013 or later (mxr.mozilla.org cert expires Nov 28th, 2013)
- $exp = static::$overrideCertExp ?: 1383282000;
+ $pin = $cert->getPin();
if ($pin !== static::MOZILLA_MXR_SSL_PIN) {
- if (time() < $exp) {
+ if (time() < static::MOZILLA_MXR_SSL_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
@@ -167,20 +151,6 @@ protected function getResponseBody($string)
protected function getRootCaBundlePath()
{
- $caBundlePaths = array(
- '/etc/pki/tls/certs/ca-bundle.crt',
- '/etc/ssl/certs/ca-certificates.crt',
- '/etc/ssl/ca-bundle.pem',
- '/usr/share/ssl/certs/ca-bundle.crt',
- __DIR__ . '/../../data/Equifax_Secure_Ca.pem',
- );
-
- foreach ($caBundlePaths as $caBundle) {
- if (is_readable($caBundle)) {
- break;
- }
- }
-
- return (static::$forceAltCaBundle ?: $caBundle);
+ return Sslurp::getSystemCaRootBundlePath() ?: __DIR__ . '/../../data/Equifax_Secure_Ca.pem';
}
}
View
56 src/Sslurp/Sslurp.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * This file is part of Sslurp.
+ * https://github.com/EvanDotPro/Sslurp
+ *
+ * (c) Evan Coury <me@evancoury.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Sslurp;
+
+class Sslurp
+{
+ /**
+ * Sslurp version number
+ */
+ const VERSION = '1.0-dev';
+
+ /**
+ * Locate the system root CA bundle.
+ *
+ * @return string
+ */
+ public static function getSystemCaRootBundlePath()
+ {
+ // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that.
+ // This mimics how OpenSSL uses the SSL_CERT_FILE env variable.
+ $envCertFile = getenv('SSL_CERT_FILE');
@EvanDotPro Owner

This could be a potential security issue, according to Kevin McAurthur.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ if ($envCertFile && is_readable($envCertFile) && openssl_x509_parse(file_get_contents($envCertFile))) {
+ // Possibly throw exception instead of ignoring SSL_CERT_FILE if it's invalid?
+ return $envCertFile;
+ }
+
+ $caBundlePaths = array(
+ '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package)
+ '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package)
+ '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package)
+ '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package)
+ '/usr/ssl/certs/ca-bundle.crt', // Cygwin
+ '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package
+ '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option)
+ '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat?
+ );
+
+ $found = false;
+ foreach ($caBundlePaths as $caBundle) {
+ if (is_readable($caBundle) && openssl_x509_parse(file_get_contents($caBundle))) {
+ $found = true;
+ break;
+ }
+ }
+
+ return $found ? $caBundle : false;
+ }
+}
View
30 src/Sslurp/X509Certificate.php
@@ -19,17 +19,22 @@ class X509Certificate
/**
* @var X.509 resource
*/
- private $certificate;
+ protected $certificate;
+
+ /**
+ * @var string
+ */
+ protected $pin;
/**
* @var resource
*/
- private $publicKey;
+ protected $publicKey;
/**
* @var array
*/
- private $publicKeyDetails;
+ protected $publicKeyDetails;
/**
* @param $certificate mixed X.509 resource, X.509 certificate string, or path to X.509 certificate file.
@@ -65,15 +70,18 @@ public function __construct($certificate)
*/
public function getPin()
{
- $pubkeydetails = $this->getPublicKeyDetails();
- $pubkeypem = $pubkeydetails['key'];
- //Convert PEM to DER before SHA1'ing
- $start = '-----BEGIN PUBLIC KEY-----';
- $end = '-----END PUBLIC KEY-----';
- $pemtrim = substr($pubkeypem, (strpos($pubkeypem, $start) + strlen($start)), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
- $der = base64_decode($pemtrim);
+ if ($this->pin === null) {
+ $pubkeydetails = $this->getPublicKeyDetails();
+ $pubkeypem = $pubkeydetails['key'];
+ //Convert PEM to DER before SHA1'ing
+ $start = '-----BEGIN PUBLIC KEY-----';
+ $end = '-----END PUBLIC KEY-----';
+ $pemtrim = substr($pubkeypem, (strpos($pubkeypem, $start) + strlen($start)), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
+ $der = base64_decode($pemtrim);
+ $this->pin = sha1($der);
+ }
- return sha1($der);
+ return $this->pin;
}
/**
View
20 test/SslurpTest/CaRootPemBundleTest.php
@@ -2,8 +2,8 @@
namespace SslurpTest;
use PHPUnit_Framework_TestCase as TestCase;
-use Sslurp\CaRootPemBundle;
-use Sslurp\MozillaCertData;
+use SslurpTest\TestAsset\MockMozillaCertData as MozillaCertData;
+use SslurpTest\TestAsset\MockCaRootPemBundle as CaRootPemBundle;
use DateTime;
use DateTimeZone;
@@ -11,16 +11,11 @@ class CaRootPemBundleTest extends TestCase
{
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));
+ $this->bundle = new CaRootPemBundle(__DIR__ . '/_files/ca-bundle.pem', new MozillaCertData);
}
public function testBuildsCaRootBundleProperly()
{
- CaRootPemBundle::$overrideDateTime = 'for testing';
$result = $this->bundle->getUpdatedCaRootBundle();
$this->assertStringEqualsFile(__DIR__ . '/_files/ca-bundle.pem', $result);
}
@@ -35,15 +30,14 @@ public function testCanParseVersionAndDateDataProperly()
public function testIsLatestMethodWorks()
{
$this->assertTrue($this->bundle->isLatest());
- $this->setUp(true);
+ $this->bundle = new CaRootPemBundle(__DIR__ . '/_files/ca-bundle.pem', new MozillaCertData);
+ $this->bundle->setPemContent(str_replace('1.85', '1.86', $this->bundle->getContent()));
$this->assertFalse($this->bundle->isLatest());
}
public function testWillFetchMozillaCertData()
{
- require_once __DIR__ . '/TestAsset/MockMozillaCertData.php';
- $bundle = new CaRootPemBundle(null, new TestAsset\MockMozillaCertData);
- $this->assertNotNull($bundle->getContent());
- $this->assertInstanceOf('Sslurp\MozillaCertData', $bundle->getMozillaCertData());
+ $this->assertNotNull($this->bundle->getContent());
+ $this->assertInstanceOf('Sslurp\MozillaCertData', $this->bundle->getMozillaCertData());
}
}
View
44 test/SslurpTest/MozillaCertDataTest.php
@@ -2,20 +2,26 @@
namespace SslurpTest;
use PHPUnit_Framework_TestCase as TestCase;
-use Sslurp\MozillaCertData;
+//use Sslurp\MozillaCertData;
use DateTime;
use DateTimeZone;
+use SslurpTest\TestAsset\MockMozillaCertData as MozillaCertData;
+use SslurpTest\TestAsset\MockMozillaCertDataInvalidPin as MozillaCertDataInvalidPin;
+use SslurpTest\TestAsset\MockMozillaCertDataInvalidPinAndExp as MozillaCertDataInvalidPinAndExp;
class MozillaCertDataTest extends TestCase
{
public function setUp()
{
- MozillaCertData::$overrideCertPin = null;
- MozillaCertData::$overrideCertExp = null;
- MozillaCertData::$forceAltCaBundle = null;
$this->mozCertData = new MozillaCertData();
}
+ public function tearDown()
+ {
+ putenv('SSL_CERT_FILE');
+ MozillaCertData::$allowOnlineTest = false;
+ }
+
public function certData()
{
return file_get_contents(__DIR__ . '/_files/certdata.txt');
@@ -26,6 +32,7 @@ public function canDoOnlineTest()
if (!($fp = @stream_socket_client('tcp://mxr.mozilla.org:80', $errNo, $errStr, 1))) {
$this->markTestSkipped('Could not reach mxr.mozilla.org for online test.');
}
+ MozillaCertData::$allowOnlineTest = true;
fclose($fp);
}
@@ -33,7 +40,6 @@ public function testContextOptionsAreSecureDefaults()
{
$context = $this->mozCertData->getStreamContext();
$opts = stream_context_get_options($context);
-
$this->assertSame(true, $opts['ssl']['capture_peer_cert']);
$this->assertSame(true, $opts['ssl']['verify_peer']);
$this->assertSame(false, $opts['ssl']['allow_self_signed']);
@@ -43,7 +49,6 @@ public function testContextOptionsAreSecureDefaults()
public function testCanParseVersionAndDateDataProperly()
{
- $this->mozCertData = new MozillaCertData($this->certData());
$dateTime = new DateTime('2012/06/28 13:50:18', new DateTimeZone('UTC'));
$this->assertEquals($dateTime, $this->mozCertData->getDateTime());
$this->assertSame('1.85', $this->mozCertData->getVersion());
@@ -51,20 +56,23 @@ public function testCanParseVersionAndDateDataProperly()
public function testExpectedCertDataReturnedFromGetContent()
{
- $this->mozCertData = new MozillaCertData('foo');
- $this->assertEquals('foo', $this->mozCertData->getContent());
- require_once __DIR__ . '/TestAsset/MockMozillaCertDataFetchLatest.php';
- $this->mozCertData = new TestAsset\MockMozillaCertDataFetchLatest();
- $this->assertEquals('latest', $this->mozCertData->getContent());
+ $this->assertEquals($this->certData(), $this->mozCertData->getContent());
}
- public function testExceptionThrownIfCertDataIsInvalid()
+ public function testExceptionThrownIfCertDataIsInvalidWhenFetchingVersion()
{
$this->setExpectedException('RuntimeException');
- $this->mozCertData = new MozillaCertData('foo');
+ $this->mozCertData->setCertData('foo');
$this->mozCertData->getVersion();
}
+ public function testExceptionThrownIfCertDataIsInvalidWhenFetchingDateTime()
+ {
+ $this->setExpectedException('RuntimeException');
+ $this->mozCertData->setCertData('foo');
+ $this->mozCertData->getDateTime();
+ }
+
public function testMozillaCertDataOnlineCheck()
{
$this->canDoOnlineTest();
@@ -74,7 +82,7 @@ public function testMozillaCertDataOnlineCheck()
public function testMozillaCertDataOnlineCheckWithInvalidPinThrowsException()
{
$this->canDoOnlineTest();
- MozillaCertData::$overrideCertPin = 'invalid';
+ $this->mozCertData = new MozillaCertDataInvalidPin;
$this->setExpectedException('RuntimeException');
$this->mozCertData->getVersion();
}
@@ -82,8 +90,7 @@ public function testMozillaCertDataOnlineCheckWithInvalidPinThrowsException()
public function testMozillaCertDataOnlineCheckWithNewCertificateShowsWarningMessage()
{
$this->canDoOnlineTest();
- MozillaCertData::$overrideCertPin = 'invalid';
- MozillaCertData::$overrideCertExp = time() - 100;
+ $this->mozCertData = new MozillaCertDataInvalidPinAndExp;
$this->setExpectedException('PHPUnit_Framework_Error_Notice');
$this->mozCertData->getVersion();
}
@@ -91,15 +98,14 @@ public function testMozillaCertDataOnlineCheckWithNewCertificateShowsWarningMess
public function testMozillaCertDataOnlineCheckWithNewCertificateStillReturnsVersion()
{
$this->canDoOnlineTest();
- MozillaCertData::$overrideCertPin = 'invalid';
- MozillaCertData::$overrideCertExp = time() - 100;
+ $this->mozCertData = new MozillaCertDataInvalidPinAndExp;
$this->assertRegExp('/^\d+\.\d+$/', @$this->mozCertData->getVersion());
}
public function testMozillaCertDataOnlineFailsIfNoCaRootBundleFound()
{
$this->canDoOnlineTest();
- MozillaCertData::$forceAltCaBundle = __DIR__ . '/_files/mxr.mozilla.org.pem';
+ putenv('SSL_CERT_FILE=' . __DIR__ . '/_files/mxr.mozilla.org.pem');
$this->setExpectedException('RuntimeException');
$this->mozCertData->getVersion();
}
View
22 test/SslurpTest/SslurpTest.php
@@ -0,0 +1,22 @@
+<?php
+namespace SslurpTest;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use Sslurp\Sslurp;
+
+class SslurpTest extends TestCase
+{
+ public function testReturnsValidSystemCaBundle()
+ {
+ // Check that it at least finds a CA bundle _somewhere_.
+ // (not sure how this will work out on Travis)
+ $caBundlePath = Sslurp::getSystemCaRootBundlePath();
+ $this->assertRegExp('/^.+\.(pem|crt)$/', $caBundlePath);
+
+ // Check that we can override it with some other valid bundle
+ putenv('SSL_CERT_FILE=' . __DIR__ . '/../../data/Equifax_Secure_CA.pem');
+ $caBundlePath = Sslurp::getSystemCaRootBundlePath();
+ $this->assertSame(__DIR__ . '/../../data/Equifax_Secure_CA.pem', $caBundlePath);
+ putenv('SSL_CERT_FILE');
+ }
+}
View
14 test/SslurpTest/TestAsset/MockCaRootPemBundle.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace SslurpTest\TestAsset;
+
+use Sslurp\CaRootPemBundle;
+
+class MockCaRootPemBundle extends CaRootPemBundle
+{
+ //protected $dateTime = 'for testing';
+ public function setPemContent($pemContent)
+ {
+ $this->pemContent = $pemContent;
+ }
+}
View
19 test/SslurpTest/TestAsset/MockMozillaCertData.php
@@ -6,8 +6,23 @@
class MockMozillaCertData extends MozillaCertData
{
- public function getContent($until = false)
+ public static $allowOnlineTest = false;
+
+ public function setCertData($certData)
{
- return 'foo';
+ $this->certData = $certData;
+ }
+
+ protected function fetchLatestCertData($until = false)
+ {
+ if (static::$allowOnlineTest) {
+ return parent::fetchLatestCertData($until);
+ }
+ $return = $this->certData ?: file_get_contents(__DIR__ . '/../_files/certdata.txt');
+ if ($until) {
+ return substr($return, 0, strpos($return, "\n", strpos($return, $until)));
+ }
+
+ return $return;
}
}
View
13 test/SslurpTest/TestAsset/MockMozillaCertDataFetchLatest.php
@@ -1,13 +0,0 @@
-<?php
-
-namespace SslurpTest\TestAsset;
-
-use Sslurp\MozillaCertData;
-
-class MockMozillaCertDataFetchLatest extends MozillaCertData
-{
- protected function fetchLatestCertData($until = false)
- {
- return 'latest';
- }
-}
View
10 test/SslurpTest/TestAsset/MockMozillaCertDataInvalidPin.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace SslurpTest\TestAsset;
+
+use Sslurp\MozillaCertData;
+
+class MockMozillaCertDataInvalidPin extends MozillaCertData
+{
+ const MOZILLA_MXR_SSL_PIN = 'invalid';
+}
View
10 test/SslurpTest/TestAsset/MockMozillaCertDataInvalidPinAndExp.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace SslurpTest\TestAsset;
+
+define('PAST', time() - 100);
+
+class MockMozillaCertDataInvalidPinAndExp extends MockMozillaCertDataInvalidPin
+{
+ const MOZILLA_MXR_SSL_EXP = PAST;
+}
View
16 test/SslurpTest/_files/ca-bundle.pem
@@ -1,20 +1,22 @@
##
## Bundle of CA Root Certificates
##
-## Generated for testing
## Generated with Sslurp (https://github.com/EvanDotPro/Sslurp)
##
-## This is a bundle of X.509 certificates of public Certificate Authorities
-## (CA). These were automatically extracted from Mozilla's root certificates
-## file (certdata.txt). This file can be found in the mozilla source tree:
-## '/mozilla/security/nss/lib/ckfw/builtins/certdata.txt'
+## This is a bundle of X.509 certificates of public Certificate Authorities.
+## These were automatically extracted from Mozilla's root certificates
+## file (certdata.txt). This file can be found in the Mozilla source tree:
+## /mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt
##
-## It contains the certificates in PEM format and therefore
+## http://www.mozilla.org/projects/security/certs/policy/
+## http://www.mozilla.org/projects/security/pki/nss/
+##
+## This file contains the certificates in PEM format and therefore
## can be directly used with curl / libcurl / php_curl, or with
## an Apache+mod_ssl webserver for SSL client authentication.
## Just configure this file as the SSLCACertificateFile.
##
-# CVS_ID "@(#) $RCSfile: certdata.txt,v $ $Revision: 1.85 $ $Date: 2012/06/28 13:50:18 $"
+# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.85 $ $Date: 2012/06/28 13:50:18 $
GTE CyberTrust Global Root
==========================
View
9 test/bootstrap.php
@@ -0,0 +1,9 @@
+<?php
+require_once __DIR__ . '/../autoload_register.php';
+spl_autoload_register(function($class) {
+ $file = str_replace(array('\\', '_'), DIRECTORY_SEPARATOR, $class) . '.php';
+ if (false === ($realpath = stream_resolve_include_path($file))) {
+ return false;
+ }
+ include_once $realpath;
+});
View
2  test/phpunit.xml
@@ -1,4 +1,4 @@
-<phpunit bootstrap="../autoload_register.php" colors="true">
+<phpunit bootstrap="./bootstrap.php" colors="true">
<testsuite name="Sslurp Test Suite">
<directory>./</directory>
</testsuite>
Please sign in to comment.
Something went wrong with that request. Please try again.