diff --git a/lib/base.php b/lib/base.php index dc09d0f533d4d..2a26307169a74 100644 --- a/lib/base.php +++ b/lib/base.php @@ -730,7 +730,7 @@ public static function init() { OC_User::setIncognitoMode(true); } - self::registerCacheHooks(); + self::registerCleanupHooks(); self::registerFilesystemHooks(); self::registerShareHooks(); self::registerEncryptionWrapper(); @@ -802,15 +802,21 @@ public static function init() { } /** - * register hooks for the cache + * register hooks for the cleanup of cache and bruteforce protection */ - public static function registerCacheHooks() { + public static function registerCleanupHooks() { //don't try to do this before we are properly setup if (\OC::$server->getSystemConfig()->getValue('installed', false) && !self::checkUpgrade(false)) { // NOTE: This will be replaced to use OCP $userSession = self::$server->getUserSession(); - $userSession->listen('\OC\User', 'postLogin', function () { + $userSession->listen('\OC\User', 'postLogin', function () use ($userSession) { + // reset brute force delay for this IP address and username + $uid = \OC::$server->getUserSession()->getUser()->getUID(); + $request = \OC::$server->getRequest(); + $throttler = \OC::$server->getBruteForceThrottler(); + $throttler->resetDelay($request->getRemoteAddress(), 'login', ['user' => $uid]); + try { $cache = new \OC\Cache\File(); $cache->gc(); diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php index 1626cee8cb33f..f08b721d14398 100644 --- a/lib/private/Security/Bruteforce/Throttler.php +++ b/lib/private/Security/Bruteforce/Throttler.php @@ -242,6 +242,33 @@ public function getDelay($ip, $action = '') { return (int) \ceil($firstDelay * 1000); } + /** + * Reset the throttling delay for an IP address, action and metadata + * + * @param string $ip + * @param string $action + * @param string $metadata + */ + public function resetDelay($ip, $action, $metadata) { + $ipAddress = new IpAddress($ip); + if ($this->isIPWhitelisted((string)$ipAddress)) { + return; + } + + $cutoffTime = (new \DateTime()) + ->sub($this->getCutoff(43200)) + ->getTimestamp(); + + $qb = $this->db->getQueryBuilder(); + $qb->delete('bruteforce_attempts') + ->where($qb->expr()->gt('occurred', $qb->createNamedParameter($cutoffTime))) + ->andWhere($qb->expr()->eq('subnet', $qb->createNamedParameter($ipAddress->getSubnet()))) + ->andWhere($qb->expr()->eq('action', $qb->createNamedParameter($action))) + ->andWhere($qb->expr()->eq('metadata', $qb->createNamedParameter(json_encode($metadata)))); + + $qb->execute(); + } + /** * Will sleep for the defined amount of time *