From 2cd159e2cefaecb54233686cd949aac4d70b9320 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 5 Mar 2021 17:40:17 +0300 Subject: [PATCH] use separate database column for OTP secrets (migrate previous format if needed) --- classes/pref/prefs.php | 7 +------ classes/pref/users.php | 5 +++++ classes/userhelper.php | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index eae67fbac..854b70549 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -352,10 +352,6 @@ class Pref_Prefs extends Handler_Protected { } - -
@@ -458,7 +454,6 @@ class Pref_Prefs extends Handler_Protected { } else { - print_warning("You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP."); print_notice("You will need to generate app passwords for the API clients if you enable OTP."); if (function_exists("imagecreatefromstring")) { @@ -479,7 +474,7 @@ class Pref_Prefs extends Handler_Protected {
- +
diff --git a/classes/pref/users.php b/classes/pref/users.php index cac0dca7c..068166863 100644 --- a/classes/pref/users.php +++ b/classes/pref/users.php @@ -119,6 +119,11 @@ class Pref_Users extends Handler_Administrative { $user->email = clean($_REQUEST["email"]); $user->otp_enabled = checkbox_to_sql_bool($_REQUEST["otp_enabled"]); + // force new OTP secret when next enabled + if (Config::get_schema_version() >= 143 && !$user->otp_enabled) { + $user->otp_secret = null; + } + $user->save(); } diff --git a/classes/userhelper.php b/classes/userhelper.php index 2bb83a02a..ce26e6c71 100644 --- a/classes/userhelper.php +++ b/classes/userhelper.php @@ -240,6 +240,12 @@ class UserHelper { if ($user) { $user->otp_enabled = false; + + // force new OTP secret when next enabled + if (Config::get_schema_version() >= 143) { + $user->otp_secret = null; + } + $user->save(); return true; @@ -281,8 +287,32 @@ class UserHelper { $user = ORM::for_table('ttrss_users')->find_one($owner_uid); if ($user) { - if (!$user->otp_enabled || $show_if_enabled) - return \ParagonIE\ConstantTime\Base32::encodeUpperUnpadded(mb_substr(sha1($user->salt), 0, 12)); + + $salt_based_secret = mb_substr(sha1($user->salt), 0, 12); + + if (Config::get_schema_version() >= 143) { + $secret = $user->otp_secret; + + if (empty($secret)) { + + /* migrate secret if OTP is already enabled, otherwise make a new one */ + if ($user->otp_enabled) { + $user->otp_secret = $salt_based_secret; + } else { + $user->otp_secret = bin2hex(get_random_bytes(6)); + } + + $user->save(); + + $secret = $user->otp_secret; + } + } else { + $secret = $salt_based_secret; + } + + if (!$user->otp_enabled || $show_if_enabled) { + return \ParagonIE\ConstantTime\Base32::encodeUpperUnpadded($secret); + } } return null;