]> git.joonet.de Git - adminer.git/commitdiff
Add login-otp plugin
authorJakub Vrana <jakub@vrana.cz>
Thu, 22 Feb 2018 10:36:11 +0000 (11:36 +0100)
committerJakub Vrana <jakub@vrana.cz>
Thu, 22 Feb 2018 10:36:11 +0000 (11:36 +0100)
adminer/include/adminer.inc.php
editor/include/adminer.inc.php
plugins/login-otp.php [new file with mode: 0644]
plugins/plugin.php

index d2dc9ce33ed653aed6828f8e5c6066bc7d1592da..ba332f91058034d503de64734eb495c4a626d92c 100644 (file)
@@ -118,19 +118,25 @@ class Adminer {
        */
        function loginForm() {
                global $drivers;
-               ?>
-<table cellspacing="0">
-<tr><th><?php echo lang('System'); ?><td><?php echo html_select("auth[driver]", $drivers, DRIVER) . "\n"; ?>
-<tr><th><?php echo lang('Server'); ?><td><input name="auth[server]" value="<?php echo h(SERVER); ?>" title="hostname[:port]" placeholder="localhost" autocapitalize="off">
-<tr><th><?php echo lang('Username'); ?><td><input name="auth[username]" id="username" value="<?php echo h($_GET["username"]); ?>" autocapitalize="off">
-<tr><th><?php echo lang('Password'); ?><td><input type="password" name="auth[password]">
-<tr><th><?php echo lang('Database'); ?><td><input name="auth[db]" value="<?php echo h($_GET["db"]); ?>" autocapitalize="off">
-</table>
-<?php
-               echo script("focus(qs('#username'));"); 
+               echo "<table cellspacing='0'>\n";
+               echo $this->loginFormField('driver', '<tr><th>' . lang('System') . '<td>' . html_select("auth[driver]", $drivers, DRIVER) . "\n");
+               echo $this->loginFormField('server', '<tr><th>' . lang('Server') . '<td><input name="auth[server]" value="' . h(SERVER) . '" title="hostname[:port]" placeholder="localhost" autocapitalize="off">' . "\n");
+               echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td><input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocapitalize="off">' . script("focus(qs('#username'));"));
+               echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td><input type="password" name="auth[password]">' . "\n");
+               echo $this->loginFormField('db', '<tr><th>' . lang('Database') . '<td><input name="auth[db]" value="' . h($_GET["db"]) . '" autocapitalize="off">' . "\n");
+               echo "</table>\n";
                echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
                echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
        }
+       
+       /** Get login form field
+       * @param string
+       * @param string HTML
+       * @return string
+       */
+       function loginFormField($name, $default) {
+               return $default;
+       }
 
        /** Authorize the user
        * @param string
index c6820f07114744f2367eac274f538ef6e877e80b..9e37413025356ed39c8e54228018bc481e30803f 100644 (file)
@@ -71,17 +71,18 @@ class Adminer {
        }
 
        function loginForm() {
-               ?>
-<table cellspacing="0">
-<tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="auth[driver]" value="server"><input name="auth[username]" id="username" value="<?php echo h($_GET["username"]); ?>" autocapitalize="off">
-<tr><th><?php echo lang('Password'); ?><td><input type="password" name="auth[password]">
-</table>
-<?php
-               echo script("focus(qs('#username'));");
+               echo "<table cellspacing='0'>\n";
+               echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td><input type="hidden" name="auth[driver]" value="server"><input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocapitalize="off">' . script("focus(qs('#username'));"));
+               echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td><input type="password" name="auth[password]">' . "\n");
+               echo "</table>\n";
                echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
                echo checkbox("auth[permanent]", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
        }
 
+       function loginFormField($name, $default) {
+               return $default;
+       }
+
        function login($login, $password) {
                return true;
        }
diff --git a/plugins/login-otp.php b/plugins/login-otp.php
new file mode 100644 (file)
index 0000000..0b8dfe7
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+/** Require One-Time Password at login
+* You can generate the secret and install it into Google Authenticator e.g. with https://github.com/sonata-project/GoogleAuthenticator
+* @link https://www.adminer.org/plugins/#use
+* @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 {
+       /** @access protected */
+       var $secret;
+       
+       /** 
+       * @param string decoded secret, e.g. base32_decode("SECRET")
+       */
+       function __construct($secret) {
+               $this->secret = $secret;
+               if ($_POST["auth"]) {
+                       $_SESSION["otp"] = (string) $_POST["auth"]["otp"];
+               }
+       }
+       
+       function loginFormField($name, $default) {
+               if ($name == 'password') {
+                       return $default . "<tr><th><acronym title='One Time Password' lang='en'>OTP</acronym><td><input type='number' name='auth[otp]' value='" . h($_SESSION["otp"]) . "' size='6' autocomplete='off'>\n";
+               }
+       }
+
+       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)) {
+                                       restart_session();
+                                       unset($_SESSION["otp"]);
+                                       stop_session();
+                                       return;
+                               }
+                       }
+                       return 'Invalid OTP.';
+               }
+       }
+       
+       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;
+       }
+}
index e7b1df14e8f293e808b201c9791900c95d45124d..5a5af671e4bb56045e72d8ec9e5e06791ed6361a 100644 (file)
@@ -160,6 +160,11 @@ class AdminerPlugin extends Adminer {
                return $this->_applyPlugin(__FUNCTION__, $args);
        }
 
+       function loginFormField($name, $default) {
+               $args = func_get_args();
+               return $this->_applyPlugin(__FUNCTION__, $args);
+       }
+
        function login($login, $password) {
                $args = func_get_args();
                return $this->_applyPlugin(__FUNCTION__, $args);