diff options
author | Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com> | 2024-07-12 16:25:49 +0200 |
---|---|---|
committer | Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com> | 2024-07-19 16:28:03 +0200 |
commit | 202e5b1e957a7692165a313710e38406ca4f6ff3 (patch) | |
tree | f1dd40c0e4399ebc0c9ca8df02e3168b7e4f7ae2 /lib/private/Security | |
parent | 8f975cda34b4b4f181646a54c15f7c511d6e8491 (diff) | |
download | nextcloud-server-202e5b1e957a7692165a313710e38406ca4f6ff3.tar.gz nextcloud-server-202e5b1e957a7692165a313710e38406ca4f6ff3.zip |
feat(security): restrict admin actions to IP ranges
Signed-off-by: Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com>
Diffstat (limited to 'lib/private/Security')
-rw-r--r-- | lib/private/Security/RemoteIpAddress.php | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/lib/private/Security/RemoteIpAddress.php b/lib/private/Security/RemoteIpAddress.php new file mode 100644 index 00000000000..ef9debf4a65 --- /dev/null +++ b/lib/private/Security/RemoteIpAddress.php @@ -0,0 +1,64 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Security; + +use IPLib\Factory; +use OCP\IConfig; +use OCP\IRequest; +use Psr\Log\LoggerInterface; + +class RemoteIpAddress { + public const SETTING_NAME = 'allowed_admin_ranges'; + + public function __construct( + private IConfig $config, + private IRequest $request, + private LoggerInterface $logger, + ) { + } + + public function allowsAdminActions(): bool { + $allowedAdminRanges = $this->config->getSystemValue(self::SETTING_NAME, false); + if ($allowedAdminRanges === false) { + // No restriction applied + return true; + } + + if (!is_array($allowedAdminRanges)) { + return true; + } + + if (empty($allowedAdminRanges)) { + return true; + } + + $ipAddress = Factory::parseAddressString($this->request->getRemoteAddress()); + if ($ipAddress === null) { + $this->logger->warning( + 'Unable to parse remote IP "{ip}"', + ['ip' => $ipAddress,] + ); + + return false; + } + + foreach ($allowedAdminRanges as $rangeString) { + $range = Factory::parseRangeString($rangeString); + if ($range === null) { + continue; + } + if ($range->contains($ipAddress)) { + return true; + } + } + + return false; + } +} |