PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 1.4.1
WP 2FA – Two-factor authentication for WordPress v1.4.1
1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / WP2FA.php
wp-2fa / includes / classes Last commit date
Admin 5 years ago Authenticator 5 years ago BackgroundProcessing 5 years ago Cron 5 years ago Shortcodes 6 years ago .gitkeep 6 years ago WP2FA.php 5 years ago
WP2FA.php
641 lines
1 <?php // phpcs:ignore
2
3 namespace WP2FA;
4
5 /**
6 * Main WP2FA Class.
7 */
8 class WP2FA {
9
10 /**
11 * Plugin version.
12 *
13 * @var string
14 */
15 public $version = WP_2FA_VERSION;
16
17 /**
18 * Options variables.
19 *
20 * @var array
21 */
22 protected static $wp_2fa_options;
23 protected static $wp_2fa_email_templates;
24
25 /**
26 * Instance wrapper.
27 *
28 * @var object
29 */
30 private static $instance = null;
31
32 /**
33 * Return plugin instance.
34 */
35 public static function get_instance() {
36
37 if ( null === self::$instance ) {
38 self::$instance = new self();
39 }
40
41 return self::$instance;
42 }
43
44 /**
45 * Contructor.
46 */
47 private function __construct() {
48 if ( self::is_this_multisite() ) {
49 self::$wp_2fa_options = get_network_option( null, 'wp_2fa_settings' );
50 self::$wp_2fa_email_templates = get_network_option( null, 'wp_2fa_email_settings' );
51 } else {
52 self::$wp_2fa_options = get_option( 'wp_2fa_settings' );
53 self::$wp_2fa_email_templates = get_option( 'wp_2fa_email_settings' );
54 }
55
56 // Activation/Deactivation.
57 register_activation_hook( WP_2FA_FILE, '\WP2FA\Core\activate' );
58 register_deactivation_hook( WP_2FA_FILE, '\WP2FA\Core\deactivate' );
59 // Register our uninstallation hook.
60 register_uninstall_hook( WP_2FA_FILE, '\WP2FA\Core\uninstall' );
61 }
62
63 /**
64 * Fire up classes.
65 */
66 public function init() {
67 // Bootstrap.
68 Core\setup();
69
70 $this->settings = new Admin\SettingsPage();
71 $this->wizard = new Admin\SetupWizard();
72 $this->authentication = new Authenticator\Authentication();
73 $this->backupcodes = new Authenticator\BackupCodes();
74 $this->login = new Authenticator\Login();
75 $this->user_notices = new Admin\UserNotices();
76 $this->crontasks = new Cron\CronTasks();
77 $this->user_registered = new Admin\UserRegistered();
78 $this->shortcodes = new Shortcodes\Shortcodes();
79 $this->bg_processing = new BackgroundProcessing\ProcessUserMetaUpdate();
80
81 global $pagenow;
82 if ( 'profile.php' !== $pagenow || 'user-edit.php' !== $pagenow ) {
83 $this->user_profiles = new Admin\UserProfile();
84 }
85
86 $this->add_actions();
87 }
88
89 /**
90 * Add our plugins actions.
91 */
92 public function add_actions() {
93 // Plugin redirect on activation, only if we have no settings currently saved.
94 if ( empty( self::$wp_2fa_options ) || ! isset( self::$wp_2fa_options ) ) {
95 add_action( 'admin_init', array( $this, 'setup_redirect' ), 10 );
96 }
97
98 // SettingsPage.
99 if ( self::is_this_multisite() ) {
100 add_action( 'network_admin_menu', array( $this->settings, 'create_settings_admin_menu_multisite' ) );
101 add_action( 'network_admin_edit_update_wp2fa_network_options', array( $this->settings, 'update_wp2fa_network_options' ) );
102 add_action( 'network_admin_edit_update_wp2fa_network_email_options', array( $this->settings, 'update_wp2fa_network_email_options' ) );
103 add_action( 'network_admin_notices', array( $this->settings, 'settings_saved_network_admin_notice' ) );
104 } else {
105 add_action( 'admin_menu', array( $this->settings, 'create_settings_admin_menu' ) );
106 }
107 add_action( 'wp_ajax_get_all_users', array( $this->settings, 'get_all_users' ) );
108 add_action( 'wp_ajax_get_all_network_sites', array( $this->settings, 'get_all_network_sites' ) );
109 add_action( 'wp_ajax_unlock_account', array( $this->settings, 'unlock_account' ), 10, 1 );
110 add_action( 'admin_action_unlock_account', array( $this->settings, 'unlock_account' ), 10, 1 );
111 add_action( 'admin_action_remove_user_2fa', array( $this->settings, 'remove_user_2fa' ), 10, 1 );
112 add_action( 'wp_ajax_remove_user_2fa', array( $this->settings, 'remove_user_2fa' ), 10, 1 );
113 add_action( 'admin_menu', array( $this->settings, 'hide_settings' ), 999 );
114 add_action( 'plugin_action_links_' . WP_2FA_BASE, array( $this->settings, 'add_plugin_action_links' ) );
115 add_filter( 'display_post_states', array( $this->settings, 'add_display_post_states' ), 10, 2 );
116
117 // SetupWizard.
118 if ( self::is_this_multisite() ) {
119 add_action( 'network_admin_menu', array( $this->wizard, 'network_admin_menus' ), 10 );
120 add_action( 'admin_menu', array( $this->wizard, 'admin_menus' ), 10 );
121 } else {
122 add_action( 'admin_menu', array( $this->wizard, 'admin_menus' ), 10 );
123 }
124 add_action( 'plugins_loaded', array( $this, 'add_wizard_actions' ), 10 );
125 add_action( 'wp_ajax_send_authentication_setup_email', array( $this->wizard, 'send_authentication_setup_email' ) );
126 add_action( 'wp_ajax_regenerate_authentication_key', array( $this->wizard, 'regenerate_authentication_key' ) );
127
128 // UserNotices.
129 add_action( 'wp_ajax_dismiss_nag', array( $this->user_notices, 'dismiss_nag' ) );
130 add_action( 'wp_ajax_dismiss_nag', array( $this->user_notices, 'dismiss_reconfigure_nag' ) );
131 add_action( 'clear_auth_cookie', array( $this->user_notices, 'reset_nag' ) );
132
133 // UserProfile.
134 global $pagenow;
135 if ( 'profile.php' !== $pagenow || 'user-edit.php' !== $pagenow ) {
136 add_action( 'show_user_profile', array( $this->user_profiles, 'user_2fa_options' ) );
137 add_action( 'edit_user_profile', array( $this->user_profiles, 'user_2fa_options' ) );
138 if ( self::is_this_multisite() ) {
139 add_action( 'personal_options_update', array( $this->user_profiles, 'save_user_2fa_options' ) );
140 }
141 }
142 add_filter( 'user_row_actions', array( $this->user_profiles, 'user_2fa_row_actions' ), 10, 2 );
143 if ( self::is_this_multisite() ) {
144 add_filter( 'ms_user_row_actions', array( $this->user_profiles, 'user_2fa_row_actions' ), 10, 2 );
145 }
146 add_action( 'wp_ajax_validate_authcode_via_ajax', array( $this->user_profiles, 'validate_authcode_via_ajax' ) );
147
148 // Login.
149 add_action( 'init', array( $this->login, 'get_providers' ) );
150 add_action( 'wp_login', array( $this->login, 'wp_login' ), 10, 2 );
151 add_action( 'login_form_validate_2fa', array( $this->login, 'login_form_validate_2fa' ) );
152 add_action( 'login_form_backup_2fa', array( $this->login, 'backup_2fa' ) );
153
154 /**
155 * Keep track of all the user sessions for which we need to invalidate the
156 * authentication cookies set during the initial password check.
157 */
158 add_action( 'set_auth_cookie', array( $this->login, 'collect_auth_cookie_tokens' ) );
159 add_action( 'set_logged_in_cookie', array( $this->login, 'collect_auth_cookie_tokens' ) );
160
161 // Run only after the core wp_authenticate_username_password() check.
162 add_filter( 'authenticate', array( $this->login, 'filter_authenticate' ), 50 );
163 add_filter( 'wp_authenticate_user', array( $this->login, 'is_user_locked' ), 10, 2 );
164
165 // User Register.
166 add_action( 'set_user_role', array( $this->user_registered, 'check_user_upon_role_change' ), 10, 3 );
167
168 // Block users from admin if needed.
169 add_action( 'init', array( $this, 'block_unconfigured_users_from_admin' ), 10 );
170 }
171
172 /**
173 * Add actions specific to the wizard.
174 */
175 public function add_wizard_actions() {
176 new BackgroundProcessing\ProcessUserMetaUpdate();
177 if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'read' ) ) {
178 add_action( 'admin_init', array( $this->wizard, 'setup_page' ), 10 );
179 }
180 }
181
182 /**
183 * Redirect user to 1st time setup.
184 */
185 public function setup_redirect() {
186
187 // Bail early before the redirect if the user can't manage options.
188 if ( ! current_user_can( 'manage_options' ) ) {
189 return;
190 }
191
192 if ( get_option( 'wp_2fa_redirect_on_activate', false ) ) {
193 // Delete redirect option.
194 delete_option( 'wp_2fa_redirect_on_activate' );
195
196 // Redirect URL.
197 $redirect = '';
198
199 // If current site is multisite and user is super-admin then redirect to network audit log.
200 if ( self::is_this_multisite() && is_super_admin() ) {
201 $redirect = add_query_arg( 'page', 'wp-2fa-setup', network_admin_url( 'index.php' ) );
202 } else {
203 // Otherwise redirect to main audit log view.
204 $redirect = add_query_arg( 'page', 'wp-2fa-setup', admin_url( 'options-general.php' ) );
205 }
206 wp_safe_redirect( $redirect );
207 exit();
208 }
209 }
210
211 /**
212 * Check is this is a multisite setup.
213 */
214 public static function is_this_multisite() {
215 return function_exists( 'is_multisite' ) && is_multisite();
216 }
217
218 /**
219 * Return user roles.
220 *
221 * @return array User roles.
222 */
223 public static function wp_2fa_get_roles() {
224 global $wp_roles;
225 $roles = $wp_roles->role_names;
226 return $roles;
227 }
228
229 /**
230 * Check to see if the user or user role is excluded.
231 *
232 * @param int $user_id User id.
233 * @return boolean Is user excluded or not.
234 */
235 public static function is_user_excluded( $user_id, $excluded_users = '', $excluded_roles = '', $excluded_sites = '' ) {
236
237 // Check if the $user_id is actually an object, if so lets just use it.
238 if ( ! is_a( $user_id, '\WP_User' ) ) {
239 if ( isset( $user_id ) ) {
240 if ( is_object( $user_id ) && isset( $user_id->ID ) ) {
241 $user = get_userdata( $user_id->ID );
242 $user_roles = $user->roles;
243 } else {
244 $user = get_user_by( 'id', $user_id );
245 $user_roles = $user->roles;
246 }
247 } elseif ( isset( $_GET['user_id'] ) ) {
248 $user_id = (int) $_GET['user_id'];
249 $user = get_user_by( 'id', $user_id );
250 $user_roles = $user->roles;
251 } else {
252 $user = wp_get_current_user();
253 $user_roles = $user->roles;
254 }
255 } else {
256 $user = $user_id;
257 $user_roles = $user->roles;
258 }
259
260 $user_excluded = false;
261
262 if ( isset( $excluded_users ) && ! empty( $excluded_users ) ) {
263 $excluded_users = $excluded_users;
264 } else {
265 $excluded_users = WP2FA::get_wp2fa_setting( 'excluded_users' );
266 }
267
268 if ( ! empty( $excluded_users ) ) {
269 // Turn it into an array.
270 $excluded_users_array = explode( ',', $excluded_users );
271 // Compare our roles with the users and see if we get a match.
272 $result = in_array( $user->user_login, $excluded_users_array, true );
273 if ( $result ) {
274 $user_excluded = true;
275 return true;
276 }
277 }
278
279 if ( isset( $excluded_roles ) && ! empty( $excluded_roles ) ) {
280 $excluded_roles = $excluded_roles;
281 } else {
282 $excluded_roles = WP2FA::get_wp2fa_setting( 'excluded_roles' );
283 }
284
285 if ( ! empty( $excluded_roles ) ) {
286 // Turn it into an array.
287 $excluded_roles_array = explode( ',', strtolower( $excluded_roles ) );
288 // Compare our roles with the users and see if we get a match.
289 $result = array_intersect( $excluded_roles_array, $user->roles );
290 if ( $result ) {
291 $user_excluded = true;
292 return true;
293 }
294 }
295
296 if ( self::is_this_multisite() ) {
297 if ( isset( $excluded_sites ) && ! empty( $excluded_sites ) ) {
298 $excluded_sites = $excluded_sites;
299 } else {
300 $excluded_sites = WP2FA::get_wp2fa_setting( 'excluded_sites' );
301 }
302
303 if ( ! empty( $excluded_sites ) ) {
304 // Turn it into an array.
305 $excluded_site_array = explode( ',', strtolower( $excluded_sites ) );
306 $site_ids_only = array();
307 // Remove everything but the excluded sites ID, which we will use to check if user is a member.
308 foreach ( $excluded_site_array as $excluded_site ) {
309 if ( isset( explode( ':', $excluded_site )[1] ) ) {
310 $id = trim( explode( ':', $excluded_site )[1] );
311 $site_ids_only[] = $id;
312 }
313 }
314 foreach ( $site_ids_only as $site_id ) {
315 if ( is_user_member_of_blog( $user->ID, $site_id ) ) {
316 // User is a member of the a blog we are excluding from 2FA.
317 $user_excluded = true;
318 return true;
319 } else {
320 // User is NOT a member of the a blog we are excluding.
321 $user_excluded = false;
322 }
323 }
324 }
325 }
326
327 if ( true === $user_excluded ) {
328 return true;
329 }
330
331 return false;
332 }
333
334 /**
335 * Util function to grab settings or apply defaults if no settings are saved into the db.
336 *
337 * @param string $setting_name Settings to grab value of.
338 * @return string Settings value or default value.
339 */
340 public static function get_wp2fa_setting( $setting_name = '' ) {
341 $default_settings = array(
342 'enable_totp' => 'enable_totp',
343 'enable_email' => 'enable_email',
344 'enforcment-policy' => 'do-not-enforce',
345 'excluded_users' => '',
346 'excluded_roles' => '',
347 'enforced_users' => '',
348 'enforced_roles' => '',
349 'grace-period' => 3,
350 'grace-period-denominator' => 'days',
351 'enable_grace_cron' => '',
352 'enable_destroy_session' => '',
353 'limit_access' => '',
354 '2fa_settings_last_updated_by' => '',
355 '2fa_main_user' => '',
356 'grace-period-expiry-time' => '',
357 'plugin_version' => WP_2FA_VERSION,
358 'delete_data_upon_uninstall' => '',
359 'excluded_sites' => '',
360 'create-custom-user-page' => 'no',
361 'custom-user-page-url' => '',
362 'custom-user-page-id' => '',
363 'hide_remove_button' => '',
364 'grace-policy' => 'use-grace-period',
365 );
366
367 $apply_defaults = false;
368
369 // If we have no setting name, return them all.
370 if ( empty( $setting_name ) ) {
371 return self::$wp_2fa_options;
372 }
373
374 // First lets check if any options have been saved.
375 if ( empty( self::$wp_2fa_options ) || ! isset( self::$wp_2fa_options ) ) {
376 $apply_defaults = true;
377 }
378
379 if ( $apply_defaults ) {
380 return $default_settings[ $setting_name ];
381 } elseif ( ! isset( self::$wp_2fa_options[ $setting_name ] ) ) {
382 return false;
383 } else {
384 return self::$wp_2fa_options[ $setting_name ];
385 }
386 }
387
388 /**
389 * Util function to grab EMAIL settings or apply defaults if no settings are saved into the db.
390 *
391 * @param string $setting_name Settings to grab value of.
392 * @return string Settings value or default value.
393 */
394 public static function get_wp2fa_email_templates( $setting_name = '', $grab_default = '' ) {
395
396 if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) {
397 // Setup enable 2fa email.
398 $enable_2fa_message = sprintf(
399 /* translators: %1$s: is the user name, %2$s is the website address */
400 '<p>%1$s %2$s %3$s <strong>%4$s</strong> %5$s <strong>%6$s.</strong></p><p>%11$s <a href="%12$s" target="_blank">%12$s.</a></p><p>%7$s</p><p>%8$s</p><p>%9$s <a href="https://www.wpwhitesecurity.com/wordpress-plugins/wp-2fa/" target="_blank">%10$s</a></p>',
401 esc_html__( 'The administrator of the website', 'wp-2fa' ),
402 '{site_url}',
403 esc_html__( 'enforced two-factor authentication. You have', 'wp-2fa' ),
404 '{grace_period}',
405 esc_html__( 'to enable and configure 2FA on your WordPress user', 'wp-2fa' ),
406 '{user_login_name}',
407 esc_html__( 'Failing to enable 2FA within the grace period will result in a locked account. In case that happens contact the website’s administrator.', 'wp-2fa' ),
408 esc_html__( 'Thank you.', 'wp-2fa' ),
409 esc_html__( 'Email sent by', 'wp-2fa' ),
410 esc_html__( 'WP 2FA plugin.', 'wp-2fa' ),
411 esc_html__( 'You can configure 2FA from this page:', 'wp-2fa' ),
412 '{2fa_settings_page_url}'
413 );
414 } else {
415 // Setup enable 2fa email.
416 $enable_2fa_message = sprintf(
417 /* translators: %1$s: is the user name, %2$s is the website address */
418 '<p>%1$s %2$s %3$s <strong>%4$s</strong> %5$s <strong>%6$s.</strong></p><p>%7$s</p><p>%8$s</p><p>%9$s <a href="https://www.wpwhitesecurity.com/wordpress-plugins/wp-2fa/" target="_blank">%10$s</a></p>',
419 esc_html__( 'The administrator of the website', 'wp-2fa' ),
420 '{site_url}',
421 esc_html__( 'enforced two-factor authentication. You have', 'wp-2fa' ),
422 '{grace_period}',
423 esc_html__( 'to enable and configure 2FA on your WordPress user', 'wp-2fa' ),
424 '{user_login_name}',
425 esc_html__( 'Failing to enable 2FA within the grace period will result in a locked account. In case that happens contact the website’s administrator.', 'wp-2fa' ),
426 esc_html__( 'Thank you.', 'wp-2fa' ),
427 esc_html__( 'Email sent by', 'wp-2fa' ),
428 esc_html__( 'WP 2FA plugin.', 'wp-2fa' )
429 );
430 }
431
432 $enable_2fa_subject = __( 'Please enable 2FA on {site_url}', 'wp-2fa' );
433 $enable_2fa_body = $enable_2fa_message;
434
435 // Setup login code email.
436 $login_code_message = sprintf(
437 /* translators: %s: the token for the user to use */
438 '<p>%1$s <strong>%2$s</strong> %3$s</p><p>%4$s</p><p>%5$s <a href="https://www.wpwhitesecurity.com/wordpress-plugins/wp-2fa/" target="_blank">%6$s</a></p>',
439 esc_html__( 'Enter', 'wp-2fa' ),
440 '{login_code}',
441 esc_html__( 'to log in.', 'wp-2fa' ),
442 esc_html__( 'Thank you.', 'wp-2fa' ),
443 esc_html__( 'Email sent by', 'wp-2fa' ),
444 esc_html__( 'WP 2FA plugin.', 'wp-2fa' )
445 );
446
447 $login_code_subject = __( 'Your login confirmation code for {site_name}', 'wp-2fa' );
448 $login_code_body = $login_code_message;
449
450 // Setup user locked email.
451 $user_locked_message = sprintf(
452 /* translators: %1$s: is the user name, %2$s is the website name */
453 '<p>%1$s</p><p>%2$s %3$s %4$s %5$s %6$s</p><p>%7$s</p><p>%8$s</p><p>%9$s <a href="https://www.wpwhitesecurity.com/wordpress-plugins/wp-2fa/" target="_blank">%10$s</a></p>',
454 esc_html__( 'Hello.', 'wp-2fa' ),
455 esc_html__( 'Since you have not enabled two-factor authentication for the user', 'wp-2fa' ),
456 '{user_login_name}',
457 esc_html__( 'on the website', 'wp-2fa' ),
458 '{site_name}',
459 esc_html__( 'within the grace period, your account has been locked.', 'wp-2fa' ),
460 esc_html__( 'Contact your website administrator to unlock your account.', 'wp-2fa' ),
461 esc_html__( 'Thank you.', 'wp-2fa' ),
462 esc_html__( 'Email sent by', 'wp-2fa' ),
463 esc_html__( 'WP 2FA plugin.', 'wp-2fa' )
464 );
465
466 $user_locked_subject = __( 'Your user on {site_name} has been locked', 'wp-2fa' );
467 $user_locked_body = $user_locked_message;
468
469 if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) {
470 // Setup user unlocked email.
471 $user_unlocked_message = sprintf(
472 /* translators: %1$s: is the user name, %2$s is the website address */
473 '<p>%1$s</p><p>%2$s <strong>%3$s</strong> %4$s %5$s %6$s</p><p>%10$s <a href="%11$s" target="_blank">%11$s.</a></p><p>%7$s</p><p>%8$s <a href="https://www.wpwhitesecurity.com/wordpress-plugins/wp-2fa/" target="_blank">%9$s</a></p>',
474 esc_html__( 'Hello,', 'wp-2fa' ),
475 esc_html__( 'Your user', 'wp-2fa' ),
476 '{user_login_name}',
477 esc_html__( 'on the website', 'wp-2fa' ),
478 '{site_url}',
479 esc_html__( 'has been unlocked. Please configure two-factor authentication within the grace period, otherwise your account will be locked again.', 'wp-2fa' ),
480 esc_html__( 'Thank you.', 'wp-2fa' ),
481 esc_html__( 'Email sent by', 'wp-2fa' ),
482 esc_html__( 'WP 2FA plugin', 'wp-2fa' ),
483 esc_html__( 'You can configure 2FA from this page:', 'wp-2fa' ),
484 '{2fa_settings_page_url}'
485 );
486 } else {
487 // Setup user unlocked email.
488 $user_unlocked_message = sprintf(
489 /* translators: %1$s: is the user name, %2$s is the website address */
490 '<p>%1$s</p><p>%2$s <strong>%3$s</strong> %4$s %5$s %6$s</p><p>%7$s</p><p>%8$s <a href="https://www.wpwhitesecurity.com/wordpress-plugins/wp-2fa/" target="_blank">%9$s</a></p>',
491 esc_html__( 'Hello,', 'wp-2fa' ),
492 esc_html__( 'Your user', 'wp-2fa' ),
493 '{user_login_name}',
494 esc_html__( 'on the website', 'wp-2fa' ),
495 '{site_url}',
496 esc_html__( 'has been unlocked. Please configure two-factor authentication within the grace period, otherwise your account will be locked again.', 'wp-2fa' ),
497 esc_html__( 'Thank you.', 'wp-2fa' ),
498 esc_html__( 'Email sent by', 'wp-2fa' ),
499 esc_html__( 'WP 2FA plugin', 'wp-2fa' )
500 );
501 }
502
503 $user_unlocked_subject = __( 'Your user on {site_name} has been unlocked', 'wp-2fa' );
504 $user_unlocked_body = $user_unlocked_message;
505
506 // Array of defaults, now we have things setup above.
507 $default_settings = array(
508 'email_from_setting' => 'use-defaults',
509 'custom_from_email_address' => '',
510 'custom_from_display_name' => '',
511 'enforced_email_subject' => $enable_2fa_subject,
512 'enforced_email_body' => $enable_2fa_body,
513 'login_code_email_subject' => $login_code_subject,
514 'login_code_email_body' => $login_code_body,
515 'user_account_locked_email_subject' => $user_locked_subject,
516 'user_account_locked_email_body' => $user_locked_body,
517 'user_account_unlocked_email_subject' => $user_unlocked_subject,
518 'user_account_unlocked_email_body' => $user_unlocked_body,
519 'send_enforced_email' => 'enable_enforced_email',
520 'send_account_locked_email' => 'enable_account_locked_email',
521 'send_account_unlocked_email' => 'enable_account_unlocked_email',
522 );
523
524 $apply_defaults = false;
525
526 // If we have no setting name, return them all.
527 if ( empty( $setting_name ) ) {
528 return self::$wp_2fa_email_templates;
529 }
530
531 // First lets check if any options have been saved.
532 if ( empty( self::$wp_2fa_email_templates ) || ! isset( self::$wp_2fa_email_templates ) ) {
533 $apply_defaults = true;
534 }
535
536 if ( $apply_defaults || ! empty( $grab_default ) ) {
537 return $default_settings[ $setting_name ];
538 } elseif ( ! isset( self::$wp_2fa_email_templates[ $setting_name ] ) ) {
539 return false;
540 } else {
541 return self::$wp_2fa_email_templates[ $setting_name ];
542 }
543 }
544
545 /**
546 * Util which we use to replace our {strings} with actual, useful stuff.
547 *
548 * @param string $input Text we are working on.
549 * @param int $user_id User id, if its needed.
550 * @param string $token Login code, if its needed..
551 * @return string The output, with all the {strings} swapped out.
552 */
553 public static function replace_email_strings( $input = '', $user_id = '', $token = '', $override_grace_period = '' ) {
554
555 // Gather grace period.
556 $grace_period = self::get_wp2fa_setting( 'grace-period' );
557 $grace_period_denominator = self::get_wp2fa_setting( 'grace-period-denominator' );
558 if ( isset( $override_grace_period ) && ! empty( $override_grace_period ) ) {
559 $grace_period = $override_grace_period;
560 } else {
561 $grace_period = $grace_period . ' ' . $grace_period_denominator;
562 }
563
564 // Setup user data.
565 if ( isset( $user_id ) && ! empty( $user_id ) ) {
566 $user = get_userdata( $user_id );
567 } else {
568 $user = wp_get_current_user();
569 }
570
571 // Setup token.
572 if ( isset( $token ) && ! empty( $token ) ) {
573 $login_code = $token;
574 } else {
575 $login_code = '';
576 }
577
578 $new_page_id = WP2FA::get_wp2fa_setting( 'custom-user-page-id' );
579 if ( ! empty( $new_page_id ) ) {
580 $new_page_permalink = get_permalink( $new_page_id );
581 } else {
582 $new_page_permalink = '';
583 }
584
585 // These are the strings we are going to search for, as well as there respective replacements.
586 $replacements = array(
587 '{site_url}' => esc_url( get_bloginfo( 'url' ) ),
588 '{site_name}' => sanitize_text_field( get_bloginfo( 'name' ) ),
589 '{grace_period}' => sanitize_text_field( $grace_period ),
590 '{user_login_name}' => sanitize_text_field( $user->user_login ),
591 '{login_code}' => sanitize_text_field( $login_code ),
592 '{2fa_settings_page_url}' => esc_url( $new_page_permalink ),
593 );
594
595 $replacements = apply_filters(
596 'wp_2fa_replacement_email_strings',
597 $replacements
598 );
599
600 $final_output = str_replace( array_keys( $replacements ), array_values( $replacements ), $input );
601 return $final_output;
602 }
603
604 /**
605 * If a user is trying to access anywhere other than the 2FA config area, this blocks them.
606 */
607 public function block_unconfigured_users_from_admin() {
608 global $pagenow;
609 $user = wp_get_current_user();
610 $is_user_instantly_enforced = get_user_meta( $user->ID, 'wp_2fa_user_enforced_instantly', true );
611 $grace_period_expiry_time = get_user_meta( $user->ID, 'wp_2fa_grace_period_expiry', true );
612 $time_now = time();
613
614 if ( 'use-grace-period' !== WP2FA::get_wp2fa_setting( 'grace-policy' ) ) {
615 if ( self::is_this_multisite() ) {
616 if ( $is_user_instantly_enforced && ! empty( $grace_period_expiry_time ) && $grace_period_expiry_time < $time_now ) {
617 if ( $pagenow !== 'index.php' || ( $pagenow !== 'index.php' ) && ( isset( $_GET['page'] ) && $_GET['page'] !== 'wp-2fa-setup' ) ) {
618 if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] === 'send_authentication_setup_email' || isset( $_REQUEST['action'] ) && $_REQUEST['action'] === 'validate_authcode_via_ajax' ) {
619 return;
620 }
621 // Grab user session and kill it, preferably with fire.
622 $manager = \WP_Session_Tokens::get_instance( $user->ID );
623 $manager->destroy_all();
624 }
625 }
626 } else {
627 if ( $is_user_instantly_enforced && ! empty( $grace_period_expiry_time ) && $grace_period_expiry_time < $time_now ) {
628 if ( $pagenow !== 'options-general.php' || ( $pagenow !== 'options-general.php' ) && ( isset( $_GET['page'] ) && $_GET['page'] !== 'wp-2fa-setup' ) ) {
629 if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] === 'send_authentication_setup_email' || isset( $_REQUEST['action'] ) && $_REQUEST['action'] === 'validate_authcode_via_ajax' ) {
630 return;
631 }
632 // Grab user session and kill it, preferably with fire.
633 $manager = \WP_Session_Tokens::get_instance( $user->ID );
634 $manager->destroy_all();
635 }
636 }
637 }
638 }
639 }
640 }
641