]> source.dussan.org Git - nextcloud-server.git/commitdiff
Let users configure security headers in their Webserver
authorLukas Reschke <lukas@owncloud.com>
Mon, 19 Jan 2015 10:56:04 +0000 (11:56 +0100)
committerLukas Reschke <lukas@owncloud.com>
Mon, 2 Mar 2015 18:07:46 +0000 (19:07 +0100)
Doing this in the PHP code is not the right approach for multiple reasons:

1. A bug in the PHP code prevents them from being added to the response.
2. They are only added when something is served via PHP and not in other cases (that makes for example the newest IE UXSS which is not yet patched by Microsoft exploitable on ownCloud)
3. Some headers such as the Strict-Transport-Security might require custom modifications by administrators. This was not possible before and lead to buggy situations.

This pull request moves those headers out of the PHP code and adds a security check to the admin settings performed via JS.

17 files changed:
.htaccess
config/config.sample.php
core/js/core.json
core/js/js.js
core/js/setupchecks.js
core/js/tests/specs/setupchecksSpec.js [new file with mode: 0644]
lib/base.php
lib/private/appframework/app.php
lib/private/appframework/http/request.php
lib/private/response.php
lib/private/user/session.php
settings/admin.php
settings/controller/securitysettingscontroller.php
settings/js/admin.js
settings/routes.php
settings/templates/admin.php
tests/settings/controller/securitysettingscontrollertest.php

index d79ee9f8871fcd12915136962bb5089c6012f488..5e24a35743dec820a6b91a35bef410a5e34d3641 100644 (file)
--- a/.htaccess
+++ b/.htaccess
@@ -45,6 +45,10 @@ Options -Indexes
         ModPagespeed Off
 </IfModule>
 <IfModule mod_headers.c>
+  Header set X-Content-Type-Options "nosniff"
+  Header set X-XSS-Protection "1; mode=block"
+  Header set X-Robots-Tag "none"
+  Header set X-Frame-Options "SAMEORIGIN"
   <FilesMatch "\.(css|js)$">
     Header set Cache-Control "max-age=7200, public"
   </FilesMatch>
