Issues (2963)

app/Http/Controllers/Auth/TwoFactorController.php (1 issue)

1
<?php
2
/**
3
 * TwoFactorController.php
4
 *
5
 * -Description-
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 *
20
 * @link       https://www.librenms.org
21
 *
22
 * @copyright  2018 Tony Murray
23
 * @author     Tony Murray <[email protected]>
24
 */
25
26
namespace App\Http\Controllers\Auth;
27
28
use App\Http\Controllers\Controller;
29
use App\Models\User;
30
use App\Models\UserPref;
31
use Illuminate\Http\Request;
32
use Illuminate\Validation\Rule;
33
use LibreNMS\Authentication\TwoFactor;
34
use LibreNMS\Config;
35
use LibreNMS\Exceptions\AuthenticationException;
36
use Session;
37
use Toastr;
38
39
class TwoFactorController extends Controller
40
{
41
    public function verifyTwoFactor(Request $request)
42
    {
43
        $this->validate($request, [
44
            'twofactor' => 'required|numeric',
45
        ]);
46
47
        try {
48
            $this->checkToken($request->user(), $request->input('twofactor'));
49
        } catch (AuthenticationException $e) {
50
            return redirect()->route('2fa.form')->withErrors($e->getMessage());
51
        }
52
53
        // token validated
54
        if (session('twofactorremove')) {
55
            UserPref::forgetPref(auth()->user(), 'twofactor');
56
            $request->session()->forget(['twofactor', 'twofactorremove']);
57
58
            \Toastr::info(__('TwoFactor auth removed.'));
59
60
            return redirect('preferences');
61
        }
62
63
        $request->session()->put('twofactor', true);
64
65
        return redirect()->intended();
66
    }
67
68
    public function showTwoFactorForm(Request $request)
69
    {
70
        $twoFactorSettings = $this->loadSettings($request->user());
71
72
        // don't allow visiting this page if not needed
73
        if (empty($twoFactorSettings) || ! Config::get('twofactor') || session('twofactor')) {
74
            return redirect()->intended();
75
        }
76
77
        $errors = [];
78
79
        // lockout the user if there are too many failures
80
        if (isset($twoFactorSettings['fails']) && $twoFactorSettings['fails'] >= 3) {
81
            $lockout_time = Config::get('twofactor_lock', 0);
82
83
            if (! $lockout_time) {
84
                $errors['lockout'] = __('Too many two-factor failures, please contact administrator.');
85
            } elseif ((time() - $twoFactorSettings['last']) < $lockout_time) {
86
                $errors['lockout'] = __('Too many two-factor failures, please wait :time seconds', ['time' => $lockout_time]);
87
            }
88
        }
89
90
        return view('auth.2fa')->with([
91
            'key' => $twoFactorSettings['key'],
92
            'uri' => TwoFactor::generateUri($request->user()->username, $twoFactorSettings['key'], $twoFactorSettings['counter'] !== false),
93
        ])->withErrors($errors);
94
    }
95
96
    /**
97
     * Show the form for creating a new resource.
98
     *
99
     * @param  Request  $request
100
     * @return \Illuminate\Http\RedirectResponse.
0 ignored issues
show
The type Illuminate\Http\RedirectResponse. was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
101
     */
102
    public function create(Request $request)
103
    {
104
        $this->validate($request, [
105
            'twofactor' => Rule::in('time', 'counter'),
106
        ]);
107
108
        $key = TwoFactor::genKey();
109
110
        // assume time based
111
        $settings = [
112
            'key' => $key,
113
            'fails' => 0,
114
            'last' => 0,
115
            'counter' => $request->get('twofactortype') == 'counter' ? 0 : false,
116
        ];
117
118
        Session::put('twofactoradd', $settings);
119
120
        return redirect()->intended();
121
    }
122
123
    /**
124
     * Remove the specified resource from storage.
125
     *
126
     * @param  Request  $request
127
     * @return \Illuminate\Http\RedirectResponse.
128
     */
129
    public function destroy(Request $request)
130
    {
131
        $request->session()->put('twofactorremove', true);
132
        $request->session()->forget('twofactor');
133
134
        return redirect()->intended();
135
    }
136
137
    /**
138
     * Remove the specified resource from storage.
139
     *
140
     * @param  Request  $request
141
     * @return \Illuminate\Http\RedirectResponse.
142
     */
143
    public function cancelAdd(Request $request)
144
    {
145
        $request->session()->forget('twofactoradd');
146
147
        return redirect()->intended();
148
    }
149
150
    /**
151
     * @param  User  $user
152
     * @param  int  $token
153
     * @return true
154
     *
155
     * @throws AuthenticationException
156
     */
157
    private function checkToken($user, $token)
158
    {
159
        if (! $token) {
160
            throw new AuthenticationException(__('No Two-Factor Token entered.'));
161
        }
162
163
        // check if this is new
164
        $twoFactorSettings = $this->loadSettings($user);
165
166
        if (empty($twoFactorSettings)) {
167
            throw new AuthenticationException(__('No Two-Factor settings, how did you get here?'));
168
        }
169
170
        if (($server_count = TwoFactor::verifyHOTP($twoFactorSettings['key'], $token, $twoFactorSettings['counter'])) === false) {
171
            if (isset($twoFactorSettings['fails'])) {
172
                $twoFactorSettings['fails']++;
173
            } else {
174
                $twoFactorSettings['fails'] = 1;
175
            }
176
            $twoFactorSettings['last'] = time();
177
            UserPref::setPref($user, 'twofactor', $twoFactorSettings);
178
            throw new AuthenticationException(__('Wrong Two-Factor Token.'));
179
        }
180
181
        // update counter
182
        if ($twoFactorSettings['counter'] !== false) {
183
            if ($server_count !== true && $server_count !== $twoFactorSettings['counter']) {
184
                $twoFactorSettings['counter'] = $server_count + 1;
185
            } else {
186
                $twoFactorSettings['counter']++;
187
            }
188
        }
189
190
        // success
191
        $twoFactorSettings['fails'] = 0;
192
        UserPref::setPref($user, 'twofactor', $twoFactorSettings);
193
194
        // notify if added
195
        if (Session::has('twofactoradd')) {
196
            Toastr::success(__('TwoFactor auth added.'));
197
            Session::forget('twofactoradd');
198
        }
199
200
        return true;
201
    }
202
203
    /**
204
     * @return mixed
205
     */
206
    private function loadSettings(User $user)
207
    {
208
        if (Session::has('twofactoradd')) {
209
            return Session::get('twofactoradd');
210
        }
211
212
        return UserPref::getPref($user, 'twofactor');
213
    }
214
}
215