PluginProbe
Two Factor Authentication / 1.2.6
Two Factor Authentication v1.2.6
1.12.2 1.13.0 1.14.10 1.14.11 1.14.14 1.14.15 1.14.16 1.14.17 1.14.23 1.14.24 1.14.26 1.14.27 1.14.3 1.14.4 1.14.5 1.14.7 1.14.8 1.15.5 1.16.0 1.2.10 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 All 98 releases
← All changes | two-factor-login.php +772 -195 1.14.41.2.6 View file →
@@ -2,258 +2,835 @@
2 2 /*
3 3 Plugin Name: Two Factor Authentication
4 4 Plugin URI: https://www.simbahosting.co.uk/s3/product/two-factor-authentication/
5 5 Description: Secure your WordPress login forms with two factor authentication - including WooCommerce login forms
6 -Author: David Anderson, original plugin by Oskar Hane and enhanced by Dee Nutbourne
6 +Author: David Nutbourne + David Anderson, original plugin by Oskar Hane
7 7 Author URI: https://www.simbahosting.co.uk
8 -Version: 1.14.4
9 -Text Domain: two-factor-authentication
10 -Domain Path: /languages
8 +Version: 1.2.6
11 9 License: GPLv2 or later
12 10 */
13 11
14 -register_activation_hook(__FILE__, 'simba_two_factor_authentication_activation');
12 +define('SIMBA_TFA_TEXT_DOMAIN', 'two-factor-authentication');
13 +define('SIMBA_TFA_PLUGIN_DIR', dirname( __FILE__ ));
14 +define('SIMBA_TFA_PLUGIN_URL', plugins_url('', __FILE__));
15 15
16 -if (!function_exists('simba_two_factor_authentication_activation')) {
17 - function simba_two_factor_authentication_activation() {
18 - if (!empty($GLOBALS['simba_two_factor_authentication'])) {
19 - $is_2fa_plugin_active = false;
20 - $installed_plugins_slugs = array_keys(get_plugins());
21 - foreach ($installed_plugins_slugs as $installed_plugin_slug) {
22 - if (is_plugin_active($installed_plugin_slug)) {
23 - $temp_split_plugin_slug = explode('/', $installed_plugin_slug);
24 - if (isset($temp_split_plugin_slug[1]) && 'two-factor-login.php' == $temp_split_plugin_slug[1]) {
25 - $is_2fa_plugin_active = true;
26 - break;
27 - }
28 - }
16 +class Simba_Two_Factor_Authentication {
17 +
18 + public $version = '1.2.6';
19 + private $php_required = '5.3';
20 +
21 + private $frontend;
22 +
23 + public function __construct() {
24 +
25 + if (version_compare(PHP_VERSION, $this->php_required, '<' )) {
26 + add_action('all_admin_notices', array($this, 'admin_notice_insufficient_php'));
27 + $abort = true;
28 + }
29 +
30 + if (!function_exists('mcrypt_get_iv_size')) {
31 + add_action('all_admin_notices', array($this, 'admin_notice_missing_mcrypt'));
32 + $abort = true;
33 + }
34 +
35 + if (!empty($abort)) return;
36 +
37 + if (file_exists(SIMBA_TFA_PLUGIN_DIR.'/premium.php')) include_once(SIMBA_TFA_PLUGIN_DIR.'/premium.php');
38 +
39 + add_action('wp_ajax_nopriv_simbatfa-init-otp', array($this, 'tfaInitLogin'));
40 +
41 + add_action('wp_ajax_simbatfa_shared_ajax', array($this, 'shared_ajax'));
42 +
43 + add_action('woocommerce_before_customer_login_form', array($this, 'woocommerce_before_customer_login_form'));
44 + // The login form on the checkout doesn't call the woocommerce_before_customer_login_form action
45 + add_action('woocommerce_before_checkout_form', array($this, 'woocommerce_before_customer_login_form'));
46 +
47 + if (is_admin()) {
48 + //Save settings
49 + add_action('admin_init', array($this, 'check_possible_reset'));
50 +
51 + //Add to Settings menu on sites
52 + add_action('admin_menu', array($this, 'menu_entry_for_admin'));
53 +
54 + //Add settings link in plugin list
55 + $plugin = plugin_basename(__FILE__);
56 + add_filter("plugin_action_links_".$plugin, array($this, 'addPluginSettingsLink' ));
57 + add_filter('network_admin_plugin_action_links_'.$plugin, array($this, 'addPluginSettingsLink' ));
58 +
59 + // Entry that everybody gets
60 + add_action('network_admin_menu', array($this, 'admin_menu'));
61 + add_action('admin_menu', array($this, 'admin_menu'));
62 +
63 + } else {
64 + add_action('init', array($this, 'check_possible_reset'));
65 + }
66 +
67 + add_action('plugins_loaded', array($this, 'plugins_loaded'));
68 + add_action('init', array($this, 'init'));
69 +
70 + //Show off sync message for hotp
71 + add_action('admin_notices', array($this, 'tfaShowHOTPOffSyncMessage'));
72 + add_action('login_enqueue_scripts', array($this, 'login_enqueue_scripts'));
73 +
74 + if (!defined('TWO_FACTOR_DISABLE') || !TWO_FACTOR_DISABLE) {
75 + add_filter('authenticate', array($this, 'tfaVerifyCodeAndUser'), 99999999999, 3);
76 + }
77 +
78 + if (file_exists(SIMBA_TFA_PLUGIN_DIR.'/updater/updater.php')) include_once(SIMBA_TFA_PLUGIN_DIR.'/updater/updater.php');
79 +
80 + if (defined('DOING_AJAX') && DOING_AJAX && defined('WP_ADMIN') && WP_ADMIN && !empty($_REQUEST['action']) && 'simbatfa-init-otp' == $_REQUEST['action']) {
81 + // Try to prevent PHP notices breaking the AJAX conversation
82 + $this->output_buffering = true;
83 + $this->logged = array();
84 + set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
85 + ob_start();
86 + }
87 +
88 + }
89 +
90 + public function get_php_errors($errno, $errstr, $errfile, $errline) {
91 + if (0 == error_reporting()) return true;
92 + $logline = $this->php_error_to_logline($errno, $errstr, $errfile, $errline);
93 + $this->logged[] = $logline;
94 + # Don't pass it up the chain (since it's going to be output to the user always)
95 + return true;
96 + }
97 +
98 + public function php_error_to_logline($errno, $errstr, $errfile, $errline) {
99 + switch ($errno) {
100 + case 1: $e_type = 'E_ERROR'; break;
101 + case 2: $e_type = 'E_WARNING'; break;
102 + case 4: $e_type = 'E_PARSE'; break;
103 + case 8: $e_type = 'E_NOTICE'; break;
104 + case 16: $e_type = 'E_CORE_ERROR'; break;
105 + case 32: $e_type = 'E_CORE_WARNING'; break;
106 + case 64: $e_type = 'E_COMPILE_ERROR'; break;
107 + case 128: $e_type = 'E_COMPILE_WARNING'; break;
108 + case 256: $e_type = 'E_USER_ERROR'; break;
109 + case 512: $e_type = 'E_USER_WARNING'; break;
110 + case 1024: $e_type = 'E_USER_NOTICE'; break;
111 + case 2048: $e_type = 'E_STRICT'; break;
112 + case 4096: $e_type = 'E_RECOVERABLE_ERROR'; break;
113 + case 8192: $e_type = 'E_DEPRECATED'; break;
114 + case 16384: $e_type = 'E_USER_DEPRECATED'; break;
115 + case 30719: $e_type = 'E_ALL'; break;
116 + default: $e_type = "E_UNKNOWN ($errno)"; break;
117 + }
118 +
119 + if (!is_string($errstr)) $errstr = serialize($errstr);
120 +
121 + if (0 === strpos($errfile, ABSPATH)) $errfile = substr($errfile, strlen(ABSPATH));
122 +
123 + return "PHP event: code $e_type: $errstr (line $errline, $errfile)";
124 +
125 + }
126 +
127 + public function init() {
128 + if ((!is_admin() || (defined('DOING_AJAX') && DOING_AJAX)) && is_user_logged_in() && file_exists(SIMBA_TFA_PLUGIN_DIR.'/includes/tfa_frontend.php')) {
129 + $this->load_frontend();
130 + } else {
131 + add_shortcode('twofactor_user_settings', array($this, 'shortcode_when_not_logged_in'));
132 + }
133 + }
134 +
135 + public function admin_notice_insufficient_php() {
136 + $this->show_admin_warning('<strong>'.__('Higher PHP version required', 'updraftplus').'</strong><br> '.sprintf(__('The Two Factor Authentication plugin requires PHP version %s or higher - your current version is only %s.', SIMBA_TFA_TEXT_DOMAIN), $this->php_required, PHP_VERSION), 'error');
137 + }
138 +
139 + public function admin_notice_missing_mcrypt() {
140 + $this->show_admin_warning('<strong>'.__('PHP Mcrypt module required', 'updraftplus').'</strong><br> '.__('The Two Factor Authentication plugin requires the PHP mcrypt module to be installed. Please ask your web hosting company to install it.', SIMBA_TFA_TEXT_DOMAIN), 'error');
141 + }
142 +
143 + public function show_admin_warning($message, $class = "updated") {
144 + echo '<div class="tfamessage '.$class.'">'."<p>$message</p></div>";
145 + }
146 +
147 + public function getTFA() {
148 + if (!class_exists('HOTP')) require_once(SIMBA_TFA_PLUGIN_DIR.'/hotp-php-master/hotp.php');
149 + if (!class_exists('Base32')) require_once(SIMBA_TFA_PLUGIN_DIR.'/Base32/Base32.php');
150 + if (!class_exists('Simba_TFA')) require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/class.TFA.php');
151 +
152 + $tfa = new Simba_TFA(new Base32(), new HOTP());
153 +
154 + return $tfa;
155 + }
156 +
157 + // "Shared" - i.e. could be called from either front-end or back-end
158 + public function shared_ajax() {
159 + if (empty($_POST['subaction']) || empty($_POST['nonce']) || !is_user_logged_in() || !wp_verify_nonce($_POST['nonce'], 'tfa_shared_nonce')) die('Security check (3).');
160 +
161 + if ($_POST['subaction'] == 'refreshotp') {
162 +
163 + global $current_user;
164 +
165 + $tfa_priv_key_64 = get_user_meta($current_user->ID, 'tfa_priv_key_64', true);
166 +
167 + if (!$tfa_priv_key_64) {
168 + echo json_encode(array('code' => ''));
169 + die;
29 170 }
30 171
31 - // We should prevent activation if and only if either the 2FA Premium or 2FA Free plugin is active.
32 - // We should not prevent activation if either the AIOWPS plugin is active.
33 - if ($is_2fa_plugin_active) {
34 - if (file_exists(__DIR__.'/simba-tfa/premium/loader.php')) {
35 - wp_die(__('To activate Two Factor Authentication Premium, first de-activate the free version (only one can be active at once).', SIMBA_TFA_TEXT_DOMAIN));
36 - } else { // If the 2FA Premium plugin is active and tries to activate the 2FA Free Plugin, it throws a fatal error and stops activating the free version.
37 - wp_die(__("You can't activate Two Factor Authentication (Free) because Two Factor Authentication Premium is active (only one can be active at once).", SIMBA_TFA_TEXT_DOMAIN));
38 - }
172 + echo json_encode(array('code' => $this->getTFA()->generateOTP($current_user->ID, $tfa_priv_key_64)));
173 + exit;
174 + }
175 +
176 + }
177 +
178 + public function tfaInitLogin() {
179 +
180 + if (empty($_POST['user'])) die('Security check (2).');
181 +
182 + if (defined('TWO_FACTOR_DISABLE') && TWO_FACTOR_DISABLE) {
183 + $res = false;
184 + } else {
185 + $tfa = $this->getTFA();
186 + $res = $tfa->preAuth(array('log' => (string)$_POST['user']));
187 + }
188 +
189 + $results = array('jsonstarter' => 'justhere', 'status' => $res);
190 +
191 + if (!empty($this->output_buffering)) {
192 + if (!empty($this->logged)) {
193 + $results['php_output'] = $this->logged;
39 194 }
195 + restore_error_handler();
196 + $buffered = ob_get_clean();
197 + if ($buffered) $results['extra_output'] = $buffered;
40 198 }
199 +
200 + echo json_encode($results);
201 + exit;
41 202 }
42 -}
203 +
43 204
44 -if (!defined('SIMBA_TFA_TEXT_DOMAIN')) define('SIMBA_TFA_TEXT_DOMAIN', 'two-factor-authentication');
45 -if (!class_exists('Simba_Two_Factor_Authentication')) require dirname(__FILE__).'/simba-tfa/simba-tfa.php';
205 + // Here's where the login action happens. Called on the 'authenticate' action.
206 + public function tfaVerifyCodeAndUser($user, $username, $password) {
46 207
47 -if (!class_exists('Simba_Two_Factor_Authentication_Plugin')):
48 -/**
49 - * This parent-child relationship enables the two to be split without affecting backwards compatibility for developers making direct calls
50 - *
51 - * This class is for the plugin encapsulation.
52 - */
53 -class Simba_Two_Factor_Authentication_Plugin extends Simba_Two_Factor_Authentication {
54 -
55 - public $version = '1.14.4';
56 -
57 - const PHP_REQUIRED = '5.6';
58 -
59 - /**
60 - * Constructor, run upon plugin initiation
61 - *
62 - * @uses __FILE__
63 - */
64 - public function __construct() {
208 + $tfa = $this->getTFA();
65 209
66 - add_action('plugins_loaded', array($this, 'plugins_loaded_load_textdomain'));
210 + if (is_wp_error($user)) return $user;
211 +
212 + $params = $_POST;
213 + $params['log'] = $username;
214 + $params['caller'] = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['REQUEST_URI'];
67 215
68 - if (version_compare(PHP_VERSION, self::PHP_REQUIRED, '<' )) {
69 - add_action('all_admin_notices', array($this, 'admin_notice_insufficient_php'));
70 - $abort = true;
216 + $code_ok = $tfa->authUserFromLogin($params);
217 +
218 + if (is_wp_error($code_ok)) return $code_ok;
219 +
220 + if (!$code_ok) return new WP_Error('authentication_failed', '<strong>'.__('Error:', SIMBA_TFA_TEXT_DOMAIN).'</strong> '.__('The one-time password (TFA code) you entered was incorrect.', SIMBA_TFA_TEXT_DOMAIN));
221 +
222 + if ($user) return $user;
223 +
224 + return wp_authenticate_username_password(null, $username, $password);
225 + }
226 +
227 + public function tfaRegisterTwoFactorAuthSettings()
228 + {
229 + global $wp_roles;
230 + if (!isset($wp_roles))
231 + $wp_roles = new WP_Roles();
232 +
233 + foreach($wp_roles->role_names as $id => $name)
234 + {
235 + register_setting('tfa_user_roles_group', 'tfa_'.$id);
236 + register_setting('tfa_user_roles_required_group', 'tfa_required_'.$id);
71 237 }
72 238
73 - if (!function_exists('mcrypt_get_iv_size') && !function_exists('openssl_cipher_iv_length')) {
74 - add_action('all_admin_notices', array($this, 'admin_notice_missing_mcrypt_and_openssl'));
75 - $abort = true;
239 + register_setting('tfa_user_roles_required_group', 'tfa_requireafter');
240 + register_setting('simba_tfa_default_hmac_group', 'tfa_default_hmac');
241 + register_setting('tfa_xmlrpc_status_group', 'tfa_xmlrpc_on');
242 + }
243 +
244 + public function tfaListEnableRadios($user_id, $long_label = false)
245 + {
246 + if(!$user_id)
247 + return;
248 +
249 + $setting = get_user_meta($user_id, 'tfa_enable_tfa', true);
250 + $setting = !$setting ? false : $setting;
251 +
252 + $tfa = $this->getTFA();
253 +
254 + if ($tfa->isRequiredForUser($user_id)) {
255 + $requireafter = absint($this->get_option('tfa_requireafter'));
256 +
257 + echo '<p class="tfa_required_warning" style="font-weight:bold; font-style:italics;">'.sprintf(__('N.B. This site is configured to forbid you to log in if you disable two-factor authentication after your account is %d days old', SIMBA_TFA_TEXT_DOMAIN), $requireafter).'</p>';
76 258 }
259 +
260 + $tfa_enabled_label = ($long_label) ? __('Enable two-factor authentication', SIMBA_TFA_TEXT_DOMAIN) : __('Enabled', SIMBA_TFA_TEXT_DOMAIN);
261 + $tfa_disabled_label = ($long_label) ? __('Disable two-factor authentication', SIMBA_TFA_TEXT_DOMAIN) : __('Disabled', SIMBA_TFA_TEXT_DOMAIN);
262 +
263 + print '<input type="radio" class="tfa_enable_radio" id="tfa_enable_tfa_true" name="tfa_enable_tfa" value="true" '.($setting == true ? 'checked="checked"' :'').'> <label class="tfa_enable_radio_label" for="tfa_enable_tfa_true">'.apply_filters('simbatfa_radiolabel_enabled', $tfa_enabled_label, $long_label).'</label> <br>';
264 +
265 + print '<input type="radio" class="tfa_enable_radio" id="tfa_enable_tfa_false" name="tfa_enable_tfa" value="false" '.($setting == false ? 'checked="checked"' :'').'> <label class="tfa_enable_radio_label" for="tfa_enable_tfa_false">'.apply_filters('simbatfa_radiolabel_disabled', $tfa_disabled_label, $long_label).'</label> <br>';
266 + }
77 267
78 - if (!empty($abort)) return;
268 +
269 + public function tfaListAlgorithmRadios($user_id)
270 + {
271 + if(!$user_id) return;
272 +
273 + $types = array('totp' => __('TOTP (time based - most common algorithm; used by Google Authenticator)', SIMBA_TFA_TEXT_DOMAIN), 'hotp' => __('HOTP (event based)', SIMBA_TFA_TEXT_DOMAIN));
79 274
80 - // Menu entries
81 - add_action('admin_menu', array($this, 'menu_entry_for_admin'));
82 - add_action('admin_menu', array($this, 'menu_entry_for_user'));
83 - add_action('network_admin_menu', array($this, 'menu_entry_for_user'));
275 + $setting = get_user_meta($user_id, 'tfa_algorithm_type', true);
276 + $setting = $setting === false || !$setting ? 'totp' : $setting;
277 +
278 + foreach($types as $id => $name) {
279 + print '<input type="radio" id="tfa_algorithm_type_'.esc_attr($id).'" name="tfa_algorithm_type" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> <label for="tfa_algorithm_type_'.esc_attr($id).'">'.$name."</label><br>\n";
280 + }
281 + }
282 +
283 + public function get_option($key) {
284 + if (!is_multisite()) return get_option($key);
285 + switch_to_blog(1);
286 + $v = get_option($key);
287 + restore_current_blog();
288 + return $v;
289 + }
290 +
291 + public function tfaListUserRolesCheckboxes()
292 + {
293 +
294 + if (is_multisite()) {
295 + // Not a real WP role; needs separate handling
296 + $id = '_super_admin';
297 + $name = __('Multisite Super Admin', SIMBA_TFA_TEXT_DOMAIN);
298 + $setting = $this->get_option('tfa_'.$id);
299 + $setting = $setting === false || $setting ? 1 : 0;
300 +
301 + print '<input type="checkbox" id="tfa_'.$id.'" name="tfa_'.$id.'" value="1" '.($setting ? 'checked="checked"' :'').'> <label for="tfa_'.$id.'">'.htmlspecialchars($name)."</label><br>\n";
302 + }
303 +
304 + global $wp_roles;
305 + if (!isset($wp_roles)) $wp_roles = new WP_Roles();
84 306
85 - // Add settings link in plugin list
86 - $plugin = plugin_basename(__FILE__);
87 - add_filter("plugin_action_links_$plugin", array($this, 'add_plugin_settings_link'));
88 - add_filter("network_admin_plugin_action_links_$plugin", array($this, 'add_plugin_settings_link'));
307 + foreach($wp_roles->role_names as $id => $name)
308 + {
309 + $setting = $this->get_option('tfa_'.$id);
310 + $setting = $setting === false || $setting ? 1 : 0;
311 +
312 + print '<input type="checkbox" id="tfa_'.$id.'" name="tfa_'.$id.'" value="1" '.($setting ? 'checked="checked"' :'').'> <label for="tfa_'.$id.'">'.htmlspecialchars($name)."</label><br>\n";
313 + }
89 314
90 - $this->set_user_settings_page_slug('two-factor-auth-user');
315 + }
91 316
92 - $settings_page_heading = sprintf(__('Two Factor Authentication (Version: %s) - Admin Settings', 'all-in-one-wp-security-and-firewall'), $this->version);
93 - $this->set_settings_page_heading($settings_page_heading);
317 + public function tfaListDefaultHMACRadios()
318 + {
319 + $tfa = $this->getTFA();
320 + $setting = $this->get_option('tfa_default_hmac');
321 + $setting = $setting === false || !$setting ? $tfa->default_hmac : $setting;
322 +
323 + $types = array('totp' => __('TOTP (time based - most common algorithm; used by Google Authenticator)', SIMBA_TFA_TEXT_DOMAIN), 'hotp' => __('HOTP (event based)', SIMBA_TFA_TEXT_DOMAIN));
324 +
325 + foreach($types as $id => $name)
326 + print '<input type="radio" id="tfa_default_hmac_'.esc_attr($id).'" name="tfa_default_hmac" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> '.'<label for="tfa_default_hmac_'.esc_attr($id).'">'."$name</label><br>\n";
327 + }
94 328
95 - $this->set_plugin_translate_url('https://translate.wordpress.org/projects/wp-plugins/two-factor-authentication/');
96 - $this->set_site_wide_administration_url(admin_url('options-general.php?page=two-factor-auth'));
97 - $this->set_premium_version_url('https://www.simbahosting.co.uk/s3/product/two-factor-authentication/');
98 - $this->set_faq_url('https://wordpress.org/plugins/two-factor-authentication/#faq');
99 - parent::__construct();
329 + public function tfaListXMLRPCStatusRadios()
330 + {
331 + $tfa = $this->getTFA();
332 + $setting = $this->get_option('tfa_xmlrpc_on');
333 + $setting = $setting === false || !$setting ? 0 : 1;
100 334
335 + $types = array(
336 + '0' => __('Do not require 2FA over XMLRPC (best option if you must use XMLRPC and your client does not support 2FA)', SIMBA_TFA_TEXT_DOMAIN),
337 + '1' => __('Do require 2FA over XMLRPC (best option if you do not use XMLRPC or are unsure)', SIMBA_TFA_TEXT_DOMAIN)
338 + );
339 +
340 + foreach($types as $id => $name)
341 + print '<input type="radio" name="tfa_xmlrpc_on" id="tfa_xmlrpc_on_'.$id.'" value="'.$id.'" '.($setting == $id ? 'checked="checked"' :'').'> <label for="tfa_xmlrpc_on_'.$id.'">'.$name."</label><br>\n";
101 342 }
102 -
103 - /**
104 - * Runs upon the WP filters plugin_action_links_(plugin) and network_plugin_action_links_(plugin)
105 - *
106 - * @param Array $links
107 - *
108 - * @return Array
109 - */
110 - public function add_plugin_settings_link($links) {
111 - if (is_multisite()) {
112 - switch_to_blog(1);
113 - $link = $this->get_settings_link();
114 - restore_current_blog();
115 - array_unshift($links, $link);
343 +
344 + public function tfaShowAdminSettingsPage()
345 + {
346 + $tfa = $this->getTFA();
347 + require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/admin_settings.php');
348 + }
349 +
350 + public function tfaShowUserSettingsPage()
351 + {
352 + $tfa = $this->getTFA();
353 + include SIMBA_TFA_PLUGIN_DIR.'/includes/user_settings.php';
354 + }
355 +
356 + public function admin_menu()
357 + {
358 + $tfa = $this->getTFA();
359 +
360 + global $current_user;
361 + if(!$tfa->isActivatedForUser($current_user->ID)) return;
362 + add_menu_page(__('Two Factor Authentication', SIMBA_TFA_TEXT_DOMAIN), __('Two Factor Auth', SIMBA_TFA_TEXT_DOMAIN), 'read', 'two-factor-auth-user', array($this, 'tfaShowUserSettingsPage'), SIMBA_TFA_PLUGIN_URL.'/img/tfa_admin_icon_16x16.png', 72);
363 + }
364 +
365 + public function menu_entry_for_admin() {
366 +
367 + // On multisite, only show the entry on site ID 1 - to ensure options get saved in the right place.
368 + global $current_site, $wpdb;
369 + // $current_site is not the right way to do this - it is internal, and could be anything
370 + if (is_multisite() && (!is_super_admin() || !is_object($wpdb) || !isset($wpdb->blogid) || 1 != $wpdb->blogid)) return;
371 +
372 + add_action( 'admin_init', array($this, 'tfaRegisterTwoFactorAuthSettings' ));
373 +
374 + add_options_page(
375 + __('Two Factor Authentication', SIMBA_TFA_TEXT_DOMAIN),
376 + __('Two Factor Authentication', SIMBA_TFA_TEXT_DOMAIN),
377 + 'manage_options',
378 + 'two-factor-auth',
379 + array($this, 'tfaShowAdminSettingsPage')
380 + );
381 + }
382 +
383 + public function addPluginSettingsLink($links)
384 + {
385 + if (!is_network_admin()) {
386 + $link = '<a href="options-general.php?page=two-factor-auth">'.__('Plugin settings', SIMBA_TFA_TEXT_DOMAIN).'</a>';
387 + array_unshift($links, $link);
116 388 } else {
117 - $link = $this->get_settings_link();
389 + switch_to_blog(1);
390 + $link = '<a href="'.admin_url('options-general.php').'?page=two-factor-auth">'.__('Plugin settings', SIMBA_TFA_TEXT_DOMAIN).'</a>';
391 + restore_current_blog();
118 392 array_unshift($links, $link);
119 393 }
120 -
121 - $link2 = '<a href="admin.php?page=two-factor-auth-user">'.__('User settings', 'two-factor-authentication').'</a>';
394 +
395 + $link2 = '<a href="admin.php?page=two-factor-auth-user">'.__('User settings', SIMBA_TFA_TEXT_DOMAIN).'</a>';
122 396 array_unshift($links, $link2);
397 +
398 + return $links;
399 + }
400 +
401 + public function check_possible_reset() {
402 + if(!empty($_GET['simbatfa_priv_key_reset']) && !empty($_REQUEST['nonce']) && wp_verify_nonce($_REQUEST['nonce'], 'simbatfa_reset_private_key'))
403 + {
404 + $this->reset_private_key_and_emergency_codes();
405 +// if (empty($_REQUEST['noredirect'])) exit;
406 + exit;
407 + }
123 408
124 - return $links;
125 409 }
126 410
127 - /**
128 - * Get 2FA settings anchor tag link.
129 - *
130 - * @return string 2FA settings anchor tag link.
131 - */
132 - private function get_settings_link() {
133 - return '<a href="'.admin_url('options-general.php').'?page=two-factor-auth">'.__('Plugin settings', 'two-factor-authentication').'</a>';
411 + public function reset_private_key_and_emergency_codes() {
412 + global $current_user;
413 + delete_user_meta($current_user->ID, 'tfa_priv_key_64');
414 + delete_user_meta($current_user->ID, 'simba_tfa_emergency_codes_64');
415 + if (empty($_REQUEST['noredirect'])) {
416 + wp_safe_redirect( admin_url('admin.php').'?page=two-factor-auth-user&settings-updated=1');
417 + } else {
418 + $url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . remove_query_arg(array('simbatfa_priv_key_reset', 'noredirect', 'nonce'));
419 +
420 + wp_redirect(esc_url_raw($url));
421 + }
134 422 }
135 -
136 - /**
137 - * Runs upon the WP actions admin_menu and network_admin_menu
138 - */
139 - public function menu_entry_for_user() {
423 +
424 + public function reset_link($admin = true) {
425 +
426 + $url_base = ($admin) ? admin_url('admin.php').'?page=two-factor-auth-user&settings-updated=1' : (( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST']);
427 +
428 + $add_query_args = array(
429 + 'simbatfa_priv_key_reset' => 1,
430 + );
431 + if (!$admin) $add_query_args['noredirect'] = 1;
432 +
433 + $url = $url_base.add_query_arg($add_query_args);
434 +
435 + $url = wp_nonce_url($url, 'simbatfa_reset_private_key', 'nonce');
436 +
437 + return '<a href="javascript:if(confirm(\''.__('Warning: if you reset this key you will have to update your apps with the new one. Are you sure you want this?', SIMBA_TFA_TEXT_DOMAIN).'\')){ window.location = \''.esc_js($url).'\'; }">'.__('Reset private key', SIMBA_TFA_TEXT_DOMAIN).'</a>';
438 +
439 + }
440 +
441 + public function footer() {
442 + $ajax_url = admin_url('admin-ajax.php');
443 + // It's possible that FORCE_ADMIN_SSL will make that SSL, whilst the user is on the front-end having logged in over non-SSL - and as a result, their login cookies won't get sent, and they're not registered as logged in.
444 + if (!is_admin() && substr(strtolower($ajax_url), 0, 6) == 'https:' && !is_ssl()) {
445 + $also_try = 'http:'.substr($ajax_url, 6);
446 + }
447 + ?>
448 + <script>
449 + jQuery(document).ready(function($) {
450 + $('.simbaotp_qr_container').qrcode({
451 + "render": "image",
452 + "text": $('.simbaotp_qr_container:first').data('qrcode'),
453 + });
454 + $('.simbaotp_refresh').click(function(e) {
455 + e.preventDefault();
456 + $(".simba_current_otp").html('<em><?php echo esc_attr(__('Updating...', SIMBA_TFA_TEXT_DOMAIN));?></em>');
457 + $.post('<?php echo esc_js($ajax_url);?>', {
458 + action: "simbatfa_shared_ajax",
459 + subaction: "refreshotp",
460 + nonce: "<?php echo esc_js(wp_create_nonce("tfa_shared_nonce"));?>"
461 + }, function(response) {
462 + var got_code = '';
463 + try {
464 + var resp = $.parseJSON(response);
465 + got_code = resp.code;
466 + } catch(err) {
467 + <?php if (!isset($also_try)) { ?>
468 + alert("<?php echo esc_js(__('Response:', 'SIMBA_TFA_TEXT_DOMAIN')); ?> "+response);
469 + <?php } ?>
470 + console.log(response);
471 + console.log(err);
472 + }
473 + <?php
474 + if (isset($also_try)) {
475 + ?>
476 + $.post('<?php echo esc_js($also_try);?>', {
477 + action: "simbatfa_shared_ajax",
478 + subaction: "refreshotp",
479 + nonce: "<?php echo esc_js(wp_create_nonce("tfa_shared_nonce"));?>"
480 + }, function(response) {
481 + try {
482 + var resp = $.parseJSON(response);
483 + if (resp.code) {
484 + $(".simba_current_otp").html(resp.code);
485 + } else {
486 + console.log(response);
487 + console.log("TFA: no code found");
488 + }
489 + } catch(err) {
490 + alert("<?php echo esc_js(__('Response:', 'SIMBA_TFA_TEXT_DOMAIN')); ?> "+response);
491 + console.log(response);
492 + console.log(err);
493 + }
494 + });
495 + <?php } else { ?>
496 + if ('' != got_code) {
497 + $(".simba_current_otp").html(got_code);
498 + } else {
499 + console.log("TFA: no code found");
500 + }
501 + <?php } ?>
502 + });
503 + });
504 + });
505 + </script>
506 + <?php
507 + }
508 +
509 + public function print_private_keys($admin, $type = 'full', $user_id = false) {
510 +
511 + $tfa = $this->getTFA();
512 + global $current_user;
513 +
514 + if ($user_id == false) $user_id = $current_user->ID;
515 +
516 + $tfa_priv_key_64 = get_user_meta($user_id, 'tfa_priv_key_64', true);
517 + if(!$tfa_priv_key_64) $tfa_priv_key_64 = $tfa->addPrivateKey($user_id);
518 +
519 + $tfa_priv_key = trim($tfa->getPrivateKeyPlain($tfa_priv_key_64, $user_id));
520 +
521 + $tfa_priv_key_32 = Base32::encode($tfa_priv_key);
522 +
523 + if ('full' == $type) {
524 + ?>
525 + <strong><?php echo __('Private key (base 32 - used by Google Authenticator and Authy):', SIMBA_TFA_TEXT_DOMAIN);?></strong>
526 + <?php echo htmlspecialchars($tfa_priv_key_32); ?><br>
527 +
528 + <strong><?php echo __('Private key:', SIMBA_TFA_TEXT_DOMAIN);?></strong>
529 + <?php echo htmlspecialchars($tfa_priv_key); ?><br>
530 + <?php
531 + } elseif ('plain' == $type) {
532 + echo htmlspecialchars($tfa_priv_key);
533 + } elseif ('base32' == $type) {
534 + echo htmlspecialchars($tfa_priv_key_32);
535 + } elseif ('base64' == $type) {
536 + echo htmlspecialchars($tfa_priv_key_64);
537 + }
538 + }
539 +
540 + public function current_otp_code($tfa, $user_id = false) {
541 + global $current_user;
542 + if (false == $user_id) $user_id = $current_user->ID;
543 + $tfa_priv_key_64 = get_user_meta($user_id, 'tfa_priv_key_64', true);
544 + return '<span class="simba_current_otp">'.$tfa->generateOTP($user_id, $tfa_priv_key_64).'</span>';
545 + }
546 +
547 + public function add_footer($admin) {
548 + static $added_footer;
549 + if (empty($added_footer)) {
550 + $added_footer = true;
551 +// wp_enqueue_script('jquery');
552 + $script_ver = (defined('WP_DEBUG') && WP_DEBUG) ? time() : $this->version;
553 + $script_file = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? 'jquery.qrcode.js' : 'jquery.qrcode.min.js';
554 + wp_enqueue_script( 'jquery-qrcode', SIMBA_TFA_PLUGIN_URL.'/includes/jquery-qrcode/'.$script_file, array('jquery'), $script_ver);
555 + add_action( $admin ? 'admin_footer' : 'wp_footer' , array($this, 'footer'));
556 + }
557 + }
558 +
559 + public function current_codes_box($admin = true, $user_id = false) {
560 +
561 + global $current_user;
562 +
563 + if (false == $user_id) {
564 + $user_id = $current_user->ID;
565 + }
566 +
567 + $tfa = $this->getTFA();
568 +
569 + $this->add_footer($admin);
570 +
571 + $url = preg_replace('/^https?:\/\//', '', site_url());
140 572
141 - $this->get_totp_controller()->potentially_port_private_keys();
573 + $tfa_priv_key_64 = get_user_meta($user_id, 'tfa_priv_key_64', true);
142 574
575 + if(!$tfa_priv_key_64) $tfa_priv_key_64 = $tfa->addPrivateKey($user_id);
576 +
577 + $tfa_priv_key = trim($tfa->getPrivateKeyPlain($tfa_priv_key_64, $user_id));
578 +
579 + $tfa_priv_key_32 = Base32::encode($tfa_priv_key);
580 +
581 + $algorithm_type = $tfa->getUserAlgorithm($user_id);
582 +
583 + if ($admin) {
584 + if ($current_user->ID == $user_id) {
585 + echo '<h2>'.__('Current codes', SIMBA_TFA_TEXT_DOMAIN).'</h2>';
586 + } else {
587 + $user = get_user_by('id', $user_id);
588 + $user_descrip = htmlspecialchars($user->user_nicename.' - '.$user->user_email);
589 + echo '<h2>'.sprintf(__('Current codes (login: %s)', SIMBA_TFA_TEXT_DOMAIN), $user_descrip).'</h2>';
590 + }
591 + } else {
592 +// echo '<h2>'.__('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' '.$this->reset_current_otp_link().'</h2>';
593 + }
594 +
595 + ?>
596 + <div class="postbox">
597 +
598 + <?php if ($admin) { ?>
599 + <h3 style="padding: 10px 6px 0px; margin:4px 0 0; cursor: default;">
600 + <span style="cursor: default;"><?php echo __('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' ';
601 + if ($current_user->ID == $user_id) { echo $this->reset_current_otp_link(); } ?>
602 + </span>
603 + <div class="inside">
604 + <p><strong style="font-size: 3em;"><?php echo $this->current_otp_code($tfa, $user_id); ?></strong></p>
605 + </div>
606 + </h3>
607 + <?php } else {
608 + ?>
609 + <div class="inside">
610 + <p class="simbatfa-frontend-current-otp" style="font-size: 1.5em; margin-top:6px;">
611 + <strong>
612 + <?php echo __('Current one-time password', SIMBA_TFA_TEXT_DOMAIN).' '.$this->reset_current_otp_link(); ?>
613 + </strong> :
614 +
615 + <span class="simba_current_otp"><?php print $tfa->generateOTP($user_id, $tfa_priv_key_64); ?></span>
616 +
617 + </p>
618 + </div>
619 +
620 + <?php } ?>
621 +
622 + <?php if ($admin) { ?>
623 + <h3 style="padding-left: 10px; cursor: default;">
624 + <span style="cursor: default;"><?php _e('QR code', SIMBA_TFA_TEXT_DOMAIN); ?></span>
625 + </h3>
626 + <?php } else {
627 + echo '<h2>'.__('QR code', SIMBA_TFA_TEXT_DOMAIN).'</h2>';
628 + } ?>
629 + <div class="inside">
630 + <p>
631 + <?php _e('For OTP apps that support scanning, scanning this code is the quickest way to set the app up (e.g. with Duo Mobile, Google Authenticator)', SIMBA_TFA_TEXT_DOMAIN); ?>.
632 +
633 + <?php _e('You are currently using', SIMBA_TFA_TEXT_DOMAIN); ?> <?php print strtoupper($algorithm_type).', '.($algorithm_type == 'totp' ? __('a time based', SIMBA_TFA_TEXT_DOMAIN) : __('an event based', SIMBA_TFA_TEXT_DOMAIN)); ?> <?php _e('algorithm', SIMBA_TFA_TEXT_DOMAIN); ?>.
634 + </p>
635 + <p title="<?php echo sprintf(__("Private key: %s (base 32: %s)", SIMBA_TFA_TEXT_DOMAIN), $tfa_priv_key, $tfa_priv_key_32);?>">
636 + <?php $qr_url = $this->tfa_qr_code_url($algorithm_type, $url, $tfa_priv_key) ?>
637 + <div class="simbaotp_qr_container" data-qrcode="<?php echo esc_attr($qr_url); ?>"></div>
638 + </p>
639 + </div>
640 +
641 + <div class="inside">
642 +
643 + <h3 class="normal" style="cursor: default"><?php _e('Private key - always to be kept secret - type this into your app to set it up (instead of scanning the code)', SIMBA_TFA_TEXT_DOMAIN); ?></h3>
644 +
645 + <p>
646 + <?php
647 + $this->print_private_keys($admin, 'full', $user_id);
648 + if ($current_user->ID == $user_id) { echo $this->reset_link($admin);}
649 + ?>
650 + </p>
651 + </div>
652 +
653 + <?php
654 + if ($admin || apply_filters('simba_tfa_emergency_codes_user_settings', false, $user_id) !== false) {
655 + ?>
656 + <div class="inside">
657 +
658 + <h3 class="normal" style="cursor: default"><?php _e('Emergency codes', SIMBA_TFA_TEXT_DOMAIN); ?></h3>
659 +
660 + <p>
661 + <?php
662 + $default_text = '<a href="https://www.simbahosting.co.uk/s3/product/two-factor-authentication/">'.__('One-time emergency codes are a feature of the Premium version of this plugin.', SIMBA_TFA_TEXT_DOMAIN).'</a>';
663 + echo apply_filters('simba_tfa_emergency_codes_user_settings', $default_text, $user_id);
664 + ?>
665 + </p>
666 +
667 + </div>
668 +
669 + <?php } ?>
670 +
671 + </div>
672 + <?php
673 + }
674 +
675 + public function reset_current_otp_link($admin = true) {
676 + return '<a href="#" class="simbaotp_refresh">'.__('(update)', SIMBA_TFA_TEXT_DOMAIN).'</a>';
677 + }
678 +
679 + public function advanced_settings_box($submit_button_callback = false) {
680 + $tfa = $this->getTFA();
681 +
143 682 global $current_user;
144 - if ($this->is_activated_for_user($current_user->ID)) {
145 - add_menu_page(__('Two Factor Authentication', 'two-factor-authentication'), __('Two Factor Auth', 'two-factor-authentication'), 'read', 'two-factor-auth-user', array($this, 'show_dashboard_user_settings_page'), $this->includes_url().'/tfa_admin_icon_16x16.png', 72);
683 + $algorithm_type = $tfa->getUserAlgorithm($current_user->ID);
684 +
685 + ?>
686 + <h2><?php _e('Advanced settings', SIMBA_TFA_TEXT_DOMAIN); ?></h2>
687 +
688 + <div id="tfa_advanced_box" class="tfa_settings_form" style="margin-top: 20px;">
689 +
690 + <?php if (false === $submit_button_callback) { ?><form method="post" action="<?php print esc_url(add_query_arg('settings-updated', 'true', $_SERVER['REQUEST_URI'])); ?>"><?php } ?>
691 +
692 + <?php _e('Choose which algorithm for One Time Passwords you want to use.', SIMBA_TFA_TEXT_DOMAIN); ?>
693 + <p>
694 + <?php
695 + $this->tfaListAlgorithmRadios($current_user->ID);
696 + if($algorithm_type == 'hotp')
697 + {
698 + $counter = $tfa->getUserCounter($current_user->ID);
699 + print '<br>'.__('Your counter on the server is currently on', SIMBA_TFA_TEXT_DOMAIN).': '.$counter;
700 + }
701 + ?>
702 +
703 + </p>
704 + <?php if (false === $submit_button_callback) { submit_button(); echo '</form>'; } else { call_user_func($submit_button_callback); } ?>
705 + </div>
706 + <?php
707 + }
708 +
709 + public function login_enqueue_scripts()
710 + {
711 +
712 + if(isset($_GET['action']) && $_GET['action'] != 'logout' && $_GET['action'] != 'login') return;
713 +
714 + // Prevent cacheing when in debug mode
715 + $script_ver = (defined('WP_DEBUG') && WP_DEBUG) ? time() : $this->version;
716 +
717 + wp_enqueue_script( 'tfa-ajax-request', SIMBA_TFA_PLUGIN_URL . '/includes/tfa.js', array( 'jquery' ), $script_ver );
718 + $localize = array(
719 + 'ajaxurl' => admin_url('admin-ajax.php'),
720 + 'click_to_enter_otp' => __("Click to enter One Time Password", SIMBA_TFA_TEXT_DOMAIN),
721 + 'enter_username_first' => __('You have to enter a username first.', SIMBA_TFA_TEXT_DOMAIN),
722 + 'otp' => __("One Time Password (i.e. 2FA)", SIMBA_TFA_TEXT_DOMAIN),
723 + 'otp_login_help' => __('(check your OTP app to get this password)', SIMBA_TFA_TEXT_DOMAIN),
724 + 'nonce' => wp_create_nonce("simba_tfa_loginform_nonce")
725 + );
726 + // Spinner exists since WC 3.8. Use the proper functions to avoid SSL warnings.
727 + if (file_exists(ABSPATH.'wp-admin/images/spinner.gif')) {
728 + $localize['spinnerimg'] = admin_url('images/spinner.gif');
729 + } elseif (file_exists(ABSPATH.WPINC.'/images/spinner.gif')) {
730 + $localize['spinnerimg'] = includes_url('images/spinner.gif');
146 731 }
732 + wp_localize_script( 'tfa-ajax-request', 'simba_tfasettings', $localize);
147 733 }
148 -
149 - /**
150 - * Runs upon the WP action admin_menu
151 - */
152 - public function menu_entry_for_admin() {
734 +
735 + public function tfaShowHOTPOffSyncMessage()
736 + {
737 + global $current_user;
738 + $is_off_sync = get_user_meta($current_user->ID, 'tfa_hotp_off_sync', true);
739 + if(!$is_off_sync)
740 + return;
153 741
154 - $this->get_totp_controller()->potentially_port_private_keys();
742 + ?>
743 + <div class="error">
744 + <h3><?php _e('Two Factor Authentication re-sync needed', SIMBA_TFA_TEXT_DOMAIN);?></h3>
745 + <p>
746 + <?php _e('You need to resync your device for Two Factor Authentication since the OTP you last used is many steps ahead of the server.', SIMBA_TFA_TEXT_DOMAIN); ?>
747 + <br>
748 + <?php _e('Please re-sync or you might not be able to log in if you generate more OTPs without logging in.', SIMBA_TFA_TEXT_DOMAIN);?>
749 + <br><br>
750 + <a href="admin.php?page=two-factor-auth-user&warning_button_clicked=1" class="button"><?php _e('Click here and re-scan the QR-Code', SIMBA_TFA_TEXT_DOMAIN);?></a>
751 + </p>
752 + </div>
155 753
156 - if (is_multisite() && (!is_super_admin() || !is_main_site())) return;
754 + <?php
157 755
158 - add_options_page(
159 - __('Two Factor Authentication', 'two-factor-authentication'),
160 - __('Two Factor Authentication', 'two-factor-authentication'),
161 - $this->get_management_capability(),
162 - 'two-factor-auth',
163 - array($this, 'show_admin_settings_page')
164 - );
165 756 }
166 -
167 - /**
168 - * Include the admin settings page code
169 - */
170 - public function show_admin_settings_page() {
171 - $totp_controller = $this->get_totp_controller();
172 - $totp_controller->setUserHMACTypes();
173 - if (!is_admin() || !current_user_can($this->get_management_capability())) return;
174 757
175 - $admin_settings_links = array();
176 - if (!class_exists('Simba_Two_Factor_Authentication_Premium')) {
177 - $admin_settings_links[] = array(
178 - 'url' => esc_url('https://www.simbahosting.co.uk/s3/product/two-factor-authentication/'),
179 - 'title' => __('Premium version', SIMBA_TFA_TEXT_DOMAIN),
180 - );
758 + // QR code image
759 + public function tfa_qr_code_url($algorithm_type, $url, $tfa_priv_key, $user_id = false){
760 + global $current_user;
761 +
762 + if ($user_id == false) {
763 + $user = $current_user;
764 + } else {
765 + $user = get_user_by('id', $user_id);
181 766 }
182 - $simba_tfa_support_url = apply_filters('simba_tfa_support_url', esc_url('https://wordpress.org/support/plugin/two-factor-authentication/'));
767 +
768 + $tfa = $this->getTFA();
769 +
770 + // Old
771 +// $encode = 'otpauth://'.$algorithm_type.'/'.$url.':%2520'.$user->user_login.'%3Fsecret%3D'.Base32::encode($tfa_priv_key).'%26issuer='.$url.'%26counter='.$tfa->getUserCounter($user->ID);
772 +//
773 +// $ret = '<img src="https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl='.$encode.'">';
183 774
184 - $admin_settings_links[] = array(
185 - 'url' => $simba_tfa_support_url,
186 - 'title' => __('Support', SIMBA_TFA_TEXT_DOMAIN),
187 - );
188 - $admin_settings_links[] = array(
189 - 'url' => esc_url('https://profiles.wordpress.org/davidanderson#content-plugins'),
190 - 'title' => __('More free plugins', SIMBA_TFA_TEXT_DOMAIN),
191 - );
192 - $admin_settings_links[] = array(
193 - 'url' => esc_url('http://updraftplus.com'),
194 - 'title' => 'UpdraftPlus - '.__('WordPress backups', SIMBA_TFA_TEXT_DOMAIN),
195 - );
196 - $admin_settings_links[] = array(
197 - 'url' => esc_url('https://www.simbahosting.co.uk/s3/shop/'),
198 - 'title' => __('More premium plugins', SIMBA_TFA_TEXT_DOMAIN),
199 - );
200 - $admin_settings_links[] = array(
201 - 'url' => esc_url('https://twitter.com/updraftplus'),
202 - 'title' => __('Twitter', SIMBA_TFA_TEXT_DOMAIN),
203 - );
204 - $admin_settings_links[] = array(
205 - 'url' => esc_url('http://david.dw-perspective.org.uk'),
206 - 'title' => __('Lead developer\'s homepage', SIMBA_TFA_TEXT_DOMAIN),
207 - );
775 + // New
776 + $encode = 'otpauth://'.$algorithm_type.'/'.$url.':'.$user->user_login.'?secret='.Base32::encode($tfa_priv_key).'&issuer='.$url.'&counter='.$tfa->getUserCounter($user->ID);
208 777
209 - $admin_settings_links = apply_filters('simba_tfa_admin_settings_links', $admin_settings_links);
778 +// $ret = '<script>var qr_details = "'.$encode.'"</script>';
210 779
211 - $this->include_template('admin-settings.php', array(
212 - 'totp_controller' => $totp_controller,
213 - 'settings_page_heading' => $this->get_settings_page_heading(),
214 - 'admin_settings_links' => $admin_settings_links,
215 - ));
780 + return $encode;
216 781 }
217 -
218 - /**
219 - * Runs conditionally on the WP action all_admin_notices
220 - */
221 - public function admin_notice_insufficient_php() {
222 - $this->show_admin_warning('<strong>'.__('Higher PHP version required', 'two-factor-authentication').'</strong><br> '.sprintf(__('The Two Factor Authentication plugin requires PHP version %s or higher - your current version is only %s.', 'two-factor-authentication'), self::PHP_REQUIRED, PHP_VERSION), 'error');
782 +
783 + public function settings_intro_notices() {
784 + ?>
785 + <p class="simba_tfa_personal_settings_notice simba_tfa_intro_notice">
786 + <?php echo __('These are your personal settings.', SIMBA_TFA_TEXT_DOMAIN).' '.__('Nothing you change here will have any effect on other users.', SIMBA_TFA_TEXT_DOMAIN); ?>
787 + </p>
788 + <p class="simba_tfa_verify_tfa_notice simba_tfa_intro_notice"><strong>
789 + <?php _e('If you activate two-factor authentication, then verify that your two-factor application is showing the same One Time Password as shown on this page before you log out.', SIMBA_TFA_TEXT_DOMAIN); ?></strong> <?php if (current_user_can('manage_options')) { ?><a href="https://wordpress.org/plugins/two-factor-authentication/faq/"><?php _e('You should also bookmark the FAQs, which explain how to de-activate the plugin even if you cannot log in.', SIMBA_TFA_TEXT_DOMAIN);?></a><?php } ?>
790 + </p>
791 + <?php
223 792 }
224 -
225 - /**
226 - * Runs conditionally on the WP action all_admin_notices
227 - */
228 - public function admin_notice_missing_mcrypt_and_openssl() {
229 - $this->show_admin_warning('<strong>'.__('PHP OpenSSL or mcrypt module required', 'two-factor-authentication').'</strong><br> '.__('The Two Factor Authentication plugin requires either the PHP openssl (preferred) or mcrypt module to be installed. Please ask your web hosting company to install one of them.', 'two-factor-authentication'), 'error');
230 - }
231 -
232 - /**
233 - * Run upon the WP plugins_loaded action. This method is called even if main loading aborts - so don't put anything else in it (use a separate method).
234 - */
235 - public function plugins_loaded_load_textdomain() {
793 +
794 + public function plugins_loaded() {
236 795 load_plugin_textdomain(
237 - 'two-factor-authentication',
796 + SIMBA_TFA_TEXT_DOMAIN,
238 797 false,
239 - dirname(plugin_basename(__FILE__)).'/languages/'
798 + dirname( plugin_basename( __FILE__ ) ) . '/languages/'
240 799 );
241 800 }
242 -}
243 -endif;
244 801
245 -$GLOBALS['simba_two_factor_authentication'] = new Simba_Two_Factor_Authentication_Plugin();
802 + public function load_frontend() {
803 + if (!class_exists('TFA_Frontend')) require_once(SIMBA_TFA_PLUGIN_DIR.'/includes/tfa_frontend.php');
804 + if (empty($this->frontend)) $this->frontend = new TFA_Frontend($this);
805 + return $this->frontend;
806 + }
246 807
247 -if (file_exists(__DIR__.'/simba-tfa/premium/loader.php') && empty($GLOBALS['simba_two_factor_authentication_premium'])) {
248 - if (!class_exists('Simba_Two_Factor_Authentication_Premium')) include_once(__DIR__.'/simba-tfa/premium/loader.php');
808 + public function shortcode_when_not_logged_in() {
809 + return '';
810 + }
249 811
250 - $GLOBALS['simba_two_factor_authentication_premium'] = new Simba_Two_Factor_Authentication_Premium($GLOBALS['simba_two_factor_authentication']);
812 + // WooCommerce login form
813 + public function woocommerce_before_customer_login_form() {
814 + $script_ver = (defined('WP_DEBUG') && WP_DEBUG) ? time() : $this->version;
815 + wp_enqueue_script( 'tfa-wc-ajax-request', SIMBA_TFA_PLUGIN_URL.'/includes/wooextend.js', array('jquery'), $script_ver);
816 + $localize = array(
817 + 'ajaxurl' => admin_url('admin-ajax.php'),
818 + 'click_to_enter_otp' => __("Enter One Time Password (if you have one)", SIMBA_TFA_TEXT_DOMAIN),
819 + 'enter_username_first' => __('You have to enter a username first.', SIMBA_TFA_TEXT_DOMAIN),
820 + 'otp' => __("One Time Password", SIMBA_TFA_TEXT_DOMAIN),
821 + 'nonce' => wp_create_nonce("simba_tfa_loginform_nonce"),
822 + 'otp_login_help' => __('(check your OTP app to get this password)', SIMBA_TFA_TEXT_DOMAIN),
823 + );
824 + // Spinner exists since WC 3.8. Use the proper functions to avoid SSL warnings.
825 + if (file_exists(ABSPATH.'wp-admin/images/spinner.gif')) {
826 + $localize['spinnerimg'] = admin_url('images/spinner.gif');
827 + } elseif (file_exists(ABSPATH.WPINC.'/images/spinner.gif')) {
828 + $localize['spinnerimg'] = includes_url('images/spinner.gif');
829 + }
251 830
252 - if (!class_exists('Updraft_Manager_Updater_1_8')) require_once(plugin_dir_path(__FILE__).'vendor/davidanderson684/simba-plugin-manager-updater/class-udm-updater.php');
831 + wp_localize_script( 'tfa-wc-ajax-request', 'simbatfa_wc_settings', $localize);
832 + }
253 833
254 - try {
255 - new Updraft_Manager_Updater_1_8('https://www.simbahosting.co.uk/s3', 1, 'two-factor-authentication-premium/two-factor-login.php', array('require_login' => false));
256 - } catch (Exception $e) {
257 - error_log($e->getMessage());
258 - }
259 834 }
835 +
836 +$simba_two_factor_authentication = new Simba_Two_Factor_Authentication();