index 1b3477417ff426403e8e6d85b294d6ddd9760fef..16575cf82edddfe3a479e739c1effbffb26b6897 100644 (file)
@@ -744,18 +744,6 @@ $CONFIG = array(
  * SSL
  */
 
-/**
- * Change this to ``true`` to require HTTPS for all connections, and to reject
- * HTTP requests.
- */
-'forcessl' => false,
-
-/**
- * Change this to ``true`` to require HTTPS connections also for all subdomains.
- * Works only together when `forcessl` is set to true.
- */
-'forceSSLforSubdomains' => false,
-
 /**
  * Extra SSL options to be used for configuration.
  */
@@ -786,13 +774,6 @@ $CONFIG = array(
  */
 'theme' => '',
 
-/**
- * X-Frame-Restriction is a header which prevents browsers from showing the site
- * inside an iframe. This is be used to prevent clickjacking. It is risky to
- * disable this, so leave it set at ``true``.
- */
-'xframe_restriction' => true,
-
 /**
  * The default cipher for encrypting files. Currently AES-128-CFB and
  * AES-256-CFB are supported.
index 7f3b313e89807bbaef49ad16d90d3b3267d9413f..b32ca5ca8f39d861803f03b614952e3bcffaa483 100644 (file)
@@ -24,6 +24,7 @@
                "config.js",
                "multiselect.js",
                "oc-requesttoken.js",
+               "setupchecks.js",
                "../search/js/search.js"
        ]
 }
index 1e9ae4cc695ba7002aa2d5a3b6d281b434a63a88..f24694124ad7f7531a0f09e3fc096b76a37c6973 100644 (file)
@@ -210,6 +210,14 @@ var OC={
                window.location = targetURL;
        },
 
+       /**
+        * Protocol that is used to access this ownCloud instance
+        * @return {string} Used protocol
+        */
+       getProtocol: function() {
+               return window.location.protocol.split(':')[0];
+       },
+
        /**
         * get the absolute path to an image file
         * if no extension is given for the image, it will automatically decide
index 00e73162c5503aba6b45c87e6d7a1115c1550f4d..d5bd1c465b2c28d3d7a292fcb6a416817d0ba89c 100644 (file)
                                url: OC.generateUrl('settings/ajax/checksetup')
                        }).then(afterCall, afterCall);
                        return deferred.promise();
+               },
+
+               /**
+                * Runs generic checks on the server side, the difference to dedicated
+                * methods is that we use the same XHR object for all checks to save
+                * requests.
+                *
+                * @return $.Deferred object resolved with an array of error messages
+                */
+               checkGeneric: function() {
+                       var self = this;
+                       var deferred = $.Deferred();
+                       var afterCall = function(data, statusText, xhr) {
+                               var messages = [];
+                               messages = messages.concat(self._checkSecurityHeaders(xhr));
+                               messages = messages.concat(self._checkSSL(xhr));
+                               deferred.resolve(messages);
+                       };
+
+                       $.ajax({
+                               type: 'GET',
+                               url: OC.generateUrl('heartbeat')
+                       }).then(afterCall, afterCall);
+
+                       return deferred.promise();
+               },
+
+               /**
+                * Runs check for some generic security headers on the server side
+                *
+                * @param {Object} xhr
+                * @return {Array} Array with error messages
+                */
+               _checkSecurityHeaders: function(xhr) {
+                       var messages = [];
+
+                       if (xhr.status === 200) {
+                               var securityHeaders = {
+                                       'X-XSS-Protection': '1; mode=block',
+                                       'X-Content-Type-Options': 'nosniff',
+                                       'X-Robots-Tag': 'none',
+                                       'X-Frame-Options': 'SAMEORIGIN'
+                               };
+
+                               for (var header in securityHeaders) {
+                                       if(xhr.getResponseHeader(header) !== securityHeaders[header]) {
+                                               messages.push(
+                                                       t('core', 'The "{header}" HTTP header is not configured to equal to "{expected}". This is a potential security risk and we recommend adjusting this setting.', {header: header, expected: securityHeaders[header]})
+                                               );
+                                       }
+                               }
+                       } else {
+                               messages.push(t('core', 'Error occurred while checking server setup'));
+                       }
+
+                       return messages;
+               },
+
+               /**
+                * Runs check for some SSL configuration issues on the server side
+                *
+                * @param {Object} xhr
+                * @return {Array} Array with error messages
+                */
+               _checkSSL: function(xhr) {
+                       var messages = [];
+
+                       if (xhr.status === 200) {
+                               if(OC.getProtocol() === 'https') {
+                                       // Extract the value of 'Strict-Transport-Security'
+                                       var transportSecurityValidity = xhr.getResponseHeader('Strict-Transport-Security');
+                                       if(transportSecurityValidity !== null && transportSecurityValidity.length > 8) {
+                                               var firstComma = transportSecurityValidity.indexOf(";");
+                                               if(firstComma !== -1) {
+                                                       transportSecurityValidity = transportSecurityValidity.substring(0, firstComma);
+                                               } else {
+                                                       transportSecurityValidity = transportSecurityValidity.substring(8);
+                                               }
+                                       }
+
+                                       if(isNaN(transportSecurityValidity) || transportSecurityValidity <= 2678399) {
+                                               messages.push(
+                                                       t('core', 'The "Strict-Transport-Security" HTTP header is not configured to least "2,678,400" seconds. This is a potential security risk and we recommend adjusting this setting.')
+                                               );
+                                       }
+                               } else {
+                                       messages.push(
+                                               t('core', 'You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead.')
+                                       );
+                               }
+                       } else {
+                               messages.push(t('core', 'Error occurred while checking server setup'));
+                       }
+
+                       return messages;
                }
        };
 })();
