]> source.dussan.org Git - nextcloud-server.git/commitdiff
Allow admins to add system wide root certificates
authorRobin Appelman <icewind@owncloud.com>
Tue, 22 Dec 2015 16:42:28 +0000 (17:42 +0100)
committerRobin Appelman <icewind@owncloud.com>
Tue, 12 Jan 2016 11:50:59 +0000 (12:50 +0100)
17 files changed:
apps/files_external/js/settings.js
lib/private/http/client/client.php
lib/private/security/certificatemanager.php
lib/private/server.php
lib/public/icertificatemanager.php
lib/public/iservercontainer.php
settings/admin.php
settings/application.php
settings/controller/certificatecontroller.php
settings/js/certificates.js [new file with mode: 0644]
settings/js/personal.js
settings/personal.php
settings/routes.php
settings/templates/certificates.php [new file with mode: 0644]
settings/templates/personal.php
tests/lib/security/certificatemanager.php
tests/settings/controller/CertificateControllerTest.php

index 59cf55d6ad50e66dba80f4873d0568018819014a..2f879e1c8504cf4406d89318cabc0eb406392b0d 100644 (file)
@@ -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() {
index 5f298e1acd72541be0f75d74d1392d38a4e91efc..8cddfc3ae03ec49f3a9f7933749cce33d91ee22d 100644 (file)
@@ -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');
index ded81863a7385fbd9cadbc1f7c4fb5efbc49be47..ce0d330c4b2ab1f680bf98178407c69a86e3f157 100644 (file)
@@ -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);
+       }
 }
index ead9fa95db8e37e75781d9dcc1d1059497dcbe6e..414f59af6124e1d14bf776224e0933046fc5230d 100644 (file)
@@ -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)) {
index b1a16d8b5ee103e9696a0e941e762ee38fbc92de..3872fdd765d0e95fbac76753f879c4b5ad46730b 100644 (file)
@@ -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 = '');
 }
index 267e5dc4d311c9cf3c21ec680fd5c18714cb63c6..e706750bb21d5f167cbe20ee1bf0d3c4e7e73125 100644 (file)
@@ -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
         */
index d484d6a1e48cacfd2ce350c1ed3a565fba19e9f3..7bd3760b6ce906a4156397af765463fecc0ae5e2 100644 (file)
@@ -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'));
@@ -151,6 +157,14 @@ $template->assign('OutdatedCacheWarning', $outdatedCaches);
 
 // add hardcoded forms from the template
 $forms = OC_App::getForms('admin');
+
+$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()  ||
index 729e61b5925e767568bb94abdf4305ccd4060df7..1c562c62a844a5d623b14c74aa3547442183949b 100644 (file)
@@ -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');
index e360a1053c3b5182d642c0dd8528137b837da5fc..1c8dfe35556d594d10d4cb8ba627276f0057ee13 100644 (file)
@@ -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 (file)
index 0000000..9ce9f9a
--- /dev/null
@@ -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();
+       }
+});
index da74f28d70ca43233550b4da118cb1a3ec2ec24b..3e1a0d7497b2d22db2a79c1910a905ea491145b0 100644 (file)
@@ -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);
index c4e1c057bf30b17378d76864628e0ad13494e65b..54698fd6d542728e8e4c185a7e2ba4905e2c8281 100644 (file)
@@ -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();
index 6b6b01501684dc78679bf3dd65606a18bcec4b41..0cc5e1eccab5545fb3704d099790a413eae1b87b 100644 (file)
@@ -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 (file)
index 0000000..c1ccdca
--- /dev/null
@@ -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>
index ce179ca8788311bd05ad032e9b8d1dc9bd5bbd79..5bae01742b62008548cdac23a7b7277db3e4e56c 100644 (file)
@@ -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>
index f2e29cab18e78c15a5cc03344b60c1241ba8ff38..e9ccea39efeef3b7e46163296040300cab644b7c 100644 (file)
@@ -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'));
        }
 
index 023d7753ccacc013ad80a528987e49a0b83c1f97..2fdbbb8b0acca31addc16d06aae9c9cabc7d1f26 100644 (file)
@@ -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
                                ]