From c1b11571ea53748d57241598dec71750637416cd Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 15 Aug 2014 17:18:46 +0200 Subject: Move certificate management interface from files_external to core --- settings/ajax/addRootCertificate.php | 34 +++++++++++++++++++++++++++++++++ settings/ajax/removeRootCertificate.php | 9 +++++++++ 2 files changed, 43 insertions(+) create mode 100644 settings/ajax/addRootCertificate.php create mode 100644 settings/ajax/removeRootCertificate.php (limited to 'settings/ajax') diff --git a/settings/ajax/addRootCertificate.php b/settings/ajax/addRootCertificate.php new file mode 100644 index 00000000000..9be8fd0025b --- /dev/null +++ b/settings/ajax/addRootCertificate.php @@ -0,0 +1,34 @@ +getCertificateManager(); + +if ($cert = $certificateManager->addCertificate($data, $filename)) { + OCP\JSON::success(array( + 'name' => $cert->getName(), + 'commonName' => $cert->getCommonName(), + 'organization' => $cert->getOrganization(), + 'validFrom' => $cert->getIssueDate()->getTimestamp(), + 'validTill' => $cert->getExpireDate()->getTimestamp(), + 'validFromString' => $l->l('date', $cert->getIssueDate()), + 'validTillString' => $l->l('date', $cert->getExpireDate()), + 'issuer' => $cert->getIssuerName(), + 'issuerOrganization' => $cert->getIssuerOrganization() + )); +} else { + OCP\JSON::error(array('error' => 'Couldn\'t import SSL root certificate, allowed formats: PEM and DER')); +} diff --git a/settings/ajax/removeRootCertificate.php b/settings/ajax/removeRootCertificate.php new file mode 100644 index 00000000000..0931138ad4b --- /dev/null +++ b/settings/ajax/removeRootCertificate.php @@ -0,0 +1,9 @@ +getCertificateManager(); +$certificateManager->removeCertificate($name); -- cgit v1.2.3 From f135130a7524e0b035a721aa395a60117494f806 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 15 Aug 2014 19:56:04 +0200 Subject: remove outdated checks --- settings/ajax/addRootCertificate.php | 2 -- settings/ajax/removeRootCertificate.php | 2 -- 2 files changed, 4 deletions(-) (limited to 'settings/ajax') diff --git a/settings/ajax/addRootCertificate.php b/settings/ajax/addRootCertificate.php index 9be8fd0025b..f055a4066ea 100644 --- a/settings/ajax/addRootCertificate.php +++ b/settings/ajax/addRootCertificate.php @@ -1,6 +1,4 @@ Date: Mon, 18 Aug 2014 13:57:38 +0200 Subject: Cleanup certificate code --- lib/private/certificate/certificate.php | 6 +++++- lib/private/certificate/certificatemanager.php | 26 +++++++++++++++++--------- settings/ajax/addRootCertificate.php | 13 ++++++------- 3 files changed, 28 insertions(+), 17 deletions(-) (limited to 'settings/ajax') diff --git a/lib/private/certificate/certificate.php b/lib/private/certificate/certificate.php index 801afa79167..6b4021cf5e0 100644 --- a/lib/private/certificate/certificate.php +++ b/lib/private/certificate/certificate.php @@ -27,6 +27,10 @@ class Certificate implements ICertificate { protected $issuerOrganization; + /** + * @param string $data base64 encoded certificate + * @param string $name + */ public function __construct($data, $name) { $this->name = $name; $info = openssl_x509_parse($data); @@ -97,7 +101,7 @@ class Certificate implements ICertificate { */ public function isExpired() { $now = new \DateTime(); - return !($this->issueDate <= $now and $now <= $this->expireDate); + return $this->issueDate > $now or $now > $this->expireDate; } /** diff --git a/lib/private/certificate/certificatemanager.php b/lib/private/certificate/certificatemanager.php index c6207f057dc..d7180f7f3fb 100644 --- a/lib/private/certificate/certificatemanager.php +++ b/lib/private/certificate/certificatemanager.php @@ -8,6 +8,7 @@ namespace OC\Certificate; +use OC\Files\Filesystem; use OCP\ICertificateManager; /** @@ -34,10 +35,7 @@ class CertificateManager implements ICertificateManager { public function listCertificates() { $path = $this->user->getHome() . '/files_external/uploads/'; if (!is_dir($path)) { - //path might not exist (e.g. non-standard OC_User::getHome() value) - //in this case create full path using 3rd (recursive=true) parameter. - //note that we use "normal" php filesystem functions here since the certs need to be local - mkdir($path, 0700, true); + return array(); } $result = array(); $handle = opendir($path); @@ -62,9 +60,7 @@ class CertificateManager implements ICertificateManager { $fh_certs = fopen($path . '/rootcerts.crt', 'w'); foreach ($certs as $cert) { $file = $path . '/uploads/' . $cert; - $fh = fopen($file, 'r'); - $data = fread($fh, filesize($file)); - fclose($fh); + $data = file_get_contents($file); if (strpos($data, 'BEGIN CERTIFICATE')) { fwrite($fh_certs, $data); fwrite($fh_certs, "\r\n"); @@ -75,6 +71,8 @@ class CertificateManager implements ICertificateManager { } /** + * Save the certificate and re-generate the certificate bundle + * * @param string $certificate the certificate data * @param string $name the filename for the certificate * @return bool | \OCP\ICertificate @@ -92,7 +90,14 @@ class CertificateManager implements ICertificateManager { } if ($isValid) { - $file = $this->user->getHome() . '/files_external/uploads/' . $name; + $dir = $this->user->getHome() . '/files_external/uploads/'; + if (!file_exists($dir)) { + //path might not exist (e.g. non-standard OC_User::getHome() value) + //in this case create full path using 3rd (recursive=true) parameter. + //note that we use "normal" php filesystem functions here since the certs need to be local + mkdir($dir, 0700, true); + } + $file = $dir . $name; file_put_contents($file, $certificate); $this->createCertificateBundle(); return new Certificate($certificate, $name); @@ -102,11 +107,13 @@ class CertificateManager implements ICertificateManager { } /** + * Remove the certificate and re-generate the certificate bundle + * * @param string $name * @return bool */ public function removeCertificate($name) { - if (!\OC\Files\Filesystem::isValidPath($name)) { + if (!Filesystem::isValidPath($name)) { return false; } $path = $this->user->getHome() . '/files_external/uploads/'; @@ -114,6 +121,7 @@ class CertificateManager implements ICertificateManager { unlink($path . $name); $this->createCertificateBundle(); } + return true; } /** diff --git a/settings/ajax/addRootCertificate.php b/settings/ajax/addRootCertificate.php index f055a4066ea..87b1460ef12 100644 --- a/settings/ajax/addRootCertificate.php +++ b/settings/ajax/addRootCertificate.php @@ -3,19 +3,18 @@ OCP\JSON::callCheck(); $l = new OC_L10N('core'); -if (!($filename = $_FILES['rootcert_import']['name'])) { - header('Location:' . OCP\Util::linkToRoute("settings_personal")); +if (!isset($_FILES['rootcert_import'])) { + OCP\JSON::error(array('error' => 'No certificate uploaded')); exit; } -$fh = fopen($_FILES['rootcert_import']['tmp_name'], 'r'); -$data = fread($fh, filesize($_FILES['rootcert_import']['tmp_name'])); -fclose($fh); -$filename = $_FILES['rootcert_import']['name']; +$data = file_get_contents($_FILES['rootcert_import']['tmp_name']); +$filename = basename($_FILES['rootcert_import']['name']); $certificateManager = \OC::$server->getCertificateManager(); -if ($cert = $certificateManager->addCertificate($data, $filename)) { +$cert = $certificateManager->addCertificate($data, $filename); +if ($cert) { OCP\JSON::success(array( 'name' => $cert->getName(), 'commonName' => $cert->getCommonName(), -- cgit v1.2.3 From 4efe6f62402482608cb1b2f4c51b9b3e41603733 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Wed, 27 Aug 2014 16:28:51 +0200 Subject: Add unit tests and fix rootcerts creation bug --- lib/private/security/certificate.php | 27 ++++---- lib/private/security/certificatemanager.php | 37 ++++++----- settings/ajax/addRootCertificate.php | 7 +- settings/js/personal.js | 2 +- settings/templates/personal.php | 9 ++- tests/data/certificates/badCertificate.crt | 13 ++++ tests/data/certificates/expiredCertificate.crt | 13 ++++ tests/data/certificates/goodCertificate.crt | 15 +++++ tests/lib/security/certificate.php | 90 ++++++++++++++++++++++++++ tests/lib/security/certificatemanager.php | 87 +++++++++++++++++++++++++ 10 files changed, 263 insertions(+), 37 deletions(-) create mode 100644 tests/data/certificates/badCertificate.crt create mode 100644 tests/data/certificates/expiredCertificate.crt create mode 100644 tests/data/certificates/goodCertificate.crt create mode 100644 tests/lib/security/certificate.php create mode 100644 tests/lib/security/certificatemanager.php (limited to 'settings/ajax') diff --git a/lib/private/security/certificate.php b/lib/private/security/certificate.php index 953111f469d..63c02a124f4 100644 --- a/lib/private/security/certificate.php +++ b/lib/private/security/certificate.php @@ -30,17 +30,22 @@ class Certificate implements ICertificate { /** * @param string $data base64 encoded certificate * @param string $name + * @throws \Exception If the certificate could not get parsed */ public function __construct($data, $name) { $this->name = $name; - $info = openssl_x509_parse($data); - $this->commonName = $info['subject']['CN']; - $this->organization = isset($info['subject']['O']) ? $info['subject']['O'] : null; - $this->serial = $this->formatSerial($info['serialNumber']); - $this->issueDate = new \DateTime('@' . $info['validFrom_time_t']); - $this->expireDate = new \DateTime('@' . $info['validTo_time_t']); - $this->issuerName = $info['issuer']['CN']; - $this->issuerOrganization = isset($info['issuer']['O']) ? $info['issuer']['O'] : null; + try { + $info = openssl_x509_parse($data); + $this->commonName = isset($info['subject']['CN']) ? $info['subject']['CN'] : null; + $this->organization = isset($info['subject']['O']) ? $info['subject']['O'] : null; + $this->serial = $this->formatSerial($info['serialNumber']); + $this->issueDate = new \DateTime('@' . $info['validFrom_time_t']); + $this->expireDate = new \DateTime('@' . $info['validTo_time_t']); + $this->issuerName = isset($info['issuer']['CN']) ? $info['issuer']['CN'] : null; + $this->issuerOrganization = isset($info['issuer']['O']) ? $info['issuer']['O'] : null; + } catch (\Exception $e) { + throw new \Exception('Certificate could not get parsed.'); + } } /** @@ -62,7 +67,7 @@ class Certificate implements ICertificate { } /** - * @return string + * @return string|null */ public function getCommonName() { return $this->commonName; @@ -105,14 +110,14 @@ class Certificate implements ICertificate { } /** - * @return string + * @return string|null */ public function getIssuerName() { return $this->issuerName; } /** - * @return string + * @return string|null */ public function getIssuerOrganization() { return $this->issuerOrganization; diff --git a/lib/private/security/certificatemanager.php b/lib/private/security/certificatemanager.php index 64a1d6431a4..cae9730eb26 100644 --- a/lib/private/security/certificatemanager.php +++ b/lib/private/security/certificatemanager.php @@ -44,7 +44,9 @@ class CertificateManager implements ICertificateManager { } while (false !== ($file = readdir($handle))) { if ($file != '.' && $file != '..') { - $result[] = new Certificate(file_get_contents($path . $file), $file); + try { + $result[] = new Certificate(file_get_contents($path . $file), $file); + } catch(\Exception $e) {} } } return $result; @@ -59,7 +61,7 @@ class CertificateManager implements ICertificateManager { $fh_certs = fopen($path . '/rootcerts.crt', 'w'); foreach ($certs as $cert) { - $file = $path . '/uploads/' . $cert; + $file = $path . '/uploads/' . $cert->getName(); $data = file_get_contents($file); if (strpos($data, 'BEGIN CERTIFICATE')) { fwrite($fh_certs, $data); @@ -75,35 +77,32 @@ class CertificateManager implements ICertificateManager { * * @param string $certificate the certificate data * @param string $name the filename for the certificate - * @return bool | \OCP\ICertificate + * @return \OCP\ICertificate|void|bool + * @throws \Exception If the certificate could not get added */ public function addCertificate($certificate, $name) { if (!Filesystem::isValidPath($name) or Filesystem::isFileBlacklisted($name)) { return false; } - $isValid = openssl_pkey_get_public($certificate); - if (!$isValid) { - $data = chunk_split(base64_encode($certificate), 64, "\n"); - $data = "-----BEGIN CERTIFICATE-----\n" . $data . "-----END CERTIFICATE-----\n"; - $isValid = openssl_pkey_get_public($data); + $dir = $this->user->getHome() . '/files_external/uploads/'; + if (!file_exists($dir)) { + //path might not exist (e.g. non-standard OC_User::getHome() value) + //in this case create full path using 3rd (recursive=true) parameter. + //note that we use "normal" php filesystem functions here since the certs need to be local + mkdir($dir, 0700, true); } - if ($isValid) { - $dir = $this->user->getHome() . '/files_external/uploads/'; - if (!file_exists($dir)) { - //path might not exist (e.g. non-standard OC_User::getHome() value) - //in this case create full path using 3rd (recursive=true) parameter. - //note that we use "normal" php filesystem functions here since the certs need to be local - mkdir($dir, 0700, true); - } + try { $file = $dir . $name; + $certificateObject = new Certificate($certificate, $name); file_put_contents($file, $certificate); $this->createCertificateBundle(); - return new Certificate($certificate, $name); - } else { - return false; + return $certificateObject; + } catch (\Exception $e) { + throw $e; } + } /** diff --git a/settings/ajax/addRootCertificate.php b/settings/ajax/addRootCertificate.php index 87b1460ef12..378ef39c1e5 100644 --- a/settings/ajax/addRootCertificate.php +++ b/settings/ajax/addRootCertificate.php @@ -1,4 +1,5 @@ getCertificateManager(); -$cert = $certificateManager->addCertificate($data, $filename); -if ($cert) { +try { + $cert = $certificateManager->addCertificate($data, $filename); OCP\JSON::success(array( 'name' => $cert->getName(), 'commonName' => $cert->getCommonName(), @@ -26,6 +27,6 @@ if ($cert) { 'issuer' => $cert->getIssuerName(), 'issuerOrganization' => $cert->getIssuerOrganization() )); -} else { +} catch(\Exception $e) { OCP\JSON::error(array('error' => 'Couldn\'t import SSL root certificate, allowed formats: PEM and DER')); } diff --git a/settings/js/personal.js b/settings/js/personal.js index d6546717d16..11e9593d74a 100644 --- a/settings/js/personal.js +++ b/settings/js/personal.js @@ -325,7 +325,7 @@ $(document).ready(function () { var row = $(''); row.addClass(isExpired? 'expired': 'valid'); row.append($('').attr('title', data.result.organization).text(data.result.commonName)); - row.append($('').attr('title', t('core,', 'Valid from {date}', {date: data.result.validFromString})) + row.append($('').attr('title', t('core,', 'Valid until {date}', {date: data.result.validFromString})) .text(data.result.validTillString)); row.append($('').attr('title', data.result.issuerOrganization).text(data.result.issuer)); row.append($('').addClass('remove').append( diff --git a/settings/templates/personal.php b/settings/templates/personal.php index 8cb7be27735..871a0ec9e39 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -2,7 +2,10 @@ * Copyright (c) 2011, Robin Appelman * This file is licensed under the Affero General Public License version 3 or later. * See the COPYING-README file. - */?> + */ + +/** @var $_ array */ +?>

t('Get the apps to sync your files'));?>

@@ -160,12 +163,12 @@ if($_['passwordChangeSupported']) { - + getCommonName()) ?> - + l('date', $rootCert->getExpireDate()) ?> diff --git a/tests/data/certificates/badCertificate.crt b/tests/data/certificates/badCertificate.crt new file mode 100644 index 00000000000..dcb1895fbad --- /dev/null +++ b/tests/data/certificates/badCertificate.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQDNdmb4pJrUeDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE0MDgyNzA4NDg1MVoXDTE1MDgyNzA4NDg1MVowRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvrMe +x5D45HVMV2U4kqTU0mzHAihHT6r+OtO6g7S9yIlJZGGVcEet6An78Ow7aYM141eI +Jfbvqql7OIblHXSw7mvkw4bOQ1ee5lmJYOYCgaMNJ6mBLJfpK9xwidb0ZvhWOA8P +DLIiBKA3T5ChXCzilD5GF2+H/BXBE9lL9tuDjM0CAwEAATANBgkqhkiG9w0BAQUF +AAOBgQCJwfJe7j+aNkopw+P8uxobfOnMWU9XC4Pu+39TVLeakeSqu2Y8vJSHmkjF +WK3VXAJr33Eul5VP/3SWGwuRPd9X4i4iLh1gJfYvi9MJf1lQNYncGCM+xtdrNu2O +u0yexkOBRrapDYjcv58BiOaFgvFLquKvtVj9HlcYRfwfM77uKQ== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/tests/data/certificates/expiredCertificate.crt b/tests/data/certificates/expiredCertificate.crt new file mode 100644 index 00000000000..5e7e5df2cbf --- /dev/null +++ b/tests/data/certificates/expiredCertificate.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQCjCIB6tCZ2sDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE0MDgyNzA5MTI0M1oXDTE0MDgyODA5MTI0M1owRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvrMe +x5D45HVMV2U4kqTU0mzHAihHT6r+OtO6g7S9yIlJZGGVcEet6An78Ow7aYM141eI +Jfbvqql7OIblHXSw7mvkw4bOQ1ee5lmJYOYCgaMNJ6mBLJfpK9xwidb0ZvhWOA8P +DLIiBKA3T5ChXCzilD5GF2+H/BXBE9lL9tuDjM0CAwEAATANBgkqhkiG9w0BAQUF +AAOBgQBuNClmOj3wudlX86nygcZgQT2+ZS8f1iJgM9lbrrkenT6tgcT1/YjcrN9C +BZR29Wz7htflpqverLUGZXh72K+gYercyR16Zu7zjt/NWuZldZmzJ3bUGq2HSoCX +2sDykAEuaDxUlzdJrztlOH4vPlRaGbxUogpC2hB1BQfxA90CIA== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/tests/data/certificates/goodCertificate.crt b/tests/data/certificates/goodCertificate.crt new file mode 100644 index 00000000000..4a5d7bd32fe --- /dev/null +++ b/tests/data/certificates/goodCertificate.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICazCCAdQCCQCySF7HjQD78DANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJD +SDEPMA0GA1UECBMGWnVyaWNoMQ8wDQYDVQQHEwZadXJpY2gxFjAUBgNVBAoTDW93 +bkNsb3VkIEluYy4xETAPBgNVBAsTCFNlY3VyaXR5MR4wHAYDVQQDExVzZWN1cml0 +eS5vd25jbG91ZC5jb20wHhcNMTQwODI3MDg0NTUyWhcNMTUwODI3MDg0NTUyWjB6 +MQswCQYDVQQGEwJDSDEPMA0GA1UECBMGWnVyaWNoMQ8wDQYDVQQHEwZadXJpY2gx +FjAUBgNVBAoTDW93bkNsb3VkIEluYy4xETAPBgNVBAsTCFNlY3VyaXR5MR4wHAYD +VQQDExVzZWN1cml0eS5vd25jbG91ZC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBAL55lB4RvU0pTyh7YsLCxPBq43xxkRZBxfZENoflCIUsBo7/mXNz2zVO +476oQ4L47heUOX3j8kemOgPmWEqA34JB8rusijCy5WqFBLnm4HsRLa66i+Jgd+Yl +QhcKvhGas1K/CVTG4oSLoAmA2coZUL94uxnRtd8aluflHMNGApIlAgMBAAEwDQYJ +KoZIhvcNAQEFBQADgYEADo08zWdOtIvCKFDnLbzRwIjSYTlAtQtQaULv7KQe3qIn +iaFAi6fAynHfdC8/2tvmSeniw0OZBkrfVGIVtUbwCSrljNSUY/lWrUR0pE61lb4r +DpX0JZjlk48XEaErRVDfu3wq6n/2nYg6HnaLOPwt8OSYYrxzvXlFPrKBH3q6R+M= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/tests/lib/security/certificate.php b/tests/lib/security/certificate.php new file mode 100644 index 00000000000..694d1f27011 --- /dev/null +++ b/tests/lib/security/certificate.php @@ -0,0 +1,90 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. +*/ + +use \OC\Security\Certificate; + +class CertificateTest extends \PHPUnit_Framework_TestCase { + + /** @var Certificate That contains a valid certificate */ + protected $goodCertificate; + /** @var Certificate That contains an invalid certificate */ + protected $invalidCertificate; + /** @var Certificate That contains an expired certificate */ + protected $expiredCertificate; + + function setUp() { + $goodCertificate = file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'); + $this->goodCertificate = new Certificate($goodCertificate, 'GoodCertificate'); + $badCertificate = file_get_contents(__DIR__.'/../../data/certificates/badCertificate.crt'); + $this->invalidCertificate = new Certificate($badCertificate, 'BadCertificate'); + $expiredCertificate = file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'); + $this->expiredCertificate = new Certificate($expiredCertificate, 'ExpiredCertificate'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Certificate could not get parsed. + */ + function testBogusData() { + new Certificate('foo', 'bar'); + } + + function testGetName() { + $this->assertSame('GoodCertificate', $this->goodCertificate->getName()); + $this->assertSame('BadCertificate', $this->invalidCertificate->getName()); + } + + function testGetCommonName() { + $this->assertSame('security.owncloud.com', $this->goodCertificate->getCommonName()); + $this->assertSame(null, $this->invalidCertificate->getCommonName()); + } + + function testGetOrganization() { + $this->assertSame('ownCloud Inc.', $this->goodCertificate->getOrganization()); + $this->assertSame('Internet Widgits Pty Ltd', $this->invalidCertificate->getOrganization()); + } + + function testGetSerial() { + $this->assertSame('7F:FF:FF:FF:FF:FF:FF:FF', $this->goodCertificate->getSerial()); + $this->assertSame('7F:FF:FF:FF:FF:FF:FF:FF', $this->invalidCertificate->getSerial()); + } + + function testGetIssueDate() { + $this->assertEquals(new DateTime('2014-08-27 08:45:52'), $this->goodCertificate->getIssueDate()); + $this->assertEquals(new DateTime('2014-08-27 08:48:51'), $this->invalidCertificate->getIssueDate()); + } + + function testGetExpireDate() { + $this->assertEquals(new DateTime('2015-08-27 08:45:52'), $this->goodCertificate->getExpireDate()); + $this->assertEquals(new DateTime('2015-08-27 08:48:51'), $this->invalidCertificate->getExpireDate()); + $this->assertEquals(new DateTime('2014-08-28 09:12:43'), $this->expiredCertificate->getExpireDate()); + } + + /** + * Obviously the following test case might fail after 2015-08-27, just create a new certificate with longer validity then + */ + function testIsExpired() { + $this->assertSame(false, $this->goodCertificate->isExpired()); + $this->assertSame(false, $this->invalidCertificate->isExpired()); + + // TODO: Change to false after tomorrow + $this->assertSame(false, $this->expiredCertificate->isExpired()); + } + + function testGetIssuerName() { + $this->assertSame('security.owncloud.com', $this->goodCertificate->getIssuerName()); + $this->assertSame(null, $this->invalidCertificate->getIssuerName()); + $this->assertSame(null, $this->expiredCertificate->getIssuerName()); + } + + function testGetIssuerOrganization() { + $this->assertSame('ownCloud Inc.', $this->goodCertificate->getIssuerOrganization()); + $this->assertSame('Internet Widgits Pty Ltd', $this->invalidCertificate->getIssuerOrganization()); + $this->assertSame('Internet Widgits Pty Ltd', $this->expiredCertificate->getIssuerOrganization()); + } +} \ No newline at end of file diff --git a/tests/lib/security/certificatemanager.php b/tests/lib/security/certificatemanager.php new file mode 100644 index 00000000000..5baf9e16e81 --- /dev/null +++ b/tests/lib/security/certificatemanager.php @@ -0,0 +1,87 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +use \OC\Security\CertificateManager; + +class CertificateManagerTest extends \PHPUnit_Framework_TestCase { + + /** @var CertificateManager */ + private $certificateManager; + /** @var String */ + private $username; + /** @var \OC\User\User */ + private $user; + + function setUp() { + $this->username = OC_Util::generateRandomBytes(20); + OC_User::createUser($this->username, OC_Util::generateRandomBytes(20)); + + \OC_Util::tearDownFS(); + \OC_User::setUserId(''); + \OC\Files\Filesystem::tearDown(); + \OC_Util::setupFS($this->username); + + $this->user = \OC::$server->getUserManager()->get($this->username); + + $this->certificateManager = new CertificateManager($this->user); + } + + function tearDown() { + \OC_User::deleteUser($this->username); + } + + protected function assertEqualsArrays($expected, $actual) { + sort($expected); + sort($actual); + + $this->assertEquals($expected, $actual); + } + + function testListCertificates() { + // Test empty certificate bundle + $this->assertSame(array(), $this->certificateManager->listCertificates()); + + // Add some certificates + $this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'), 'GoodCertificate'); + $certificateStore = array(); + $certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'), 'GoodCertificate'); + $this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates()); + + // Add another certificates + $this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate'); + $certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate'); + $this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates()); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Certificate could not get parsed. + */ + function testAddInvalidCertificate() { + $this->certificateManager->addCertificate('InvalidCertificate', 'invalidCertificate'); + } + + function testAddDangerousFile() { + $this->assertFalse($this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), '.htaccess')); + $this->assertFalse($this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), '../../foo.txt')); + } + + function testRemoveDangerousFile() { + $this->assertFalse($this->certificateManager->removeCertificate('../../foo.txt')); + } + + function testRemoveExistingFile() { + $this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'), 'GoodCertificate'); + $this->assertTrue($this->certificateManager->removeCertificate('GoodCertificate')); + } + + function testGetCertificateBundle() { + $this->assertSame($this->user->getHome().'/files_external/rootcerts.crt', $this->certificateManager->getCertificateBundle()); + } + +} \ No newline at end of file -- cgit v1.2.3