1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* |
4
|
|
|
* 2FA extension for the phpBB Forum Software package. |
5
|
|
|
* |
6
|
|
|
* @copyright (c) 2015 Paul Sohier |
7
|
|
|
* @license GNU General Public License, version 2 (GPL-2.0) |
8
|
|
|
* |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace paul999\tfa\modules; |
12
|
|
|
|
13
|
|
|
use paul999\tfa\helper\registration_helper; |
14
|
|
|
use paul999\u2f\AuthenticationResponse; |
15
|
|
|
use paul999\u2f\Exceptions\U2fError; |
16
|
|
|
use paul999\u2f\SignRequest; |
17
|
|
|
use phpbb\db\driver\driver_interface; |
18
|
|
|
use phpbb\request\request_interface; |
19
|
|
|
use phpbb\template\template; |
20
|
|
|
use phpbb\user; |
21
|
|
|
use phpbrowscap\Browscap; |
22
|
|
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; |
23
|
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
24
|
|
|
|
25
|
|
|
class u2f implements module_interface |
26
|
|
|
{ |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var driver_interface |
30
|
|
|
*/ |
31
|
|
|
private $db; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var user |
35
|
|
|
*/ |
36
|
|
|
private $user; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @var request_interface |
40
|
|
|
*/ |
41
|
|
|
private $request; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @var template |
45
|
|
|
*/ |
46
|
|
|
private $template; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var string |
50
|
|
|
*/ |
51
|
|
|
private $registration_table; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @var string |
55
|
|
|
*/ |
56
|
|
|
private $root_path; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @var \paul999\u2f\U2F |
60
|
|
|
*/ |
61
|
|
|
private $u2f; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @var array |
65
|
|
|
*/ |
66
|
|
|
private $reg_data; |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* u2f constructor. |
70
|
|
|
* @param driver_interface $db |
71
|
|
|
* @param user $user |
72
|
|
|
* @param request_interface $request |
73
|
|
|
* @param template $template |
74
|
|
|
* @param string $registration_table |
75
|
|
|
* @param string $root_path |
76
|
|
|
*/ |
77
|
|
|
public function __construct(driver_interface $db, user $user, request_interface $request, template $template, $registration_table, $root_path) |
78
|
|
|
{ |
79
|
|
|
$this->db = $db; |
80
|
|
|
$this->user = $user; |
81
|
|
|
$this->request = $request; |
82
|
|
|
$this->template = $template; |
83
|
|
|
$this->root_path= $root_path; |
84
|
|
|
|
85
|
|
|
$this->registration_table = $registration_table; |
86
|
|
|
|
87
|
|
|
$this->u2f = new \paul999\u2f\U2F('https://' . $this->request->server('HTTP_HOST')); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Return if this module is enabled by the admin |
92
|
|
|
* (And all server requirements are met). |
93
|
|
|
* |
94
|
|
|
* Do not return false in case a specific user disabeld this module, |
95
|
|
|
* OR if the user is unable to use this specific module. |
96
|
|
|
* @return boolean |
97
|
|
|
*/ |
98
|
|
|
public function is_enabled() |
99
|
|
|
{ |
100
|
|
|
return true; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Check if the current user is able to use this module. |
105
|
|
|
* |
106
|
|
|
* This means that the user enabled it in the UCP, |
107
|
|
|
* And has it setup up correctly. |
108
|
|
|
* This method will be called during login, not during registration/ |
109
|
|
|
* |
110
|
|
|
* @param int $user_id |
111
|
|
|
* @return bool |
112
|
|
|
*/ |
113
|
|
|
public function is_usable($user_id) |
114
|
|
|
{ |
115
|
|
|
if (!$this->is_potentially_usable($user_id)) |
116
|
|
|
{ |
117
|
|
|
return false; |
118
|
|
|
} |
119
|
|
|
$sql = 'SELECT COUNT(registration_id) as reg_id |
120
|
|
|
FROM ' . $this->registration_table . ' |
121
|
|
|
WHERE |
122
|
|
|
user_id = ' . (int) $user_id; |
123
|
|
|
$result = $this->db->sql_query($sql); |
124
|
|
|
$row = $this->db->sql_fetchrow($result); |
125
|
|
|
$this->db->sql_freeresult($result); |
126
|
|
|
|
127
|
|
|
return $row && $row['reg_id'] > 0; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Check if the user can potentially use this. |
132
|
|
|
* This method is called at registration page. |
133
|
|
|
* |
134
|
|
|
* You can, for example, check if the current browser is suitable. |
135
|
|
|
* |
136
|
|
|
* @param int|boolean $user_id Use false to ignore user |
137
|
|
|
* @return bool |
138
|
|
|
*/ |
139
|
|
|
public function is_potentially_usable($user_id = false) |
140
|
|
|
{ |
141
|
|
|
$browsercap = new Browscap($this->root_path . 'cache/'); |
142
|
|
|
$info = $browsercap->getBrowser($this->request->server('HTTP_USER_AGENT')); |
143
|
|
|
return strtolower($info->Browser) === 'chrome' && $this->is_ssl(); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Check if the current session is secure. |
148
|
|
|
* |
149
|
|
|
* @return bool |
150
|
|
|
*/ |
151
|
|
|
private function is_ssl() |
152
|
|
|
{ |
153
|
|
|
$secure = $this->request->server('HTTPS'); |
154
|
|
|
if (!empty($secure)) |
155
|
|
|
{ |
156
|
|
|
return 'on' == strtolower($secure) || '1' == $secure; |
157
|
|
|
} |
158
|
|
|
else if ('443' == $this->request->server('SERVER_PORT')) |
159
|
|
|
{ |
160
|
|
|
return true; |
161
|
|
|
} |
162
|
|
|
return false; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Get the priority for this module. |
167
|
|
|
* A lower priority means more chance it gets selected as default option |
168
|
|
|
* |
169
|
|
|
* There can be only one module with a specific priority! |
170
|
|
|
* If there is already a module registered with this priority, |
171
|
|
|
* a Exception might be thrown |
172
|
|
|
* |
173
|
|
|
* @return int |
174
|
|
|
*/ |
175
|
|
|
public function get_priority() |
176
|
|
|
{ |
177
|
|
|
return 10; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Start of the login procedure. |
182
|
|
|
* @param int $user_id |
183
|
|
|
* @return void |
184
|
|
|
* @throws BadRequestHttpException |
185
|
|
|
*/ |
186
|
|
|
public function login_start($user_id) |
187
|
|
|
{ |
188
|
|
|
$registrations = json_encode($this->u2f->getAuthenticateData($this->getRegistrations($user_id)), JSON_UNESCAPED_SLASHES); |
189
|
|
|
|
190
|
|
|
$sql_ary = array( |
191
|
|
|
'u2f_request' => $registrations |
192
|
|
|
); |
193
|
|
|
|
194
|
|
|
$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' |
195
|
|
|
WHERE |
196
|
|
|
session_id = \'' . $this->db->sql_escape($this->user->data['session_id']) . '\' AND |
197
|
|
|
session_user_id = ' . (int) $this->user->data['user_id']; |
198
|
|
|
$this->db->sql_query($sql); |
199
|
|
|
$count = $this->db->sql_affectedrows(); |
200
|
|
|
|
201
|
|
|
if ($count != 1) |
202
|
|
|
{ |
203
|
|
|
if ($count > 1) |
204
|
|
|
{ |
205
|
|
|
// Reset sessions table. We had multiple sessions with same ID!!! |
206
|
|
|
$sql_ary['u2f_request'] = ''; |
207
|
|
|
$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' |
208
|
|
|
WHERE |
209
|
|
|
session_id = \'' . $this->db->sql_escape($this->user->data['session_id']) . '\' AND |
210
|
|
|
session_user_id = ' . (int) $this->user->data['user_id']; |
211
|
|
|
$this->db->sql_query($sql); |
212
|
|
|
} |
213
|
|
|
throw new BadRequestHttpException('TFA_UNABLE_TO_UPDATE_SESSION'); |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
$this->template->assign_var('U2F_REQ', $registrations); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Actual login procedure |
221
|
|
|
* @param int $user_id |
222
|
|
|
* @throws AccessDeniedHttpException |
223
|
|
|
*/ |
224
|
|
|
public function login($user_id) |
225
|
|
|
{ |
226
|
|
|
try |
227
|
|
|
{ |
228
|
|
|
$sql = 'SELECT u2f_request |
229
|
|
|
FROM ' . SESSIONS_TABLE . ' |
230
|
|
|
WHERE |
231
|
|
|
session_id = \'' . $this->db->sql_escape($this->user->data['session_id']) . '\' AND |
232
|
|
|
session_user_id = ' . (int) $this->user->data['user_id']; |
233
|
|
|
$result = $this->db->sql_query($sql); |
234
|
|
|
$row = $this->db->sql_fetchrow($result); |
235
|
|
|
$this->db->sql_freeresult($result); |
236
|
|
|
|
237
|
|
|
if (!$row || empty($row['u2f_request'])) |
238
|
|
|
{ |
239
|
|
|
throw new AccessDeniedHttpException($this->user->lang('TFA_NO_ACCESS')); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
$response = json_decode(htmlspecialchars_decode($this->request->variable('authenticate', ''))); |
243
|
|
|
|
244
|
|
|
if (property_exists($response, 'errorCode')) |
245
|
|
|
{ |
246
|
|
|
if ($response->errorCode == 4) // errorCode 4 means that this device wasn't registered |
247
|
|
|
{ |
248
|
|
|
throw new AccessDeniedHttpException($this->user->lang('TFA_NOT_REGISTERED')); |
249
|
|
|
} |
250
|
|
|
throw new BadRequestHttpException($this->user->lang('TFA_SOMETHING_WENT_WRONG')); |
251
|
|
|
} |
252
|
|
|
$result = new AuthenticationResponse($response->signatureData, $response->clientData, $response->keyHandle, $response->errorCode); |
253
|
|
|
|
254
|
|
|
/** @var \paul999\tfa\helper\registration_helper $reg */ |
255
|
|
|
$reg = $this->u2f->doAuthenticate($this->convertRequests(json_decode($row['u2f_request'])), $this->getRegistrations($user_id), $result); |
256
|
|
|
$sql_ary = array( |
257
|
|
|
'counter' => $reg->getCounter(), |
258
|
|
|
'last_used' => time(), |
259
|
|
|
); |
260
|
|
|
|
261
|
|
|
$sql = 'UPDATE ' . $this->registration_table . ' SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' WHERE registration_id = ' . (int) $reg->getId(); |
262
|
|
|
$this->db->sql_query($sql); |
263
|
|
|
} |
264
|
|
|
catch (U2fError $error) |
265
|
|
|
{ |
266
|
|
|
$this->createError($error); |
267
|
|
|
} |
268
|
|
|
catch (\InvalidArgumentException $invalid) |
269
|
|
|
{ |
270
|
|
|
throw new BadRequestHttpException($this->user->lang('TFA_SOMETHING_WENT_WRONG') . '<br />' . $invalid->getMessage(), $invalid); |
271
|
|
|
} |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* @param array $requests |
276
|
|
|
* @return array |
277
|
|
|
*/ |
278
|
|
|
private function convertRequests($requests) |
279
|
|
|
{ |
280
|
|
|
$result = array(); |
281
|
|
|
foreach ($requests as $request) |
282
|
|
|
{ |
283
|
|
|
$result[] = new SignRequest($request->challenge, $request->keyHandle, $request->appId); |
284
|
|
|
} |
285
|
|
|
return $result; |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
/** |
289
|
|
|
* Start of registration |
290
|
|
|
* @return string |
291
|
|
|
*/ |
292
|
|
|
public function register_start() |
293
|
|
|
{ |
294
|
|
|
$data = $this->u2f->getRegisterData($this->reg_data); |
295
|
|
|
|
296
|
|
|
$sql_ary = array( |
297
|
|
|
'u2f_request' => json_encode($data[0], JSON_UNESCAPED_SLASHES), |
298
|
|
|
); |
299
|
|
|
|
300
|
|
|
$count = $this->update_session($sql_ary); |
301
|
|
|
|
302
|
|
|
if ($count == 0) |
303
|
|
|
{ |
304
|
|
|
trigger_error('TFA_UNABLE_TO_UPDATE_SESSION'); |
305
|
|
|
} |
306
|
|
|
else if ($count > 1) |
307
|
|
|
{ |
308
|
|
|
// Reset sessions table. We had multiple sessions with same ID!!! |
309
|
|
|
$sql_ary['u2f_request'] = ''; |
310
|
|
|
$this->update_session($sql_ary); |
311
|
|
|
|
312
|
|
|
trigger_error('TFA_UNABLE_TO_UPDATE_SESSION'); |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
$this->template->assign_vars(array( |
316
|
|
|
'U2F_REG' => true, |
317
|
|
|
'U2F_SIGN_REQUEST' => json_encode($data[0], JSON_UNESCAPED_SLASHES), |
318
|
|
|
'U2F_SIGN' => json_encode($data[1], JSON_UNESCAPED_SLASHES), |
319
|
|
|
)); |
320
|
|
|
|
321
|
|
|
return 'tfa_u2f_ucp_new'; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Actual registration |
326
|
|
|
* @return void |
327
|
|
|
* @throws BadRequestHttpException |
328
|
|
|
*/ |
329
|
|
|
public function register() |
330
|
|
|
{ |
331
|
|
|
try |
332
|
|
|
{ |
333
|
|
|
$reg = $this->u2f->doRegister(json_decode($this->user->data['u2f_request']), json_decode(htmlspecialchars_decode($this->request->variable('register', '')))); |
334
|
|
|
|
335
|
|
|
$sql_ary = array( |
336
|
|
|
'user_id' => $this->user->data['user_id'], |
337
|
|
|
'key_handle' => $reg->getKeyHandle(), |
338
|
|
|
'public_key' => $reg->getPublicKey(), |
339
|
|
|
'certificate' => $reg->getCertificate(), |
340
|
|
|
'counter' => ($reg->getCounter() > 0) ? $reg->getCounter() : 0, |
341
|
|
|
'registered' => time(), |
342
|
|
|
'last_used' => time(), |
343
|
|
|
); |
344
|
|
|
|
345
|
|
|
$sql = 'INSERT INTO ' . $this->registration_table . ' ' . $this->db->sql_build_array('INSERT', $sql_ary); |
346
|
|
|
$this->db->sql_query($sql); |
347
|
|
|
|
348
|
|
|
$sql_ary = array( |
349
|
|
|
'u2f_request' => '', |
350
|
|
|
); |
351
|
|
|
|
352
|
|
|
$this->update_session($sql_ary); |
353
|
|
|
} |
354
|
|
|
catch (U2fError $err) |
355
|
|
|
{ |
356
|
|
|
$this->createError($err); |
357
|
|
|
} |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* This method is called to show the UCP page. |
362
|
|
|
* You can assign template variables to the template, or do anything else here. |
363
|
|
|
*/ |
364
|
|
|
public function show_ucp() |
365
|
|
|
{ |
366
|
|
|
$sql = 'SELECT * |
367
|
|
|
FROM ' . $this->registration_table . ' |
368
|
|
|
WHERE user_id = ' . (int) $this->user->data['user_id'] . ' |
369
|
|
|
ORDER BY registration_id ASC'; |
370
|
|
|
|
371
|
|
|
$result = $this->db->sql_query($sql); |
372
|
|
|
//$this->reg_data = array(); |
|
|
|
|
373
|
|
|
|
374
|
|
|
while ($row = $this->db->sql_fetchrow($result)) |
375
|
|
|
{ |
376
|
|
|
$this->template->assign_block_vars('keys', array( |
377
|
|
|
'CLASS' => $this->get_name(), |
378
|
|
|
'ID' => $row['registration_id'], |
379
|
|
|
'REGISTERED' => $this->user->format_date($row['registered']), |
380
|
|
|
'LAST_USED' => $this->user->format_date($row['last_used']), |
381
|
|
|
)); |
382
|
|
|
/* |
|
|
|
|
383
|
|
|
$reg = new registration_helper(); |
384
|
|
|
$reg->setCounter($row['counter']); |
385
|
|
|
$reg->setCertificate($row['certificate']); |
386
|
|
|
$reg->setKeyHandle($row['key_handle']); |
387
|
|
|
$reg->setPublicKey($row['public_key']); |
388
|
|
|
$reg->setId($row['registration_id']); |
389
|
|
|
|
390
|
|
|
$this->reg_data[] = $reg; */ |
391
|
|
|
} |
392
|
|
|
$this->db->sql_freeresult($result); |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* Delete a specific row from the UCP. |
397
|
|
|
* The data is based on the data provided in show_ucp. |
398
|
|
|
* @param int $key |
399
|
|
|
* @return void |
400
|
|
|
*/ |
401
|
|
|
public function delete($key) |
402
|
|
|
{ |
403
|
|
|
$sql = 'DELETE FROM ' . $this->registration_table . ' |
404
|
|
|
WHERE user_id = ' . (int) $this->user->data['user_id'] . ' |
405
|
|
|
AND registration_id =' . (int) $key; |
406
|
|
|
|
407
|
|
|
$this->db->sql_query($sql); |
408
|
|
|
|
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
/** |
412
|
|
|
* If this module can add new keys (Or other things) |
413
|
|
|
* |
414
|
|
|
* @return boolean |
415
|
|
|
*/ |
416
|
|
|
public function can_register() |
417
|
|
|
{ |
418
|
|
|
return $this->is_potentially_usable(false); |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
/** |
422
|
|
|
* Return the name of the current module |
423
|
|
|
* This is for internal use only |
424
|
|
|
* @return string |
425
|
|
|
*/ |
426
|
|
|
public function get_name() |
427
|
|
|
{ |
428
|
|
|
return 'u2f'; |
429
|
|
|
} |
430
|
|
|
|
431
|
|
|
/** |
432
|
|
|
* Get a language key for this specific module. |
433
|
|
|
* @return string |
434
|
|
|
*/ |
435
|
|
|
public function get_translatable_name() |
436
|
|
|
{ |
437
|
|
|
return 'MODULE_U2F'; |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
/** |
441
|
|
|
* Select all registration objects from the database |
442
|
|
|
* @param integer $user_id |
443
|
|
|
* @return array |
444
|
|
|
*/ |
445
|
|
|
private function getRegistrations($user_id) |
446
|
|
|
{ |
447
|
|
|
$sql = 'SELECT * FROM ' . $this->registration_table . ' WHERE user_id = ' . (int) $user_id; |
448
|
|
|
$result = $this->db->sql_query($sql); |
449
|
|
|
$rows = array(); |
450
|
|
|
|
451
|
|
|
while ($row = $this->db->sql_fetchrow($result)) |
452
|
|
|
{ |
453
|
|
|
$reg = new registration_helper(); |
454
|
|
|
$reg->setCounter($row['counter']); |
455
|
|
|
$reg->setCertificate($row['certificate']); |
456
|
|
|
$reg->setKeyHandle($row['key_handle']); |
457
|
|
|
$reg->setPublicKey($row['public_key']); |
458
|
|
|
$reg->setId($row['registration_id']); |
459
|
|
|
|
460
|
|
|
$rows[] = $reg; |
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
$this->db->sql_freeresult($result); |
464
|
|
|
return $rows; |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
/** |
468
|
|
|
* @param U2fError $error |
469
|
|
|
* @throws BadRequestHttpException |
470
|
|
|
*/ |
471
|
|
|
private function createError(U2fError $error) |
472
|
|
|
{ |
473
|
|
|
switch ($error->getCode()) |
474
|
|
|
{ |
475
|
|
|
/** Error for the authentication message not matching any outstanding |
476
|
|
|
* authentication request */ |
477
|
|
|
case U2fError::ERR_NO_MATCHING_REQUEST: |
478
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_NO_MATCHING_REQUEST'), $error); |
479
|
|
|
|
480
|
|
|
/** Error for the authentication message not matching any registration */ |
481
|
|
|
case U2fError::ERR_NO_MATCHING_REGISTRATION: |
482
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_NO_MATCHING_REGISTRATION'), $error); |
483
|
|
|
|
484
|
|
|
/** Error for the signature on the authentication message not verifying with |
485
|
|
|
* the correct key */ |
486
|
|
|
case U2fError::ERR_AUTHENTICATION_FAILURE: |
487
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_AUTHENTICATION_FAILURE'), $error); |
488
|
|
|
|
489
|
|
|
/** Error for the challenge in the registration message not matching the |
490
|
|
|
* registration challenge */ |
491
|
|
|
case U2fError::ERR_UNMATCHED_CHALLENGE: |
492
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_UNMATCHED_CHALLENGE'), $error); |
493
|
|
|
|
494
|
|
|
/** Error for the attestation signature on the registration message not |
495
|
|
|
* verifying */ |
496
|
|
|
case U2fError::ERR_ATTESTATION_SIGNATURE: |
497
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_ATTESTATION_SIGNATURE'), $error); |
498
|
|
|
|
499
|
|
|
/** Error for the attestation verification not verifying */ |
500
|
|
|
case U2fError::ERR_ATTESTATION_VERIFICATION: |
501
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_ATTESTATION_VERIFICATION'), $error); |
502
|
|
|
|
503
|
|
|
/** Error for not getting good random from the system */ |
504
|
|
|
case U2fError::ERR_BAD_RANDOM: |
505
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_BAD_RANDOM'), $error); |
506
|
|
|
|
507
|
|
|
/** Error when the counter is lower than expected */ |
508
|
|
|
case U2fError::ERR_COUNTER_TOO_LOW: |
509
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_COUNTER_TOO_LOW'), $error); |
510
|
|
|
|
511
|
|
|
/** Error decoding public key */ |
512
|
|
|
case U2fError::ERR_PUBKEY_DECODE: |
513
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_PUBKEY_DECODE'), $error); |
514
|
|
|
|
515
|
|
|
/** Error user-agent returned error */ |
516
|
|
|
case U2fError::ERR_BAD_UA_RETURNING: |
517
|
|
|
throw new BadRequestHttpException($this->user->lang('ERR_BAD_UA_RETURNING'), $error); |
518
|
|
|
|
519
|
|
|
/** Error old OpenSSL version */ |
520
|
|
|
case U2fError::ERR_OLD_OPENSSL: |
521
|
|
|
throw new BadRequestHttpException(sprintf($this->user->lang('ERR_OLD_OPENSSL'), OPENSSL_VERSION_TEXT), $error); |
522
|
|
|
|
523
|
|
|
default: |
524
|
|
|
throw new BadRequestHttpException($this->user->lang('TFA_UNKNOWN_ERROR'), $error); |
525
|
|
|
} |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
/** |
529
|
|
|
* Update the session with new TFA data |
530
|
|
|
* @param $sql_ary |
531
|
|
|
* @return int |
532
|
|
|
*/ |
533
|
|
|
private function update_session($sql_ary) |
534
|
|
|
{ |
535
|
|
|
$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' |
536
|
|
|
WHERE |
537
|
|
|
session_id = \'' . $this->db->sql_escape($this->user->data['session_id']) . '\' AND |
538
|
|
|
session_user_id = ' . (int) $this->user->data['user_id']; |
539
|
|
|
$this->db->sql_query($sql); |
540
|
|
|
|
541
|
|
|
return $this->db->sql_affectedrows(); |
542
|
|
|
} |
543
|
|
|
} |
544
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.