Skip to content

Commit 98811d0

Browse files
CarlSchwanbackportbot[bot]
authored andcommitted
feat: Add setting to bypass password confirmation on a selected ip ranges
feat: Add setting to bypass password confirmation on a selected ip ranges Signed-off-by: Carl Schwan <carl@carlschwan.eu> [skip ci]
1 parent 0131bd9 commit 98811d0

5 files changed

Lines changed: 55 additions & 0 deletions

File tree

‎config/config.sample.php‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,6 +2538,19 @@
25382538
*/
25392539
'allowed_admin_ranges' => ['192.0.2.42/32', '233.252.0.0/24', '2001:db8::13:37/64'],
25402540

2541+
/**
2542+
* List of trusted IP ranges that can bypass password confirmation.
2543+
* If non-empty, all endpoints marked with the PasswordConfirmationRequired attribute
2544+
* won't need a password confirmation when originating from IPs within these ranges.
2545+
*
2546+
* Supported formats:
2547+
* - IPv4 addresses or ranges, e.g., ``192.0.2.42/32``, ``233.252.0.0/24``
2548+
* - IPv6 addresses or ranges, e.g., ``2001:db8::13:37/64``
2549+
*
2550+
* Defaults to ``[]`` (empty array)
2551+
*/
2552+
'allowed_no_password_confirmation_ranges' => ['192.0.2.42/32', '233.252.0.0/24', '2001:db8::13:37/64'],
2553+
25412554
/**
25422555
* Maximum file size (in megabytes) for animating GIFs on public sharing pages.
25432556
* If a GIF exceeds this size, a static preview is shown.

‎lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use OCP\IRequest;
2222
use OCP\ISession;
2323
use OCP\IUserSession;
24+
use OCP\Security\Ip\IRemoteAddress;
2425
use OCP\Session\Exceptions\SessionNotAvailableException;
2526
use OCP\User\Backend\IPasswordConfirmationBackend;
2627
use Psr\Log\LoggerInterface;
@@ -39,6 +40,7 @@ public function __construct(
3940
private readonly LoggerInterface $logger,
4041
private readonly IRequest $request,
4142
private readonly Manager $userManager,
43+
private readonly IRemoteAddress $remoteAddress,
4244
) {
4345
}
4446

@@ -72,6 +74,10 @@ public function beforeController(Controller $controller, string $methodName) {
7274
return;
7375
}
7476
} catch (SessionNotAvailableException|InvalidTokenException|WipeTokenException|ExpiredTokenException) {
77+
if ($this->remoteAddress->allowsBypassPasswordConfirmation()) {
78+
return;
79+
}
80+
7581
// No scope to test
7682
}
7783

‎lib/private/Security/Ip/RemoteAddress.php‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
class RemoteAddress implements IRemoteAddress, IAddress {
1919
public const SETTING_NAME = 'allowed_admin_ranges';
20+
public const SETTING_PASSWORD_CONFIRMATION_NAME = 'allowed_no_password_confirmation_ranges';
2021

2122
private readonly ?IAddress $ip;
2223

@@ -65,6 +66,32 @@ public function allowsAdminActions(): bool {
6566
return false;
6667
}
6768

69+
#[\Override]
70+
public function allowsBypassPasswordConfirmation(): bool {
71+
if ($this->ip === null) {
72+
return false;
73+
}
74+
75+
$allowedAdminRanges = $this->config->getSystemValue(self::SETTING_PASSWORD_CONFIRMATION_NAME, false);
76+
77+
// Apply restrictions on empty or invalid configuration
78+
if (
79+
$allowedAdminRanges === false
80+
|| !is_array($allowedAdminRanges)
81+
|| empty($allowedAdminRanges)
82+
) {
83+
return false;
84+
}
85+
86+
foreach ($allowedAdminRanges as $allowedAdminRange) {
87+
if ((new Range($allowedAdminRange))->contains($this->ip)) {
88+
return true;
89+
}
90+
}
91+
92+
return false;
93+
}
94+
6895
public function __toString(): string {
6996
return (string)$this->ip;
7097
}

‎lib/public/Security/Ip/IRemoteAddress.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,10 @@ interface IRemoteAddress {
1919
* @since 30.0.0
2020
*/
2121
public function allowsAdminActions(): bool;
22+
23+
/**
24+
* Check if the current remote address is allowed to bypass the password confirmation.
25+
* @since 35.0.0
26+
*/
27+
public function allowsBypassPasswordConfirmation(): bool;
2228
}

‎tests/lib/AppFramework/Middleware/Security/PasswordConfirmationMiddlewareTest.php‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class PasswordConfirmationMiddlewareTest extends TestCase {
4343
private IRequest $request;
4444
/** @var Manager&\PHPUnit\Framework\MockObject\MockObject */
4545
private Manager $userManager;
46+
private IRemoteAddress&MockObject $remoteAddress;
4647

4748
protected function setUp(): void {
4849
$this->reflector = new ControllerMethodReflector(\OCP\Server::get(LoggerInterface::class));
@@ -58,6 +59,7 @@ protected function setUp(): void {
5859
'test',
5960
$this->createMock(IRequest::class)
6061
);
62+
$this->remoteAddress = $this->createMock(IRemoteAddress::class);
6163

6264
$this->middleware = new PasswordConfirmationMiddleware(
6365
$this->reflector,
@@ -68,6 +70,7 @@ protected function setUp(): void {
6870
$this->logger,
6971
$this->request,
7072
$this->userManager,
73+
$this->remoteAddress,
7174
);
7275
}
7376

0 commit comments

Comments
 (0)