-
diff --git a/core/js/tests/specs/setupchecksSpec.js b/core/js/tests/specs/setupchecksSpec.js
new file mode 100644 (file)
index 0000000..2fb0989
--- /dev/null
@@ -0,0 +1,326 @@
+/**
+ * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com>
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+describe('OC.SetupChecks tests', function() {
+       var suite = this;
+
+       beforeEach( function(){
+               suite.server = sinon.fakeServer.create();
+       });
+
+       afterEach( function(){
+               suite.server.restore();
+       });
+
+       describe('checkWebDAV', function() {
+               it('should fail with another response status code than 201 or 207', function(done) {
+                       var async = OC.SetupChecks.checkWebDAV();
+
+                       suite.server.requests[0].respond(200);
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual(['Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken.']);
+                       });
+               });
+
+               it('should return no error with a response status code of 207', function(done) {
+                       var async = OC.SetupChecks.checkWebDAV();
+
+                       suite.server.requests[0].respond(207);
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual([]);
+                       });
+               });
+
+               it('should return no error with a response status code of 401', function(done) {
+                       var async = OC.SetupChecks.checkWebDAV();
+
+                       suite.server.requests[0].respond(401);
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual([]);
+                       });
+               });
+       });
+
+       describe('checkSetup', function() {
+               it('should return an error if server has no internet connection', function(done) {
+                       var async = OC.SetupChecks.checkSetup();
+
+                       suite.server.requests[0].respond(
+                               200,
+                               {
+                                       'Content-Type': 'application/json'
+                               },
+                               JSON.stringify({data: {serverHasInternetConnection: false}})
+                       );
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual(['This server has no working Internet connection. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. We suggest to enable Internet connection for this server if you want to have all features.', 'Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root.']);
+                       });
+               });
+
+               it('should return an error if server has no internet connection and data directory is not protected', function(done) {
+                       var async = OC.SetupChecks.checkSetup();
+
+                       suite.server.requests[0].respond(
+                               200,
+                               {
+                                       'Content-Type': 'application/json'
+                               },
+                               JSON.stringify({data: {serverHasInternetConnection: false, dataDirectoryProtected: false}})
+                       );
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual(['This server has no working Internet connection. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. We suggest to enable Internet connection for this server if you want to have all features.', 'Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root.']);
+                       });
+               });
+
+               it('should return an error if the response has no statuscode 200', function(done) {
+                       var async = OC.SetupChecks.checkSetup();
+
+                       suite.server.requests[0].respond(
+                               500,
+                               {
+                                       'Content-Type': 'application/json'
+                               },
+                               JSON.stringify({data: {serverHasInternetConnection: false, dataDirectoryProtected: false}})
+                       );
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual(['Error occurred while checking server setup']);
+                       });
+               });
+       });
+
+       describe('checkGeneric', function() {
+               it('should return an error if the response has no statuscode 200', function(done) {
+                       var async = OC.SetupChecks.checkGeneric();
+
+                       suite.server.requests[0].respond(
+                               500,
+                               {
+                                       'Content-Type': 'application/json'
+                               }
+                       );
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual(['Error occurred while checking server setup', 'Error occurred while checking server setup']);
+                       });
+               });
+
+               it('should return all errors if all headers are missing', function(done) {
+                       var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+                       var async = OC.SetupChecks.checkGeneric();
+
+                       suite.server.requests[0].respond(
+                               200,
+                               {
+                                       'Content-Type': 'application/json',
+                                       'Strict-Transport-Security': '2678400'
+                               }
+                       );
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual(['The "X-XSS-Protection" HTTP header is not configured to equal to "1; mode=block". This is a potential security risk and we recommend adjusting this setting.', 'The "X-Content-Type-Options" HTTP header is not configured to equal to "nosniff". This is a potential security risk and we recommend adjusting this setting.', 'The "X-Robots-Tag" HTTP header is not configured to equal to "none". This is a potential security risk and we recommend adjusting this setting.', 'The "X-Frame-Options" HTTP header is not configured to equal to "SAMEORIGIN". This is a potential security risk and we recommend adjusting this setting.']);
+                       });
+                       protocolStub.restore();
+               });
+
+               it('should return only some errors if just some headers are missing', function(done) {
+                       var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+                       var async = OC.SetupChecks.checkGeneric();
+
+                       suite.server.requests[0].respond(
+                               200,
+                               {
+                                       'X-Robots-Tag': 'none',
+                                       'X-Frame-Options': 'SAMEORIGIN',
+                                       'Strict-Transport-Security': '2678400'
+
+                               }
+                       );
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual(['The "X-XSS-Protection" HTTP header is not configured to equal to "1; mode=block". This is a potential security risk and we recommend adjusting this setting.', 'The "X-Content-Type-Options" HTTP header is not configured to equal to "nosniff". This is a potential security risk and we recommend adjusting this setting.']);
+                       });
+                       protocolStub.restore();
+               });
+
+               it('should return none errors if all headers are there', function(done) {
+                       var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+                       var async = OC.SetupChecks.checkGeneric();
+
+                       suite.server.requests[0].respond(
+                               200,
+                               {
+                                       'X-XSS-Protection': '1; mode=block',
+                                       'X-Content-Type-Options': 'nosniff',
+                                       'X-Robots-Tag': 'none',
+                                       'X-Frame-Options': 'SAMEORIGIN',
+                                       'Strict-Transport-Security': '2678400'
+                               }
+                       );
+
+                       async.done(function( data, s, x ){
+                               expect(data).toEqual([]);
+                       });
+                       protocolStub.restore();
+               });
+       });
+
+       it('should return a SSL warning if HTTPS is not used', function(done) {
+               var protocolStub = sinon.stub(OC, 'getProtocol').returns('http');
+               var async = OC.SetupChecks.checkGeneric();
+
+               suite.server.requests[0].respond(200,
+                       {
+                               'X-XSS-Protection': '1; mode=block',
+                               'X-Content-Type-Options': 'nosniff',
+                               'X-Robots-Tag': 'none',
+                               'X-Frame-Options': 'SAMEORIGIN'
+                       }
+               );
+
+               async.done(function( data, s, x ){
+                       expect(data).toEqual(['You are accessing this site via HTTP. We strongly suggest you configure your server to require using HTTPS instead.']);
+               });
+               protocolStub.restore();
+       });
+
+       it('should return an error if the response has no statuscode 200', function(done) {
+               var async = OC.SetupChecks.checkGeneric();
+
+               suite.server.requests[0].respond(
+                       500,
+                       {
+                               'Content-Type': 'application/json'
+                       },
+                       JSON.stringify({data: {serverHasInternetConnection: false, dataDirectoryProtected: false}})
+               );
+               async.done(function( data, s, x ){
+                       expect(data).toEqual(['Error occurred while checking server setup', 'Error occurred while checking server setup']);
+               });
+       });
+
+       it('should return a SSL warning if SSL used without Strict-Transport-Security-Header', function(done) {
+               var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+               var async = OC.SetupChecks.checkGeneric();
+
+               suite.server.requests[0].respond(200,
+                       {
+                               'X-XSS-Protection': '1; mode=block',
+                               'X-Content-Type-Options': 'nosniff',
+                               'X-Robots-Tag': 'none',
+                               'X-Frame-Options': 'SAMEORIGIN'
+                       }
+               );
+
+               async.done(function( data, s, x ){
+                       expect(data).toEqual(['The "Strict-Transport-Security" HTTP header is not configured to least "2,678,400" seconds. This is a potential security risk and we recommend adjusting this setting.']);
+               });
+               protocolStub.restore();
+       });
+
+       it('should return a SSL warning if SSL used with to small Strict-Transport-Security-Header', function(done) {
+               var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+               var async = OC.SetupChecks.checkGeneric();
+
+               suite.server.requests[0].respond(200,
+                       {
+                               'Strict-Transport-Security': '2678399',
+                               'X-XSS-Protection': '1; mode=block',
+                               'X-Content-Type-Options': 'nosniff',
+                               'X-Robots-Tag': 'none',
+                               'X-Frame-Options': 'SAMEORIGIN'
+                       }
+               );
+
+               async.done(function( data, s, x ){
+                       expect(data).toEqual(['The "Strict-Transport-Security" HTTP header is not configured to least "2,678,400" seconds. This is a potential security risk and we recommend adjusting this setting.']);
+               });
+               protocolStub.restore();
+       });
+
+       it('should return a SSL warning if SSL used with to a bogus Strict-Transport-Security-Header', function(done) {
+               var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+               var async = OC.SetupChecks.checkGeneric();
+
+               suite.server.requests[0].respond(200,
+                       {
+                               'Strict-Transport-Security': 'iAmABogusHeader342',
+                               'X-XSS-Protection': '1; mode=block',
+                               'X-Content-Type-Options': 'nosniff',
+                               'X-Robots-Tag': 'none',
+                               'X-Frame-Options': 'SAMEORIGIN'
+                       }
+               );
+
+               async.done(function( data, s, x ){
+                       expect(data).toEqual(['The "Strict-Transport-Security" HTTP header is not configured to least "2,678,400" seconds. This is a potential security risk and we recommend adjusting this setting.']);
+               });
+               protocolStub.restore();
+       });
+
+       it('should return no SSL warning if SSL used with to exact the minimum Strict-Transport-Security-Header', function(done) {
+               var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+               var async = OC.SetupChecks.checkGeneric();
+
+               suite.server.requests[0].respond(200, {
+                       'Strict-Transport-Security': '2678400',
+                       'X-XSS-Protection': '1; mode=block',
+                       'X-Content-Type-Options': 'nosniff',
+                       'X-Robots-Tag': 'none',
+                       'X-Frame-Options': 'SAMEORIGIN'
+               });
+
+               async.done(function( data, s, x ){
+                       expect(data).toEqual([]);
+               });
+               protocolStub.restore();
+       });
+
+       it('should return no SSL warning if SSL used with to more than the minimum Strict-Transport-Security-Header', function(done) {
+               var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+               var async = OC.SetupChecks.checkGeneric();
+
+               suite.server.requests[0].respond(200, {
+                       'Strict-Transport-Security': '12678400',
+                       'X-XSS-Protection': '1; mode=block',
+                       'X-Content-Type-Options': 'nosniff',
+                       'X-Robots-Tag': 'none',
+                       'X-Frame-Options': 'SAMEORIGIN'
+               });
+
+               async.done(function( data, s, x ){
+                       expect(data).toEqual([]);
+               });
+               protocolStub.restore();
+       });
+
+       it('should return no SSL warning if SSL used with to more than the minimum Strict-Transport-Security-Header and includeSubDomains parameter', function(done) {
+               var protocolStub = sinon.stub(OC, 'getProtocol').returns('https');
+               var async = OC.SetupChecks.checkGeneric();
+
+               suite.server.requests[0].respond(200, {
+                       'Strict-Transport-Security': '12678400; includeSubDomains',
+                       'X-XSS-Protection': '1; mode=block',
+                       'X-Content-Type-Options': 'nosniff',
+                       'X-Robots-Tag': 'none',
+                       'X-Frame-Options': 'SAMEORIGIN'
+               });
+
+               async.done(function( data, s, x ){
+                       expect(data).toEqual([]);
+               });
+               protocolStub.restore();
+       });
+});
index 1f2e90deefd72cb227ea0a2ba29aa4b760c0b12d..84616090ec8ec112d302eee84b0ff83271ec7d06 100644 (file)
@@ -247,34 +247,6 @@ class OC {
                }
        }
 
-       public static function checkSSL() {
-               $request = \OC::$server->getRequest();
-
-               // redirect to https site if configured
-               if (\OC::$server->getSystemConfig()->getValue('forcessl', false)) {
-                       // Default HSTS policy
-                       $header = 'Strict-Transport-Security: max-age=31536000';
-
-                       // If SSL for subdomains is enabled add "; includeSubDomains" to the header
-                       if(\OC::$server->getSystemConfig()->getValue('forceSSLforSubdomains', false)) {
-                               $header .= '; includeSubDomains';
-                       }
-                       header($header);
-                       ini_set('session.cookie_secure', true);
-
-                       if ($request->getServerProtocol() <> 'https' && !OC::$CLI) {
-                               $url = 'https://' . $request->getServerHost() . $request->getRequestUri();
-                               header("Location: $url");
-                               exit();
-                       }
-               } else {
-                       // Invalidate HSTS headers
-                       if ($request->getServerProtocol() === 'https') {
-                               header('Strict-Transport-Security: max-age=0');
-                       }
-               }
-       }
-
        public static function checkMaintenanceMode() {
                // Allow ajax update script to execute without being stopped
                if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
@@ -569,8 +541,11 @@ class OC {
                self::initTemplateEngine();
                self::checkConfig();
                self::checkInstalled();
-               self::checkSSL();
+
                OC_Response::addSecurityHeaders();
+               if(self::$server->getRequest()->getServerProtocol() === 'https') {
+                       ini_set('session.cookie_secure', true);
+               }
 
                $errors = OC_Util::checkServer(\OC::$server->getConfig());
                if (count($errors) > 0) {
index 6d54b931d5a815ad1ceaf1a675558b23f1e1a455..1e1915c85d822a80e80f191d7976af561c4c8b1e 100644 (file)
@@ -123,7 +123,7 @@ class App {
                                $expireDate,
                                $container->getServer()->getWebRoot(),
                                null,
-                               $container->getServer()->getConfig()->getSystemValue('forcessl', false),
+                               $container->getServer()->getRequest()->getServerProtocol() === 'https',
                                true
                        );
                }
index f6a89b358dbaaa34c29a1425cd242b4b47175844..b1b4b713287df6c80eae3e4a725c7f648a2474f0 100644 (file)
@@ -475,7 +475,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
        private function isOverwriteCondition($type = '') {
                $regex = '/' . $this->config->getSystemValue('overwritecondaddr', '')  . '/';
                return $regex === '//' || preg_match($regex, $this->server['REMOTE_ADDR']) === 1
-               || ($type !== 'protocol' && $this->config->getSystemValue('forcessl', false));
+               || $type !== 'protocol';
        }
 
        /**
index 600b702810cabaec0e5a0612a142adb9278fdca2..2bec5e3decd5235381e455ef7664268c6e5b00a3 100644 (file)
@@ -195,15 +195,6 @@ class OC_Response {
         * components (e.g. SabreDAV) also benefit from this headers.
         */
        public static function addSecurityHeaders() {
-               header('X-XSS-Protection: 1; mode=block'); // Enforce browser based XSS filters
-               header('X-Content-Type-Options: nosniff'); // Disable sniffing the content type for IE
-
-               // iFrame Restriction Policy
-               $xFramePolicy = OC_Config::getValue('xframe_restriction', true);
-               if ($xFramePolicy) {
-                       header('X-Frame-Options: Sameorigin'); // Disallow iFraming from other domains
-               }
-
                /**
                 * FIXME: Content Security Policy for legacy ownCloud components. This
                 * can be removed once \OCP\AppFramework\Http\Response from the AppFramework
@@ -219,9 +210,6 @@ class OC_Response {
                        . 'media-src *; ' 
                        . 'connect-src *';
                header('Content-Security-Policy:' . $policy);
-
-               // https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag
-               header('X-Robots-Tag: none');
        }
 
 }
index 67a4c7a4361938ffd36866df1051e270b2eb9f07..a756795205396df5f55446cc0c04866dade096dc 100644 (file)
@@ -265,7 +265,7 @@ class Session implements IUserSession, Emitter {
         * @param string $token
         */
        public function setMagicInCookie($username, $token) {
-               $secureCookie = \OC_Config::getValue("forcessl", false); //TODO: DI for cookies and OC_Config
+               $secureCookie = \OC::$server->getRequest()->getServerProtocol() === 'https';
                $expires = time() + \OC_Config::getValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
                setcookie("oc_username", $username, $expires, \OC::$WEBROOT, '', $secureCookie, true);
                setcookie("oc_token", $token, $expires, \OC::$WEBROOT, '', $secureCookie, true);
index 95940db728233282eeb2909879f1d61dacb5bc5b..da25ab55a936243efa716c4675edf7b2413b243c 100644 (file)
@@ -58,11 +58,6 @@ $excludedGroupsList = $appConfig->getValue('core', 'shareapi_exclude_groups_list
 $excludedGroupsList = explode(',', $excludedGroupsList); // FIXME: this should be JSON!
 $template->assign('shareExcludedGroupsList', implode('|', $excludedGroupsList));
 
-// Check if connected using HTTPS
-$template->assign('isConnectedViaHTTPS', $request->getServerProtocol() === 'https');
-$template->assign('enforceHTTPSEnabled', $config->getSystemValue('forcessl', false));
-$template->assign('forceSSLforSubdomainsEnabled', $config->getSystemValue('forceSSLforSubdomains', false));
-
 // If the current web root is non-empty but the web root from the config is,
 // and system cron is used, the URL generator fails to build valid URLs.
 $shouldSuggestOverwriteCliUrl = $config->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'cron' &&
index af60df8dc3b94bc910059d1bc72b609d506f40ab..50e70ebb70ea3912468767b62326fda6cc9cd552 100644 (file)
@@ -42,43 +42,6 @@ class SecuritySettingsController extends Controller {
                );
        }
 
-       /**
-        * @return array
-        */
-       protected function returnError() {
-               return array(
-                       'status' => 'error'
-               );
-       }
-
-       /**
-        * Enforce or disable the enforcement of SSL
-        * @param boolean $enforceHTTPS Whether SSL should be enforced
-        * @return array
-        */
-       public function enforceSSL($enforceHTTPS = false) {
-               if(!is_bool($enforceHTTPS)) {
-                       return $this->returnError();
-               }
-               $this->config->setSystemValue('forcessl', $enforceHTTPS);
-
-               return $this->returnSuccess();
-       }
-
-       /**
-        * Enforce or disable the enforcement for SSL on subdomains
-        * @param bool $forceSSLforSubdomains Whether SSL on subdomains should be enforced
-        * @return array
-        */
-       public function enforceSSLForSubdomains($forceSSLforSubdomains = false) {
-               if(!is_bool($forceSSLforSubdomains)) {
-                       return $this->returnError();
-               }
-               $this->config->setSystemValue('forceSSLforSubdomains', $forceSSLforSubdomains);
-
-               return $this->returnSuccess();
-       }
-
        /**
         * Add a new trusted domain
         * @param string $newTrustedDomain The newly to add trusted domain
index 34bc246604889fbf349c4b71620b59d9be3f5feb..9fe4226827c83c0cf19fcd32071f8757ce09beca 100644 (file)
@@ -75,32 +75,6 @@ $(document).ready(function(){
                $('#setDefaultExpireDate').toggleClass('hidden', !(this.checked && $('#shareapiDefaultExpireDate')[0].checked));
        });
 
-       $('#forcessl').change(function(){
-               $(this).val(($(this).val() !== 'true'));
-               var forceSSLForSubdomain = $('#forceSSLforSubdomainsSpan');
-
-               $.post(OC.generateUrl('settings/admin/security/ssl'), {
-                       enforceHTTPS: $(this).val()
-               },function(){} );
-
-               if($(this).val() === 'true') {
-                       forceSSLForSubdomain.prop('disabled', false);
-                       forceSSLForSubdomain.removeClass('hidden');
-               } else {
-                       forceSSLForSubdomain.prop('disabled', true);
-                       forceSSLForSubdomain.addClass('hidden');
-               }
-       });
-
-       $('#forceSSLforSubdomains').change(function(){
-               $(this).val(($(this).val() !== 'true'));
-
-               $.post(OC.generateUrl('settings/admin/security/ssl/subdomains'), {
-                       forceSSLforSubdomains: $(this).val()
-               },function(){} );
-       });
-
-
        $('#mail_smtpauth').change(function() {
                if (!this.checked) {
                        $('#mail_credentials').addClass('hidden');
@@ -158,9 +132,10 @@ $(document).ready(function(){
        // run setup checks then gather error messages
        $.when(
                OC.SetupChecks.checkWebDAV(),
-               OC.SetupChecks.checkSetup()
-       ).then(function(check1, check2) {
-               var errors = [].concat(check1, check2);
+               OC.SetupChecks.checkSetup(),
+               OC.SetupChecks.checkGeneric()
+       ).then(function(check1, check2, check3) {
+               var errors = [].concat(check1, check2, check3);
                var $el = $('#postsetupchecks');
                var $errorsEl;
                $el.find('.loading').addClass('hidden');
index 942d9b0fb283058c4b1bd4c2aba705a9007a07b5..ea49cc24eb74c5ea0591074a5af9adedb383c3d2 100644 (file)
@@ -20,8 +20,6 @@ $application->registerRoutes($this, array(
                array('name' => 'MailSettings#sendTestMail', 'url' => '/settings/admin/mailtest', 'verb' => 'POST'),
                array('name' => 'AppSettings#listCategories', 'url' => '/settings/apps/categories', 'verb' => 'GET'),
                array('name' => 'AppSettings#listApps', 'url' => '/settings/apps/list', 'verb' => 'GET'),
-               array('name' => 'SecuritySettings#enforceSSL', 'url' => '/settings/admin/security/ssl', 'verb' => 'POST'),
-               array('name' => 'SecuritySettings#enforceSSLForSubdomains', 'url' => '/settings/admin/security/ssl/subdomains', 'verb' => 'POST'),
                array('name' => 'SecuritySettings#trustedDomains', 'url' => '/settings/admin/security/trustedDomains', 'verb' => 'POST'),
                array('name' => 'Users#setMailAddress', 'url' => '/settings/users/{id}/mailAddress', 'verb' => 'PUT'),
                array('name' => 'LogSettings#setLogLevel', 'url' => '/settings/admin/log/level', 'verb' => 'POST'),
index 1608aa8123bb0aacfcbea9e3ab8bbedb23d23f21..b6326108bf6f25c1e0886e8e312c2bb8fa68bf6a 100644 (file)
@@ -66,20 +66,6 @@ if ($_['mail_smtpmode'] == 'qmail') {
 <div id="security-warning">
 <?php
 
-// is ssl working ?
-if (!$_['isConnectedViaHTTPS']) {
-       ?>
-<div class="section">
-       <h2><?php p($l->t('Security Warning'));?></h2>
-
-       <span class="securitywarning">
-               <?php p($l->t('You are accessing %s via HTTP. We strongly suggest you configure your server to require using HTTPS instead.', $theme->getTitle())); ?>
-       </span>
-
-</div>
-<?php
-}
-
 // is read only config enabled
 if ($_['readOnlyConfigEnabled']) {
 ?>
@@ -370,51 +356,6 @@ if ($_['cronErrors']) {
                        </p>
 </div>
 
-<div class="section" id="security">
-       <h2><?php p($l->t('Security'));?></h2>
-       <p>
-               <input type="checkbox" name="forcessl"  id="forcessl"
-                       <?php if ($_['enforceHTTPSEnabled']) {
-                               print_unescaped('checked="checked" ');
-                               print_unescaped('value="true"');
-                       }  else {
-                               print_unescaped('value="false"');
-                       }
-                       ?>
-                       <?php if (!$_['isConnectedViaHTTPS']) p('disabled'); ?> />
-               <label for="forcessl"><?php p($l->t('Enforce HTTPS'));?></label><br/>
-               <em><?php p($l->t(
-                       'Forces the clients to connect to %s via an encrypted connection.',
-                       $theme->getName()
-               )); ?></em><br/>
-               <span id="forceSSLforSubdomainsSpan" <?php if(!$_['enforceHTTPSEnabled']) { print_unescaped('class="hidden"'); } ?>>
-                       <input type="checkbox" name="forceSSLforSubdomains"  id="forceSSLforSubdomains"
-                               <?php if ($_['forceSSLforSubdomainsEnabled']) {
-                                       print_unescaped('checked="checked" ');
-                                       print_unescaped('value="true"');
-                               }  else {
-                                       print_unescaped('value="false"');
-                               }
-                               ?>
-                               <?php if (!$_['isConnectedViaHTTPS']) { p('disabled'); } ?> />
-                       <label for="forceSSLforSubdomains"><?php p($l->t('Enforce HTTPS for subdomains'));?></label><br/>
-                       <em><?php p($l->t(
-                                       'Forces the clients to connect to %s and subdomains via an encrypted connection.',
-                                       $theme->getName()
-                               )); ?></em>
-               </span>
-               <?php if (!$_['isConnectedViaHTTPS']) {
-                       print_unescaped("<br/><em>");
-                       p($l->t(
-                               'Please connect to your %s via HTTPS to enable or disable the SSL enforcement.',
-                               $theme->getName()
-                       ));
-                       print_unescaped("</em>");
-               }
-               ?>
-       </p>
-</div>
-
 <div class="section">
        <form id="mail_general_settings" class="mail_settings">
                <h2><?php p($l->t('Email Server'));?></h2>
index d89e4932368082b32340c1c65aaa42c07501bd80..56848d8df3099b9ddc2825083a3f92501b1b7306 100644 (file)
@@ -31,77 +31,6 @@ class SecuritySettingsControllerTest extends \PHPUnit_Framework_TestCase {
                $this->securitySettingsController = $this->container['SecuritySettingsController'];
        }
 
-
-       public function testEnforceSSLEmpty() {
-               $this->container['Config']
-                       ->expects($this->once())
-                       ->method('setSystemValue')
-                       ->with('forcessl', false);
-
-               $response = $this->securitySettingsController->enforceSSL();
-               $expectedResponse = array('status' => 'success');
-
-               $this->assertSame($expectedResponse, $response);
-       }
-
-       public function testEnforceSSL() {
-               $this->container['Config']
-                       ->expects($this->once())
-                       ->method('setSystemValue')
-                       ->with('forcessl', true);
-
-               $response = $this->securitySettingsController->enforceSSL(true);
-               $expectedResponse = array('status' => 'success');
-
-               $this->assertSame($expectedResponse, $response);
-       }
-
-       public function testEnforceSSLInvalid() {
-               $this->container['Config']
-                       ->expects($this->exactly(0))
-                       ->method('setSystemValue');
-
-               $response = $this->securitySettingsController->enforceSSL('blah');
-               $expectedResponse = array('status' => 'error');
-
-               $this->assertSame($expectedResponse, $response);
-       }
-
-       public function testEnforceSSLForSubdomainsEmpty() {
-               $this->container['Config']
-                       ->expects($this->once())
-                       ->method('setSystemValue')
-                       ->with('forceSSLforSubdomains', false);
-
-               $response = $this->securitySettingsController->enforceSSLForSubdomains();
-               $expectedResponse = array('status' => 'success');
-
-               $this->assertSame($expectedResponse, $response);
-       }
-
-       public function testEnforceSSLForSubdomains() {
-               $this->container['Config']
-                       ->expects($this->once())
-                       ->method('setSystemValue')
-                       ->with('forceSSLforSubdomains', true);
-
-               $response = $this->securitySettingsController->enforceSSLForSubdomains(true);
-               $expectedResponse = array('status' => 'success');
-
-               $this->assertSame($expectedResponse, $response);
-       }
-
-       public function testEnforceSSLForSubdomainsInvalid() {
-               $this->container['Config']
-                       ->expects($this->exactly(0))
-                       ->method('setSystemValue');
-
-               $response = $this->securitySettingsController->enforceSSLForSubdomains('blah');
-               $expectedResponse = array('status' => 'error');
-
-               $this->assertSame($expectedResponse, $response);
-       }
-
        public function testTrustedDomainsWithExistingValues() {
                $this->container['Config']
                        ->expects($this->once())