summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Müller <thomas.mueller@tmit.eu>2016-01-12 15:01:46 +0100
committerThomas Müller <thomas.mueller@tmit.eu>2016-01-12 15:01:46 +0100
commiteac5d9fb3a52932fafdb200a2cf5d50fe9f1c759 (patch)
treeb5ebb8da406d6d667632beb4b764568c8ff954a3
parent2493cfede92c472c29cffc098206b8cdb7a2ca30 (diff)
parent0d0377ebfb123e079822632ae4bc6855a11eb117 (diff)
downloadnextcloud-server-eac5d9fb3a52932fafdb200a2cf5d50fe9f1c759.tar.gz
nextcloud-server-eac5d9fb3a52932fafdb200a2cf5d50fe9f1c759.zip
Merge pull request #21336 from owncloud/system-root-certs
Allow admins to add system wide root certificates
-rw-r--r--apps/files_external/js/settings.js7
-rw-r--r--config/config.sample.php5
-rw-r--r--lib/private/http/client/client.php9
-rw-r--r--lib/private/security/certificatemanager.php89
-rw-r--r--lib/private/server.php6
-rw-r--r--lib/public/icertificatemanager.php12
-rw-r--r--lib/public/iservercontainer.php2
-rw-r--r--settings/admin.php16
-rw-r--r--settings/application.php4
-rw-r--r--settings/controller/certificatecontroller.php71
-rw-r--r--settings/js/certificates.js69
-rw-r--r--settings/js/personal.js67
-rw-r--r--settings/personal.php19
-rw-r--r--settings/routes.php2
-rw-r--r--settings/templates/certificates.php44
-rw-r--r--settings/templates/personal.php42
-rw-r--r--tests/lib/security/certificatemanager.php23
-rw-r--r--tests/settings/controller/CertificateControllerTest.php4
18 files changed, 323 insertions, 168 deletions
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index 59cf55d6ad5..2f879e1c850 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -1210,13 +1210,6 @@ $(document).ready(function() {
});
mountConfigListView.loadStorages();
- $('#sslCertificate').on('click', 'td.remove>img', function() {
- var $tr = $(this).closest('tr');
- $.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), {cert: $tr.attr('id')});
- $tr.remove();
- return true;
- });
-
// TODO: move this into its own View class
var $allowUserMounting = $('#allowUserMounting');
$allowUserMounting.bind('change', function() {
diff --git a/config/config.sample.php b/config/config.sample.php
index 525a0895b07..b0ede5cc6de 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -854,6 +854,11 @@ $CONFIG = array(
),
/**
+ * Allow the configuration of system wide trusted certificates
+ */
+'enable_certificate_management' => false,
+
+/**
* Memory caching backend configuration
*
* Available cache backends:
diff --git a/lib/private/http/client/client.php b/lib/private/http/client/client.php
index 5f298e1acd7..8cddfc3ae03 100644
--- a/lib/private/http/client/client.php
+++ b/lib/private/http/client/client.php
@@ -58,12 +58,11 @@ class Client implements IClient {
* Sets the default options to the client
*/
private function setDefaultOptions() {
- // Either use default bundle or the user bundle if nothing is specified
- if($this->certificateManager->listCertificates() !== []) {
- $dataDir = $this->config->getSystemValue('datadirectory');
- $this->client->setDefaultOption('verify', $dataDir.'/'.$this->certificateManager->getCertificateBundle());
+ // Either use user bundle or the system bundle if nothing is specified
+ if ($this->certificateManager->listCertificates() !== []) {
+ $this->client->setDefaultOption('verify', $this->certificateManager->getAbsoluteBundlePath());
} else {
- $this->client->setDefaultOption('verify', \OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
+ $this->client->setDefaultOption('verify', $this->certificateManager->getAbsoluteBundlePath(null));
}
$this->client->setDefaultOption('headers/User-Agent', 'ownCloud Server Crawler');
diff --git a/lib/private/security/certificatemanager.php b/lib/private/security/certificatemanager.php
index ded81863a73..ce0d330c4b2 100644
--- a/lib/private/security/certificatemanager.php
+++ b/lib/private/security/certificatemanager.php
@@ -50,7 +50,7 @@ class CertificateManager implements ICertificateManager {
/**
* @param string $uid
- * @param \OC\Files\View $view relative zu data/
+ * @param \OC\Files\View $view relative to data/
* @param IConfig $config
*/
public function __construct($uid, \OC\Files\View $view, IConfig $config) {
@@ -83,7 +83,8 @@ class CertificateManager implements ICertificateManager {
if ($file != '.' && $file != '..') {
try {
$result[] = new Certificate($this->view->file_get_contents($path . $file), $file);
- } catch(\Exception $e) {}
+ } catch (\Exception $e) {
+ }
}
}
closedir($handle);
@@ -97,22 +98,34 @@ class CertificateManager implements ICertificateManager {
$path = $this->getPathToCertificates();
$certs = $this->listCertificates();
- $fh_certs = $this->view->fopen($path . '/rootcerts.crt', 'w');
+ if (!$this->view->file_exists($path)) {
+ $this->view->mkdir($path);
+ }
+
+ $fhCerts = $this->view->fopen($path . '/rootcerts.crt', 'w');
// Write user certificates
foreach ($certs as $cert) {
$file = $path . '/uploads/' . $cert->getName();
$data = $this->view->file_get_contents($file);
if (strpos($data, 'BEGIN CERTIFICATE')) {
- fwrite($fh_certs, $data);
- fwrite($fh_certs, "\r\n");
+ fwrite($fhCerts, $data);
+ fwrite($fhCerts, "\r\n");
}
}
// Append the default certificates
$defaultCertificates = file_get_contents(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
- fwrite($fh_certs, $defaultCertificates);
- fclose($fh_certs);
+ fwrite($fhCerts, $defaultCertificates);
+
+ // Append the system certificate bundle
+ $systemBundle = $this->getCertificateBundle(null);
+ if ($this->view->file_exists($systemBundle)) {
+ $systemCertificates = $this->view->file_get_contents($systemBundle);
+ fwrite($fhCerts, $systemCertificates);
+ }
+
+ fclose($fhCerts);
}
/**
@@ -166,18 +179,72 @@ class CertificateManager implements ICertificateManager {
/**
* Get the path to the certificate bundle for this user
*
+ * @param string $uid (optional) user to get the certificate bundle for, use `null` to get the system bundle
* @return string
*/
- public function getCertificateBundle() {
- return $this->getPathToCertificates() . 'rootcerts.crt';
+ public function getCertificateBundle($uid = '') {
+ if ($uid === '') {
+ $uid = $this->uid;
+ }
+ return $this->getPathToCertificates($uid) . 'rootcerts.crt';
+ }
+
+ /**
+ * Get the full local path to the certificate bundle for this user
+ *
+ * @param string $uid (optional) user to get the certificate bundle for, use `null` to get the system bundle
+ * @return string
+ */
+ public function getAbsoluteBundlePath($uid = '') {
+ if ($uid === '') {
+ $uid = $this->uid;
+ }
+ if ($this->needsRebundling($uid)) {
+ if (is_null($uid)) {
+ $manager = new CertificateManager(null, $this->view, $this->config);
+ $manager->createCertificateBundle();
+ } else {
+ $this->createCertificateBundle();
+ }
+ }
+ return $this->view->getLocalFile($this->getCertificateBundle($uid));
}
/**
+ * @param string $uid (optional) user to get the certificate path for, use `null` to get the system path
* @return string
*/
- private function getPathToCertificates() {
- $path = is_null($this->uid) ? '/files_external/' : '/' . $this->uid . '/files_external/';
+ private function getPathToCertificates($uid = '') {
+ if ($uid === '') {
+ $uid = $this->uid;
+ }
+ $path = is_null($uid) ? '/files_external/' : '/' . $uid . '/files_external/';
return $path;
}
+
+ /**
+ * Check if we need to re-bundle the certificates because one of the sources has updated
+ *
+ * @param string $uid (optional) user to get the certificate path for, use `null` to get the system path
+ * @return bool
+ */
+ private function needsRebundling($uid = '') {
+ if ($uid === '') {
+ $uid = $this->uid;
+ }
+ $sourceMTimes = [filemtime(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt')];
+ $targetBundle = $this->getCertificateBundle($uid);
+ if (!$this->view->file_exists($targetBundle)) {
+ return true;
+ }
+ if (!is_null($uid)) { // also depend on the system bundle
+ $sourceBundles[] = $this->view->filemtime($this->getCertificateBundle(null));
+ }
+
+ $sourceMTime = array_reduce($sourceMTimes, function ($max, $mtime) {
+ return max($max, $mtime);
+ }, 0);
+ return $sourceMTime > $this->view->filemtime($targetBundle);
+ }
}
diff --git a/lib/private/server.php b/lib/private/server.php
index ead9fa95db8..414f59af612 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -921,11 +921,11 @@ class Server extends ServerContainer implements IServerContainer {
/**
* Get the certificate manager for the user
*
- * @param string $userId (optional) if not specified the current loggedin user is used
+ * @param string $userId (optional) if not specified the current loggedin user is used, use null to get the system certificate manager
* @return \OCP\ICertificateManager | null if $uid is null and no user is logged in
*/
- public function getCertificateManager($userId = null) {
- if (is_null($userId)) {
+ public function getCertificateManager($userId = '') {
+ if ($userId === '') {
$userSession = $this->getUserSession();
$user = $userSession->getUser();
if (is_null($user)) {
diff --git a/lib/public/icertificatemanager.php b/lib/public/icertificatemanager.php
index b1a16d8b5ee..3872fdd765d 100644
--- a/lib/public/icertificatemanager.php
+++ b/lib/public/icertificatemanager.php
@@ -54,8 +54,18 @@ interface ICertificateManager {
/**
* Get the path to the certificate bundle for this user
*
+ * @param string $uid (optional) user to get the certificate bundle for, use `null` to get the system bundle (since 9.0.0)
* @return string
* @since 8.0.0
*/
- public function getCertificateBundle();
+ public function getCertificateBundle($uid = '');
+
+ /**
+ * Get the full local path to the certificate bundle for this user
+ *
+ * @param string $uid (optional) user to get the certificate bundle for, use `null` to get the system bundle
+ * @return string
+ * @since 9.0.0
+ */
+ public function getAbsoluteBundlePath($uid = '');
}
diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php
index 267e5dc4d31..e706750bb21 100644
--- a/lib/public/iservercontainer.php
+++ b/lib/public/iservercontainer.php
@@ -326,7 +326,7 @@ interface IServerContainer {
/**
* Get the certificate manager for the user
*
- * @param string $userId (optional) if not specified the current loggedin user is used
+ * @param string $userId (optional) if not specified the current loggedin user is used, use null to get the system certificate manager
* @return \OCP\ICertificateManager | null if $userId is null and no user is logged in
* @since 8.0.0
*/
diff --git a/settings/admin.php b/settings/admin.php
index 25db05d99ac..112b9d38c90 100644
--- a/settings/admin.php
+++ b/settings/admin.php
@@ -38,6 +38,10 @@ OC_Util::checkAdminUser();
$template = new OC_Template('settings', 'admin', 'user');
$l = \OC::$server->getL10N('settings');
+OC_Util::addScript('settings', 'certificates');
+OC_Util::addScript('files', 'jquery.iframe-transport');
+OC_Util::addScript('files', 'jquery.fileupload');
+
$showLog = (\OC::$server->getConfig()->getSystemValue('log_type', 'owncloud') === 'owncloud');
$numEntriesToLoad = 3;
$entries = OC_Log_Owncloud::getEntries($numEntriesToLoad + 1);
@@ -52,6 +56,8 @@ if($doesLogFileExist) {
$config = \OC::$server->getConfig();
$appConfig = \OC::$server->getAppConfig();
$request = \OC::$server->getRequest();
+$certificateManager = \OC::$server->getCertificateManager(null);
+$urlGenerator = \OC::$server->getURLGenerator();
// Should we display sendmail as an option?
$template->assign('sendmail_is_available', (bool) \OC_Helper::findBinaryPath('sendmail'));
@@ -152,6 +158,16 @@ $template->assign('OutdatedCacheWarning', $outdatedCaches);
// add hardcoded forms from the template
$forms = OC_App::getForms('admin');
+
+if ($config->getSystemValue('enable_certificate_management', false)) {
+ $certificatesTemplate = new OC_Template('settings', 'certificates');
+ $certificatesTemplate->assign('type', 'admin');
+ $certificatesTemplate->assign('uploadRoute', 'settings.Certificate.addSystemRootCertificate');
+ $certificatesTemplate->assign('certs', $certificateManager->listCertificates());
+ $certificatesTemplate->assign('urlGenerator', $urlGenerator);
+ $forms[] = $certificatesTemplate->fetchPage();
+}
+
$formsAndMore = array();
if ($request->getServerProtocol() !== 'https' || !OC_Util::isAnnotationsWorking() ||
$suggestedOverwriteCliUrl || !OC_Util::isSetLocaleWorking() ||
diff --git a/settings/application.php b/settings/application.php
index 729e61b5925..1c562c62a84 100644
--- a/settings/application.php
+++ b/settings/application.php
@@ -107,6 +107,7 @@ class Application extends App {
$c->query('AppName'),
$c->query('Request'),
$c->query('CertificateManager'),
+ $c->query('SystemCertificateManager'),
$c->query('L10N'),
$c->query('IAppManager')
);
@@ -243,6 +244,9 @@ class Application extends App {
$container->registerService('CertificateManager', function(IContainer $c){
return $c->query('ServerContainer')->getCertificateManager();
});
+ $container->registerService('SystemCertificateManager', function (IContainer $c) {
+ return $c->query('ServerContainer')->getCertificateManager(null);
+ });
$container->registerService('Checker', function(IContainer $c) {
/** @var Server $server */
$server = $c->query('ServerContainer');
diff --git a/settings/controller/certificatecontroller.php b/settings/controller/certificatecontroller.php
index e360a1053c3..1c8dfe35556 100644
--- a/settings/controller/certificatecontroller.php
+++ b/settings/controller/certificatecontroller.php
@@ -36,7 +36,9 @@ use OCP\IRequest;
*/
class CertificateController extends Controller {
/** @var ICertificateManager */
- private $certificateManager;
+ private $userCertificateManager;
+ /** @var ICertificateManager */
+ private $systemCertificateManager;
/** @var IL10N */
private $l10n;
/** @var IAppManager */
@@ -45,17 +47,20 @@ class CertificateController extends Controller {
/**
* @param string $appName
* @param IRequest $request
- * @param ICertificateManager $certificateManager
+ * @param ICertificateManager $userCertificateManager
+ * @param ICertificateManager $systemCertificateManager
* @param IL10N $l10n
* @param IAppManager $appManager
*/
public function __construct($appName,
IRequest $request,
- ICertificateManager $certificateManager,
+ ICertificateManager $userCertificateManager,
+ ICertificateManager $systemCertificateManager,
IL10N $l10n,
IAppManager $appManager) {
parent::__construct($appName, $request);
- $this->certificateManager = $certificateManager;
+ $this->userCertificateManager = $userCertificateManager;
+ $this->systemCertificateManager = $systemCertificateManager;
$this->l10n = $l10n;
$this->appManager = $appManager;
}
@@ -68,6 +73,16 @@ class CertificateController extends Controller {
* @return array
*/
public function addPersonalRootCertificate() {
+ return $this->addCertificate($this->userCertificateManager);
+ }
+
+ /**
+ * Add a new root certificate to a trust store
+ *
+ * @param ICertificateManager $certificateManager
+ * @return array
+ */
+ private function addCertificate(ICertificateManager $certificateManager) {
$headers = [];
if ($this->request->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE_8])) {
// due to upload iframe workaround, need to set content-type to text/plain
@@ -79,23 +94,23 @@ class CertificateController extends Controller {
}
$file = $this->request->getUploadedFile('rootcert_import');
- if(empty($file)) {
+ if (empty($file)) {
return new DataResponse(['message' => 'No file uploaded'], Http::STATUS_UNPROCESSABLE_ENTITY, $headers);
}
try {
- $certificate = $this->certificateManager->addCertificate(file_get_contents($file['tmp_name']), $file['name']);
+ $certificate = $certificateManager->addCertificate(file_get_contents($file['tmp_name']), $file['name']);
return new DataResponse(
[
- 'name' => $certificate->getName(),
- 'commonName' => $certificate->getCommonName(),
- 'organization' => $certificate->getOrganization(),
- 'validFrom' => $certificate->getIssueDate()->getTimestamp(),
- 'validTill' => $certificate->getExpireDate()->getTimestamp(),
- 'validFromString' => $this->l10n->l('date', $certificate->getIssueDate()),
- 'validTillString' => $this->l10n->l('date', $certificate->getExpireDate()),
- 'issuer' => $certificate->getIssuerName(),
- 'issuerOrganization' => $certificate->getIssuerOrganization(),
+ 'name' => $certificate->getName(),
+ 'commonName' => $certificate->getCommonName(),
+ 'organization' => $certificate->getOrganization(),
+ 'validFrom' => $certificate->getIssueDate()->getTimestamp(),
+ 'validTill' => $certificate->getExpireDate()->getTimestamp(),
+ 'validFromString' => $this->l10n->l('date', $certificate->getIssueDate()),
+ 'validTillString' => $this->l10n->l('date', $certificate->getExpireDate()),
+ 'issuer' => $certificate->getIssuerName(),
+ 'issuerOrganization' => $certificate->getIssuerOrganization(),
],
Http::STATUS_OK,
$headers
@@ -119,7 +134,7 @@ class CertificateController extends Controller {
return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
}
- $this->certificateManager->removeCertificate($certificateIdentifier);
+ $this->userCertificateManager->removeCertificate($certificateIdentifier);
return new DataResponse();
}
@@ -140,4 +155,28 @@ class CertificateController extends Controller {
return false;
}
+ /**
+ * Add a new personal root certificate to the system's trust store
+ *
+ * @return array
+ */
+ public function addSystemRootCertificate() {
+ return $this->addCertificate($this->systemCertificateManager);
+ }
+
+ /**
+ * Removes a personal root certificate from the users' trust store
+ *
+ * @param string $certificateIdentifier
+ * @return DataResponse
+ */
+ public function removeSystemRootCertificate($certificateIdentifier) {
+
+ if ($this->isCertificateImportAllowed() === false) {
+ return new DataResponse('Individual certificate management disabled', Http::STATUS_FORBIDDEN);
+ }
+
+ $this->systemCertificateManager->removeCertificate($certificateIdentifier);
+ return new DataResponse();
+ }
}
diff --git a/settings/js/certificates.js b/settings/js/certificates.js
new file mode 100644
index 00000000000..9ce9f9aa8d8
--- /dev/null
+++ b/settings/js/certificates.js
@@ -0,0 +1,69 @@
+$(document).ready(function () {
+ var type = $('#sslCertificate').data('type');
+ $('#sslCertificate').on('click', 'td.remove', function () {
+ var row = $(this).parent();
+ $.ajax(OC.generateUrl('settings/' + type + '/certificate/{certificate}', {certificate: row.data('name')}), {
+ type: 'DELETE'
+ });
+ row.remove();
+
+ if ($('#sslCertificate > tbody > tr').length === 0) {
+ $('#sslCertificate').hide();
+ }
+ return true;
+ });
+
+ $('#sslCertificate tr > td').tipsy({gravity: 'n', live: true});
+
+ $('#rootcert_import').fileupload({
+ submit: function (e, data) {
+ data.formData = _.extend(data.formData || {}, {
+ requesttoken: OC.requestToken
+ });
+ },
+ success: function (data) {
+ if (typeof data === 'string') {
+ data = $.parseJSON(data);
+ } else if (data && data.length) {
+ // fetch response from iframe
+ data = $.parseJSON(data[0].body.innerText);
+ }
+ if (!data || typeof(data) === 'string') {
+ // IE8 iframe workaround comes here instead of fail()
+ OC.Notification.showTemporary(
+ t('settings', 'An error occurred. Please upload an ASCII-encoded PEM certificate.'));
+ return;
+ }
+ var issueDate = new Date(data.validFrom * 1000);
+ var expireDate = new Date(data.validTill * 1000);
+ var now = new Date();
+ var isExpired = !(issueDate <= now && now <= expireDate);
+
+ var row = $('<tr/>');
+ row.data('name', data.name);
+ row.addClass(isExpired ? 'expired' : 'valid');
+ row.append($('<td/>').attr('title', data.organization).text(data.commonName));
+ row.append($('<td/>').attr('title', t('core,', 'Valid until {date}', {date: data.validTillString}))
+ .text(data.validTillString));
+ row.append($('<td/>').attr('title', data.issuerOrganization).text(data.issuer));
+ row.append($('<td/>').addClass('remove').append(
+ $('<img/>').attr({
+ alt: t('core', 'Delete'),
+ title: t('core', 'Delete'),
+ src: OC.imagePath('core', 'actions/delete.svg')
+ }).addClass('action')
+ ));
+
+ $('#sslCertificate tbody').append(row);
+ $('#sslCertificate').show();
+ },
+ fail: function () {
+ OC.Notification.showTemporary(
+ t('settings', 'An error occurred. Please upload an ASCII-encoded PEM certificate.'));
+ }
+ });
+
+ if ($('#sslCertificate > tbody > tr').length === 0) {
+ $('#sslCertificate').hide();
+ }
+});
diff --git a/settings/js/personal.js b/settings/js/personal.js
index da74f28d70c..3e1a0d7497b 100644
--- a/settings/js/personal.js
+++ b/settings/js/personal.js
@@ -339,73 +339,6 @@ $(document).ready(function () {
}
});
- $('#sslCertificate').on('click', 'td.remove > img', function () {
- var row = $(this).parent().parent();
- $.ajax(OC.generateUrl('settings/personal/certificate/{certificate}', {certificate: row.data('name')}), {
- type: 'DELETE'
- });
- row.remove();
-
- if ($('#sslCertificate > tbody > tr').length === 0) {
- $('#sslCertificate').hide();
- }
- return true;
- });
-
- $('#sslCertificate tr > td').tipsy({gravity: 'n', live: true});
-
- $('#rootcert_import').fileupload({
- submit: function(e, data) {
- data.formData = _.extend(data.formData || {}, {
- requesttoken: OC.requestToken
- });
- },
- success: function (data) {
- if (typeof data === 'string') {
- data = $.parseJSON(data);
- } else if (data && data.length) {
- // fetch response from iframe
- data = $.parseJSON(data[0].body.innerText);
- }
- if (!data || typeof(data) === 'string') {
- // IE8 iframe workaround comes here instead of fail()
- OC.Notification.showTemporary(
- t('settings', 'An error occurred. Please upload an ASCII-encoded PEM certificate.'));
- return;
- }
- var issueDate = new Date(data.validFrom * 1000);
- var expireDate = new Date(data.validTill * 1000);
- var now = new Date();
- var isExpired = !(issueDate <= now && now <= expireDate);
-
- var row = $('<tr/>');
- row.data('name', data.name);
- row.addClass(isExpired? 'expired': 'valid');
- row.append($('<td/>').attr('title', data.organization).text(data.commonName));
- row.append($('<td/>').attr('title', t('core,', 'Valid until {date}', {date: data.validTillString}))
- .text(data.validTillString));
- row.append($('<td/>').attr('title', data.issuerOrganization).text(data.issuer));
- row.append($('<td/>').addClass('remove').append(
- $('<img/>').attr({
- alt: t('core', 'Delete'),
- title: t('core', 'Delete'),
- src: OC.imagePath('core', 'actions/delete.svg')
- }).addClass('action')
- ));
-
- $('#sslCertificate tbody').append(row);
- $('#sslCertificate').show();
- },
- fail: function () {
- OC.Notification.showTemporary(
- t('settings', 'An error occurred. Please upload an ASCII-encoded PEM certificate.'));
- }
- });
-
- if ($('#sslCertificate > tbody > tr').length === 0) {
- $('#sslCertificate').hide();
- }
-
// Load the big avatar
if (oc_config.enable_avatars) {
$('#avatar .avatardiv').avatar(OC.currentUser, 145);
diff --git a/settings/personal.php b/settings/personal.php
index c4e1c057bf3..54698fd6d54 100644
--- a/settings/personal.php
+++ b/settings/personal.php
@@ -43,6 +43,7 @@ $urlGenerator = \OC::$server->getURLGenerator();
// Highlight navigation entry
OC_Util::addScript( 'settings', 'personal' );
+OC_Util::addScript('settings', 'certificates');
OC_Util::addStyle( 'settings', 'settings' );
\OC_Util::addVendorScript('strengthify/jquery.strengthify');
\OC_Util::addVendorStyle('strengthify/strengthify');
@@ -168,6 +169,17 @@ $formsAndMore[]= ['anchor' => 'clientsbox', 'section-name' => $l->t('Sync client
$forms=OC_App::getForms('personal');
+
+// add bottom hardcoded forms from the template
+if ($enableCertImport) {
+ $certificatesTemplate = new OC_Template('settings', 'certificates');
+ $certificatesTemplate->assign('type', 'personal');
+ $certificatesTemplate->assign('uploadRoute', 'settings.Certificate.addPersonalRootCertificate');
+ $certificatesTemplate->assign('certs', $certificateManager->listCertificates());
+ $certificatesTemplate->assign('urlGenerator', $urlGenerator);
+ $forms[] = $certificatesTemplate->fetchPage();
+}
+
$formsMap = array_map(function($form){
if (preg_match('%(<h2(?P<class>[^>]*)>.*?</h2>)%i', $form, $regs)) {
$sectionName = str_replace('<h2'.$regs['class'].'>', '', $regs[0]);
@@ -188,12 +200,5 @@ $formsMap = array_map(function($form){
$formsAndMore = array_merge($formsAndMore, $formsMap);
-// add bottom hardcoded forms from the template
-if($enableCertImport) {
- $formsAndMore[]= array( 'anchor' => 'ssl-root-certificates', 'section-name' => $l->t('SSL root certificates') );
-}
-
-
-
$tmpl->assign('forms', $formsAndMore);
$tmpl->printPage();
diff --git a/settings/routes.php b/settings/routes.php
index 6b6b0150168..0cc5e1eccab 100644
--- a/settings/routes.php
+++ b/settings/routes.php
@@ -57,6 +57,8 @@ $application->registerRoutes($this, [
['name' => 'CheckSetup#rescanFailedIntegrityCheck', 'url' => '/settings/integrity/rescan', 'verb' => 'GET'],
['name' => 'Certificate#addPersonalRootCertificate', 'url' => '/settings/personal/certificate', 'verb' => 'POST'],
['name' => 'Certificate#removePersonalRootCertificate', 'url' => '/settings/personal/certificate/{certificateIdentifier}', 'verb' => 'DELETE'],
+ ['name' => 'Certificate#addSystemRootCertificate', 'url' => '/settings/admin/certificate', 'verb' => 'POST'],
+ ['name' => 'Certificate#removeSystemRootCertificate', 'url' => '/settings/admin/certificate/{certificateIdentifier}', 'verb' => 'DELETE'],
]
]);
diff --git a/settings/templates/certificates.php b/settings/templates/certificates.php
new file mode 100644
index 00000000000..c1ccdcaef95
--- /dev/null
+++ b/settings/templates/certificates.php
@@ -0,0 +1,44 @@
+<div class="section">
+ <h2><?php p($l->t('SSL Root Certificates')); ?></h2>
+ <table id="sslCertificate" class="grid" data-type="<?php p($_['type']); ?>">
+ <thead>
+ <tr>
+ <th><?php p($l->t('Common Name')); ?></th>
+ <th><?php p($l->t('Valid until')); ?></th>
+ <th><?php p($l->t('Issued By')); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($_['certs'] as $rootCert): /**@var \OCP\ICertificate $rootCert */ ?>
+ <tr class="<?php echo ($rootCert->isExpired()) ? 'expired' : 'valid' ?>"
+ data-name="<?php p($rootCert->getName()) ?>">
+ <td class="rootCert"
+ title="<?php p($rootCert->getOrganization()) ?>">
+ <?php p($rootCert->getCommonName()) ?>
+ </td>
+ <td title="<?php p($l->t('Valid until %s', $l->l('date', $rootCert->getExpireDate()))) ?>">
+ <?php echo $l->l('date', $rootCert->getExpireDate()) ?>
+ </td>
+ <td title="<?php p($rootCert->getIssuerOrganization()) ?>">
+ <?php p($rootCert->getIssuerName()) ?>
+ </td>
+ <td <?php if ($rootCert != ''): ?>class="remove"
+ <?php else: ?>style="visibility:hidden;"
+ <?php endif; ?>><img alt="<?php p($l->t('Delete')); ?>"
+ title="<?php p($l->t('Delete')); ?>"
+ class="svg action"
+ src="<?php print_unescaped(image_path('core', 'actions/delete.svg')); ?>"/>
+ </td>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+ <form class="uploadButton" method="post"
+ action="<?php p($_['urlGenerator']->linkToRoute($_['uploadRoute'])); ?>"
+ target="certUploadFrame">
+ <label for="rootcert_import" class="inlineblock button"
+ id="rootcert_import_button"><?php p($l->t('Import root certificate')); ?></label>
+ <input type="file" id="rootcert_import" name="rootcert_import"
+ class="hiddenuploadfield">
+ </form>
+</div>
diff --git a/settings/templates/personal.php b/settings/templates/personal.php
index ce179ca8788..5bae01742b6 100644
--- a/settings/templates/personal.php
+++ b/settings/templates/personal.php
@@ -204,48 +204,6 @@ if($_['passwordChangeSupported']) {
<?php }
};?>
-<?php if($_['showCertificates']) : ?>
-<div id="ssl-root-certificates" class="section">
- <h2><?php p($l->t('SSL root certificates')); ?></h2>
- <table id="sslCertificate" class="grid">
- <thead>
- <tr>
- <th><?php p($l->t('Common Name')); ?></th>
- <th><?php p($l->t('Valid until')); ?></th>
- <th><?php p($l->t('Issued By')); ?></th>
- <th></th>
- </tr>
- </thead>
- <tbody>
- <?php foreach ($_['certs'] as $rootCert): /**@var \OCP\ICertificate $rootCert*/ ?>
- <tr class="<?php echo ($rootCert->isExpired()) ? 'expired' : 'valid' ?>" data-name="<?php p($rootCert->getName()) ?>">
- <td class="rootCert" title="<?php p($rootCert->getOrganization())?>">
- <?php p($rootCert->getCommonName()) ?>
- </td>
- <td title="<?php p($l->t('Valid until %s', $l->l('date', $rootCert->getExpireDate()))) ?>">
- <?php echo $l->l('date', $rootCert->getExpireDate()) ?>
- </td>
- <td title="<?php p($rootCert->getIssuerOrganization()) ?>">
- <?php p($rootCert->getIssuerName()) ?>
- </td>
- <td <?php if ($rootCert != ''): ?>class="remove"
- <?php else: ?>style="visibility:hidden;"
- <?php endif; ?>><img alt="<?php p($l->t('Delete')); ?>"
- title="<?php p($l->t('Delete')); ?>"
- class="svg action"
- src="<?php print_unescaped(image_path('core', 'actions/delete.svg')); ?>"/>
- </td>
- </tr>
- <?php endforeach; ?>
- </tbody>
- </table>
- <form class="uploadButton" method="post" action="<?php p($_['urlGenerator']->linkToRoute('settings.Certificate.addPersonalRootCertificate')); ?>" target="certUploadFrame">
- <label for="rootcert_import" class="inlineblock button" id="rootcert_import_button"><?php p($l->t('Import root certificate')); ?></label>
- <input type="file" id="rootcert_import" name="rootcert_import" class="hiddenuploadfield">
- </form>
-</div>
-<?php endif; ?>
-
<div class="section">
<h2><?php p($l->t('Version'));?></h2>
<p><a href="<?php print_unescaped($theme->getBaseUrl()); ?>" target="_blank"><?php p($theme->getTitle()); ?></a> <?php p(OC_Util::getHumanVersion()) ?></p>
diff --git a/tests/lib/security/certificatemanager.php b/tests/lib/security/certificatemanager.php
index f2e29cab18e..e9ccea39efe 100644
--- a/tests/lib/security/certificatemanager.php
+++ b/tests/lib/security/certificatemanager.php
@@ -14,6 +14,8 @@ use \OC\Security\CertificateManager;
* @group DB
*/
class CertificateManagerTest extends \Test\TestCase {
+ use \Test\Traits\UserTrait;
+ use \Test\Traits\MountProviderTrait;
/** @var CertificateManager */
private $certificateManager;
@@ -24,7 +26,10 @@ class CertificateManagerTest extends \Test\TestCase {
parent::setUp();
$this->username = $this->getUniqueID('', 20);
- \OC::$server->getUserManager()->createUser($this->username, $this->getUniqueID('', 20));
+ $this->createUser($this->username, '');
+
+ $storage = new \OC\Files\Storage\Temporary();
+ $this->registerMount($this->username, $storage, '/' . $this->username . '/');
\OC_Util::tearDownFS();
\OC_User::setUserId('');
@@ -40,7 +45,9 @@ class CertificateManagerTest extends \Test\TestCase {
protected function tearDown() {
$user = \OC::$server->getUserManager()->get($this->username);
- if ($user !== null) { $user->delete(); }
+ if ($user !== null) {
+ $user->delete();
+ }
parent::tearDown();
}
@@ -56,14 +63,14 @@ class CertificateManagerTest extends \Test\TestCase {
$this->assertSame(array(), $this->certificateManager->listCertificates());
// Add some certificates
- $this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
+ $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');
+ $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->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());
}
@@ -93,7 +100,7 @@ class CertificateManagerTest extends \Test\TestCase {
* @param string $filename
*/
function testAddDangerousFile($filename) {
- $this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), $filename);
+ $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt'), $filename);
}
function testRemoveDangerousFile() {
@@ -101,7 +108,7 @@ class CertificateManagerTest extends \Test\TestCase {
}
function testRemoveExistingFile() {
- $this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
+ $this->certificateManager->addCertificate(file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
$this->assertTrue($this->certificateManager->removeCertificate('GoodCertificate'));
}
diff --git a/tests/settings/controller/CertificateControllerTest.php b/tests/settings/controller/CertificateControllerTest.php
index 023d7753cca..2fdbbb8b0ac 100644
--- a/tests/settings/controller/CertificateControllerTest.php
+++ b/tests/settings/controller/CertificateControllerTest.php
@@ -44,12 +44,15 @@ class CertificateControllerTest extends \Test\TestCase {
private $l10n;
/** @var IAppManager */
private $appManager;
+ /** @var ICertificateManager */
+ private $systemCertificateManager;
public function setUp() {
parent::setUp();
$this->request = $this->getMock('\OCP\IRequest');
$this->certificateManager = $this->getMock('\OCP\ICertificateManager');
+ $this->systemCertificateManager = $this->getMock('\OCP\ICertificateManager');
$this->l10n = $this->getMock('\OCP\IL10N');
$this->appManager = $this->getMock('OCP\App\IAppManager');
@@ -59,6 +62,7 @@ class CertificateControllerTest extends \Test\TestCase {
'settings',
$this->request,
$this->certificateManager,
+ $this->systemCertificateManager,
$this->l10n,
$this->appManager
]