Files
adminer/plugins/login-otp.php

54 lines
1.6 KiB
PHP
Raw Normal View History

2018-02-22 11:36:11 +01:00
<?php
/** Require One-Time Password at login
2021-02-10 18:49:22 +01:00
* @link https://www.adminer.org/plugins/otp/
2018-02-22 11:36:11 +01:00
* @author Jakub Vrana, https://www.vrana.cz/
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerLoginOtp {
2025-03-11 07:21:13 +01:00
protected $secret;
2025-02-21 13:53:18 +01:00
/**
2025-03-28 07:06:34 +01:00
* @param string $secret decoded secret, e.g. base64_decode("SECRET")
2018-02-22 11:36:11 +01:00
*/
function __construct(string $secret) {
2018-02-22 11:36:11 +01:00
$this->secret = $secret;
if ($_POST["auth"]) {
$_SESSION["otp"] = (string) $_POST["auth"]["otp"];
}
}
2025-02-21 13:53:18 +01:00
function loginFormField($name, $heading, $value) {
2018-02-22 11:36:11 +01:00
if ($name == 'password') {
2025-02-25 17:36:37 +01:00
return $heading . $value . "\n"
2018-02-22 11:39:09 +01:00
. "<tr><th><acronym title='One Time Password' lang='en'>OTP</acronym>"
2025-03-05 11:40:56 +01:00
. "<td><input type='number' name='auth[otp]' value='" . Adminer\h($_SESSION["otp"]) . "' size='6' autocomplete='one-time-code' inputmode='numeric' maxlength='6' pattern='\d{6}'>\n"
2018-02-22 11:39:09 +01:00
;
2018-02-22 11:36:11 +01:00
}
}
function login($login, $password) {
if (isset($_SESSION["otp"])) {
$timeSlot = floor(time() / 30);
foreach (array(0, -1, 1) as $skew) {
if ($_SESSION["otp"] == $this->getOtp($timeSlot + $skew)) {
2025-03-05 11:40:56 +01:00
Adminer\restart_session();
2018-02-22 11:36:11 +01:00
unset($_SESSION["otp"]);
2025-03-05 11:40:56 +01:00
Adminer\stop_session();
2018-02-22 11:36:11 +01:00
return;
}
}
return 'Invalid OTP.';
}
}
2025-02-21 13:53:18 +01:00
2018-02-22 11:36:11 +01:00
function getOtp($timeSlot) {
$data = str_pad(pack('N', $timeSlot), 8, "\0", STR_PAD_LEFT);
$hash = hash_hmac('sha1', $data, $this->secret, true);
$offset = ord(substr($hash, -1)) & 0xF;
$unpacked = unpack('N', substr($hash, $offset, 4));
return ($unpacked[1] & 0x7FFFFFFF) % 1e6;
}
}