Exemple #1
0
 public static function authenticateFilter($authUser, $username, $passwd)
 {
     wfConfig::inc('totalLoginHits');
     //The total hits to wp-login.php including logins, logouts and just hits.
     $IP = wfUtils::getIP();
     $secEnabled = wfConfig::get('loginSecurityEnabled');
     if ($secEnabled && !self::getLog()->isWhitelisted($IP) && wfConfig::get('isPaid')) {
         $twoFactorUsers = wfConfig::get_ser('twoFactorUsers', array());
         if (isset($twoFactorUsers) && is_array($twoFactorUsers) && sizeof($twoFactorUsers) > 0) {
             $userDat = isset($_POST['wordfence_userDat']) ? $_POST['wordfence_userDat'] : false;
             if (is_object($userDat) && get_class($authUser) == 'WP_User') {
                 //Valid username and password either with or without the 'wf...' code. Users is now logged in at this point.
                 if (isset($_POST['wordfence_authFactor']) && $_POST['wordfence_authFactor']) {
                     //user entered a valid user and password with ' wf....' appended
                     foreach ($twoFactorUsers as &$t) {
                         if ($t[0] == $userDat->ID && $t[3] == 'activated') {
                             if ($_POST['wordfence_authFactor'] == $t[2] && $t[4] > time()) {
                                 // Set this 2FA code to expire in 30 seconds (for other plugins hooking into the auth process)
                                 $t[4] = time() + 30;
                                 wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                             } else {
                                 if ($_POST['wordfence_authFactor'] == $t[2]) {
                                     $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                                     try {
                                         $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $t[1]));
                                         if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                                             break;
                                             //Let them sign in without two factor
                                         }
                                         if (isset($codeResult['ok']) && $codeResult['ok']) {
                                             $t[2] = $codeResult['code'];
                                             $t[4] = time() + 1800;
                                             //30 minutes until code expires
                                             wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                                             //save the code the user needs to enter and return an error.
                                             self::$authError = new WP_Error('twofactor_required', __('<strong>CODE EXPIRED. CHECK YOUR PHONE:</strong> The code you entered has expired. Codes are only valid for 30 minutes for security reasons. We have sent you a new code. Please sign in using your username and your password followed by a space and the new code we sent you.'));
                                             return self::$authError;
                                         } else {
                                             break;
                                             //No new code was received. Let them sign in with the expired code.
                                         }
                                     } catch (Exception $e) {
                                         // Couldn't connect to noc1, let them sign in since the password was correct.
                                         break;
                                     }
                                 } else {
                                     //Bad code, so cancel the login and return an error to user.
                                     self::$authError = new WP_Error('twofactor_required', __('<strong>INVALID CODE</strong>: You need to enter your password followed by a space and the code we sent to your phone. The code should start with \'wf\' and should be four characters. e.g. wfAB12. In this case you would enter your password as: \'mypassword wfAB12\' without quotes.'));
                                     return self::$authError;
                                 }
                             }
                         }
                         //No user matches and has TF activated so let user sign in.
                     }
                 } else {
                     //valid login with no code entered
                     foreach ($twoFactorUsers as &$t) {
                         if ($t[0] == $userDat->ID && $t[3] == 'activated') {
                             //Yup, enabled, so lets send the code
                             $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                             try {
                                 $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $t[1]));
                                 if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                                     break;
                                     //Let them sign in without two factor if their API key has expired or they're not paid and for some reason they have this set up.
                                 }
                             } catch (Exception $e) {
                                 // Couldn't connect to noc1, let them sign in since the password was correct.
                                 break;
                             }
                             if (isset($codeResult['ok']) && $codeResult['ok']) {
                                 $t[2] = $codeResult['code'];
                                 $t[4] = time() + 1800;
                                 //30 minutes until code expires
                                 wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                                 //save the code the user needs to enter and return an error.
                                 if (self::hasGDLimitLoginsMUPlugin() && function_exists('limit_login_get_address')) {
                                     $retries = get_option('limit_login_retries', array());
                                     $ip = limit_login_get_address();
                                     if (!is_array($retries)) {
                                         $retries = array();
                                     }
                                     if (isset($retries[$ip]) && is_int($retries[$ip])) {
                                         $retries[$ip]--;
                                     } else {
                                         $retries[$ip] = 0;
                                     }
                                     update_option('limit_login_retries', $retries);
                                 }
                                 self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Please sign in again and add a space and the code to the end of your password.'));
                                 return self::$authError;
                             } else {
                                 //oops, our API returned an error.
                                 break;
                                 //Let them sign in without two factor because the API is broken and we don't want to lock users out of their own systems.
                             }
                         }
                         //User is not present in two factor list or is not activated. Sign in without twofactor.
                     }
                     //Two facto users is empty. Sign in without two factor.
                 }
             }
         }
     }
     if (self::getLog()->isWhitelisted($IP)) {
         return $authUser;
     }
     if (wfConfig::get('other_WFNet') && is_wp_error($authUser) && ($authUser->get_error_code() == 'invalid_username' || $authUser->get_error_code() == 'incorrect_password')) {
         if ($maxBlockTime = self::wfsnIsBlocked($IP, 'brute')) {
             self::getLog()->blockIP($IP, "Blocked by Wordfence Security Network", true, false, $maxBlockTime);
             $secsToGo = wfConfig::get('blockedTime');
             self::getLog()->do503($secsToGo, "Blocked by Wordfence Security Network");
         }
     }
     if ($secEnabled) {
         if (is_wp_error($authUser) && $authUser->get_error_code() == 'invalid_username') {
             if ($blacklist = wfConfig::get('loginSec_userBlacklist')) {
                 $users = explode("\n", wfUtils::cleanupOneEntryPerLine($blacklist));
                 foreach ($users as $user) {
                     if (strtolower($username) == strtolower($user)) {
                         self::getLog()->blockIP($IP, "Blocked by login security setting.");
                         $secsToGo = wfConfig::get('blockedTime');
                         self::getLog()->do503($secsToGo, "Blocked by login security setting.");
                         break;
                     }
                 }
             }
             if (wfConfig::get('loginSec_lockInvalidUsers')) {
                 if (strlen($username) > 0 && preg_match('/[^\\r\\s\\n\\t]+/', $username)) {
                     self::lockOutIP($IP, "Used an invalid username '" . $username . "' to try to sign in.");
                 }
                 require 'wfLockedOut.php';
             }
         }
         $tKey = 'wflginfl_' . bin2hex(wfUtils::inet_pton($IP));
         if (is_wp_error($authUser) && ($authUser->get_error_code() == 'invalid_username' || $authUser->get_error_code() == 'incorrect_password')) {
             $tries = get_transient($tKey);
             if ($tries) {
                 $tries++;
             } else {
                 $tries = 1;
             }
             if ($tries >= wfConfig::get('loginSec_maxFailures')) {
                 self::lockOutIP($IP, "Exceeded the maximum number of login failures which is: " . wfConfig::get('loginSec_maxFailures') . ". The last username they tried to sign in with was: '" . $username . "'");
                 require 'wfLockedOut.php';
             }
             set_transient($tKey, $tries, wfConfig::get('loginSec_countFailMins') * 60);
         } else {
             if (get_class($authUser) == 'WP_User') {
                 delete_transient($tKey);
                 //reset counter on success
             }
         }
     }
     if (is_wp_error($authUser)) {
         if ($authUser->get_error_code() == 'invalid_username') {
             self::getLog()->logLogin('loginFailInvalidUsername', 1, $username);
         } else {
             self::getLog()->logLogin('loginFailValidUsername', 1, $username);
         }
     }
     if (is_wp_error($authUser) && ($authUser->get_error_code() == 'invalid_username' || $authUser->get_error_code() == 'incorrect_password') && wfConfig::get('loginSec_maskLoginErrors')) {
         return new WP_Error('incorrect_password', sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%2$s" title="Password Lost and Found">Lost your password</a>?'), $username, wp_lostpassword_url()));
     }
     return $authUser;
 }
 public static function authenticateFilter($authUser, $username, $passwd)
 {
     wfConfig::inc('totalLoginHits');
     //The total hits to wp-login.php including logins, logouts and just hits.
     $IP = wfUtils::getIP();
     $secEnabled = wfConfig::get('loginSecurityEnabled');
     $twoFactorUsers = wfConfig::get_ser('twoFactorUsers', array());
     $userDat = isset($_POST['wordfence_userDat']) ? $_POST['wordfence_userDat'] : false;
     $checkTwoFactor = $secEnabled && !self::getLog()->isWhitelisted($IP) && wfConfig::get('isPaid') && isset($twoFactorUsers) && is_array($twoFactorUsers) && sizeof($twoFactorUsers) > 0 && is_object($userDat) && get_class($userDat) == 'WP_User';
     if ($checkTwoFactor) {
         $twoFactorRecord = false;
         $hasActivatedTwoFactorUser = false;
         foreach ($twoFactorUsers as &$t) {
             if ($t[3] == 'activated') {
                 $userID = $t[0];
                 $testUser = get_user_by('ID', $userID);
                 if (is_object($testUser) && wfUtils::isAdmin($testUser)) {
                     $hasActivatedTwoFactorUser = true;
                 }
                 if ($userID == $userDat->ID) {
                     $twoFactorRecord =& $t;
                 }
             }
         }
         if (isset($_POST['wordfence_authFactor']) && $_POST['wordfence_authFactor'] && $twoFactorRecord) {
             //User authenticated with name and password, 2FA code ready to check
             $userID = $userDat->ID;
             if (get_class($authUser) == 'WP_User' && $authUser->ID == $userID) {
                 //Do nothing. This is the code path the old method of including the code in the password field will take -- since we already have a valid $authUser, skip the nonce verification portion
             } else {
                 if (isset($_POST['wordfence_twoFactorNonce'])) {
                     $twoFactorNonce = preg_replace('/[^a-f0-9]/i', '', $_POST['wordfence_twoFactorNonce']);
                     if (!self::verifyTwoFactorIntermediateValues($userID, $twoFactorNonce)) {
                         self::$authError = new WP_Error('twofactor_required', __('<strong>VERIFICATION FAILED</strong>: Two factor authentication verification failed. Please try again.'));
                         return self::processBruteForceAttempt(self::$authError, $username, $passwd);
                     }
                 } else {
                     //Code path for old method, invalid password the second time
                     self::$authError = $authUser;
                     if (is_wp_error(self::$authError) && (self::$authError->get_error_code() == 'invalid_username' || $authUser->get_error_code() == 'invalid_email' || self::$authError->get_error_code() == 'incorrect_password' || $authUser->get_error_code() == 'authentication_failed') && wfConfig::get('loginSec_maskLoginErrors')) {
                         self::$authError = new WP_Error('incorrect_password', sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%2$s" title="Password Lost and Found">Lost your password</a>?'), $username, wp_lostpassword_url()));
                     }
                     return self::processBruteForceAttempt(self::$authError, $username, $passwd);
                 }
             }
             if (isset($twoFactorRecord[5])) {
                 //New method TOTP
                 $mode = $twoFactorRecord[5];
                 $code = preg_replace('/[^a-f0-9]/i', '', $_POST['wordfence_authFactor']);
                 $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                 try {
                     $codeResult = $api->call('twoFactorTOTP_verify', array(), array('totpid' => $twoFactorRecord[6], 'code' => $code, 'mode' => $mode));
                     if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                         //No longer a paid key, let them sign in without two factor
                     } else {
                         if (isset($codeResult['ok']) && $codeResult['ok']) {
                             //Everything's good, let the sign in continue
                         } else {
                             if (get_class($authUser) == 'WP_User' && $authUser->ID == $userID) {
                                 //Using the old method of appending the code to the password
                                 if ($mode == 'authenticator') {
                                     self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: Please sign in again and add a space, the letters <code>wf</code>, and the code from your authenticator app to the end of your password (e.g., <code>wf123456</code>).'));
                                 } else {
                                     self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: Please sign in again and add a space, the letters <code>wf</code>, and the code sent to your phone to the end of your password (e.g., <code>wf123456</code>).'));
                                 }
                             } else {
                                 $loginNonce = wfWAFUtils::random_bytes(20);
                                 if ($loginNonce === false) {
                                     //Should never happen but is technically possible
                                     self::$authError = new WP_Error('twofactor_required', __('<strong>AUTHENTICATION FAILURE</strong>: A temporary failure was encountered while trying to log in. Please try again.'));
                                     return self::$authError;
                                 }
                                 $loginNonce = bin2hex($loginNonce);
                                 update_user_meta($userDat->ID, '_wf_twoFactorNonce', $loginNonce);
                                 update_user_meta($userDat->ID, '_wf_twoFactorNonceTime', time());
                                 if ($mode == 'authenticator') {
                                     self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: You need to enter the code generated by your authenticator app. The code should be a six digit number (e.g., 123456).') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                 } else {
                                     self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: You need to enter the code generated sent to your phone. The code should be a six digit number (e.g., 123456).') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                 }
                             }
                             return self::processBruteForceAttempt(self::$authError, $username, $passwd);
                         }
                     }
                 } catch (Exception $e) {
                     if (self::isDebugOn()) {
                         error_log('TOTP validation error: ' . $e->getMessage());
                     }
                 }
                 // Couldn't connect to noc1, let them sign in since the password was correct.
             } else {
                 //Old method phone authentication
                 $authFactor = $_POST['wordfence_authFactor'];
                 if (strlen($authFactor) == 4) {
                     $authFactor = 'wf' . $authFactor;
                 }
                 if ($authFactor == $twoFactorRecord[2] && $twoFactorRecord[4] > time()) {
                     // Set this 2FA code to expire in 30 seconds (for other plugins hooking into the auth process)
                     $twoFactorRecord[4] = time() + 30;
                     wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                 } else {
                     if ($authFactor == $twoFactorRecord[2]) {
                         $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                         try {
                             $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $twoFactorRecord[1]));
                             if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                                 //No longer a paid key, let them sign in without two factor
                             } else {
                                 if (isset($codeResult['ok']) && $codeResult['ok']) {
                                     $twoFactorRecord[2] = $codeResult['code'];
                                     $twoFactorRecord[4] = time() + 1800;
                                     //30 minutes until code expires
                                     wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                                     //save the code the user needs to enter and return an error.
                                     $loginNonce = wfWAFUtils::random_bytes(20);
                                     if ($loginNonce === false) {
                                         //Should never happen but is technically possible
                                         self::$authError = new WP_Error('twofactor_required', __('<strong>AUTHENTICATION FAILURE</strong>: A temporary failure was encountered while trying to log in. Please try again.'));
                                         return self::$authError;
                                     }
                                     $loginNonce = bin2hex($loginNonce);
                                     update_user_meta($userDat->ID, '_wf_twoFactorNonce', $loginNonce);
                                     update_user_meta($userDat->ID, '_wf_twoFactorNonceTime', time());
                                     self::$authError = new WP_Error('twofactor_required', __('<strong>CODE EXPIRED. CHECK YOUR PHONE:</strong> The code you entered has expired. Codes are only valid for 30 minutes for security reasons. We have sent you a new code. Please sign in using your username, password, and the new code we sent you.') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                     return self::$authError;
                                 }
                             }
                             //else: No new code was received. Let them sign in with the expired code.
                         } catch (Exception $e) {
                             // Couldn't connect to noc1, let them sign in since the password was correct.
                         }
                     } else {
                         //Bad code, so cancel the login and return an error to user.
                         $loginNonce = wfWAFUtils::random_bytes(20);
                         if ($loginNonce === false) {
                             //Should never happen but is technically possible
                             self::$authError = new WP_Error('twofactor_required', __('<strong>AUTHENTICATION FAILURE</strong>: A temporary failure was encountered while trying to log in. Please try again.'));
                             return self::$authError;
                         }
                         $loginNonce = bin2hex($loginNonce);
                         update_user_meta($userDat->ID, '_wf_twoFactorNonce', $loginNonce);
                         update_user_meta($userDat->ID, '_wf_twoFactorNonceTime', time());
                         self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: You need to enter your password and the code we sent to your phone. The code should start with \'wf\' and should be four characters (e.g., wfAB12).') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                         return self::processBruteForceAttempt(self::$authError, $username, $passwd);
                     }
                 }
             }
             delete_user_meta($userDat->ID, '_wf_twoFactorNonce');
             delete_user_meta($userDat->ID, '_wf_twoFactorNonceTime');
             $authUser = $userDat;
             //Log in as the user we saved in the wp_authenticate action
         } else {
             if (get_class($authUser) == 'WP_User') {
                 //User authenticated with name and password, prompt for the 2FA code
                 //Verify at least one administrator has 2FA enabled
                 $requireAdminTwoFactor = $hasActivatedTwoFactorUser && wfConfig::get('loginSec_requireAdminTwoFactor');
                 if ($twoFactorRecord) {
                     if ($twoFactorRecord[0] == $userDat->ID && $twoFactorRecord[3] == 'activated') {
                         //Yup, enabled, so require the code
                         $loginNonce = wfWAFUtils::random_bytes(20);
                         if ($loginNonce === false) {
                             //Should never happen but is technically possible, allow login
                             $requireAdminTwoFactor = false;
                         } else {
                             $loginNonce = bin2hex($loginNonce);
                             update_user_meta($userDat->ID, '_wf_twoFactorNonce', $loginNonce);
                             update_user_meta($userDat->ID, '_wf_twoFactorNonceTime', time());
                             if (isset($twoFactorRecord[5])) {
                                 //New method TOTP authentication
                                 if ($twoFactorRecord[5] == 'authenticator') {
                                     if (self::hasGDLimitLoginsMUPlugin() && function_exists('limit_login_get_address')) {
                                         $retries = get_option('limit_login_retries', array());
                                         $ip = limit_login_get_address();
                                         if (!is_array($retries)) {
                                             $retries = array();
                                         }
                                         if (isset($retries[$ip]) && is_int($retries[$ip])) {
                                             $retries[$ip]--;
                                         } else {
                                             $retries[$ip] = 0;
                                         }
                                         update_option('limit_login_retries', $retries);
                                     }
                                     $allowSeparatePrompt = ini_get('output_buffering') > 0;
                                     if (wfConfig::get('loginSec_enableSeparateTwoFactor') && $allowSeparatePrompt) {
                                         self::$authError = new WP_Error('twofactor_required', __('<strong>CODE REQUIRED</strong>: Please check your authenticator app for the current code. Enter it below to sign in.') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                         return self::$authError;
                                     } else {
                                         self::$authError = new WP_Error('twofactor_required', __('<strong>CODE REQUIRED</strong>: Please check your authenticator app for the current code. Please sign in again and add a space, the letters <code>wf</code>, and the code to the end of your password (e.g., <code>wf123456</code>).'));
                                         return self::$authError;
                                     }
                                 } else {
                                     //Phone TOTP
                                     $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                                     try {
                                         $codeResult = $api->call('twoFactorTOTP_sms', array(), array('totpid' => $twoFactorRecord[6]));
                                         if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                                             $requireAdminTwoFactor = false;
                                             //Let them sign in without two factor if their API key has expired or they're not paid and for some reason they have this set up.
                                         } else {
                                             if (isset($codeResult['ok']) && $codeResult['ok']) {
                                                 if (self::hasGDLimitLoginsMUPlugin() && function_exists('limit_login_get_address')) {
                                                     $retries = get_option('limit_login_retries', array());
                                                     $ip = limit_login_get_address();
                                                     if (!is_array($retries)) {
                                                         $retries = array();
                                                     }
                                                     if (isset($retries[$ip]) && is_int($retries[$ip])) {
                                                         $retries[$ip]--;
                                                     } else {
                                                         $retries[$ip] = 0;
                                                     }
                                                     update_option('limit_login_retries', $retries);
                                                 }
                                                 $allowSeparatePrompt = ini_get('output_buffering') > 0;
                                                 if (wfConfig::get('loginSec_enableSeparateTwoFactor') && $allowSeparatePrompt) {
                                                     self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Enter it below to sign in.') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                                     return self::$authError;
                                                 } else {
                                                     self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Please sign in again and add a space, the letters <code>wf</code>, and the code to the end of your password (e.g., <code>wf123456</code>).'));
                                                     return self::$authError;
                                                 }
                                             } else {
                                                 //oops, our API returned an error.
                                                 $requireAdminTwoFactor = false;
                                                 //Let them sign in without two factor because the API is broken and we don't want to lock users out of their own systems.
                                             }
                                         }
                                     } catch (Exception $e) {
                                         if (self::isDebugOn()) {
                                             error_log('TOTP SMS error: ' . $e->getMessage());
                                         }
                                         $requireAdminTwoFactor = false;
                                         // Couldn't connect to noc1, let them sign in since the password was correct.
                                     }
                                 }
                             } else {
                                 //Old method phone authentication
                                 $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                                 try {
                                     $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $twoFactorRecord[1]));
                                     if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                                         $requireAdminTwoFactor = false;
                                         //Let them sign in without two factor if their API key has expired or they're not paid and for some reason they have this set up.
                                     } else {
                                         if (isset($codeResult['ok']) && $codeResult['ok']) {
                                             $twoFactorRecord[2] = $codeResult['code'];
                                             $twoFactorRecord[4] = time() + 1800;
                                             //30 minutes until code expires
                                             wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                                             //save the code the user needs to enter and return an error.
                                             if (self::hasGDLimitLoginsMUPlugin() && function_exists('limit_login_get_address')) {
                                                 $retries = get_option('limit_login_retries', array());
                                                 $ip = limit_login_get_address();
                                                 if (!is_array($retries)) {
                                                     $retries = array();
                                                 }
                                                 if (isset($retries[$ip]) && is_int($retries[$ip])) {
                                                     $retries[$ip]--;
                                                 } else {
                                                     $retries[$ip] = 0;
                                                 }
                                                 update_option('limit_login_retries', $retries);
                                             }
                                             $allowSeparatePrompt = ini_get('output_buffering') > 0;
                                             if (wfConfig::get('loginSec_enableSeparateTwoFactor') && $allowSeparatePrompt) {
                                                 self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Enter it below to sign in.') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                                 return self::$authError;
                                             } else {
                                                 self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Please sign in again and add a space and the code to the end of your password (e.g., <code>wfABCD</code>).'));
                                                 return self::$authError;
                                             }
                                         } else {
                                             //oops, our API returned an error.
                                             $requireAdminTwoFactor = false;
                                             //Let them sign in without two factor because the API is broken and we don't want to lock users out of their own systems.
                                         }
                                     }
                                 } catch (Exception $e) {
                                     $requireAdminTwoFactor = false;
                                     // Couldn't connect to noc1, let them sign in since the password was correct.
                                 }
                             }
                             //end: Old method phone authentication
                         }
                     }
                 }
                 if ($requireAdminTwoFactor && wfUtils::isAdmin($authUser)) {
                     $username = $authUser->user_login;
                     self::getLog()->logLogin('loginFailValidUsername', 1, $username);
                     wordfence::alert("Admin Login Blocked", "A user with username \"{$username}\" who has administrator access tried to sign in to your WordPress site. Access was denied because all administrator accounts are required to have Cellphone Sign-in enabled but this account does not.", wfUtils::getIP());
                     self::$authError = new WP_Error('twofactor_disabled_required', __('<strong>Cellphone Sign-in Required</strong>: Cellphone Sign-in is required for all administrator accounts. Please contact the site administrator to enable it for your account.'));
                     return self::$authError;
                 }
                 //User is not configured for two factor. Sign in without two factor.
             }
         }
     }
     //End: if ($checkTwoFactor)
     return self::processBruteForceAttempt($authUser, $username, $passwd);
 }