rebase on oct-10-2023

This commit is contained in:
Rachit Bhargava
2023-10-10 17:23:21 -04:00
parent d37566ffb6
commit d096058d7d
4789 changed files with 254611 additions and 307223 deletions

View File

@@ -57,17 +57,17 @@ class Controller_AJAX {
),
'save_options' => array(
'handler' => array($this, '_ajax_save_options_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to change options.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to change options.', 'wordfence')),
'required_parameters' => array('nonce', 'changes'),
),
'send_grace_period_notification' => array(
'handler' => array($this, '_ajax_send_grace_period_notification_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to send notifications.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to send notifications.', 'wordfence')),
'required_parameters' => array('nonce', 'role', 'url'),
),
'update_ip_preview' => array(
'handler' => array($this, '_ajax_update_ip_preview_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to change options.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to change options.', 'wordfence')),
'required_parameters' => array('nonce', 'ip_source', 'ip_source_trusted_proxies'),
),
'dismiss_notice' => array(
@@ -77,32 +77,32 @@ class Controller_AJAX {
),
'reset_recaptcha_stats' => array(
'handler' => array($this, '_ajax_reset_recaptcha_stats_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to reset reCAPTCHA statistics.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to reset reCAPTCHA statistics.', 'wordfence')),
'required_parameters' => array('nonce'),
),
'reset_2fa_grace_period' => array (
'handler' => array($this, '_ajax_reset_2fa_grace_period_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to reset the 2FA grace period.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to reset the 2FA grace period.', 'wordfence')),
'required_parameters' => array('nonce', 'user_id')
),
'revoke_2fa_grace_period' => array (
'handler' => array($this, '_ajax_revoke_2fa_grace_period_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to revoke the 2FA grace period.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to revoke the 2FA grace period.', 'wordfence')),
'required_parameters' => array('nonce', 'user_id')
),
'reset_ntp_failure_count' => array(
'handler' => array($this, '_ajax_reset_ntp_failure_count_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to reset the NTP failure count.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to reset the NTP failure count.', 'wordfence')),
'required_parameters' => array(),
),
'disable_ntp' => array(
'handler' => array($this, '_ajax_disable_ntp_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to disable NTP.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to disable NTP.', 'wordfence')),
'required_parameters' => array(),
),
'dismiss_persistent_notice' => array(
'handler' => array($this, '_ajax_dismiss_persistent_notice_callback'),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to dismiss this notice.', 'wordfence-2fa')),
'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to dismiss this notice.', 'wordfence')),
'required_parameters' => array('nonce', 'notice_id')
)
);
@@ -136,14 +136,14 @@ class Controller_AJAX {
if (preg_match('~wordfence_ls_([a-zA-Z_0-9]+)$~', $action, $matches)) {
$action = $matches[1];
if (!isset($this->_actions[$action])) {
self::send_json(array('error' => esc_html__('An unknown action was provided.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('An unknown action was provided.', 'wordfence')));
}
$parameters = $this->_actions[$action];
if (!empty($parameters['required_parameters'])) {
foreach ($parameters['required_parameters'] as $k) {
if (!isset($_POST[$k])) {
self::send_json(array('error' => esc_html__('An expected parameter was not provided.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('An expected parameter was not provided.', 'wordfence')));
}
}
}
@@ -151,7 +151,7 @@ class Controller_AJAX {
if (!isset($parameters['nonce']) || $parameters['nonce']) {
$nonce = (isset($_POST['nonce']) && is_string($_POST['nonce']) && $_POST['nonce']) ? $_POST['nonce'] : $_GET['nonce'];
if (!is_string($nonce) || !wp_verify_nonce($nonce, 'wp-ajax')) {
self::send_json(array('error' => esc_html__('Your browser sent an invalid security token. Please try reloading this page.', 'wordfence-2fa'), 'tokenInvalid' => 1));
self::send_json(array('error' => esc_html__('Your browser sent an invalid security token. Please try reloading this page.', 'wordfence'), 'tokenInvalid' => 1));
}
}
@@ -183,7 +183,7 @@ class Controller_AJAX {
}
}
if (empty($username) || empty($password)) {
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: A username and password must be provided. <a href="%s" title="Password Lost and Found">Lost your password</a>?', 'wordfence-2fa'), wp_lostpassword_url()), array('strong'=>array(), 'a'=>array('href'=>array(), 'title'=>array())))));
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: A username and password must be provided. <a href="%s" title="Password Lost and Found">Lost your password</a>?', 'wordfence'), wp_lostpassword_url()), array('strong'=>array(), 'a'=>array('href'=>array(), 'title'=>array())))));
}
$legacy2FAActive = Controller_WordfenceLS::shared()->legacy_2fa_active();
@@ -207,7 +207,7 @@ class Controller_AJAX {
$reset = false;
foreach ($user->get_error_codes() as $code) {
if ($code == 'invalid_username' || $code == 'invalid_email' || $code == 'incorrect_password' || $code == 'authentication_failed') {
$errors[] = wp_kses(sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%s" title="Password Lost and Found">Lost your password</a>?', 'wordfence-2fa'), wp_lostpassword_url()), array('strong'=>array(), 'a'=>array('href'=>array(), 'title'=>array())));
$errors[] = wp_kses(sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%s" title="Password Lost and Found">Lost your password</a>?', 'wordfence'), wp_lostpassword_url()), array('strong'=>array(), 'a'=>array('href'=>array(), 'title'=>array())));
}
else {
if ($code == 'wfls_twofactor_invalid') {
@@ -239,7 +239,7 @@ class Controller_AJAX {
}
}
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%s" title="Password Lost and Found">Lost your password</a>?', 'wordfence-2fa'), wp_lostpassword_url()), array('strong'=>array(), 'a'=>array('href'=>array(), 'title'=>array())))));
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%s" title="Password Lost and Found">Lost your password</a>?', 'wordfence'), wp_lostpassword_url()), array('strong'=>array(), 'a'=>array('href'=>array(), 'title'=>array())))));
}
public function _ajax_register_support_callback() {
@@ -254,7 +254,7 @@ class Controller_AJAX {
$email === null ||
!isset($_POST['wfls-message']) || !is_string($_POST['wfls-message']) ||
!isset($_POST['wfls-message-nonce']) || !is_string($_POST['wfls-message-nonce'])) {
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.', 'wordfence-2fa')), array('strong'=>array()))));
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.', 'wordfence')), array('strong'=>array()))));
}
$email = sanitize_email($email);
@@ -265,7 +265,7 @@ class Controller_AJAX {
$nonce = $_POST['wfls-message-nonce'];
if ((isset($_POST['user_login']) && empty($login)) || empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL) || empty($message)) {
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.', 'wordfence-2fa')), array('strong'=>array()))));
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.', 'wordfence')), array('strong'=>array()))));
}
$jwt = Model_JWT::decode_jwt($_POST['wfls-message-nonce']);
@@ -273,30 +273,30 @@ class Controller_AJAX {
$decryptedIP = Model_Symmetric::decrypt($jwt->payload['ip']);
$decryptedScore = Model_Symmetric::decrypt($jwt->payload['score']);
if ($decryptedIP === false || $decryptedScore === false || Model_IP::inet_pton($decryptedIP) !== Model_IP::inet_pton(Model_Request::current()->ip())) { //JWT IP and the current request's IP don't match, refuse the message
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.', 'wordfence-2fa')), array('strong'=>array()))));
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.', 'wordfence')), array('strong'=>array()))));
}
$identifier = bin2hex(Model_IP::inet_pton($decryptedIP));
$tokenBucket = new Model_TokenBucket('rate:' . $identifier, 2, 1 / (6 * Model_TokenBucket::HOUR)); //Maximum of two requests, refilling at a rate of one per six hours
if (!$tokenBucket->consume(1)) {
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. You have exceeded the maximum number of messages that may be sent at this time. Please try again later.', 'wordfence-2fa')), array('strong'=>array()))));
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. You have exceeded the maximum number of messages that may be sent at this time. Please try again later.', 'wordfence')), array('strong'=>array()))));
}
$email = array(
'to' => get_site_option('admin_email'),
'subject' => __('Blocked User Registration Contact Form', 'wordfence-2fa'),
'body' => sprintf(__("A visitor blocked from registration sent the following message.\n\n----------------------------------------\n\nIP: %s\nUsername: %s\nEmail: %s\nreCAPTCHA Score: %f\n\n----------------------------------------\n\n%s", 'wordfence-2fa'), $decryptedIP, $login, $email, $decryptedScore, $message),
'subject' => __('Blocked User Registration Contact Form', 'wordfence'),
'body' => sprintf(__("A visitor blocked from registration sent the following message.\n\n----------------------------------------\n\nIP: %s\nUsername: %s\nEmail: %s\nreCAPTCHA Score: %f\n\n----------------------------------------\n\n%s", 'wordfence'), $decryptedIP, $login, $email, $decryptedScore, $message),
'headers' => '',
);
$success = wp_mail($email['to'], $email['subject'], $email['body'], $email['headers']);
if ($success) {
self::send_json(array('message' => wp_kses(sprintf(__('<strong>MESSAGE SENT</strong>: Your message was sent to the site owner.', 'wordfence-2fa')), array('strong'=>array()))));
self::send_json(array('message' => wp_kses(sprintf(__('<strong>MESSAGE SENT</strong>: Your message was sent to the site owner.', 'wordfence')), array('strong'=>array()))));
}
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: An error occurred while sending the message. Please try again.', 'wordfence-2fa')), array('strong'=>array()))));
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: An error occurred while sending the message. Please try again.', 'wordfence')), array('strong'=>array()))));
}
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.', 'wordfence-2fa')), array('strong'=>array()))));
self::send_json(array('error' => wp_kses(sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.', 'wordfence')), array('strong'=>array()))));
}
public function _ajax_activate_callback() {
@@ -304,31 +304,31 @@ class Controller_AJAX {
$user = wp_get_current_user();
if ($user->ID != $userID) {
if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
self::send_json(array('error' => esc_html__('You do not have permission to activate the given user.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('You do not have permission to activate the given user.', 'wordfence')));
}
else {
$user = new \WP_User($userID);
if (!$user->exists()) {
self::send_json(array('error' => esc_html__('The given user does not exist.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('The given user does not exist.', 'wordfence')));
}
}
}
else if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_SELF)) {
self::send_json(array('error' => esc_html__('You do not have permission to activate 2FA.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('You do not have permission to activate 2FA.', 'wordfence')));
}
if (Controller_Users::shared()->has_2fa_active($user)) {
self::send_json(array('error' => esc_html__('The given user already has two-factor authentication active.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('The given user already has two-factor authentication active.', 'wordfence')));
}
$matches = (isset($_POST['secret']) && isset($_POST['code']) && is_string($_POST['secret']) && is_string($_POST['code']) && Controller_TOTP::shared()->check_code($_POST['secret'], $_POST['code']));
if ($matches === false) {
self::send_json(array('error' => esc_html__('The code provided does not match the expected value. Please verify that the time on your authenticator device is correct and that this server\'s time is correct.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('The code provided does not match the expected value. Please verify that the time on your authenticator device is correct and that this server\'s time is correct.', 'wordfence')));
}
Controller_TOTP::shared()->activate_2fa($user, $_POST['secret'], $_POST['recovery'], $matches);
Controller_Notices::shared()->remove_notice(false, 'wfls-will-be-required', $user);
self::send_json(array('activated' => 1, 'text' => sprintf(count($_POST['recovery']) == 1 ? esc_html__('%d unused recovery code remains. You may generate a new set by clicking below.', 'wordfence-2fa') : esc_html__('%d unused recovery codes remain. You may generate a new set by clicking below.', 'wordfence-2fa'), count($_POST['recovery']))));
self::send_json(array('activated' => 1, 'text' => sprintf(count($_POST['recovery']) == 1 ? esc_html__('%d unused recovery code remains. You may generate a new set by clicking below.', 'wordfence') : esc_html__('%d unused recovery codes remain. You may generate a new set by clicking below.', 'wordfence'), count($_POST['recovery']))));
}
public function _ajax_deactivate_callback() {
@@ -336,21 +336,21 @@ class Controller_AJAX {
$user = wp_get_current_user();
if ($user->ID != $userID) {
if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
self::send_json(array('error' => esc_html__('You do not have permission to deactivate the given user.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('You do not have permission to deactivate the given user.', 'wordfence')));
}
else {
$user = new \WP_User($userID);
if (!$user->exists()) {
self::send_json(array('error' => esc_html__('The user does not exist.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('The user does not exist.', 'wordfence')));
}
}
}
else if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_SELF)) {
self::send_json(array('error' => esc_html__('You do not have permission to deactivate 2FA.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('You do not have permission to deactivate 2FA.', 'wordfence')));
}
if (!Controller_Users::shared()->has_2fa_active($user)) {
self::send_json(array('error' => esc_html__('The user specified does not have two-factor authentication active.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('The user specified does not have two-factor authentication active.', 'wordfence')));
}
Controller_Users::shared()->deactivate_2fa($user);
@@ -362,25 +362,25 @@ class Controller_AJAX {
$user = wp_get_current_user();
if ($user->ID != $userID) {
if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
self::send_json(array('error' => esc_html__('You do not have permission to generate new recovery codes for the given user.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('You do not have permission to generate new recovery codes for the given user.', 'wordfence')));
}
else {
$user = new \WP_User($userID);
if (!$user->exists()) {
self::send_json(array('error' => esc_html__('The user does not exist.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('The user does not exist.', 'wordfence')));
}
}
}
else if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_SELF)) {
self::send_json(array('error' => esc_html__('You do not have permission to generate new recovery codes.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('You do not have permission to generate new recovery codes.', 'wordfence')));
}
if (!Controller_Users::shared()->has_2fa_active($user)) {
self::send_json(array('error' => esc_html__('The user specified does not have two-factor authentication active.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('The user specified does not have two-factor authentication active.', 'wordfence')));
}
$codes = Controller_Users::shared()->regenerate_recovery_codes($user);
self::send_json(array('regenerated' => 1, 'recovery' => array_map(function($r) { return implode(' ', str_split(bin2hex($r), 4)); }, $codes), 'text' => sprintf(count($codes) == 1 ? esc_html__('%d unused recovery code remains. You may generate a new set by clicking below.', 'wordfence-2fa') : esc_html__('%d unused recovery codes remain. You may generate a new set by clicking below.', 'wordfence-2fa'), count($codes))));
self::send_json(array('regenerated' => 1, 'recovery' => array_map(function($r) { return implode(' ', str_split(bin2hex($r), 4)); }, $codes), 'text' => sprintf(count($codes) == 1 ? esc_html__('%d unused recovery code remains. You may generate a new set by clicking below.', 'wordfence') : esc_html__('%d unused recovery codes remain. You may generate a new set by clicking below.', 'wordfence'), count($codes))));
}
public function _ajax_save_options_callback() {
@@ -390,7 +390,7 @@ class Controller_AJAX {
if ($errors !== true) {
if (count($errors) == 1) {
$e = array_shift($errors);
self::send_json(array('error' => esc_html(sprintf(__('An error occurred while saving the configuration: %s', 'wordfence-2fa'), $e))));
self::send_json(array('error' => esc_html(sprintf(__('An error occurred while saving the configuration: %s', 'wordfence'), $e))));
}
else if (count($errors) > 1) {
$compoundMessage = array();
@@ -398,13 +398,13 @@ class Controller_AJAX {
$compoundMessage[] = esc_html($e);
}
self::send_json(array(
'error' => wp_kses(sprintf(__('Errors occurred while saving the configuration: %s', 'wordfence-2fa'), '<ul><li>' . implode('</li><li>', $compoundMessage) . '</li></ul>'), array('ul'=>array(), 'li'=>array())),
'error' => wp_kses(sprintf(__('Errors occurred while saving the configuration: %s', 'wordfence'), '<ul><li>' . implode('</li><li>', $compoundMessage) . '</li></ul>'), array('ul'=>array(), 'li'=>array())),
'html' => true,
));
}
self::send_json(array(
'error' => esc_html__('Errors occurred while saving the configuration.', 'wordfence-2fa'),
'error' => esc_html__('Errors occurred while saving the configuration.', 'wordfence'),
));
}
@@ -424,7 +424,7 @@ class Controller_AJAX {
}
self::send_json(array(
'error' => esc_html__('No configuration changes were provided to save.', 'wordfence-2fa'),
'error' => esc_html__('No configuration changes were provided to save.', 'wordfence'),
));
}
@@ -435,17 +435,17 @@ class Controller_AJAX {
if (!empty($url)) {
$url = get_site_url(null, $url);
if (filter_var($url, FILTER_VALIDATE_URL) === false) {
self::send_json(array('error' => esc_html__('The specified URL is invalid.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('The specified URL is invalid.', 'wordfence')));
}
}
$userCount = count($users);
if (!$notifyAll && $userCount > self::MAX_USERS_TO_NOTIFY)
self::send_json(array('error' => esc_html(sprintf(__('More than %d users exist for the selected role. This notification is not designed to handle large groups of users. In such instances, using a different solution for notifying users of upcoming 2FA requirements is recommended.', 'wordfence-2fa'), self::MAX_USERS_TO_NOTIFY)), 'limit_exceeded' => true));
self::send_json(array('error' => esc_html(sprintf(__('More than %d users exist for the selected role. This notification is not designed to handle large groups of users. In such instances, using a different solution for notifying users of upcoming 2FA requirements is recommended.', 'wordfence'), self::MAX_USERS_TO_NOTIFY)), 'limit_exceeded' => true));
$sent = 0;
foreach ($users as $user) {
Controller_Users::shared()->requires_2fa($user, $inGracePeriod, $requiredAt);
if ($inGracePeriod && !Controller_Users::shared()->has_2fa_active($user)) {
$subject = sprintf(__('2FA will soon be required on %s', 'wordfence-2fa'), home_url());
$subject = sprintf(__('2FA will soon be required on %s', 'wordfence'), home_url());
$requiredDate = Controller_Time::format_local_time('F j, Y g:i A', $requiredAt);
if (empty($url)) {
$userUrl = (is_multisite() && is_super_admin($user->ID)) ? network_admin_url('admin.php?page=WFLS') : admin_url('admin.php?page=WFLS');
@@ -455,7 +455,7 @@ class Controller_AJAX {
}
$message = sprintf(
__("<html><body><p>You do not currently have two-factor authentication active on your account, which will be required beginning %s.</p><p><a href=\"%s\">Configure 2FA</a></p></body></html>", 'wordfence-2fa'),
__("<html><body><p>You do not currently have two-factor authentication active on your account, which will be required beginning %s.</p><p><a href=\"%s\">Configure 2FA</a></p></body></html>", 'wordfence'),
$requiredDate,
htmlentities($userUrl)
);
@@ -466,15 +466,15 @@ class Controller_AJAX {
}
if ($userCount == 0) {
self::send_json(array('error' => esc_html__('No users currently exist with the selected role.', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('No users currently exist with the selected role.', 'wordfence')));
}
else if ($sent == 0) {
self::send_json(array('confirmation' => esc_html__('All users with the selected role already have two-factor authentication activated or have been locked out.', 'wordfence-2fa')));
self::send_json(array('confirmation' => esc_html__('All users with the selected role already have two-factor authentication activated or have been locked out.', 'wordfence')));
}
else if ($sent == 1) {
self::send_json(array('confirmation' => esc_html(sprintf(__('A reminder to activate two-factor authentication was sent to %d user.', 'wordfence-2fa'), $sent))));
self::send_json(array('confirmation' => esc_html(sprintf(__('A reminder to activate two-factor authentication was sent to %d user.', 'wordfence'), $sent))));
}
self::send_json(array('confirmation' => esc_html(sprintf(__('A reminder to activate two-factor authentication was sent to %d users.', 'wordfence-2fa'), $sent))));
self::send_json(array('confirmation' => esc_html(sprintf(__('A reminder to activate two-factor authentication was sent to %d users.', 'wordfence'), $sent))));
}
public function _ajax_update_ip_preview_callback() {
@@ -519,21 +519,21 @@ class Controller_AJAX {
$gracePeriodOverride = array_key_exists('grace_period_override', $_POST) ? (int) $_POST['grace_period_override'] : null;
$user = get_userdata($userId);
if ($user === false)
self::send_json(array('error' => esc_html__('Invalid user specified', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('Invalid user specified', 'wordfence')));
if ($gracePeriodOverride < 0 || $gracePeriodOverride > Controller_Settings::MAX_REQUIRE_2FA_USER_GRACE_PERIOD)
self::send_json(array('error' => esc_html__('Invalid grace period override', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('Invalid grace period override', 'wordfence')));
$gracePeriodAllowed = Controller_Users::shared()->get_grace_period_allowed_flag($userId);
if (!$gracePeriodAllowed)
Controller_Users::shared()->allow_grace_period($userId);
if (!Controller_Users::shared()->reset_2fa_grace_period($user, $gracePeriodOverride))
self::send_json(array('error' => esc_html__('Failed to reset grace period', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('Failed to reset grace period', 'wordfence')));
self::send_json(array('success' => true));
}
public function _ajax_revoke_2fa_grace_period_callback() {
$user = get_userdata((int) $_POST['user_id']);
if ($user === false)
self::send_json(array('error' => esc_html__('Invalid user specified', 'wordfence-2fa')));
self::send_json(array('error' => esc_html__('Invalid user specified', 'wordfence')));
Controller_Users::shared()->revoke_grace_period($user);
self::send_json(array('success' => true));
}
@@ -552,7 +552,7 @@ class Controller_AJAX {
if ($userId !== 0 && Controller_Notices::shared()->dismiss_persistent_notice($userId, $noticeId))
self::send_json(array('success' => true));
self::send_json(array(
'error' => esc_html__('Unable to dismiss notice', 'wordfence-2fa')
'error' => esc_html__('Unable to dismiss notice', 'wordfence')
));
}
}

View File

@@ -199,19 +199,19 @@ class Controller_Settings {
$parsed = array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $value)));
foreach ($parsed as $entry) {
if (!Controller_Whitelist::shared()->is_valid_range($entry)) {
return sprintf(__('The IP/range %s is invalid.', 'wordfence-2fa'), esc_html($entry));
return sprintf(__('The IP/range %s is invalid.', 'wordfence'), esc_html($entry));
}
}
return true;
case self::OPTION_IP_SOURCE:
if (!in_array($value, array(Model_Request::IP_SOURCE_AUTOMATIC, Model_Request::IP_SOURCE_REMOTE_ADDR, Model_Request::IP_SOURCE_X_FORWARDED_FOR, Model_Request::IP_SOURCE_X_REAL_IP))) {
return __('An invalid IP source was provided.', 'wordfence-2fa');
return __('An invalid IP source was provided.', 'wordfence');
}
return true;
case self::OPTION_REQUIRE_2FA_GRACE_PERIOD:
$gracePeriodEnd = strtotime($value);
if ($gracePeriodEnd <= \WordfenceLS\Controller_Time::time()) {
return __('The grace period end time must be in the future.', 'wordfence-2fa');
return __('The grace period end time must be in the future.', 'wordfence');
}
return true;
case self::OPTION_REMEMBER_DEVICE_DURATION:
@@ -233,11 +233,11 @@ class Controller_Settings {
$data = wp_remote_retrieve_body($response);
if (strpos($data, 'grecaptcha') === false) {
return __('Unable to validate the reCAPTCHA site key. Please check the key and try again.', 'wordfence-2fa');
return __('Unable to validate the reCAPTCHA site key. Please check the key and try again.', 'wordfence');
}
return true;
}
return sprintf(__('An error was encountered while validating the reCAPTCHA site key: %s', 'wordfence-2fa'), $response->get_error_message());
return sprintf(__('An error was encountered while validating the reCAPTCHA site key: %s', 'wordfence'), $response->get_error_message());
case self::OPTION_REQUIRE_2FA_USER_GRACE_PERIOD:
return is_numeric($value) && $value >= 0 && $value <= self::MAX_REQUIRE_2FA_USER_GRACE_PERIOD;
}

View File

@@ -546,13 +546,13 @@ SQL
public function _manage_users_columns($columns = array()) {
if (user_can(wp_get_current_user(), Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
$columns['wfls_2fa_status'] = esc_html__('2FA Status', 'wordfence-2fa');
$columns['wfls_2fa_status'] = esc_html__('2FA Status', 'wordfence');
}
if (Controller_Settings::shared()->are_login_history_columns_enabled() && Controller_Permissions::shared()->can_manage_settings(wp_get_current_user())) {
$columns['wfls_last_login'] = esc_html__('Last Login', 'wordfence-2fa');
$columns['wfls_last_login'] = esc_html__('Last Login', 'wordfence');
if (Controller_CAPTCHA::shared()->enabled()) {
$columns['wfls_last_captcha'] = esc_html__('Last CAPTCHA', 'wordfence-2fa');
$columns['wfls_last_captcha'] = esc_html__('Last CAPTCHA', 'wordfence');
}
}
return $columns;
@@ -562,21 +562,21 @@ SQL
switch($column_name) {
case 'wfls_2fa_status':
$user = new \WP_User($user_id);
$value = __('Not Allowed', 'wordfence-2fa');
$value = __('Not Allowed', 'wordfence');
if (Controller_Users::shared()->can_activate_2fa($user)) {
$has2fa = Controller_Users::shared()->has_2fa_active($user);
$requires2fa = $this->requires_2fa($user, $inGracePeriod);
if ($has2fa) {
$value = esc_html__('Active', 'wordfence-2fa');
$value = esc_html__('Active', 'wordfence');
}
elseif ($inGracePeriod) {
$value = wp_kses(__('Inactive<small class="wfls-sub-status">(Grace Period)</small>', 'wordfence-2fa'), array('small'=>array('class'=>array())));
$value = wp_kses(__('Inactive<small class="wfls-sub-status">(Grace Period)</small>', 'wordfence'), array('small'=>array('class'=>array())));
}
elseif (($requires2fa && !$has2fa)) {
$value = wp_kses($inGracePeriod === null ? __('Locked Out<small class="wfls-sub-status">(Grace Period Disabled)</small>', 'wordfence-2fa') : __('Locked Out<small class="wfls-sub-status">(Grace Period Exceeded)</small>', 'wordfence-2fa'), array('small'=>array('class'=>array())));
$value = wp_kses($inGracePeriod === null ? __('Locked Out<small class="wfls-sub-status">(Grace Period Disabled)</small>', 'wordfence') : __('Locked Out<small class="wfls-sub-status">(Grace Period Exceeded)</small>', 'wordfence'), array('small'=>array('class'=>array())));
}
else {
$value = esc_html__('Inactive', 'wordfence-2fa');
$value = esc_html__('Inactive', 'wordfence');
}
}
break;
@@ -589,7 +589,7 @@ SQL
case 'wfls_last_captcha':
$user = new \WP_User($user_id);
if (Controller_Users::shared()->can_activate_2fa($user) && Controller_Users::shared()->has_2fa_active($user)) {
$value = __('(not required)', 'wordfence-2fa');
$value = __('(not required)', 'wordfence');
}
else {
$value = '-';
@@ -683,7 +683,7 @@ SQL
//Format is 'view' => '<a href="https://wfpremium.dev1.ryanbritton.com/author/ryan/" aria-label="View posts by ryan">View</a>'
if (user_can(wp_get_current_user(), Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS) && (Controller_Users::shared()->can_activate_2fa($user) || Controller_Users::shared()->has_2fa_active($user))) {
$url = (is_multisite() ? network_admin_url('admin.php?page=WFLS&user=' . $user->ID) : admin_url('admin.php?page=WFLS&user=' . $user->ID));
$actions['wf2fa'] = '<a href="' . esc_url($url) . '" aria-label="' . esc_attr(sprintf(__('Edit two-factor authentication for %s', 'wordfence-2fa'), $user->user_login)) . '">' . esc_html__('2FA', 'wordfence-2fa') . '</a>';
$actions['wf2fa'] = '<a href="' . esc_url($url) . '" aria-label="' . esc_attr(sprintf(__('Edit two-factor authentication for %s', 'wordfence'), $user->user_login)) . '">' . esc_html__('2FA', 'wordfence') . '</a>';
}
return $actions;
}
@@ -694,8 +694,8 @@ SQL
if (user_can(wp_get_current_user(), Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS) && version_compare($wp_version, '4.4.0', '>=')) {
$counts = $this->user_counts();
$views['all'] = str_replace(' class="current" aria-current="page"', '', $views['all']);
$views['wfls-active'] = '<a href="' . esc_url(add_query_arg('wf2fa', 'active', 'users.php')) . '"' . (isset($_GET['wf2fa']) && $_GET['wf2fa'] == 'active' ? ' class="current" aria-current="page"' : '') . '>' . esc_html__('2FA Active', 'wordfence-2fa') . ' <span class="count">(' . number_format($counts['active_users']) . ')</span></a>';
$views['wfls-inactive'] = '<a href="' . esc_url(add_query_arg('wf2fa', 'inactive', 'users.php')) . '"' . (isset($_GET['wf2fa']) && $_GET['wf2fa'] == 'inactive' ? ' class="current" aria-current="page"' : '') . '>' . esc_html__('2FA Inactive', 'wordfence-2fa') . ' <span class="count">(' . number_format($counts['inactive_users']) . ')</span></a>';
$views['wfls-active'] = '<a href="' . esc_url(add_query_arg('wf2fa', 'active', 'users.php')) . '"' . (isset($_GET['wf2fa']) && $_GET['wf2fa'] == 'active' ? ' class="current" aria-current="page"' : '') . '>' . esc_html__('2FA Active', 'wordfence') . ' <span class="count">(' . number_format($counts['active_users']) . ')</span></a>';
$views['wfls-inactive'] = '<a href="' . esc_url(add_query_arg('wf2fa', 'inactive', 'users.php')) . '"' . (isset($_GET['wf2fa']) && $_GET['wf2fa'] == 'inactive' ? ' class="current" aria-current="page"' : '') . '>' . esc_html__('2FA Inactive', 'wordfence') . ' <span class="count">(' . number_format($counts['inactive_users']) . ')</span></a>';
}
return $views;
}

View File

@@ -85,6 +85,8 @@ class Controller_WordfenceLS {
}
public function _wordpress_init() {
if (!WORDFENCE_LS_FROM_CORE)
load_plugin_textdomain('wordfence-login-security', false, WORDFENCE_LS_PATH . 'languages');
if ($this->is_shortcode_enabled())
add_shortcode(self::SHORTCODE_2FA_MANAGEMENT, array($this, '_handle_user_2fa_management_shortcode'));
}
@@ -104,17 +106,17 @@ class Controller_WordfenceLS {
public function _admin_init() {
if (WORDFENCE_LS_FROM_CORE) {
\wfModuleController::shared()->addOptionIndex('wfls-option-enable-2fa-roles', __('Login Security: Enable 2FA for these roles', 'wordfence-2fa'));
\wfModuleController::shared()->addOptionIndex('wfls-option-allow-remember', __('Login Security: Allow remembering device for 30 days', 'wordfence-2fa'));
\wfModuleController::shared()->addOptionIndex('wfls-option-require-2fa-xml-rpc', __('Login Security: Require 2FA for XML-RPC call authentication', 'wordfence-2fa'));
\wfModuleController::shared()->addOptionIndex('wfls-option-disable-xml-rpc', __('Login Security: Disable XML-RPC authentication', 'wordfence-2fa'));
\wfModuleController::shared()->addOptionIndex('wfls-option-whitelist-2fa', __('Login Security: Allowlisted IP addresses that bypass 2FA and reCAPTCHA', 'wordfence-2fa'));
\wfModuleController::shared()->addOptionIndex('wfls-option-enable-captcha', __('Login Security: Enable reCAPTCHA on the login and user registration pages', 'wordfence-2fa'));
\wfModuleController::shared()->addOptionIndex('wfls-option-enable-2fa-roles', __('Login Security: Enable 2FA for these roles', 'wordfence'));
\wfModuleController::shared()->addOptionIndex('wfls-option-allow-remember', __('Login Security: Allow remembering device for 30 days', 'wordfence'));
\wfModuleController::shared()->addOptionIndex('wfls-option-require-2fa-xml-rpc', __('Login Security: Require 2FA for XML-RPC call authentication', 'wordfence'));
\wfModuleController::shared()->addOptionIndex('wfls-option-disable-xml-rpc', __('Login Security: Disable XML-RPC authentication', 'wordfence'));
\wfModuleController::shared()->addOptionIndex('wfls-option-whitelist-2fa', __('Login Security: Allowlisted IP addresses that bypass 2FA and reCAPTCHA', 'wordfence'));
\wfModuleController::shared()->addOptionIndex('wfls-option-enable-captcha', __('Login Security: Enable reCAPTCHA on the login and user registration pages', 'wordfence'));
$title = __('Login Security Options', 'wordfence-2fa');
$description = __('Login Security options are available on the Login Security options page', 'wordfence-2fa');
$title = __('Login Security Options', 'wordfence');
$description = __('Login Security options are available on the Login Security options page', 'wordfence');
$url = esc_url(network_admin_url('admin.php?page=WFLS#top#settings'));
$link = __('Login Security Options', 'wordfence-2fa');;
$link = __('Login Security Options', 'wordfence');;
\wfModuleController::shared()->addOptionBlock(<<<END
<div class="wf-row">
<div class="wf-col-xs-12">
@@ -184,19 +186,19 @@ END
*/
public function _jetpack_xml_rpc_notice() {
echo '<div class="notice notice-warning"><p>' . wp_kses(sprintf(__('XML-RPC authentication is disabled. Jetpack is currently active and requires XML-RPC authentication to work correctly. <a href="%s">Manage Settings</a>', 'wordfence-2fa'), esc_url(network_admin_url('admin.php?page=WFLS#top#settings'))), array('a'=>array('href'=>array()))) . '</p></div>';
echo '<div class="notice notice-warning"><p>' . wp_kses(sprintf(__('XML-RPC authentication is disabled. Jetpack is currently active and requires XML-RPC authentication to work correctly. <a href="%s">Manage Settings</a>', 'wordfence'), esc_url(network_admin_url('admin.php?page=WFLS#top#settings'))), array('a'=>array('href'=>array()))) . '</p></div>';
}
public function _recaptcha_test_notice() {
echo '<div class="notice notice-warning"><p>' . wp_kses(sprintf(__('reCAPTCHA test mode is enabled. While enabled, login and registration requests will be checked for their score but will not be blocked if the score is below the minimum score. <a href="%s">Manage Settings</a>', 'wordfence-2fa'), esc_url(network_admin_url('admin.php?page=WFLS#top#settings'))), array('a'=>array('href'=>array()))) . '</p></div>';
echo '<div class="notice notice-warning"><p>' . wp_kses(sprintf(__('reCAPTCHA test mode is enabled. While enabled, login and registration requests will be checked for their score but will not be blocked if the score is below the minimum score. <a href="%s">Manage Settings</a>', 'wordfence'), esc_url(network_admin_url('admin.php?page=WFLS#top#settings'))), array('a'=>array('href'=>array()))) . '</p></div>';
}
public function _woocommerce_integration_notice() {
?>
<div id="<?php echo esc_attr(Controller_Notices::PERSISTENT_NOTICE_WOOCOMMERCE_INTEGRATION) ?>" class="notice notice-warning is-dismissible wfls-persistent-notice">
<p>
<?php esc_html_e('WooCommerce appears to be installed, but the Wordfence Login Security WooCommerce integration is not currently enabled. Without this feature, WooCommerce forms will not support all functionality provided by Wordfence Login Security, including CAPTCHA for the login page and user registration.', 'wordfence-2fa'); ?>
<a href="<?php echo esc_attr(esc_url(network_admin_url('admin.php?page=WFLS#top#settings'))) ?>"><?php esc_html_e('Manage Settings', 'wordfence-2fa') ?></a>
<?php esc_html_e('WooCommerce appears to be installed, but the Wordfence Login Security WooCommerce integration is not currently enabled. Without this feature, WooCommerce forms will not support all functionality provided by Wordfence Login Security, including CAPTCHA for the login page and user registration.', 'wordfence'); ?>
<a href="<?php echo esc_attr(esc_url(network_admin_url('admin.php?page=WFLS#top#settings'))) ?>"><?php esc_html_e('Manage Settings', 'wordfence') ?></a>
</p>
</div>
<?php
@@ -330,7 +332,20 @@ END
if ($useCAPTCHA || Controller_Users::shared()->any_2fa_active()) {
$this->validate_email_verification_token(null, $verification);
wp_enqueue_script('wordfence-ls-login', Model_Asset::js('login.js'), array('jquery'), WORDFENCE_LS_VERSION);
Model_Script::create('wordfence-ls-login', Model_Asset::js('login.js'), array('jquery'), WORDFENCE_LS_VERSION)
->withTranslations(array(
'Message to Support' => __('Message to Support', 'wordfence'),
'Send' => __('Send', 'wordfence'),
'An error was encountered while trying to send the message. Please try again.' => __('An error was encountered while trying to send the message. Please try again.', 'wordfence'),
'<strong>ERROR</strong>: An error was encountered while trying to send the message. Please try again.' => wp_kses(__('<strong>ERROR</strong>: An error was encountered while trying to send the message. Please try again.', 'wordfence'), array('strong' => array())),
'Wordfence 2FA Code' => __('Wordfence 2FA Code', 'wordfence'),
'Remember for 30 days' => __('Remember for 30 days', 'wordfence'),
'Log In' => __('Log In', 'wordfence'),
'<strong>ERROR</strong>: An error was encountered while trying to authenticate. Please try again.' => wp_kses(__('<strong>ERROR</strong>: An error was encountered while trying to authenticate. Please try again.', 'wordfence'), array('strong' => array())),
'The Wordfence 2FA Code can be found within the authenticator app you used when first activating two-factor authentication. You may also use one of your recovery codes.' => __('The Wordfence 2FA Code can be found within the authenticator app you used when first activating two-factor authentication. You may also use one of your recovery codes.', 'wordfence')
))
->setTranslationObjectName('WFLS_LOGIN_TRANSLATIONS')
->enqueue();
wp_enqueue_style('wordfence-ls-login', Model_Asset::css('login.css'), array(), WORDFENCE_LS_VERSION);
wp_localize_script('wordfence-ls-login', 'WFLSVars', array(
'ajaxurl' => admin_url('admin-ajax.php'),
@@ -348,10 +363,10 @@ END
'WFLSVars' => array(
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wp-ajax'),
'modalTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '${message}', 'primaryButton' => array('id' => 'wfls-generic-modal-close', 'label' => __('Close', 'wordfence-2fa'), 'link' => '#')))->render(),
'modalTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '${message}', 'primaryButton' => array('id' => 'wfls-generic-modal-close', 'label' => __('Close', 'wordfence'), 'link' => '#')))->render(),
'modalNoButtonsTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '${message}'))->render(),
'tokenInvalidTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '${message}', 'primaryButton' => array('id' => 'wfls-token-invalid-modal-reload', 'label' => __('Reload', 'wordfence-2fa'), 'link' => '#')))->render(),
'modalHTMLTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '{{html message}}', 'primaryButton' => array('id' => 'wfls-generic-modal-close', 'label' => __('Close', 'wordfence-2fa'), 'link' => '#')))->render()
'tokenInvalidTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '${message}', 'primaryButton' => array('id' => 'wfls-token-invalid-modal-reload', 'label' => __('Reload', 'wordfence'), 'link' => '#')))->render(),
'modalHTMLTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '{{html message}}', 'primaryButton' => array('id' => 'wfls-generic-modal-close', 'label' => __('Close', 'wordfence'), 'link' => '#')))->render()
)
);
}
@@ -374,9 +389,11 @@ END
$assets[] = Model_Style::create('wordfence-ls-jquery-ui-css.structure', Model_Asset::css('jquery-ui.structure.min.css'), array(), WORDFENCE_LS_VERSION);
$assets[] = Model_Style::create('wordfence-ls-jquery-ui-css.theme', Model_Asset::css('jquery-ui.theme.min.css'), array(), WORDFENCE_LS_VERSION);
}
$assets[] = Model_Script::create('wordfence-ls-admin', Model_Asset::js('admin.js'), array('jquery'), WORDFENCE_LS_VERSION);
$assets[] = Model_Script::create('wordfence-ls-admin', Model_Asset::js('admin.js'), array('jquery'), WORDFENCE_LS_VERSION)
->withTranslation('You have unsaved changes to your options. If you leave this page, those changes will be lost.', __('You have unsaved changes to your options. If you leave this page, those changes will be lost.', 'wordfence'))
->setTranslationObjectName('WFLS_ADMIN_TRANSLATIONS');
$registered = array(
Model_Script::create('chart-js', Model_Asset::js('Chart.bundle.min.js'), array('jquery'), '2.4.0')->setRegistered(),
Model_Script::create('chart-js', Model_Asset::js('chart.umd.js'), array('jquery'), '4.2.1')->setRegistered(),
Model_Script::create('wordfence-select2-js', Model_Asset::js('wfselect2.min.js'), array('jquery'), WORDFENCE_LS_VERSION)->setRegistered(),
Model_Style::create('wordfence-select2-css', Model_Asset::css('wfselect2.min.css'), array(), WORDFENCE_LS_VERSION)->setRegistered()
);
@@ -456,30 +473,30 @@ END
$hasGracePeriod = Controller_Settings::shared()->get_user_2fa_grace_period() > 0;
if ($userAllowed2fa && ($viewerIsUser || $viewerCanManage2fa)):
?>
<h2 id="wfls-user-settings"><?php esc_html_e('Wordfence Login Security', 'wordfence-2fa'); ?></h2>
<h2 id="wfls-user-settings"><?php esc_html_e('Wordfence Login Security', 'wordfence'); ?></h2>
<table class="form-table">
<tr id="wordfence-ls">
<th><label for="wordfence-ls-btn"><?php esc_html_e('2FA Status', 'wordfence-2fa'); ?></label></th>
<th><label for="wordfence-ls-btn"><?php esc_html_e('2FA Status', 'wordfence'); ?></label></th>
<td>
<?php if ($userAllowed2fa): ?>
<p>
<strong><?php echo $lockedOut ? esc_html__('Locked Out', 'wordfence-2fa') : ($has2fa ? esc_html__('Active', 'wordfence-2fa') : esc_html__('Inactive', 'wordfence-2fa')); ?>:</strong>
<strong><?php echo $lockedOut ? esc_html__('Locked Out', 'wordfence') : ($has2fa ? esc_html__('Active', 'wordfence') : esc_html__('Inactive', 'wordfence')); ?>:</strong>
<?php echo $lockedOut ?
($viewerIsUser ? esc_html__('Two-factor authentication is required for your account, but has not been configured.', 'wordfence-2fa') : esc_html__('Two-factor authentication is required for this account, but has not been configured.', 'wordfence-2fa'))
: ($has2fa ? esc_html__('Wordfence 2FA is active.', 'wordfence-2fa') : esc_html__('Wordfence 2FA is inactive.', 'wordfence-2fa')); ?>
<a href="<?php echo Controller_Support::esc_supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Learn More', 'wordfence-2fa'); ?></a>
($viewerIsUser ? esc_html__('Two-factor authentication is required for your account, but has not been configured.', 'wordfence') : esc_html__('Two-factor authentication is required for this account, but has not been configured.', 'wordfence'))
: ($has2fa ? esc_html__('Wordfence 2FA is active.', 'wordfence') : esc_html__('Wordfence 2FA is inactive.', 'wordfence')); ?>
<a href="<?php echo Controller_Support::esc_supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Learn More', 'wordfence'); ?></a>
</p>
<?php if (!$has2fa && $inGracePeriod): ?>
<p><strong><?php echo sprintf($viewerIsUser ?
esc_html__('Two-factor authentication must be activated for your account prior to %s to avoid losing access.', 'wordfence-2fa')
: esc_html__('Two-factor authentication must be activated for this account prior to %s.', 'wordfence-2fa')
esc_html__('Two-factor authentication must be activated for your account prior to %s to avoid losing access.', 'wordfence')
: esc_html__('Two-factor authentication must be activated for this account prior to %s.', 'wordfence')
, Controller_Time::format_local_time('F j, Y g:i A', $requiredAt)) ?></strong></p>
<?php endif ?>
<?php if ($has2fa || $viewerIsUser): ?><p><a href="<?php echo esc_url($manageURL); ?>" class="button"><?php echo (Controller_Users::shared()->has_2fa_active($user) ? esc_html__('Manage 2FA', 'wordfence-2fa') : esc_html__('Activate 2FA', 'wordfence-2fa')); ?></a></p><?php endif ?>
<?php if ($has2fa || $viewerIsUser): ?><p><a href="<?php echo esc_url($manageURL); ?>" class="button"><?php echo (Controller_Users::shared()->has_2fa_active($user) ? esc_html__('Manage 2FA', 'wordfence') : esc_html__('Activate 2FA', 'wordfence')); ?></a></p><?php endif ?>
<?php endif ?>
<?php if ($viewerCanManage2fa): ?>
<?php if (!$userAllowed2fa): ?>
<p><strong><?php esc_html_e('Disabled', 'wordfence-2fa'); ?>:</strong> <?php esc_html_e('Two-factor authentication is not currently enabled for this account type. To enable it, visit the Wordfence 2FA Settings page.', 'wordfence-2fa'); ?> <a href="#"><?php esc_html_e('Learn More', 'wordfence-2fa'); ?></a></p>
<p><strong><?php esc_html_e('Disabled', 'wordfence'); ?>:</strong> <?php esc_html_e('Two-factor authentication is not currently enabled for this account type. To enable it, visit the Wordfence 2FA Settings page.', 'wordfence'); ?> <a href="#"><?php esc_html_e('Learn More', 'wordfence'); ?></a></p>
<?php endif ?>
<?php if ($lockedOut): ?>
<?php echo Model_View::create(
@@ -496,7 +513,7 @@ END
))->render() ?>
<?php endif ?>
<p>
<a href="<?php echo esc_url(is_multisite() ? network_admin_url('admin.php?page=WFLS#top#settings') : admin_url('admin.php?page=WFLS#top#settings')); ?>" class="button"><?php esc_html_e('Manage 2FA Settings', 'wordfence-2fa'); ?></a>
<a href="<?php echo esc_url(is_multisite() ? network_admin_url('admin.php?page=WFLS#top#settings') : admin_url('admin.php?page=WFLS#top#settings')); ?>" class="button"><?php esc_html_e('Manage 2FA Settings', 'wordfence'); ?></a>
</p>
<?php endif ?>
</td>
@@ -642,9 +659,9 @@ END
'ip' => Model_Request::current()->ip(),
'canEnable2FA' => Controller_Users::shared()->can_activate_2fa($user),
));
wp_mail($user->user_email, __('Login Verification Required', 'wordfence-2fa'), $view->render(), "Content-Type: text/html");
wp_mail($user->user_email, __('Login Verification Required', 'wordfence'), $view->render(), "Content-Type: text/html");
return new \WP_Error('wfls_captcha_verify', wp_kses(__('<strong>VERIFICATION REQUIRED</strong>: Additional verification is required for login. Please check the email address associated with the account for a verification link.', 'wordfence-2fa'), array('strong'=>array())));
return new \WP_Error('wfls_captcha_verify', wp_kses(__('<strong>VERIFICATION REQUIRED</strong>: Additional verification is required for login. Please check the email address associated with the account for a verification link.', 'wordfence'), array('strong'=>array())));
}
}
@@ -662,7 +679,7 @@ END
return $user;
}
else {
return new \WP_Error('wfls_twofactor_failed', wp_kses(__('<strong>CODE INVALID</strong>: The 2FA code provided is either expired or invalid. Please try again.', 'wordfence-2fa'), array('strong'=>array())));
return new \WP_Error('wfls_twofactor_failed', wp_kses(__('<strong>CODE INVALID</strong>: The 2FA code provided is either expired or invalid. Please try again.', 'wordfence'), array('strong'=>array())));
}
}
}
@@ -671,15 +688,15 @@ END
if (Controller_Users::shared()->has_2fa_active($user)) {
$legacy2FAActive = Controller_WordfenceLS::shared()->legacy_2fa_active();
if ($legacy2FAActive) {
return new \WP_Error('wfls_twofactor_required', wp_kses(__('<strong>CODE REQUIRED</strong>: Please enter your 2FA code immediately after your password in the same field.', 'wordfence-2fa'), array('strong'=>array())));
return new \WP_Error('wfls_twofactor_required', wp_kses(__('<strong>CODE REQUIRED</strong>: Please enter your 2FA code immediately after your password in the same field.', 'wordfence'), array('strong'=>array())));
}
return new \WP_Error('wfls_twofactor_required', wp_kses(__('<strong>CODE REQUIRED</strong>: Please provide your 2FA code when prompted.', 'wordfence-2fa'), array('strong'=>array())));
return new \WP_Error('wfls_twofactor_required', wp_kses(__('<strong>CODE REQUIRED</strong>: Please provide your 2FA code when prompted.', 'wordfence'), array('strong'=>array())));
}
else if (Controller_Users::shared()->requires_2fa($user, $in2faGracePeriod, $time2faRequired)) {
return new \WP_Error('wfls_twofactor_blocked', wp_kses(__('<strong>LOGIN BLOCKED</strong>: 2FA is required to be active on your account. Please contact the site administrator.', 'wordfence-2fa'), array('strong'=>array())));
return new \WP_Error('wfls_twofactor_blocked', wp_kses(__('<strong>LOGIN BLOCKED</strong>: 2FA is required to be active on your account. Please contact the site administrator.', 'wordfence'), array('strong'=>array())));
}
else if ($in2faGracePeriod) {
Controller_Notices::shared()->add_notice(Model_Notice::SEVERITY_CRITICAL, new Model_HTML(wp_kses(sprintf(__('You do not currently have two-factor authentication active on your account, which will be required beginning %s. <a href="%s">Configure 2FA</a>', 'wordfence-2fa'), Controller_Time::format_local_time('F j, Y g:i A', $time2faRequired), esc_url((is_multisite() && is_super_admin($user->ID)) ? network_admin_url('admin.php?page=WFLS') : admin_url('admin.php?page=WFLS'))), array('a'=>array('href'=>array())))), 'wfls-will-be-required', $user);
Controller_Notices::shared()->add_notice(Model_Notice::SEVERITY_CRITICAL, new Model_HTML(wp_kses(sprintf(__('You do not currently have two-factor authentication active on your account, which will be required beginning %s. <a href="%s">Configure 2FA</a>', 'wordfence'), Controller_Time::format_local_time('F j, Y g:i A', $time2faRequired), esc_url((is_multisite() && is_super_admin($user->ID)) ? network_admin_url('admin.php?page=WFLS') : admin_url('admin.php?page=WFLS'))), array('a'=>array('href'=>array())))), 'wfls-will-be-required', $user);
}
}
@@ -729,10 +746,10 @@ END
$emailVerificationTokenValid = $this->validate_email_verification_token();
if (!$has_errors && $emailVerificationTokenValid !== null) {
if ($emailVerificationTokenValid) {
$errors->add('wfls_email_verified', esc_html__('Email verification succeeded. Please continue logging in.', 'wordfence-2fa'), 'message');
$errors->add('wfls_email_verified', esc_html__('Email verification succeeded. Please continue logging in.', 'wordfence'), 'message');
}
else {
$errors->add('wfls_email_not_verified', esc_html__('Email verification invalid or expired. Please try again.', 'wordfence-2fa'), 'message');
$errors->add('wfls_email_not_verified', esc_html__('Email verification invalid or expired. Please try again.', 'wordfence'), 'message');
}
}
return $errors;
@@ -786,10 +803,10 @@ END
}
if ($useSubmenu) {
add_submenu_page('Wordfence', __('Login Security', 'wordfence-2fa'), __('Login Security', 'wordfence-2fa'), Controller_Permissions::CAP_ACTIVATE_2FA_SELF, 'WFLS', array($this, '_menu'));
add_submenu_page('Wordfence', __('Login Security', 'wordfence'), __('Login Security', 'wordfence'), Controller_Permissions::CAP_ACTIVATE_2FA_SELF, 'WFLS', array($this, '_menu'));
}
else {
add_menu_page(__('Login Security', 'wordfence-2fa'), __('Login Security', 'wordfence-2fa'), Controller_Permissions::CAP_ACTIVATE_2FA_SELF, 'WFLS', array($this, '_menu'), Model_Asset::img('menu.svg'));
add_menu_page(__('Login Security', 'wordfence'), __('Login Security', 'wordfence'), Controller_Permissions::CAP_ACTIVATE_2FA_SELF, 'WFLS', array($this, '_menu'), Model_Asset::img('menu.svg'));
}
}
@@ -817,15 +834,15 @@ END
$roleKey = $_GET['role'];
$roles = new \WP_Roles();
$role = $roles->get_role($roleKey);
$roleTitle = $roleKey === 'super-admin' ? __('Super Administrator', 'wordfence-2fa') : $roles->role_names[$roleKey];
$roleTitle = $roleKey === 'super-admin' ? __('Super Administrator', 'wordfence') : $roles->role_names[$roleKey];
$requiredAt = Controller_Settings::shared()->get_required_2fa_role_activation_time($roleKey);
$states = array(
'grace_period' => array(
'title' => __('Grace Period', 'wordfence-2fa'),
'title' => __('Grace Period', 'wordfence'),
'gracePeriod' => true
),
'locked_out' => array(
'title' => __('Locked Out', 'wordfence-2fa'),
'title' => __('Locked Out', 'wordfence'),
'gracePeriod' => false
)
);
@@ -840,7 +857,7 @@ END
$users = Controller_Users::shared()->get_inactive_2fa_users($roleKey, $state['gracePeriod'], $page, self::USERS_PER_PAGE, $lastPage);
$sections[] = array(
'tab' => new Model_Tab($key, $key, $title, $title),
'title' => new Model_Title($key, sprintf(__('Users without 2FA active (%s)', 'wordfence-2fa'), $title) . ' - ' . $roleTitle),
'title' => new Model_Title($key, sprintf(__('Users without 2FA active (%s)', 'wordfence'), $title) . ' - ' . $roleTitle),
'content' => new Model_View('page/role', array(
'role' => $role,
'roleTitle' => $roleTitle,
@@ -858,8 +875,8 @@ END
}
else {
$sections[] = array(
'tab' => new Model_Tab('manage', 'manage', __('Two-Factor Authentication', 'wordfence-2fa'), __('Two-Factor Authentication', 'wordfence-2fa')),
'title' => new Model_Title('manage', __('Two-Factor Authentication', 'wordfence-2fa'), Controller_Support::supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA), new Model_HTML(wp_kses(__('Learn more<span class="wfls-hidden-xs"> about Two-Factor Authentication</span>', 'wordfence-2fa'), array('span'=>array('class'=>array()))))),
'tab' => new Model_Tab('manage', 'manage', __('Two-Factor Authentication', 'wordfence'), __('Two-Factor Authentication', 'wordfence')),
'title' => new Model_Title('manage', __('Two-Factor Authentication', 'wordfence'), Controller_Support::supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA), new Model_HTML(wp_kses(__('Learn more<span class="wfls-hidden-xs"> about Two-Factor Authentication</span>', 'wordfence'), array('span'=>array('class'=>array()))))),
'content' => new Model_View('page/manage', array(
'user' => $user,
'canEditUsers' => $canEditUsers,
@@ -868,8 +885,8 @@ END
if ($administrator) {
$sections[] = array(
'tab' => new Model_Tab('settings', 'settings', __('Settings', 'wordfence-2fa'), __('Settings', 'wordfence-2fa')),
'title' => new Model_Title('settings', __('Login Security Settings', 'wordfence-2fa'), Controller_Support::supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY), new Model_HTML(wp_kses(__('Learn more<span class="wfls-hidden-xs"> about Login Security</span>', 'wordfence-2fa'), array('span'=>array('class'=>array()))))),
'tab' => new Model_Tab('settings', 'settings', __('Settings', 'wordfence'), __('Settings', 'wordfence')),
'title' => new Model_Title('settings', __('Login Security Settings', 'wordfence'), Controller_Support::supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY), new Model_HTML(wp_kses(__('Learn more<span class="wfls-hidden-xs"> about Login Security</span>', 'wordfence'), array('span'=>array('class'=>array()))))),
'content' => new Model_View('page/settings', array(
'hasWoocommerce' => $this->has_woocommerce()
)),
@@ -895,14 +912,14 @@ END
if ($requireCaptcha) {
if ($token === null && !$captchaController->test_mode()) {
return array(
'message' => wp_kses(__('<strong>REGISTRATION ATTEMPT BLOCKED</strong>: This site requires a security token created when the page loads for all registration attempts. Please ensure JavaScript is enabled and try again.', 'wordfence-2fa'), array('strong'=>array())),
'message' => wp_kses(__('<strong>REGISTRATION ATTEMPT BLOCKED</strong>: This site requires a security token created when the page loads for all registration attempts. Please ensure JavaScript is enabled and try again.', 'wordfence'), array('strong'=>array())),
'category' => 'wfls_captcha_required'
);
}
$score = $captchaController->score($token);
if ($score === false && !$captchaController->test_mode()) {
return array(
'message' => wp_kses(__('<strong>REGISTRATION ATTEMPT BLOCKED</strong>: The security token for the login attempt was invalid or expired. Please reload the page and try again.', 'wordfence-2fa'), array('strong'=>array())),
'message' => wp_kses(__('<strong>REGISTRATION ATTEMPT BLOCKED</strong>: The security token for the login attempt was invalid or expired. Please reload the page and try again.', 'wordfence'), array('strong'=>array())),
'category' => 'wfls_captcha_required'
);
}
@@ -915,10 +932,10 @@ END
);
if ($encryptedIP && $encryptedScore && filter_var(get_site_option('admin_email'), FILTER_VALIDATE_EMAIL)) {
$jwt = new Model_JWT(array('ip' => $encryptedIP, 'score' => $encryptedScore), Controller_Time::time() + 600);
$result['message'] = wp_kses(sprintf(__('<strong>REGISTRATION BLOCKED</strong>: The registration request was blocked because it was flagged as spam. Please try again or <a href="#" class="wfls-registration-captcha-contact" data-token="%s">contact the site owner</a> for help.', 'wordfence-2fa'), esc_attr((string)$jwt)), array('strong'=>array(), 'a'=>array('href'=>array(), 'class'=>array(), 'data-token'=>array())));
$result['message'] = wp_kses(sprintf(__('<strong>REGISTRATION BLOCKED</strong>: The registration request was blocked because it was flagged as spam. Please try again or <a href="#" class="wfls-registration-captcha-contact" data-token="%s">contact the site owner</a> for help.', 'wordfence'), esc_attr((string)$jwt)), array('strong'=>array(), 'a'=>array('href'=>array(), 'class'=>array(), 'data-token'=>array())));
}
else {
$result['message'] = wp_kses(__('<strong>REGISTRATION BLOCKED</strong>: The registration request was blocked because it was flagged as spam. Please try again or contact the site owner for help.', 'wordfence-2fa'), array('strong'=>array()));
$result['message'] = wp_kses(__('<strong>REGISTRATION BLOCKED</strong>: The registration request was blocked because it was flagged as spam. Please try again or contact the site owner for help.', 'wordfence'), array('strong'=>array()));
}
return $result;
}
@@ -988,7 +1005,7 @@ END
public function _woocommerce_account_menu_items($items) {
if ($this->can_user_activate_2fa_self()) {
$endpointId = self::WOOCOMMERCE_ENDPOINT;
$label = __('Wordfence 2FA', 'wordfence-2fa');
$label = __('Wordfence 2FA', 'wordfence');
if (!Utility_Array::insertAfter($items, 'edit-account', $endpointId, $label)) {
$items[$endpointId] = $label;
}