diff --git a/apps/settings/composer/composer/autoload_classmap.php b/apps/settings/composer/composer/autoload_classmap.php index a02d47e87f063..73ff50886fd4d 100644 --- a/apps/settings/composer/composer/autoload_classmap.php +++ b/apps/settings/composer/composer/autoload_classmap.php @@ -84,6 +84,7 @@ 'OCA\\Settings\\SetupChecks\\PhpGetEnv' => $baseDir . '/../lib/SetupChecks/PhpGetEnv.php', 'OCA\\Settings\\SetupChecks\\PhpOutdated' => $baseDir . '/../lib/SetupChecks/PhpOutdated.php', 'OCA\\Settings\\SetupChecks\\PhpOutputBuffering' => $baseDir . '/../lib/SetupChecks/PhpOutputBuffering.php', + 'OCA\\Settings\\SetupChecks\\RandomnessSecure' => $baseDir . '/../lib/SetupChecks/RandomnessSecure.php', 'OCA\\Settings\\SetupChecks\\ReadOnlyConfig' => $baseDir . '/../lib/SetupChecks/ReadOnlyConfig.php', 'OCA\\Settings\\SetupChecks\\SupportedDatabase' => $baseDir . '/../lib/SetupChecks/SupportedDatabase.php', 'OCA\\Settings\\SetupChecks\\TransactionIsolation' => $baseDir . '/../lib/SetupChecks/TransactionIsolation.php', diff --git a/apps/settings/composer/composer/autoload_static.php b/apps/settings/composer/composer/autoload_static.php index 90e8577b6ae2e..712ac9ca6e418 100644 --- a/apps/settings/composer/composer/autoload_static.php +++ b/apps/settings/composer/composer/autoload_static.php @@ -99,6 +99,7 @@ class ComposerStaticInitSettings 'OCA\\Settings\\SetupChecks\\PhpGetEnv' => __DIR__ . '/..' . '/../lib/SetupChecks/PhpGetEnv.php', 'OCA\\Settings\\SetupChecks\\PhpOutdated' => __DIR__ . '/..' . '/../lib/SetupChecks/PhpOutdated.php', 'OCA\\Settings\\SetupChecks\\PhpOutputBuffering' => __DIR__ . '/..' . '/../lib/SetupChecks/PhpOutputBuffering.php', + 'OCA\\Settings\\SetupChecks\\RandomnessSecure' => __DIR__ . '/..' . '/../lib/SetupChecks/RandomnessSecure.php', 'OCA\\Settings\\SetupChecks\\ReadOnlyConfig' => __DIR__ . '/..' . '/../lib/SetupChecks/ReadOnlyConfig.php', 'OCA\\Settings\\SetupChecks\\SupportedDatabase' => __DIR__ . '/..' . '/../lib/SetupChecks/SupportedDatabase.php', 'OCA\\Settings\\SetupChecks\\TransactionIsolation' => __DIR__ . '/..' . '/../lib/SetupChecks/TransactionIsolation.php', diff --git a/apps/settings/lib/AppInfo/Application.php b/apps/settings/lib/AppInfo/Application.php index d900d7fa8198a..a51faf9b718fb 100644 --- a/apps/settings/lib/AppInfo/Application.php +++ b/apps/settings/lib/AppInfo/Application.php @@ -59,6 +59,7 @@ use OCA\Settings\SetupChecks\PhpGetEnv; use OCA\Settings\SetupChecks\PhpOutdated; use OCA\Settings\SetupChecks\PhpOutputBuffering; +use OCA\Settings\SetupChecks\RandomnessSecure; use OCA\Settings\SetupChecks\ReadOnlyConfig; use OCA\Settings\SetupChecks\SupportedDatabase; use OCA\Settings\SetupChecks\TransactionIsolation; @@ -162,6 +163,7 @@ public function register(IRegistrationContext $context): void { $context->registerSetupCheck(PhpGetEnv::class); $context->registerSetupCheck(PhpOutdated::class); $context->registerSetupCheck(PhpOutputBuffering::class); + $context->registerSetupCheck(RandomnessSecure::class); $context->registerSetupCheck(ReadOnlyConfig::class); $context->registerSetupCheck(SupportedDatabase::class); $context->registerSetupCheck(TransactionIsolation::class); diff --git a/apps/settings/lib/Controller/CheckSetupController.php b/apps/settings/lib/Controller/CheckSetupController.php index 09682705494cb..dac4ea39a3c97 100644 --- a/apps/settings/lib/Controller/CheckSetupController.php +++ b/apps/settings/lib/Controller/CheckSetupController.php @@ -80,7 +80,6 @@ use OCP\Lock\ILockingProvider; use OCP\Notification\IManager; use OCP\Security\Bruteforce\IThrottler; -use OCP\Security\ISecureRandom; use OCP\SetupCheck\ISetupCheckManager; use Psr\Log\LoggerInterface; @@ -108,8 +107,6 @@ class CheckSetupController extends Controller { private $dateTimeFormatter; /** @var MemoryInfo */ private $memoryInfo; - /** @var ISecureRandom */ - private $secureRandom; /** @var IniGetWrapper */ private $iniGetWrapper; /** @var IDBConnection */ @@ -139,7 +136,6 @@ public function __construct($AppName, ILockingProvider $lockingProvider, IDateTimeFormatter $dateTimeFormatter, MemoryInfo $memoryInfo, - ISecureRandom $secureRandom, IniGetWrapper $iniGetWrapper, IDBConnection $connection, IThrottler $throttler, @@ -162,7 +158,6 @@ public function __construct($AppName, $this->lockingProvider = $lockingProvider; $this->dateTimeFormatter = $dateTimeFormatter; $this->memoryInfo = $memoryInfo; - $this->secureRandom = $secureRandom; $this->iniGetWrapper = $iniGetWrapper; $this->connection = $connection; $this->tempManager = $tempManager; @@ -189,20 +184,6 @@ private function isFairUseOfFreePushService(): bool { return $this->manager->isFairUseOfFreePushService(); } - /** - * Whether PHP can generate "secure" pseudorandom integers - * - * @return bool - */ - private function isRandomnessSecure() { - try { - $this->secureRandom->generate(1); - } catch (\Exception $ex) { - return false; - } - return true; - } - /** * Public for the sake of unit-testing * @@ -796,8 +777,6 @@ public function check() { 'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(), 'isBruteforceThrottled' => $this->throttler->getAttempts($this->request->getRemoteAddress()) !== 0, 'bruteforceRemoteAddress' => $this->request->getRemoteAddress(), - 'isRandomnessSecure' => $this->isRandomnessSecure(), - 'securityDocs' => $this->urlGenerator->linkToDocs('admin-security'), 'isUsedTlsLibOutdated' => $this->isUsedTlsLibOutdated(), 'forwardedForHeadersWorking' => $this->forwardedForHeadersWorking(), 'reverseProxyDocs' => $this->urlGenerator->linkToDocs('admin-reverse-proxy'), diff --git a/apps/settings/lib/SetupChecks/RandomnessSecure.php b/apps/settings/lib/SetupChecks/RandomnessSecure.php new file mode 100644 index 0000000000000..c30d4f2f79ac0 --- /dev/null +++ b/apps/settings/lib/SetupChecks/RandomnessSecure.php @@ -0,0 +1,63 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Settings\SetupChecks; + +use OCP\IConfig; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\Security\ISecureRandom; +use OCP\SetupCheck\ISetupCheck; +use OCP\SetupCheck\SetupResult; + +class RandomnessSecure implements ISetupCheck { + public function __construct( + private IL10N $l10n, + private IConfig $config, + private IURLGenerator $urlGenerator, + private ISecureRandom $secureRandom, + ) { + } + + public function getName(): string { + return $this->l10n->t('Random generator'); + } + + public function getCategory(): string { + return 'security'; + } + + public function run(): SetupResult { + try { + $this->secureRandom->generate(1); + } catch (\Exception $ex) { + return SetupResult::error( + $this->l10n->t('No suitable source for randomness found by PHP which is highly discouraged for security reasons.'), + $this->urlGenerator->linkToDocs('admin-security') + ); + } + return SetupResult::success($this->l10n->t('Secure')); + } +} diff --git a/apps/settings/tests/Controller/CheckSetupControllerTest.php b/apps/settings/tests/Controller/CheckSetupControllerTest.php index 05bf39acc26a8..cc522ed72be8e 100644 --- a/apps/settings/tests/Controller/CheckSetupControllerTest.php +++ b/apps/settings/tests/Controller/CheckSetupControllerTest.php @@ -449,8 +449,6 @@ public function testCheck() { 'backgroundJobsUrl' => 'https://example.org', ], 'cronErrors' => [], - 'isRandomnessSecure' => self::invokePrivate($this->checkSetupController, 'isRandomnessSecure'), - 'securityDocs' => 'https://docs.example.org/server/8.1/admin_manual/configuration_server/hardening.html', 'isUsedTlsLibOutdated' => '', 'forwardedForHeadersWorking' => false, 'reverseProxyDocs' => 'reverse-proxy-doc-link', diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js index b133e01d33f49..b07011e04a9f8 100644 --- a/core/js/setupchecks.js +++ b/core/js/setupchecks.js @@ -224,14 +224,6 @@ type: OC.SetupChecks.MESSAGE_TYPE_ERROR }); } - if(!data.isRandomnessSecure) { - messages.push({ - msg: t('core', 'No suitable source for randomness found by PHP which is highly discouraged for security reasons. Further information can be found in the {linkstart}documentation ↗{linkend}.') - .replace('{linkstart}', '') - .replace('{linkend}', ''), - type: OC.SetupChecks.MESSAGE_TYPE_ERROR - }); - } if(data.isUsedTlsLibOutdated) { messages.push({ msg: data.isUsedTlsLibOutdated, diff --git a/core/js/tests/specs/setupchecksSpec.js b/core/js/tests/specs/setupchecksSpec.js index afdbe8b138578..2043bda002c16 100644 --- a/core/js/tests/specs/setupchecksSpec.js +++ b/core/js/tests/specs/setupchecksSpec.js @@ -224,7 +224,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -287,7 +286,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -350,7 +348,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -399,64 +396,6 @@ describe('OC.SetupChecks tests', function() { }); }); - it('should return an error if /dev/urandom is not accessible', function(done) { - var async = OC.SetupChecks.checkSetup(); - - suite.server.requests[0].respond( - 200, - { - 'Content-Type': 'application/json', - }, - JSON.stringify({ - suggestedOverwriteCliURL: '', - isRandomnessSecure: false, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', - isFairUseOfFreePushService: true, - forwardedForHeadersWorking: true, - isCorrectMemcachedPHPModuleInstalled: true, - hasPassedCodeIntegrityCheck: true, - OpcacheSetupRecommendations: [], - isSettimelimitAvailable: true, - hasFreeTypeSupport: true, - missingIndexes: [], - missingPrimaryKeys: [], - missingColumns: [], - cronErrors: [], - cronInfo: { - diffInSeconds: 0 - }, - isMemoryLimitSufficient: true, - appDirsWithDifferentOwner: [], - isImagickEnabled: true, - areWebauthnExtensionsEnabled: true, - is64bit: true, - recommendedPHPModules: [], - pendingBigIntConversionColumns: [], - isMysqlUsedWithoutUTF8MB4: false, - isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true, - reverseProxyGeneratedURL: 'https://server', - temporaryDirectoryWritable: true, - generic: { - network: { - "Internet connectivity": { - severity: "success", - description: null, - linkToDoc: null - } - }, - }, - }) - ); - - async.done(function( data, s, x ){ - expect(data).toEqual([{ - msg: 'No suitable source for randomness found by PHP which is highly discouraged for security reasons. Further information can be found in the documentation ↗.', - type: OC.SetupChecks.MESSAGE_TYPE_ERROR - }]); - done(); - }); - }); - it('should return an error if the wrong memcache PHP module is installed', function(done) { var async = OC.SetupChecks.checkSetup(); @@ -467,8 +406,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: false, @@ -525,8 +462,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -585,7 +520,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: false, reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html', @@ -643,7 +577,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, isBruteforceThrottled: true, bruteforceRemoteAddress: '::1', @@ -703,7 +636,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html', @@ -761,7 +693,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html', @@ -839,8 +770,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -904,8 +833,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -962,8 +889,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1020,8 +945,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1082,8 +1005,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1141,8 +1062,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1197,8 +1116,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1256,8 +1173,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1315,8 +1230,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1373,8 +1286,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1431,8 +1342,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1496,8 +1405,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true,