diff --git a/apps/settings/composer/composer/autoload_classmap.php b/apps/settings/composer/composer/autoload_classmap.php index c045d8975ca8c..c69b49ec309c2 100644 --- a/apps/settings/composer/composer/autoload_classmap.php +++ b/apps/settings/composer/composer/autoload_classmap.php @@ -85,6 +85,7 @@ 'OCA\\Settings\\SetupChecks\\PhpModules' => $baseDir . '/../lib/SetupChecks/PhpModules.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 5506a36e58ab3..eba8fadc98a7c 100644 --- a/apps/settings/composer/composer/autoload_static.php +++ b/apps/settings/composer/composer/autoload_static.php @@ -100,6 +100,7 @@ class ComposerStaticInitSettings 'OCA\\Settings\\SetupChecks\\PhpModules' => __DIR__ . '/..' . '/../lib/SetupChecks/PhpModules.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 b0c6bfbc63632..0770418c3bb7e 100644 --- a/apps/settings/lib/AppInfo/Application.php +++ b/apps/settings/lib/AppInfo/Application.php @@ -60,6 +60,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; @@ -164,6 +165,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 ccdadcb3ceadb..f5849cce5a83a 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; @@ -194,20 +189,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 * @@ -767,8 +748,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 f992ecf8591c0..157db6218770b 100644 --- a/apps/settings/tests/Controller/CheckSetupControllerTest.php +++ b/apps/settings/tests/Controller/CheckSetupControllerTest.php @@ -443,8 +443,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 a334c0bd789b1..029096b43b2e4 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 7d8504d6146c5..984c27fa973ca 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, @@ -286,7 +285,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -348,7 +346,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -396,63 +393,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, - 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(); @@ -463,8 +403,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: false, @@ -520,8 +458,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -579,7 +515,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: false, reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html', @@ -636,7 +571,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, isBruteforceThrottled: true, bruteforceRemoteAddress: '::1', @@ -695,7 +629,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html', @@ -752,7 +685,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html', @@ -829,8 +761,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -893,8 +823,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -950,8 +878,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1007,8 +933,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1068,8 +992,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1126,8 +1048,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1181,8 +1101,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1239,8 +1157,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1297,8 +1213,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1354,8 +1268,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1411,8 +1323,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true, @@ -1475,8 +1385,6 @@ describe('OC.SetupChecks tests', function() { }, JSON.stringify({ suggestedOverwriteCliURL: '', - isRandomnessSecure: true, - securityDocs: 'https://docs.nextcloud.com/myDocs.html', isFairUseOfFreePushService: true, forwardedForHeadersWorking: true, isCorrectMemcachedPHPModuleInstalled: true,