summaryrefslogtreecommitdiff
path: root/plugins/auth_internal/init.php
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/auth_internal/init.php')
-rw-r--r--plugins/auth_internal/init.php205
1 files changed, 137 insertions, 68 deletions
diff --git a/plugins/auth_internal/init.php b/plugins/auth_internal/init.php
index 8200ddc02..bcba7970a 100644
--- a/plugins/auth_internal/init.php
+++ b/plugins/auth_internal/init.php
@@ -10,81 +10,99 @@ class Auth_Internal extends Plugin implements IAuthModule {
true);
}
- /* @var PluginHost $host */
- function init($host) {
+ /* @var PluginHost $host */
+ function init($host) {
$this->host = $host;
$this->pdo = Db::pdo();
$host->add_hook($host::HOOK_AUTH_USER, $this);
}
- function authenticate($login, $password) {
+ function authenticate($login, $password, $service = '') {
$pwd_hash1 = encrypt_password($password);
$pwd_hash2 = encrypt_password($password, $login);
$otp = $_REQUEST["otp"];
if (get_schema_version() > 96) {
- if (!defined('AUTH_DISABLE_OTP') || !AUTH_DISABLE_OTP) {
- $sth = $this->pdo->prepare("SELECT otp_enabled,salt FROM ttrss_users WHERE
- login = ?");
- $sth->execute([$login]);
+ $sth = $this->pdo->prepare("SELECT otp_enabled,salt FROM ttrss_users WHERE
+ login = ?");
+ $sth->execute([$login]);
- if ($row = $sth->fetch()) {
+ if ($row = $sth->fetch()) {
+ $otp_enabled = $row['otp_enabled'];
+
+ if ($otp_enabled) {
+
+ // only allow app password checking if OTP is enabled
+ if ($service && get_schema_version() > 138) {
+ return $this->check_app_password($login, $password, $service);
+ }
- $base32 = new \OTPHP\Base32();
-
- $otp_enabled = $row['otp_enabled'];
- $secret = $base32->encode(sha1($row['salt']));
-
- $topt = new \OTPHP\TOTP($secret);
- $otp_check = $topt->now();
-
- if ($otp_enabled) {
- if ($otp) {
- if ($otp != $otp_check) {
- return false;
- }
- } else {
- $return = urlencode($_REQUEST["return"]);
- ?>
- <!DOCTYPE html>
- <html>
- <head>
- <title>Tiny Tiny RSS</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- </head>
- <?php echo stylesheet_tag("css/default.css") ?>
- <body class="ttrss_utility otp">
- <h1><?php echo __("Authentication") ?></h1>
- <div class="content">
- <form action="public.php?return=<?php echo $return ?>"
- method="POST" class="otpform">
- <input type="hidden" name="op" value="login">
- <input type="hidden" name="login" value="<?php echo htmlspecialchars($login) ?>">
- <input type="hidden" name="password" value="<?php echo htmlspecialchars($password) ?>">
- <input type="hidden" name="bw_limit" value="<?php echo htmlspecialchars($_POST["bw_limit"]) ?>">
- <input type="hidden" name="remember_me" value="<?php echo htmlspecialchars($_POST["remember_me"]) ?>">
- <input type="hidden" name="profile" value="<?php echo htmlspecialchars($_POST["profile"]) ?>">
-
- <fieldset>
- <label><?php echo __("Please enter your one time password:") ?></label>
- <input autocomplete="off" size="6" name="otp" value=""/>
- <input type="submit" value="Continue"/>
- </fieldset>
- </form></div>
- <script type="text/javascript">
- document.forms[0].otp.focus();
- </script>
- <?php
- exit;
+ if ($otp) {
+ $base32 = new \OTPHP\Base32();
+
+ $secret = $base32->encode(mb_substr(sha1($row["salt"]), 0, 12), false);
+ $secret_legacy = $base32->encode(sha1($row["salt"]));
+
+ $totp = new \OTPHP\TOTP($secret);
+ $otp_check = $totp->now();
+
+ $totp_legacy = new \OTPHP\TOTP($secret_legacy);
+ $otp_check_legacy = $totp_legacy->now();
+
+ if ($otp != $otp_check && $otp != $otp_check_legacy) {
+ return false;
}
+ } else {
+ $return = urlencode($_REQUEST["return"]);
+ ?>
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <title>Tiny Tiny RSS</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ </head>
+ <?php echo stylesheet_tag("css/default.css") ?>
+ <body class="ttrss_utility otp">
+ <h1><?php echo __("Authentication") ?></h1>
+ <div class="content">
+ <form action="public.php?return=<?php echo $return ?>"
+ method="POST" class="otpform">
+ <input type="hidden" name="op" value="login">
+ <input type="hidden" name="login" value="<?php echo htmlspecialchars($login) ?>">
+ <input type="hidden" name="password" value="<?php echo htmlspecialchars($password) ?>">
+ <input type="hidden" name="bw_limit" value="<?php echo htmlspecialchars($_POST["bw_limit"]) ?>">
+ <input type="hidden" name="remember_me" value="<?php echo htmlspecialchars($_POST["remember_me"]) ?>">
+ <input type="hidden" name="profile" value="<?php echo htmlspecialchars($_POST["profile"]) ?>">
+
+ <fieldset>
+ <label><?php echo __("Please enter your one time password:") ?></label>
+ <input autocomplete="off" size="6" name="otp" value=""/>
+ <input type="submit" value="Continue"/>
+ </fieldset>
+ </form></div>
+ <script type="text/javascript">
+ document.forms[0].otp.focus();
+ </script>
+ <?php
+ exit;
}
}
}
}
+ // check app passwords first but allow regular password as a fallback for the time being
+ // if OTP is not enabled
+
+ if ($service && get_schema_version() > 138) {
+ $user_id = $this->check_app_password($login, $password, $service);
+
+ if ($user_id)
+ return $user_id;
+ }
+
if (get_schema_version() > 87) {
$sth = $this->pdo->prepare("SELECT salt FROM ttrss_users WHERE login = ?");
@@ -96,7 +114,7 @@ class Auth_Internal extends Plugin implements IAuthModule {
if ($salt == "") {
$sth = $this->pdo->prepare("SELECT id FROM ttrss_users WHERE
- login = ? AND (pwd_hash = ? OR pwd_hash = ?)");
+ login = ? AND (pwd_hash = ? OR pwd_hash = ?)");
$sth->execute([$login, $pwd_hash1, $pwd_hash2]);
@@ -111,7 +129,7 @@ class Auth_Internal extends Plugin implements IAuthModule {
$pwd_hash = encrypt_password($password, $salt, true);
$sth = $this->pdo->prepare("UPDATE ttrss_users SET
- pwd_hash = ?, salt = ? WHERE login = ?");
+ pwd_hash = ?, salt = ? WHERE login = ?");
$sth->execute([$pwd_hash, $salt, $login]);
@@ -125,8 +143,8 @@ class Auth_Internal extends Plugin implements IAuthModule {
$pwd_hash = encrypt_password($password, $salt, true);
$sth = $this->pdo->prepare("SELECT id
- FROM ttrss_users WHERE
- login = ? AND pwd_hash = ?");
+ FROM ttrss_users WHERE
+ login = ? AND pwd_hash = ?");
$sth->execute([$login, $pwd_hash]);
if ($row = $sth->fetch()) {
@@ -136,8 +154,8 @@ class Auth_Internal extends Plugin implements IAuthModule {
} else {
$sth = $this->pdo->prepare("SELECT id
- FROM ttrss_users WHERE
- login = ? AND (pwd_hash = ? OR pwd_hash = ?)");
+ FROM ttrss_users WHERE
+ login = ? AND (pwd_hash = ? OR pwd_hash = ?)");
$sth->execute([$login, $pwd_hash1, $pwd_hash2]);
@@ -147,22 +165,22 @@ class Auth_Internal extends Plugin implements IAuthModule {
}
} else {
$sth = $this->pdo->prepare("SELECT id
- FROM ttrss_users WHERE
- login = ? AND (pwd_hash = ? OR pwd_hash = ?)");
+ FROM ttrss_users WHERE
+ login = ? AND (pwd_hash = ? OR pwd_hash = ?)");
$sth->execute([$login, $pwd_hash1, $pwd_hash2]);
if ($row = $sth->fetch()) {
return $row['id'];
}
- }
+ }
return false;
}
function check_password($owner_uid, $password) {
- $sth = $this->pdo->prepare("SELECT salt,login FROM ttrss_users WHERE
+ $sth = $this->pdo->prepare("SELECT salt,login,otp_enabled FROM ttrss_users WHERE
id = ?");
$sth->execute([$owner_uid]);
@@ -176,7 +194,7 @@ class Auth_Internal extends Plugin implements IAuthModule {
$password_hash2 = encrypt_password($password, $login);
$sth = $this->pdo->prepare("SELECT id FROM ttrss_users WHERE
- id = ? AND (pwd_hash = ? OR pwd_hash = ?)");
+ id = ? AND (pwd_hash = ? OR pwd_hash = ?)");
$sth->execute([$owner_uid, $password_hash1, $password_hash2]);
@@ -186,7 +204,7 @@ class Auth_Internal extends Plugin implements IAuthModule {
$password_hash = encrypt_password($password, $salt, true);
$sth = $this->pdo->prepare("SELECT id FROM ttrss_users WHERE
- id = ? AND pwd_hash = ?");
+ id = ? AND pwd_hash = ?");
$sth->execute([$owner_uid, $password_hash]);
@@ -194,7 +212,7 @@ class Auth_Internal extends Plugin implements IAuthModule {
}
}
- return false;
+ return false;
}
function change_password($owner_uid, $old_password, $new_password) {
@@ -211,15 +229,66 @@ class Auth_Internal extends Plugin implements IAuthModule {
$_SESSION["pwd_hash"] = $new_password_hash;
+ $sth = $this->pdo->prepare("SELECT email, login FROM ttrss_users WHERE id = ?");
+ $sth->execute([$owner_uid]);
+
+ if ($row = $sth->fetch()) {
+ $mailer = new Mailer();
+
+ require_once "lib/MiniTemplator.class.php";
+
+ $tpl = new MiniTemplator;
+
+ $tpl->readTemplateFromFile("templates/password_change_template.txt");
+
+ $tpl->setVariable('LOGIN', $row["login"]);
+ $tpl->setVariable('TTRSS_HOST', SELF_URL_PATH);
+
+ $tpl->addBlock('message');
+
+ $tpl->generateOutputToString($message);
+
+ $mailer->mail(["to_name" => $row["login"],
+ "to_address" => $row["email"],
+ "subject" => "[tt-rss] Password change notification",
+ "message" => $message]);
+
+ }
+
return __("Password has been changed.");
} else {
return "ERROR: ".__('Old password is incorrect.');
}
}
+ private function check_app_password($login, $password, $service) {
+ $sth = $this->pdo->prepare("SELECT p.id, p.pwd_hash, u.id AS uid
+ FROM ttrss_app_passwords p, ttrss_users u
+ WHERE p.owner_uid = u.id AND u.login = ? AND service = ?");
+ $sth->execute([$login, $service]);
+
+ while ($row = $sth->fetch()) {
+ list ($algo, $hash, $salt) = explode(":", $row["pwd_hash"]);
+
+ if ($algo == "SSHA-512") {
+ $test_hash = hash('sha512', $salt . $password);
+
+ if ($test_hash == $hash) {
+ $usth = $this->pdo->prepare("UPDATE ttrss_app_passwords SET last_used = NOW() WHERE id = ?");
+ $usth->execute([$row['id']]);
+
+ return $row['uid'];
+ }
+ } else {
+ user_error("Got unknown algo of app password for user $login: $algo");
+ }
+ }
+
+ return false;
+ }
+
function api_version() {
return 2;
}
}
-?>