Skip to content

Commit

Permalink
chore: use local variable for remote address
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
  • Loading branch information
kesselb authored and miaulalala committed Mar 16, 2023
1 parent 9aa7ed7 commit cc1b616
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 1 deletion.
16 changes: 15 additions & 1 deletion lib/private/User/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
use OCP\IUser;
use OCP\IUserSession;
use OCP\Lockdown\ILockdownManager;
use OCP\Security\Bruteforce\IThrottler;
use OCP\Security\ISecureRandom;
use OCP\Session\Exceptions\SessionNotAvailableException;
use OCP\User\Events\PostLoginEvent;
Expand Down Expand Up @@ -426,7 +427,8 @@ public function logClientIn($user,
$password,
IRequest $request,
OC\Security\Bruteforce\Throttler $throttler) {
$currentDelay = $throttler->sleepDelay($request->getRemoteAddress(), 'login');
$remoteAddress = $request->getRemoteAddress();
$currentDelay = $throttler->sleepDelay($remoteAddress, 'login');

if ($this->manager instanceof PublicEmitter) {
$this->manager->emit('\OC\User', 'preLogin', [$user, $password]);
Expand All @@ -451,6 +453,7 @@ public function logClientIn($user,

// Failed, maybe the user used their email address
if (!filter_var($user, FILTER_VALIDATE_EMAIL)) {
$this->handleLoginFailed($throttler, $currentDelay, $remoteAddress, $user, $password);
return false;
}
$users = $this->manager->getByEmail($user);
Expand Down Expand Up @@ -478,6 +481,17 @@ public function logClientIn($user,
return true;
}

private function handleLoginFailed(IThrottler $throttler, int $currentDelay, string $remoteAddress, string $user, ?string $password) {
$this->logger->warning("Login failed: '" . $user . "' (Remote IP: '" . $remoteAddress . "')", ['app' => 'core']);

$throttler->registerAttempt('login', $remoteAddress, ['user' => $user]);
$this->dispatcher->dispatchTyped(new OC\Authentication\Events\LoginFailed($user));

if ($currentDelay === 0) {
$throttler->sleepDelay($remoteAddress, 'login');
}
}

protected function supportsCookies(IRequest $request) {
if (!is_null($request->getCookie('cookie_test'))) {
return true;
Expand Down
97 changes: 97 additions & 0 deletions tests/lib/User/SessionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace Test\User;

use OC\AppFramework\Http\Request;
use OC\Authentication\Events\LoginFailed;
use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
use OC\Authentication\Token\IProvider;
Expand Down Expand Up @@ -1057,4 +1058,100 @@ public function testUpdateTokens() {

$this->userSession->updateTokens('uid', 'pass');
}

public function testLogClientInThrottlerUsername() {
$manager = $this->createMock(Manager::class);
$session = $this->createMock(ISession::class);
$request = $this->createMock(IRequest::class);

/** @var Session $userSession */
$userSession = $this->getMockBuilder(Session::class)
->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
->setMethods(['isTokenPassword', 'login', 'supportsCookies', 'createSessionToken', 'getUser'])
->getMock();

$userSession->expects($this->once())
->method('isTokenPassword')
->willReturn(true);
$userSession->expects($this->once())
->method('login')
->with('john', 'I-AM-AN-PASSWORD')
->willReturn(false);

$session->expects($this->never())
->method('set');
$request
->method('getRemoteAddress')
->willReturn('192.168.0.1');
$this->throttler
->expects($this->exactly(2))
->method('sleepDelay')
->with('192.168.0.1');
$this->throttler
->expects($this->any())
->method('getDelay')
->with('192.168.0.1')
->willReturn(0);

$this->throttler
->expects($this->once())
->method('registerAttempt')
->with('login', '192.168.0.1', ['user' => 'john']);
$this->dispatcher
->expects($this->once())
->method('dispatchTyped')
->with(new LoginFailed('john', 'I-AM-AN-PASSWORD'));

$this->assertFalse($userSession->logClientIn('john', 'I-AM-AN-PASSWORD', $request, $this->throttler));
}

public function testLogClientInThrottlerEmail() {
$manager = $this->createMock(Manager::class);
$session = $this->createMock(ISession::class);
$request = $this->createMock(IRequest::class);

/** @var Session $userSession */
$userSession = $this->getMockBuilder(Session::class)
->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher])
->setMethods(['isTokenPassword', 'login', 'supportsCookies', 'createSessionToken', 'getUser'])
->getMock();

$userSession->expects($this->once())
->method('isTokenPassword')
->willReturn(true);
$userSession->expects($this->once())
->method('login')
->with('john@foo.bar', 'I-AM-AN-PASSWORD')
->willReturn(false);
$manager
->method('getByEmail')
->with('john@foo.bar')
->willReturn([]);

$session->expects($this->never())
->method('set');
$request
->method('getRemoteAddress')
->willReturn('192.168.0.1');
$this->throttler
->expects($this->exactly(2))
->method('sleepDelay')
->with('192.168.0.1');
$this->throttler
->expects($this->any())
->method('getDelay')
->with('192.168.0.1')
->willReturn(0);

$this->throttler
->expects($this->once())
->method('registerAttempt')
->with('login', '192.168.0.1', ['user' => 'john@foo.bar']);
$this->dispatcher
->expects($this->once())
->method('dispatchTyped')
->with(new LoginFailed('john@foo.bar', 'I-AM-AN-PASSWORD'));

$this->assertFalse($userSession->logClientIn('john@foo.bar', 'I-AM-AN-PASSWORD', $request, $this->throttler));
}
}

0 comments on commit cc1b616

Please sign in to comment.