1<?php
2/**
3 * DokuWiki Plugin logindelay (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Anna Dabrowska <dokuwiki@cosmocode.de>
7 */
8
9class action_plugin_logindelay_login extends DokuWiki_Action_Plugin
10{
11
12    /**
13     * Registers a callback function for a given event
14     *
15     * @param Doku_Event_Handler $controller DokuWiki's event controller object
16     *
17     * @return void
18     */
19    public function register(Doku_Event_Handler $controller)
20    {
21        $controller->register_hook('AUTH_LOGIN_CHECK', 'BEFORE', $this, 'checkDelay');
22        $controller->register_hook('AUTH_LOGIN_CHECK', 'AFTER', $this, 'processLoginAttempt');
23    }
24
25    /**
26     * Check if login attempt should be allowed or delayed
27     *
28     * @param Doku_Event $event
29     */
30    public function checkDelay(Doku_Event $event)
31    {
32        $user = $event->data['user'];
33
34        // no user to check
35        if (empty($user)) return;
36
37        $logHelper = new \helper_plugin_logindelay_log($user);
38
39        // should the login attempt be delayed?
40        $delay = $logHelper->calculateDelay();
41
42        if ($delay > 0) {
43            $event->preventDefault();
44            $this->displayMessage($delay);
45        }
46    }
47
48    /**
49     * Check status of login attempt on the result of auth_login_wrapper()
50     *
51     * @param Doku_Event $event
52     */
53    public function processLoginAttempt(Doku_Event $event)
54    {
55        global $ACT;
56        if ($ACT !== 'login') return;
57
58        $authenticatedUser = $_SERVER['REMOTE_USER'];
59        $loginUser = $event->data['user'];
60
61        $logHelper = new \helper_plugin_logindelay_log($loginUser);
62
63        // exit early if this attempt should be delayed
64        $delay = $logHelper->calculateDelay();
65        if ($delay > 0) {
66            $this->displayMessage($delay);
67            return;
68        }
69
70        // failed login attempt, intervene
71        if ($loginUser && $loginUser !== $authenticatedUser) {
72            if ($logHelper->putFailStrike() > $this->getConf('maxFailures')) {
73                $delay = $logHelper->calculateDelay();
74                $this->displayMessage($delay);
75            }
76            return;
77        }
78
79        // successful login, clear any previous failures
80        $logHelper->clearFailStrikes();
81    }
82
83    /**
84     * Display error message with hint when a retry will be allowed
85     *
86     * @param $allowedRetry
87     */
88    protected function displayMessage($allowedRetry)
89    {
90        msg(sprintf($this->getLang('errorMessage'), $allowedRetry), -1);
91    }
92}
93
94