-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(security): Add public API to allow validating IP Ranges and chec…
…king for "in range" Signed-off-by: Joas Schilling <coding@schilljs.com> Signed-off-by: Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com>
- Loading branch information
1 parent
1f9a8f5
commit 17a6845
Showing
17 changed files
with
311 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
namespace OC\Security\Ip; | ||
|
||
use InvalidArgumentException; | ||
use IPLib\Address\AddressInterface; | ||
use IPLib\Factory; | ||
use OCP\Security\Ip\IAddress; | ||
use OCP\Security\Ip\IRange; | ||
|
||
/** | ||
* @since 30.0.0 | ||
*/ | ||
class Address implements IAddress { | ||
private readonly AddressInterface $ip; | ||
|
||
public function __construct(string $ip) { | ||
$ip = Factory::parseAddressString($ip); | ||
if ($ip === null) { | ||
throw new InvalidArgumentException('Given IP address can’t be parsed'); | ||
} | ||
$this->ip = $ip; | ||
} | ||
|
||
public static function isValid(string $ip): bool { | ||
return Factory::parseAddressString($ip) !== null; | ||
} | ||
|
||
public function matches(IRange... $ranges): bool { | ||
foreach($ranges as $range) { | ||
if ($range->contains($this)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public function __toString(): string { | ||
return $this->ip->toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
namespace OC\Security\Ip; | ||
|
||
use InvalidArgumentException; | ||
use IPLib\Factory; | ||
use IPLib\Range\RangeInterface; | ||
use OCP\Security\Ip\IAddress; | ||
use OCP\Security\Ip\IRange; | ||
|
||
class Range implements IRange { | ||
private readonly RangeInterface $range; | ||
|
||
public function __construct(string $range) { | ||
$range = Factory::parseRangeString($range); | ||
if ($range === null) { | ||
throw new InvalidArgumentException('Given range can’t be parsed'); | ||
} | ||
$this->range = $range; | ||
} | ||
|
||
public static function isValid(string $range): bool { | ||
return Factory::parseRangeString($range) !== null; | ||
} | ||
|
||
public function contains(IAddress $address): bool { | ||
return $this->range->contains(Factory::parseAddressString((string) $address)); | ||
} | ||
|
||
public function __toString(): string { | ||
return $this->range->toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
namespace OC\Security\Ip; | ||
|
||
use OCP\IConfig; | ||
use OCP\IRequest; | ||
use OCP\Security\Ip\IAddress; | ||
use OCP\Security\Ip\IRange; | ||
use OCP\Security\Ip\IRemoteAddress; | ||
|
||
class RemoteAddress implements IRemoteAddress, IAddress { | ||
public const SETTING_NAME = 'allowed_admin_ranges'; | ||
|
||
private readonly ?IAddress $ip; | ||
|
||
public function __construct( | ||
private IConfig $config, | ||
IRequest $request, | ||
) { | ||
$remoteAddress = $request->getRemoteAddress(); | ||
$this->ip = $remoteAddress === '' | ||
? null | ||
: new Address($remoteAddress); | ||
} | ||
|
||
public static function isValid(string $ip): bool { | ||
return Address::isValid($ip); | ||
} | ||
|
||
public function matches(IRange... $ranges): bool { | ||
return $this->ip === null | ||
? true | ||
: $this->ip->matches(... $ranges); | ||
} | ||
|
||
public function allowsAdminActions(): bool { | ||
if ($this->ip === null) { | ||
return true; | ||
} | ||
|
||
$allowedAdminRanges = $this->config->getSystemValue(self::SETTING_NAME, false); | ||
|
||
// Don't apply restrictions on empty or invalid configuration | ||
if ( | ||
$allowedAdminRanges === false | ||
|| !is_array($allowedAdminRanges) | ||
|| empty($allowedAdminRanges) | ||
) { | ||
return true; | ||
} | ||
|
||
foreach ($allowedAdminRanges as $allowedAdminRange) { | ||
if ((new Range($allowedAdminRange))->contains($this->ip)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public function __toString(): string { | ||
return (string) $this->ip; | ||
} | ||
} |
Oops, something went wrong.