Detect old NSS and OpenSSL versions
This will detect old NSS and OpenSSL versions and show appropriate errors in the admin interface. Fixes https://github.com/owncloud/core/issues/17901
This commit is contained in:
parent
c34e63bb1f
commit
0d515de13e
4 changed files with 221 additions and 11 deletions
|
@ -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'));
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,6 +116,66 @@ class CheckSetupController extends Controller {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -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(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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'));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue