summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin McCorkell <rmccorkell@owncloud.com>2015-07-28 21:26:44 +0100
committerRobin McCorkell <rmccorkell@owncloud.com>2015-07-28 21:26:44 +0100
commit6d54d2fad71a57d08cfd5a5a2d76948ac0983ff6 (patch)
tree1cb1415dd7d52a44b3ce43d5196aeb8af9f73677
parent6f72c3746403cdba5dbaae9a21870f0db0e5226e (diff)
parent0d515de13e0832447ed341c0b8377e01d350e48c (diff)
downloadnextcloud-server-6d54d2fad71a57d08cfd5a5a2d76948ac0983ff6.tar.gz
nextcloud-server-6d54d2fad71a57d08cfd5a5a2d76948ac0983ff6.zip
Merge pull request #17912 from owncloud/detect-old-openssl-versions
Detect old NSS and OpenSSL versions
-rw-r--r--core/js/setupchecks.js3
-rw-r--r--settings/application.php3
-rw-r--r--settings/controller/checksetupcontroller.php70
-rw-r--r--tests/settings/controller/CheckSetupControllerTest.php156
4 files changed, 221 insertions, 11 deletions
diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js
index 02d7ef94b7e..35f24b188fa 100644
--- a/core/js/setupchecks.js
+++ b/core/js/setupchecks.js
@@ -69,6 +69,9 @@
t('core', '/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a href="{docLink}">documentation</a>.', {docLink: data.securityDocs})
);
}
+ if(data.isUsedTlsLibOutdated) {
+ messages.push(data.isUsedTlsLibOutdated);
+ }
} else {
messages.push(t('core', 'Error occurred while checking server setup'));
}
diff --git a/settings/application.php b/settings/application.php
index a2f25935e12..8da835c18d2 100644
--- a/settings/application.php
+++ b/settings/application.php
@@ -154,7 +154,8 @@ class Application extends App {
$c->query('Config'),
$c->query('ClientService'),
$c->query('URLGenerator'),
- $c->query('Util')
+ $c->query('Util'),
+ $c->query('L10N')
);
});
diff --git a/settings/controller/checksetupcontroller.php b/settings/controller/checksetupcontroller.php
index 0b4c72acab7..f849e3ed565 100644
--- a/settings/controller/checksetupcontroller.php
+++ b/settings/controller/checksetupcontroller.php
@@ -23,10 +23,12 @@
namespace OC\Settings\Controller;
+use GuzzleHttp\Exception\ClientException;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
+use OCP\IL10N;
use OCP\IRequest;
use OC_Util;
use OCP\IURLGenerator;
@@ -43,6 +45,8 @@ class CheckSetupController extends Controller {
private $util;
/** @var IURLGenerator */
private $urlGenerator;
+ /** @var IL10N */
+ private $l10n;
/**
* @param string $AppName
@@ -51,18 +55,21 @@ class CheckSetupController extends Controller {
* @param IClientService $clientService
* @param IURLGenerator $urlGenerator
* @param \OC_Util $util
+ * @param IL10N $l10n
*/
public function __construct($AppName,
IRequest $request,
IConfig $config,
IClientService $clientService,
IURLGenerator $urlGenerator,
- \OC_Util $util) {
+ \OC_Util $util,
+ IL10N $l10n) {
parent::__construct($AppName, $request);
$this->config = $config;
$this->clientService = $clientService;
$this->util = $util;
$this->urlGenerator = $urlGenerator;
+ $this->l10n = $l10n;
}
/**
@@ -110,6 +117,66 @@ class CheckSetupController extends Controller {
}
/**
+ * Public for the sake of unit-testing
+ *
+ * @return array
+ */
+ public function getCurlVersion() {
+ return curl_version();
+ }
+
+ /**
+ * Check if the used SSL lib is outdated. Older OpenSSL and NSS versions do
+ * have multiple bugs which likely lead to problems in combination with
+ * functionalities required by ownCloud such as SNI.
+ *
+ * @link https://github.com/owncloud/core/issues/17446#issuecomment-122877546
+ * @link https://bugzilla.redhat.com/show_bug.cgi?id=1241172
+ * @return string
+ */
+ private function isUsedTlsLibOutdated() {
+ $versionString = $this->getCurlVersion();
+ if(isset($versionString['ssl_version'])) {
+ $versionString = $versionString['ssl_version'];
+ } else {
+ return '';
+ }
+
+ $features = (string)$this->l10n->t('installing and updating apps via the app store or Federated Cloud Sharing');
+ if(OC_Util::getEditionString() !== '') {
+ $features = (string)$this->l10n->t('Federated Cloud Sharing');
+ }
+
+ // Check if at least OpenSSL after 1.01d or 1.0.2b
+ if(strpos($versionString, 'OpenSSL/') === 0) {
+ $majorVersion = substr($versionString, 8, 5);
+ $patchRelease = substr($versionString, 13, 6);
+
+ if(($majorVersion === '1.0.1' && ord($patchRelease) < ord('d')) ||
+ ($majorVersion === '1.0.2' && ord($patchRelease) < ord('b'))) {
+ return (string) $this->l10n->t('cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably.', ['OpenSSL', $versionString, $features]);
+ }
+ }
+
+ // Check if NSS and perform heuristic check
+ if(strpos($versionString, 'NSS/') === 0) {
+ try {
+ $firstClient = $this->clientService->newClient();
+ $firstClient->get('https://www.owncloud.org/');
+
+ $secondClient = $this->clientService->newClient();
+ $secondClient->get('https://owncloud.org/');
+ } catch (ClientException $e) {
+ if($e->getResponse()->getStatusCode() === 400) {
+ return (string) $this->l10n->t('cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably.', ['NSS', $versionString, $features]);
+ }
+ }
+ }
+
+ return '';
+ }
+
+ /**
* @return DataResponse
*/
public function check() {
@@ -121,6 +188,7 @@ class CheckSetupController extends Controller {
'memcacheDocs' => $this->urlGenerator->linkToDocs('admin-performance'),
'isUrandomAvailable' => $this->isUrandomAvailable(),
'securityDocs' => $this->urlGenerator->linkToDocs('admin-security'),
+ 'isUsedTlsLibOutdated' => $this->isUsedTlsLibOutdated(),
]
);
}
diff --git a/tests/settings/controller/CheckSetupControllerTest.php b/tests/settings/controller/CheckSetupControllerTest.php
index b39d13ac26b..6096aae8652 100644
--- a/tests/settings/controller/CheckSetupControllerTest.php
+++ b/tests/settings/controller/CheckSetupControllerTest.php
@@ -24,6 +24,7 @@ namespace OC\Settings\Controller;
use OCP\AppFramework\Http\DataResponse;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
+use OCP\IL10N;
use OCP\IRequest;
use OCP\IURLGenerator;
use OC_Util;
@@ -47,6 +48,8 @@ class CheckSetupControllerTest extends TestCase {
private $urlGenerator;
/** @var OC_Util */
private $util;
+ /** @var IL10N */
+ private $l10n;
public function setUp() {
parent::setUp();
@@ -63,15 +66,24 @@ class CheckSetupControllerTest extends TestCase {
->disableOriginalConstructor()->getMock();
$this->urlGenerator = $this->getMockBuilder('\OCP\IURLGenerator')
->disableOriginalConstructor()->getMock();
-
- $this->checkSetupController = new CheckSetupController(
- 'settings',
- $this->request,
- $this->config,
- $this->clientService,
- $this->urlGenerator,
- $this->util
- );
+ $this->l10n = $this->getMockBuilder('\OCP\IL10N')
+ ->disableOriginalConstructor()->getMock();
+ $this->l10n->expects($this->any())
+ ->method('t')
+ ->will($this->returnCallback(function($message, array $replace) {
+ return vsprintf($message, $replace);
+ }));
+ $this->checkSetupController = $this->getMockBuilder('\OC\Settings\Controller\CheckSetupController')
+ ->setConstructorArgs([
+ 'settings',
+ $this->request,
+ $this->config,
+ $this->clientService,
+ $this->urlGenerator,
+ $this->util,
+ $this->l10n,
+ ])
+ ->setMethods(['getCurlVersion'])->getMock();
}
public function testIsInternetConnectionWorkingDisabledViaConfig() {
@@ -241,8 +253,134 @@ class CheckSetupControllerTest extends TestCase {
'memcacheDocs' => 'http://doc.owncloud.org/server/go.php?to=admin-performance',
'isUrandomAvailable' => self::invokePrivate($this->checkSetupController, 'isUrandomAvailable'),
'securityDocs' => 'https://doc.owncloud.org/server/8.1/admin_manual/configuration_server/hardening.html',
+ 'isUsedTlsLibOutdated' => '',
]
);
$this->assertEquals($expected, $this->checkSetupController->check());
}
+
+ public function testGetCurlVersion() {
+ $checkSetupController = $this->getMockBuilder('\OC\Settings\Controller\CheckSetupController')
+ ->setConstructorArgs([
+ 'settings',
+ $this->request,
+ $this->config,
+ $this->clientService,
+ $this->urlGenerator,
+ $this->util,
+ $this->l10n,
+ ])
+ ->setMethods(null)->getMock();
+
+ $this->assertArrayHasKey('ssl_version', $checkSetupController->getCurlVersion());
+ }
+
+ public function testIsUsedTlsLibOutdatedWithAnotherLibrary() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'SSLlib']));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithMisbehavingCurl() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue([]));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithOlderOpenSsl() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.1c']));
+ $this->assertSame('cURL is using an outdated OpenSSL version (OpenSSL/1.0.1c). Please update your operating system or features such as installing and updating apps via the app store or Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithOlderOpenSsl1() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.2a']));
+ $this->assertSame('cURL is using an outdated OpenSSL version (OpenSSL/1.0.2a). Please update your operating system or features such as installing and updating apps via the app store or Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithMatchingOpenSslVersion() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.1d']));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsUsedTlsLibOutdatedWithMatchingOpenSslVersion1() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.2b']));
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+ public function testIsBuggyNss400() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'NSS/1.0.2b']));
+ $client = $this->getMockBuilder('\OCP\Http\Client\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $exception = $this->getMockBuilder('\GuzzleHttp\Exception\ClientException')
+ ->disableOriginalConstructor()->getMock();
+ $response = $this->getMockBuilder('\GuzzleHttp\Message\ResponseInterface')
+ ->disableOriginalConstructor()->getMock();
+ $response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue(400));
+ $exception->expects($this->once())
+ ->method('getResponse')
+ ->will($this->returnValue($response));
+
+ $client->expects($this->at(0))
+ ->method('get')
+ ->with('https://www.owncloud.org/', [])
+ ->will($this->throwException($exception));
+
+ $this->clientService->expects($this->once())
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+ $this->assertSame('cURL is using an outdated NSS version (NSS/1.0.2b). Please update your operating system or features such as installing and updating apps via the app store or Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
+
+ public function testIsBuggyNss200() {
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'NSS/1.0.2b']));
+ $client = $this->getMockBuilder('\OCP\Http\Client\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $exception = $this->getMockBuilder('\GuzzleHttp\Exception\ClientException')
+ ->disableOriginalConstructor()->getMock();
+ $response = $this->getMockBuilder('\GuzzleHttp\Message\ResponseInterface')
+ ->disableOriginalConstructor()->getMock();
+ $response->expects($this->once())
+ ->method('getStatusCode')
+ ->will($this->returnValue(200));
+ $exception->expects($this->once())
+ ->method('getResponse')
+ ->will($this->returnValue($response));
+
+ $client->expects($this->at(0))
+ ->method('get')
+ ->with('https://www.owncloud.org/', [])
+ ->will($this->throwException($exception));
+
+ $this->clientService->expects($this->once())
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+ $this->assertSame('', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
}