ports/mail/roundcube-twofactor_gauthenticator/files/patch-Issue165
Bernard Spil c88031b675 mail/roundcube-twofactor_gauthenticator: Fix PHP 8.1 compat
* Mark 8.1 compatible for Roundcube 1.6.0
 * Add patch [1]

[1]: https://github.com/alexandregz/twofactor_gauthenticator/pull/165

PR:		265653
2022-09-18 10:29:27 +00:00

781 lines
38 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff -ruN 2FA_qr_code.js.orig 2FA_qr_code.js
--- 2FA_qr_code.js.orig 2022-04-04 01:10:32.000000000 +0200
+++ 2FA_qr_code.js 2022-08-26 10:13:19.458764000 +0200
@@ -7,9 +7,9 @@
text: url_qr_code_values,
width: 200,
height: 200,
- colorDark : "#000000",
+ colorDark : rcmail.env.qr_image_colour,
colorLight : "#ffffff",
- correctLevel : QRCode.CorrectLevel.M // like charts.googleapis.com
+ correctLevel : QRCode.CorrectLevel.M //like charts.googleapis.com
});
$('#2FA_qr_code').prop('title', ''); // enjoy the silence (qrcode.js uses text to set title)
diff -ruN config.inc.php.dist.orig config.inc.php.dist
--- config.inc.php.dist.orig 2022-04-04 01:10:32.000000000 +0200
+++ config.inc.php.dist 2022-08-29 15:50:06.293339000 +0200
@@ -8,12 +8,17 @@
// Admin can disable saving devices for all users (paranoid mode)
// Default: allow saving devices (true)
-$rcmail_config['allow_save_device_30days'] = true;
+$rcmail_config['allow_save_device_xdays'] = true;
+$rcmail_config['save_device_xdays'] = 30;
+
+$rcmail_config['qr_image_colour'] = "#000000";
+
// Make the 2-step field a masked password input type
// Default: form field will be text (false)
$rcmail_config['twofactor_formfield_as_password'] = false;
+$rcmail_config['enable_ua2fa'] = false;
// Users allowed to use plugin (IMPORTANT: other users DON'T have plugin activated)
$rcmail_config['users_allowed_2FA'] = array('ale.*@tereborace.com', 'administrator@tereborace.com');
diff -ruN localization/cs_CZ.inc.orig localization/cs_CZ.inc
--- localization/cs_CZ.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/cs_CZ.inc 2022-09-17 15:26:27.718498000 +0200
@@ -31,7 +31,7 @@
$labels['code_ok'] = 'Správný kód';
$labels['code_ko'] = 'Špatný kód';
-$labels['dont_ask_me_30days'] = 'Neptat se na tomto stroji znovu na kódy následujích 30 dnů';
+$labels['dont_ask_me_xdays'] = 'Neptat se na tomto stroji znovu na kódy následujích % dnů';
$labels['check_code_to_activate'] = 'Pro uložení, naskenujte QR kód a vložte následně vygenerovaný dvoufázový kód níže.';
diff -ruN localization/da_DK.inc ./localization/da_DK.inc
--- localization/da_DK.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/da_DK.inc 2022-09-17 15:26:27.718746000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Koden er OK';
$labels['code_ko'] = 'Koden er forkert';
-$labels['dont_ask_me_30days'] = 'Spørg mig ikke igen de næste 30 dage på denne computer';
+$labels['dont_ask_me_xdays'] = 'Spørg mig ikke igen de næste % dage på denne computer';
$labels['check_code_to_activate'] = 'For at gemme, scan QR koden og indtast verificeringskoden nederst.';
diff -ruN localization/de_DE.inc.orig localization/de_DE.inc
--- localization/de_DE.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/de_DE.inc 2022-09-17 15:26:27.718988000 +0200
@@ -31,7 +31,7 @@
$labels['code_ok'] = 'Code OK';
$labels['code_ko'] = 'Falscher Code';
-$labels['dont_ask_me_30days'] = 'Nicht erneut nach dem Code fragen für die nächsten 30 Tage';
+$labels['dont_ask_me_xdays'] = 'Nicht erneut nach dem Code fragen für die nächsten % Tage';
$labels['check_code_to_activate'] = 'Um zu speichern, muss mindestens 1 Code zuvor geprüpft werden';
diff -ruN localization/en_UK.inci.orig localization/en_UK.inc
--- localization/en_UK.inc.orig 1970-01-01 01:00:00.000000000 +0100
+++ localization/en_UK.inc 2022-08-29 16:54:34.478291000 +0200
@@ -0,0 +1,41 @@
+<?php
+// Labels used for different portions of the plugin
+$labels = array();
+$labels['activate'] = 'Activate';
+$labels['twofactor_gauthenticator'] = 'Two-Factor Authentication';
+$labels['code'] = 'Google Authenticator Code';
+
+$labels['two_step_verification_form'] = '2-Factor Authentication Code:';
+
+$labels['secret'] = 'Secret';
+$labels['qr_code'] = 'QR Code';
+$labels['msg_infor'] = 'You can scan this QR code containing the 2-Factor settings using a TOTP compatible app such as <a href="https://github.com/google/google-authenticator" target="_blank">google-authenticator</a>';
+
+$labels['show_secret'] = 'Show secret';
+$labels['hide_secret'] = 'Hide secret';
+$labels['create_secret'] = 'Create secret';
+
+$labels['show_qr_code'] = 'Show QR Code';
+$labels['hide_qr_code'] = 'Hide QR Code';
+
+$labels['recovery_codes'] = 'Recovery codes';
+$labels['show_recovery_codes'] = 'Show recovery codes';
+$labels['hide_recovery_codes'] = 'Hide recovery codes';
+
+$labels['setup_all_fields'] = 'Fill all fields (make sure you click save to store your settings)';
+
+$labels['enrollment_dialog_title'] = '2-Factor authentication enrollment';
+$labels['enrollment_dialog_msg'] = '<strong>2-Factor authentication codes</strong> are required for increased security, please configure them now.';
+
+$labels['check_code'] = 'Check code';
+$labels['code_ok'] = 'Code OK';
+$labels['code_ko'] = 'Incorrect code';
+
+$labels['dont_ask_me_xdays'] = 'Don&#39;t ask me codes again on this computer for % days';
+
+$labels['check_code_to_activate'] = 'To save, please scan the QR Code and enter the current 2-Factor code below.';
+
+// Messages used for the different portions of the plugin
+$messages = array();
+$messages['successfully_saved'] = '2-Factor authentication settings saved successfully.';
+
diff -ruN localization/en_US.inc.orig localization/en_US.inc
--- localization/en_US.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/en_US.inc 2022-08-29 16:54:34.478453000 +0200
@@ -2,7 +2,7 @@
// Labels used for different portions of the plugin
$labels = array();
$labels['activate'] = 'Activate';
-$labels['twofactor_gauthenticator'] = '2-Factor Authentication';
+$labels['twofactor_gauthenticator'] = 'Two-Factor Authentication';
$labels['code'] = 'Google Authenticator Code';
$labels['two_step_verification_form'] = '2-Factor Authentication Code:';
@@ -31,11 +31,10 @@
$labels['code_ok'] = 'Code OK';
$labels['code_ko'] = 'Incorrect code';
-$labels['dont_ask_me_30days'] = 'Don&#39;t ask me codes again on this computer for 30 days';
+$labels['dont_ask_me_xdays'] = 'Don&#39;t ask me codes again on this computer for % days';
$labels['check_code_to_activate'] = 'To save, please scan the QR Code and enter the current 2-Factor code below.';
// Messages used for the different portions of the plugin
$messages = array();
$messages['successfully_saved'] = '2-Factor authentication settings saved successfully.';
-
diff -ruN localization/es_AR.inc.orig localization/es_AR.inc
--- localization/es_AR.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/es_AR.inc 2022-09-17 15:26:27.719230000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Código correcto';
$labels['code_ko'] = 'Código incorrecto';
-$labels['dont_ask_me_30days'] = 'No solicitar códigos en esta computadora durante 30 días';
+$labels['dont_ask_me_xdays'] = 'No solicitar códigos en esta computadora durante % días';
$labels['check_code_to_activate'] = 'Para poder guardar, antes debe de chequearse algún código';
diff -ruN localization/es_ES.inc.orig localization/es_ES.inc
--- localization/es_ES.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/es_ES.inc 2022-09-17 15:26:27.719477000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Codigo correcto';
$labels['code_ko'] = 'Codigo erróneo';
-$labels['dont_ask_me_30days'] = 'No solicitar códigos en este ordenador durante 30 días';
+$labels['dont_ask_me_xdays'] = 'No solicitar códigos en este ordenador durante % días';
$labels['check_code_to_activate'] = 'Para poder guardar, antes debe de comprobarse algún código';
diff -ruN localization/fr_FR.inc.orig ./localization/fr_FR.inc
--- localization/fr_FR.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/fr_FR.inc 2022-09-17 15:26:27.719708000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Code OK';
$labels['code_ko'] = 'Code incorrect';
-$labels['dont_ask_me_30days'] = 'Ne plus me demander de codes pour 30 jours.';
+$labels['dont_ask_me_xdays'] = 'Ne plus me demander de codes pour % jours.';
$labels['check_code_to_activate'] = 'Pour enregistrer, scannez le QR Code et entrez un premier code de vérification ci-dessous.';
diff -ruN localization/gl_ES.inc.orig localization/gl_ES.inc
--- localization/gl_ES.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/gl_ES.inc 2022-09-17 15:26:27.719937000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Codigo correcto';
$labels['code_ko'] = 'Codigo erróneo';
-$labels['dont_ask_me_30days'] = 'Non solicitar códigos nesta computadora durante 30 días';
+$labels['dont_ask_me_xdays'] = 'Non solicitar códigos nesta computadora durante % días';
$labels['check_code_to_activate'] = 'Para poder gardar, antes debese ter comprobado a validez dalgún código';
diff -ruN localization/he_IL.inc.orig localization/he_IL.inc
--- localization/he_IL.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/he_IL.inc 2022-09-17 15:26:27.720169000 +0200
@@ -22,7 +22,7 @@
$labels['check_code'] = 'בדוק קוד';
$labels['code_ok'] = 'הקוד תקין';
$labels['code_ko'] = 'הקוד לא תקין';
-$labels['dont_ask_me_30days'] = 'אל תבקש ממני קודים אלו שוב במחשב זה למשך 30 יום';
+$labels['dont_ask_me_xdays'] = 'אל תבקש ממני קודים אלו שוב במחשב זה למשך % יום';
$labels['check_code_to_activate'] = 'כדי לשמור, אנא סרוק את קוד ה-QR והכנס למטה את קוד האימות הדו-שלבי הנוכחי.';
// Messages used for the different portions of the plugin
$messages = array();
diff -ruN localization/hu_HU.inc.orig localization/hu_HU.inc
--- localization/hu_HU.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/hu_HU.inc 2022-09-17 15:26:27.720411000 +0200
@@ -31,7 +31,7 @@
$labels['code_ok'] = 'Helyes kód';
$labels['code_ko'] = 'Hibás kód';
-$labels['dont_ask_me_30days'] = 'Ne kérdezze tőlem a kódot a következő 30 napban';
+$labels['dont_ask_me_xdays'] = 'Ne kérdezze tőlem a kódot a következő % napban';
$labels['check_code_to_activate'] = 'A mentéshez kérem olvassa be a QR-kódot és írja be a kapott kétfaktoros kódot.';
diff -ruN localization/it_IT.inc.orig localization/it_IT.inc
--- localization/it_IT.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/it_IT.inc 2022-09-17 15:26:27.720632000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Codice OK';
$labels['code_ko'] = 'Codicec non corretto';
-$labels['dont_ask_me_30days'] = 'Non chiedermi più codici per i prossimi 30 giorni su questo computer';
+$labels['dont_ask_me_xdays'] = 'Non chiedermi più codici per i prossimi % giorni su questo computer';
$labels['check_code_to_activate'] = 'Per salvare devi prima verificare il codice';
diff -ruN localization/ja_JP.inc.orig localization/ja_JP.inc
--- localization/ja_JP.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/ja_JP.inc 2022-09-17 15:26:27.720851000 +0200
@@ -31,7 +31,7 @@
$labels['code_ok'] = 'コードOK';
$labels['code_ko'] = 'コードが違ってます';
-$labels['dont_ask_me_30days'] = '子の端末で以後30日間コードを求めるな';
+$labels['dont_ask_me_xdays'] = '子の端末で以後%日間コードを求めるな';
$labels['check_code_to_activate'] = '保存する前にコードを確認してください';
diff -ruN localization/nl_NL.inc.orig localization/nl_NL.inc
--- localization/nl_NL.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/nl_NL.inc 2022-09-17 15:26:27.721067000 +0200
@@ -16,13 +16,13 @@
$labels['recovery_codes'] = 'Herstelcodes';
$labels['show_recovery_codes'] = 'Herstelcodes weergeven';
$labels['hide_recovery_codes'] = 'Herstelcodes verbergen';
-$labels['setup_all_fields'] = 'Alle velden instellen (vereist )';
+$labels['setup_all_fields'] = 'Alle velden instellen (vereist)';
$labels['enrollment_dialog_title'] = '2-staps verificatie';
$labels['enrollment_dialog_msg'] = '<strong>2-staps verificatiecodes</strong> zijn vereist voor veiligheid, stel ze alstublieft in';
$labels['check_code'] = 'Check code';
$labels['code_ok'] = 'Code correct';
$labels['code_ko'] = 'Code incorrect';
-$labels['dont_ask_me_30days'] = 'Vraag me de komende 30 dagen niet opnieuw op deze computer';
+$labels['dont_ask_me_xdays'] = 'Vraag me de komende % dagen niet opnieuw op deze computer';
$labels['check_code_to_activate'] = 'Om op te slaan, scan alstublieft de QR Code en voer de verificatiecode hieronder in.';
// Messages used for the different portions of the plugin
$messages = array();
diff -ruN localization/pl_PL.inc localization/pl_PL.inc
--- localization/pl_PL.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/pl_PL.inc 2022-09-17 15:26:27.721291000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Kod OK';
$labels['code_ko'] = 'Błędny kod';
-$labels['dont_ask_me_30days'] = 'Nie pytaj ponownie o kod na tym komputerze przez następne 30 dni';
+$labels['dont_ask_me_xdays'] = 'Nie pytaj ponownie o kod na tym komputerze przez następne % dni';
$labels['check_code_to_activate'] = 'Aby zapisać, zeskanuj kod QR i zweryfikuj go przyciskiem Sprawdź Kod';
diff -ruN localization/pt_BR.inc.orig localization/pt_BR.inc
--- localization/pt_BR.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/pt_BR.inc 2022-09-17 15:26:27.721519000 +0200
@@ -31,7 +31,7 @@
$labels['code_ok'] = 'QR Code Válido';
$labels['code_ko'] = 'QR Code Incorreto';
-$labels['dont_ask_me_30days'] = 'Não perguntar por 30 dias';
+$labels['dont_ask_me_xdays'] = 'Não perguntar por % dias';
$labels['check_code_to_activate'] = 'Para salvar, escaneie o QR code e introduza o código da Verificação em Duas Etapas [2FA] abaixo.';
diff -ruN localization/ru_RU.inc.orig localization/ru_RU.inc
--- localization/ru_RU.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/ru_RU.inc 2022-09-17 15:26:27.721744000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Код в порядке';
$labels['code_ko'] = 'Неверный код';
-$labels['dont_ask_me_30days'] = 'Не спрашивать коды на этом компьютере 30 дней';
+$labels['dont_ask_me_xdays'] = 'Не спрашивать коды на этом компьютере % дней';
$labels['check_code_to_activate'] = 'Для сохранения, необходимо проверить код';
diff -ruN localization/sk_SK.inc.orig localization/sk_SK.inc
--- localization/sk_SK.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/sk_SK.inc 2022-09-17 15:26:27.721968000 +0200
@@ -31,7 +31,7 @@
$labels['code_ok'] = 'Správny kód';
$labels['code_ko'] = 'Neplatný kód';
-$labels['dont_ask_me_30days'] = 'Nepýtať si na tomto zariadení kódy 30 dní ';
+$labels['dont_ask_me_xdays'] = 'Nepýtať si na tomto zariadení kódy % dní ';
$labels['check_code_to_activate'] = 'Pre aktiváciu naskenujte QR kód v TOTP aplikácii (napr. Google Authenticator alebo Authy) a následne zadajte vygenerovaný kód.';
diff -ruN localization/sv_SE.inc.orig localization/sv_SE.inc
--- localization/sv_SE.inc.orig 2022-04-04 01:10:32.000000000 +0200
+++ localization/sv_SE.inc 2022-09-17 15:26:27.722189000 +0200
@@ -32,7 +32,7 @@
$labels['code_ok'] = 'Koden godkänd';
$labels['code_ko'] = 'Inkorrekt kod';
-$labels['dont_ask_me_30days'] = 'KOm i håg mig på den här enheten i 30 dagar';
+$labels['dont_ask_me_xdays'] = 'KOm i håg mig på den här enheten i % dagar';
$labels['check_code_to_activate'] = 'KOntrollera kod för att aktivera';
diff -ruN twofactor_gauthenticator.js.orig twofactor_gauthenticator.js
--- twofactor_gauthenticator.js.orig 2022-04-04 01:10:32.000000000 +0200
+++ twofactor_gauthenticator.js 2022-08-26 10:13:19.459868000 +0200
@@ -50,14 +50,14 @@
// add qr-code before msg_infor
var url_qr_code_values = 'otpauth://totp/' +$('#prefs-title').html().split(/ - /)[1]+ '?secret=' +$('#2FA_secret').get(0).value +'&issuer=RoundCube2FA%20'+window.location.hostname;
- $('table tr:last').before('<tr><td>' +rcmail.gettext('qr_code', 'twofactor_gauthenticator')+ '</td><td><input type="button" class="button mainaction btn btn-primary" id="2FA_change_qr_code" value="'
+ $('table tr:last').before('<tr class="form-group row"><td class="title col-sm-6">' +rcmail.gettext('qr_code', 'twofactor_gauthenticator')+ '</td><td class="col-sm-6"><input type="button" class="button mainaction btn btn-primary" id="2FA_change_qr_code" value="'
+rcmail.gettext('hide_qr_code', 'twofactor_gauthenticator')+ '"><div id="2FA_qr_code" style="display: visible; margin-top: 10px;"></div></td></tr>');
var qrcode = new QRCode(document.getElementById("2FA_qr_code"), {
text: url_qr_code_values,
width: 200,
height: 200,
- colorDark : "#000000",
+ colorDark : rcmail.env.qr_image_colour,
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.L // like charts.googleapis.com
});
@@ -129,7 +129,9 @@
$('#2FA_check_code').click(function(){
url = "./?_action=plugin.twofactor_gauthenticator-checkcode&code=" +$('#2FA_code_to_check').val() + '&secret='+$('#2FA_secret').val();
$.post(url, function(data){
- alert(data);
+
+ alert(data);
+
if(data == rcmail.gettext('code_ok', 'twofactor_gauthenticator'))
$('#2FA_setup_fields').prev().removeAttr('disabled');
diff -ruN twofactor_gauthenticator.php twofactor_gauthenticator.php
--- twofactor_gauthenticator.php 2022-04-04 01:10:32.000000000 +0200
+++ twofactor_gauthenticator.php.orig 2022-09-17 15:26:27.722699000 +0200
@@ -19,8 +19,9 @@
{
private $_number_recovery_codes = 4;
- // relative from RC home dir, not plugin directory
- private $_logs_file = '/logs/log_errors_2FA.txt';
+ // relative to $config['log_dir'], not plugin directory
+ private $_log_dir = '.';
+ private $_log_file = 'twofactor_gauthenticator.txt';
function init()
{
@@ -32,7 +33,8 @@
$this->add_hook('render_page', array($this, 'popup_msg_enrollment'));
$this->load_config();
-
+ $this->_log_dir = realpath($rcmail->config->get('log_dir','.')).DIRECTORY_SEPARATOR;
+
$allowedPlugin = $this->__pluginAllowedByConfig();
// skipping all logic and plugin not appears
@@ -52,11 +54,13 @@
$this->include_script('qrcode.min.js');
// settings we will export to the form javascript
- //$this_output = $this->api->output;
- //if ($this_output) {
- // $this->api->output->set_env('allow_save_device_30days',$rcmail->config->get('allow_save_device_30days',true));
- // $this->api->output->set_env('twofactor_formfield_as_password',$rcmail->config->get('twofactor_formfield_as_password',false));
- //}
+ $this_output = $this->api->output;
+ if ($this_output) {
+ $this->api->output->set_env('allow_save_device_xdays',$rcmail->config->get('allow_save_device_xdays',true));
+ $this->api->output->set_env('save_device_xdays',$rcmail->config->get('save_device_xdays',30));
+ $this->api->output->set_env('twofactor_formfield_as_password',$rcmail->config->get('twofactor_formfield_as_password',false));
+ $this->api->output->set_env('qr_image_colour',$rcmail->config->get('qr_image_colour',"#000000"));
+ }
}
// check if user are valid from config.inc.php or true (by default) if config.inc.php not exists
@@ -65,23 +69,27 @@
$this->load_config();
- // users allowed to use plugin (not showed for others!).
- // -- From config.inc.php file.
- // -- You can use regexp: admin.*@domain.com
- $users = $rcmail->config->get('users_allowed_2FA');
- if(is_array($users)) { // exists "users" from config.inc.php
- foreach($users as $u) {
- if (isset( $rcmail->user->data['username'])){
- preg_match("/$u/", $rcmail->user->data['username'], $matches);
+ if($rcmail->config->get('enable_ua2fa')){
+
+ // users allowed to use plugin (not showed for others!).
+ // -- From config.inc.php file.
+ // -- You can use regexp: admin.*@domain.com
+ $users = $rcmail->config->get('users_allowed_2FA');
+ if(is_array($users)) { // exists "users" from config.inc.php
+ foreach($users as $u) {
+ if (isset( $rcmail->user->data['username'])){
+ preg_match("/$u/", $rcmail->user->data['username'], $matches);
- if(isset($matches[0])) {
- return true;
- }
- }
- }
+ if(isset($matches[0])) {
+ return true;
+ }
+ }
+ }
- // not allowed for all, except explicit
- return false;
+ // not allowed for all, except explicit
+ return false;
+ }
+
}
// by default, all users have plugin activated
@@ -98,7 +106,7 @@
$config_2FA = self::__get2FAconfig();
- if(!($config_2FA['activate'] ?? false))
+ if(!$config_2FA['activate'])
{
if($rcmail->config->get('force_enrollment_users'))
{
@@ -115,12 +123,9 @@
$rcmail->output->set_pagetitle($this->gettext('twofactor_gauthenticator'));
- $rcmail->output->set_env('allow_save_device_30days',$rcmail->config->get('allow_save_device_30days',true));
- $rcmail->output->set_env('twofactor_formfield_as_password',$rcmail->config->get('twofactor_formfield_as_password',false));
-
$this->add_texts('localization', true);
$this->include_script('twofactor_gauthenticator_form.js');
-
+
$rcmail->output->send('login');
}
@@ -130,21 +135,21 @@
$rcmail = rcmail::get_instance();
$config_2FA = self::__get2FAconfig();
- if($config_2FA['activate'] ?? false)
+
+ if($config_2FA['activate'])
{
- // with IP allowed, we don't need to check anything
- if($rcmail->config->get('whitelist')) {
- foreach($rcmail->config->get('whitelist') as $ip_to_check) {
- if(CIDR::match($_SERVER['REMOTE_ADDR'], $ip_to_check)) {
- if(isset($_SESSION['twofactor_gauthenticator_login'])) {
+ // with IP allowed, we don't need to check anything
+ if($rcmail->config->get('whitelist')) {
+ if(is_array($rcmail->config->get('whitelist'))){
+ foreach($rcmail->config->get('whitelist') as $ip_to_check) {
+ if(CIDR::match($_SERVER['REMOTE_ADDR'], $ip_to_check)) {
if($rcmail->task === 'login') $this->__goingRoundcubeTask('mail');
return $p;
}
- }
- }
+ }
+ }
}
-
$code = rcube_utils::get_input_value('_code_2FA', rcube_utils::INPUT_POST);
$remember = rcube_utils::get_input_value('_remember_2FA', rcube_utils::INPUT_POST);
@@ -172,7 +177,7 @@
}
}
// we're into some task but marked with login...
- elseif($rcmail->task !== 'login' && ! $_SESSION['twofactor_gauthenticator_2FA_login'] >= $_SESSION['twofactor_gauthenticator_login'])
+ elseif($rcmail->task !== 'login' && array_key_exists("twofactor_gauthenticator_2FA_login",$_SESSION) && ! $_SESSION['twofactor_gauthenticator_2FA_login'] >= $_SESSION['twofactor_gauthenticator_login'])
{
$this->__exitSession();
}
@@ -196,7 +201,7 @@
$rcmail = rcmail::get_instance();
$config_2FA = self::__get2FAconfig();
- if(!($config_2FA['activate'] ?? false)
+ if(!$config_2FA['activate']
&& $rcmail->config->get('force_enrollment_users') && $rcmail->task == 'settings' && $rcmail->action == 'plugin.twofactor_gauthenticator')
{
// add overlay input box to html page
@@ -230,16 +235,16 @@
function twofactor_gauthenticator_save()
{
$rcmail = rcmail::get_instance();
-
- // 2022-04-03: Corrected security incidente reported by kototilt@haiiro.dev
- // "2FA in twofactor_gauthenticator can be bypassed allowing an attacker to disable 2FA or change the TOTP secret."
- //
- // Solution: if user don't have session created by any rendered page, we kick out
- $config_2FA = self::__get2FAconfig();
- if(!$_SESSION['twofactor_gauthenticator_2FA_login'] && $config_2FA['activate']) {
- $this->__exitSession();
- }
+ // 2022-04-03: Corrected security incidente reported by kototilt@haiiro.dev
+ // "2FA in twofactor_gauthenticator can be bypassed allowing an attacker to disable 2FA or change the TOTP secret."
+ //
+ // Solution: if user don't have session created by any rendered page, we kick out
+ $config_2FA = self::__get2FAconfig();
+ if(!array_key_exists("twofactor_gauthenticator_2FA_login",$_SESSION) && $config_2FA['activate']) {
+ $this->__exitSession();
+ }
+
$this->add_texts('localization/', true);
$this->register_handler('plugin.body', array($this, 'twofactor_gauthenticator_form'));
$rcmail->output->set_pagetitle($this->gettext('twofactor_gauthenticator'));
@@ -250,12 +255,24 @@
$recovery_codes = rcube_utils::get_input_value('2FA_recovery_codes', rcube_utils::INPUT_POST);
// remove recovery codes without value
- $recovery_codes = array_values(array_diff($recovery_codes, array('')));
+ if($recovery_codes != null){
+ $recovery_codes = array_values(array_diff($recovery_codes, array('')));
+ }else{
+ $recovery_codes = array('');
+ }
$data = self::__get2FAconfig();
- $data['secret'] = $secret;
- $data['activate'] = $activate ? true : false;
- $data['recovery_codes'] = $recovery_codes;
+
+ $data['activate'] = $activate ? true : false;
+
+ if($data['activate']){
+ $data['secret'] = $secret;
+ $data['recovery_codes'] = $recovery_codes;
+ }else{
+ $data['secret'] = null;
+ $data['recovery_codes'] = null;
+ }
+
self::__set2FAconfig($data);
// if we can't save time into SESSION, the plugin logouts
@@ -279,29 +296,40 @@
$data = self::__get2FAconfig();
// Fields will be positioned inside of a table
- $table = new html_table(array('cols' => 2));
+ $table = new html_table(array('cols' => 2, 'class' => 'propform cols-sm-8'));
// Activate/deactivate
$field_id = '2FA_activate';
- $checkbox_activate = new html_checkbox(array('name' => $field_id, 'id' => $field_id, 'type' => 'checkbox'));
+
+
+ $activateData = array('name' => $field_id, 'id' => $field_id, 'type' => 'checkbox');
+
+ if($data != null && array_key_exists('secret', $data) && $data['secret']){
+ $activateData['checked'] = "checked";
+ }
+
+ $checkbox_activate = new html_checkbox($activateData);
$table->add('title', html::label($field_id, rcube::Q($this->gettext('activate'))));
$checked = $data['activate'] ? null: 1; // :-?
$table->add(null, $checkbox_activate->show( $checked ));
-
// secret
$field_id = '2FA_secret';
- $input_descsecret = new html_inputfield(array('name' => $field_id, 'id' => $field_id, 'size' => 60, 'type' => 'password', 'value' => $data['secret'], 'autocomplete' => 'new-password'));
+
+ $input_descsecret = new html_inputfield(array('name' => $field_id, 'id' => $field_id, 'size' => 60, 'type' => 'password', 'value' => $data['secret'], 'autocomplete' => 'new-password'));
$table->add('title', html::label($field_id, rcube::Q($this->gettext('secret'))));
$html_secret = $input_descsecret->show();
+ $html_secret = "<div style='display:block;'>".$html_secret;
if($data['secret'])
{
- $html_secret .= '<input type="button" class="button mainaction" id="2FA_change_secret" value="'.$this->gettext('show_secret').'">';
+ $html_secret .= '<hr /><input type="button" class="button mainaction" id="2FA_change_secret" value="'.$this->gettext('show_secret').'"><br /><br />';
}
else
{
- $html_secret .= '<input type="button" class="button mainaction" id="2FA_create_secret" disabled="disabled" value="'.$this->gettext('create_secret').'">';
+ $html_secret .= '<hr /><input type="button" class="button mainaction" id="2FA_create_secret" disabled="disabled" value="'.$this->gettext('create_secret').'"><br /><br />';
}
+ $html_secret .= "</div>";
+
$table->add(null, $html_secret);
@@ -313,13 +341,18 @@
for($i = 0; $i < $this->_number_recovery_codes; $i++)
{
$value = isset($data['recovery_codes'][$i]) ? $data['recovery_codes'][$i] : '';
- $html_recovery_codes .= ' <input type="password" name="2FA_recovery_codes[]" value="'.$value.'" maxlength="10"> &nbsp; ';
+ if(($i+1) == $this->_number_recovery_codes){
+ $html_recovery_codes .= ' <input type="password" name="2FA_recovery_codes[]" value="'.$value.'" maxlength="10"> <hr /> ';
+ }else{
+ $html_recovery_codes .= ' <input type="password" name="2FA_recovery_codes[]" value="'.$value.'" maxlength="10"> <br /> ';
+ }
+
}
if($data['secret']) {
- $html_recovery_codes .= '<input type="button" class="button mainaction" id="2FA_show_recovery_codes" value="'.$this->gettext('show_recovery_codes').'">';
+ $html_recovery_codes .= '<input type="button" class="button mainaction" id="2FA_show_recovery_codes" value="'.$this->gettext('show_recovery_codes').'"><br /><br />';
}
else {
- $html_recovery_codes .= '<input type="button" class="button mainaction" id="2FA_show_recovery_codes" disabled="disabled" value="'.$this->gettext('show_recovery_codes').'">';
+ $html_recovery_codes .= '<input type="button" class="button mainaction" id="2FA_show_recovery_codes" disabled="disabled" value="'.$this->gettext('show_recovery_codes').'"><br /><br />';
}
$table->add(null, $html_recovery_codes);
@@ -328,7 +361,7 @@
if($data['secret']) {
$table->add('title', $this->gettext('qr_code'));
$table->add(null, '<input type="button" class="button mainaction" id="2FA_change_qr_code" value="'.$this->gettext('show_qr_code').'">
- <div id="2FA_qr_code" style="display: none; margin-top: 10px;"></div>');
+ <div id="2FA_qr_code" style="display: none; margin-top: 10px; text-align: center;"></div>');
// new JS qr-code, without call to Google
$this->include_script('2FA_qr_code.js');
@@ -340,24 +373,21 @@
// button to setup all fields if doesn't exists secret
$html_setup_all_fields = '';
if(!$data['secret']) {
- $html_setup_all_fields = '<input type="button" class="button mainaction" id="2FA_setup_fields" value="'.$this->gettext('setup_all_fields').'">';
+ $html_setup_all_fields = '<button type="button" class="button mainaction btn btn-primary submit" id="2FA_setup_fields" value="fill">Fill all fields</button><br />'.$this->gettext('setup_all_fields').'<br /><hr />';
}
- $html_check_code = '<br /><br /><input type="button" class="button mainaction" id="2FA_check_code" value="'.$this->gettext('check_code').'"> &nbsp;&nbsp; <input type="text" id="2FA_code_to_check" maxlength="10">';
+ $html_check_code = '<div style="text-align:center;"><input data-icon="key" size="40" autocapitalize="off" autocomplete="off" placeholder="Enter TOTP code..." type="text" class="form-control" style="display: inline-block; width: 250px; margin-right: 10px; margin-bottom: 5px;" id="2FA_code_to_check" maxlength="10" /><button style="margin-bottom: 5px;" type="button" class="button mainaction btn btn-primary" id="2FA_check_code" value="'.$this->gettext('check_code').'">'.$this->gettext('check_code').'</button></div>';
-
-
// Build the table with the divs around it
- $out = html::div(array('class' => 'settingsbox', 'style' => 'margin: 0;'),
- html::div(array('id' => 'prefs-title', 'class' => ''), $this->gettext('twofactor_gauthenticator') . ' - ' . $rcmail->user->data['username']) .
+ $out = html::tag('fieldset', array('class' => 'main'), html::tag('legend', array('id' => 'prefs-title', 'class' => 'boxtitle'), $this->gettext('twofactor_gauthenticator')). html::tag('legend', array('id' => 'prefs-title'), $rcmail->user->data['username']). html::div(array('class' => 'settingsbox', 'style' => 'margin: 0;'),
html::div(array('class' => 'boxcontent'), $table->show() .
html::p(null,
$rcmail->output->button(array(
'command' => 'plugin.twofactor_gauthenticator-save',
- 'type' => 'input',
- 'class' => 'button mainaction',
+ 'type' => 'button',
+ 'class' => 'button mainaction btn btn-primary submit',
'label' => 'save'
- ))
+ ))."<hr>"
// button show/hide secret
//.'<input type="button" class="button mainaction" id="2FA_change_secret" value="'.$this->gettext('show_secret').'">'
@@ -367,7 +397,9 @@
.$html_check_code
)
)
- );
+ ));
+
+
// Construct the form
$rcmail->output->add_gui_object('twofactor_gauthenticatorform', 'twofactor_gauthenticator-form');
@@ -378,8 +410,10 @@
'method' => 'post',
'action' => './?_task=settings&_action=plugin.twofactor_gauthenticator-save',
), $out);
+
+
- $out = "<div class='box formcontainer scroller'>".$out."</div>";
+ $out = "<div class='box formcontainer scroller formcontent'>".$out."</div>";
return $out;
}
@@ -428,7 +462,7 @@
$user = $rcmail->user;
$arr_prefs = $user->get_prefs();
- return $arr_prefs['twofactor_gauthenticator'] ?? null;
+ return array_key_exists('twofactor_gauthenticator',$arr_prefs) ? $arr_prefs['twofactor_gauthenticator'] : [];
}
// we can set array to NULL to remove
@@ -501,7 +535,13 @@
$name = hash_hmac('md5', $rcmail->user->data['username'], $rcmail->config->get('des_key'));
if ($set) {
- $expires = time() + 2592000; // 30 days from now
+ $daysInSeconds = intval($rcmail->config->get('save_device_xdays',true));
+ if(is_numeric($daysInSeconds) && $daysInSeconds > 0){
+ $daysInSeconds = $daysInSeconds * 86400;
+ }else{
+ $daysInSeconds = 2592000;
+ }
+ $expires = time() + $daysInSeconds; // X days from now
$rand = mt_rand();
$signature = hash_hmac('sha512', implode("\1\0\1", array($rcmail->user->data['username'], $this->__getSecret(), $user_agent, $rand, $expires)), $rcmail->config->get('des_key'), TRUE);
$plain_content = sprintf("%d:%d:%s", $expires, $rand, $signature);
@@ -521,7 +561,7 @@
if ($plain_content !== false) {
$now = time();
list($expires, $rand, $signature) = explode(':', $plain_content, 3);
- if ($expires > $now && ($expires - $now) <= 2592000) {
+ if ($expires > $now && ($expires - $now) <= $daysInSeconds) {
$signature_verification = hash_hmac('sha512', implode("\1\0\1", array($rcmail->user->data['username'], $this->__getSecret(), $user_agent, $rand, $expires)), $rcmail->config->get('des_key'), TRUE);
// constant time
$cmp = strlen($signature) ^ strlen($signature_verification);
@@ -541,8 +581,8 @@
// log error into $_logs_file directory
- private function __logError() {
- file_put_contents(realpath(".").$this->_logs_file, date("Y-m-d H:i:s")."|".$_SERVER['HTTP_X_FORWARDED_FOR']."|".$_SERVER['REMOTE_ADDR']."\n", FILE_APPEND);
+ private function __logError($msg = '') {
+ file_put_contents($this->_log_dir.$this->_log_file, date("Y-m-d H:i:s")."|".$_SERVER['HTTP_X_FORWARDED_FOR']."|".$_SERVER['REMOTE_ADDR']."|".$msg."\n", FILE_APPEND);
}
}
diff -ruN twofactor_gauthenticator_form.js.orig twofactor_gauthenticator_form.js
--- twofactor_gauthenticator_form.js.orig 2022-04-04 01:10:32.000000000 +0200
+++ twofactor_gauthenticator_form.js 2022-08-26 10:13:19.460924000 +0200
@@ -17,18 +17,28 @@
var twoFactorCodeFieldType = 'text';
//twofactor input form
- var text = '';
- text += '<tr>';
- text += '<td class="title"><label for="2FA_code">'+rcmail.gettext('two_step_verification_form', 'twofactor_gauthenticator')+'</label></td>';
- text += '<td class="input"><input name="_code_2FA" id="2FA_code" size="10" autocapitalize="off" autocomplete="off" type="' + twoFactorCodeFieldType + '" maxlength="10"></td>';
- text += '</tr>';
+ var text = '<tr class="form-group row">';
+ text += `<td class="input input-group input-group-lg"><span class="input-group-prepend">
+<i class="input-group-text icon key"></i>
+</span>
+<input class="form-control" required="" data-icon="key" size="40" value="" name="_code_2FA" id="2FA_code" autocapitalize="off" autocomplete="off" type="` + twoFactorCodeFieldType + `" maxlength="10" placeholder="Mobile App (TOTP)">
+</td></tr>`;
+
// remember option
- if(rcmail.env.allow_save_device_30days){
- text += '<tr>';
- text += '<td class="title" colspan="2"><input type="checkbox" id="remember_2FA" name="_remember_2FA" value="yes"/><label for="remember_2FA">'+rcmail.gettext('dont_ask_me_30days', 'twofactor_gauthenticator')+'</label></td>';
- text += '</tr>';
- }
+ if(rcmail.env.allow_save_device_xdays){
+ text += `<tr class="form-group row">
+ <td class="title" style="display: none;">
+ <label for="rcmloginuser">Username</label>
+ </td>
+ <td class="input input-group input-group-lg">
+ <div class="custom-control custom-switch">
+ <input type="checkbox" class="custom-control-input" id="remember_2FA" name="_remember_2FA" value="yes">
+ <label class="custom-control-label" for="remember_2FA">`+rcmail.gettext('dont_ask_me_xdays', 'twofactor_gauthenticator').replace("%",rcmail.env.save_device_xdays)+`</label>
+ </div>
+ </td>
+ </tr>`;
+ }
// create textbox
$('form > table > tbody:last').append(text);