OS : Linux
PHP Version : 7.4.33
Software : Apache/2.4.6 (CentOS) PHP/7.4.33
Information System : Linux apprendre2 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
Disable Function : ID ) ) {
return new WP_Error( 'no-user', 'Invalid user data' );
}
$cus = cerber_get_set( CRB_USER_SET, $user->ID );
$tfm = crb_array_get( $cus, 'tfm' );
if ( $tfm === 2 ) {
return false;
}
$login = (string) $login;
$go = false;
if ( $tfm == 1 ) {
$go = true;
}
else {
$u_roles = null;
if ( ! empty( $user->roles ) ) {
$u_roles = $user->roles;
}
else { // a backup way
$data = get_userdata( $user->ID );
if ( ! empty( $data->roles ) ) {
$u_roles = $data->roles;
}
}
if ( empty( $u_roles ) ) {
return new WP_Error( 'no-roles', 'No roles found for the user #' . $user->ID );
}
$go = self::check_role_policies( $user->ID, $cus, $u_roles );
}
if ( ! $go ) {
return false;
}
// This user must complete 2FA
$ret = self::initiate_2fa( $user, $login );
if ( crb_is_wp_error( $ret ) ) {
return $ret;
}
cerber_log( 400, $login, $user->ID );
wp_safe_redirect( get_home_url() );
exit;
}
/**
* @param int $user_id
* @param array $cus
* @param array $roles
*
* @return bool
*/
private static function check_role_policies( $user_id, $cus, $roles ) {
foreach ( $roles as $role ) {
$policies = cerber_get_role_policies( $role );
if ( empty( $policies['2famode'] )
|| ( $policies['2famode'] == 2 && ! lab_lab() ) ) {
continue;
}
elseif ( $policies['2famode'] == 1 ) {
return true;
}
if ( $history = crb_array_get( $cus, '2fa_history' ) ) {
if ( ( $logins = crb_array_get( $policies, '2falogins' ) )
&& ( $history[0] >= $logins ) ) {
return true;
}
if ( ( $days = crb_array_get( $policies, '2fadays' ) )
&& ( ( time() - $history[1] ) > $days * 24 * 3600 ) ) {
return true;
}
}
if ( $last_login = crb_array_get( $cus, 'last_login' ) ) {
if ( crb_array_get( $policies, '2fanewip' ) ) {
if ( $last_login['ip'] != cerber_get_remote_ip() ) {
return true;
}
}
if ( crb_array_get( $policies, '2fanewnet4' ) ) {
if ( cerber_get_subnet_ipv4( $last_login['ip'] ) != cerber_get_subnet_ipv4( cerber_get_remote_ip() ) ) {
return true;
}
}
if ( crb_array_get( $policies, '2fanewua' ) ) {
if ( $last_login['ua'] != sha1( crb_array_get( $_SERVER, 'HTTP_USER_AGENT', '' ) ) ) {
return true;
}
}
}
if ( $limit = crb_array_get( $policies, '2fasessions' ) ) {
if ( $limit < crb_sessions_get_num( $user_id ) ) {
return true;
}
}
if ( $last_login ) {
if ( crb_array_get( $policies, '2fanewcountry' ) ) {
if ( lab_get_country( $last_login['ip'], false ) != lab_get_country( cerber_get_remote_ip(), false ) ) {
return true;
}
}
}
}
return false;
}
/**
* Initiate 2FA process
*
* @param $user
* @param string $login
*
* @return bool|string|WP_Error
*/
private static function initiate_2fa( $user, $login = '' ) {
if ( ! $pin = self::generate_pin( $user->ID ) ) {
return new WP_Error( '2fa-error', 'Unable to create PIN for the user #' . $user->ID );
}
$data = array(
'login' => $login,
'to' => cerber_2fa_get_redirect_to( $user ),
'ajax' => cerber_is_wp_ajax(),
'interim' => isset( $_REQUEST['interim-login'] ) ? 1 : 0,
);
self::update_2fa_data( $data, $user->ID );
return $pin;
}
/**
* Generates PIN and its expiration
*
* @param $user_id
*
* @return bool|string
*/
private static function generate_pin( $user_id ) {
$pin = substr( str_shuffle( '1234567890' ), 0, CERBER_PIN_LENGTH );
$data = array(
'pin' => $pin,
'expires' => time() + CERBER_PIN_EXPIRES * 60,
'attempts' => 0,
'ip' => cerber_get_remote_ip(),
'ua' => sha1( crb_array_get( $_SERVER, 'HTTP_USER_AGENT', '' ) )
);
if ( self::update_2fa_data( $data, $user_id ) ) {
self::send_user_pin( $user_id, $pin );
return $pin;
}
return false;
}
/**
* @param null $user_id User ID
*
*/
static function restrict_and_verify( $user_id = null ) {
static $done = false;
if ( $done ) {
return;
}
$done = true;
if ( ! $user_id && ! $user_id = get_current_user_id() ) {
return;
}
self::$user_id = $user_id;
$cus = cerber_get_set( CRB_USER_SET, $user_id );
$twofactor = self::get_2fa_data( $user_id );
if ( empty( $twofactor['pin'] ) ) {
return;
}
if ( crb_acl_is_white() ) {
self::delete_2fa( $user_id );
return;
}
// Check user settings again
$tfm = crb_array_get( $cus, 'tfm' );
if ( $tfm === 2 ) {
self::delete_2fa( $user_id, true );
return;
}
elseif ( ! $tfm ) {
$user = wp_get_current_user();
if ( ! self::check_role_policies( $user_id, $cus, $user->roles ) ) {
self::delete_2fa( $user_id );
return;
}
}
// Check the context
if ( ( $sts = ( $twofactor['ip'] != cerber_get_remote_ip() ? 540 : 0 ) )
|| ( $sts = ( $twofactor['ua'] != sha1( crb_array_get( $_SERVER, 'HTTP_USER_AGENT', '' ) ) ? 541 : 0 ) )
|| ( $sts = ( cerber_is_ip_allowed() ? 0 : CRB_Globals::$act_status ) ) ) {
self::delete_2fa( $user_id );
cerber_user_logout( $sts );
wp_redirect( get_home_url() );
exit;
}
// User wants to abort 2FA?
if ( $now = cerber_get_get( 'cerber_2fa_now' ) ) {
$go = null;
if ( $now == 'different' ) {
$go = wp_login_url( ( ! empty( $twofactor['to'] ) ) ? urldecode( $twofactor['to'] ) : '' );
}
if ( $now == 'cancel' ) {
$go = get_home_url();
}
if ( $go ) {
cerber_user_logout( 28 );
wp_redirect( $go );
exit;
}
}
if ( $twofactor['attempts'] > 5 ) {
cerber_soft_block_add( cerber_get_remote_ip(), 721 );
cerber_user_logout( 542 );
wp_redirect( get_home_url() );
exit;
}
$new_pin = '';
if ( $twofactor['expires'] < time() ) {
$new_pin = self::generate_pin( $user_id );
}
// The first step of verification, ajax
if ( cerber_is_http_post() ) {
self::process_ajax( $new_pin );
}
// The second, final step of verification
if ( cerber_is_http_post()
&& ! empty( $twofactor['nonce'] )
&& $_POST['cerber_tag'] === $twofactor['nonce']
&& ( $pin = cerber_get_post( 'cerber_pin' ) )
&& self::verify_pin( trim( $pin ) ) ) {
self::delete_2fa( $user_id );
cerber_log( CRB_EV_LIN, $twofactor['login'], $user_id, 27 );
cerber_login_history( $user_id, true );
cerber_2fa_checker( true );
$url = ( ! empty( $twofactor['to'] ) ) ? $twofactor['to'] : get_home_url();
wp_safe_redirect( $url );
exit;
}
self::show_2fa_page();
exit;
}
static function process_ajax( $new_pin ) {
if ( ( ! $nonce = cerber_get_post( 'the_2fa_nonce', '\w+' ) )
|| ( ! $pin = cerber_get_post( 'cerber_verify_pin' ) ) ) {
return;
}
$err = '';
if ( ! wp_verify_nonce( $nonce, 'crb-ajax-2fa' ) ) {
$err = 'Nonce error.';
}
elseif ( $new_pin ) {
$err = __( 'This verification PIN code is expired. We have just sent a new one to your email.', 'wp-cerber' );
}
elseif ( ! self::verify_pin( trim( $pin ), $nonce ) ) {
$err = __( 'You have entered an incorrect verification PIN code', 'wp-cerber' );
}
echo json_encode( array( 'error' => $err ) );
exit;
}
private static function verify_pin( $pin, $nonce = null ) {
$data = self::get_2fa_data();
if ( empty( $data['pin'] )
|| $data['expires'] < time() ) {
return false;
}
if ( (string) $pin === (string) $data['pin'] ) {
$ret = true;
if ( ! $nonce ) {
return $ret;
}
$data['nonce'] = $nonce;
}
else {
$data['attempts'] ++;
$ret = false;
}
self::update_2fa_data( $data );
return $ret;
}
static function show_2fa_page( $echo = true ) {
@ini_set( 'display_errors', 0 );
$ajax_vars = 'var ajaxurl = "' . admin_url( 'admin-ajax.php' ) . '";';
$ajax_vars .= 'var nonce2fa = "'. wp_create_nonce( 'crb-ajax-2fa' ).'";';
if ( ! defined( 'CONCATENATE_SCRIPTS' ) ) {
define( 'CONCATENATE_SCRIPTS', false );
}
wp_enqueue_script( 'jquery' );
ob_start();
?>
'. __( 'Enter the code from the email in the field below.', 'wp-cerber' ).' '.__( 'Did not receive the email?', 'wp-cerber' ) .'' . $entry['pin'] . ' ' . __( 'expires', 'wp-cerber' ) . ' ' . cerber_ago_time( $entry['expires'] );
}
if ( ! $pins ) {
return '';
}
return implode( '
', $pins );
}
static function update_2fa_data( $data, $user_id = null ) {
$token = self::cerber_2fa_session_id();
if ( ! $user_id ) {
$user_id = get_current_user_id();
}
$cus = cerber_get_set( CRB_USER_SET, $user_id );
if ( ! is_array( $cus ) ) {
$cus = array();
}
if ( ! isset( $cus['2fa'] ) ) {
$cus['2fa'] = array();
}
if ( ! isset( $cus['2fa'][ $token ] ) ) {
$cus['2fa'][ $token ] = array();
}
$cus['2fa'][ $token ] = array_merge( $cus['2fa'][ $token ], $data );
return cerber_update_set( CRB_USER_SET, $cus, $user_id );
}
static function get_2fa_data( $user_id = null ) {
$token = self::cerber_2fa_session_id();
if ( ! $user_id ) {
$user_id = get_current_user_id();
}
if ( ! $cus = cerber_get_set( CRB_USER_SET, $user_id ) ) {
return array();
}
return crb_array_get( $cus, array( '2fa', $token ), array() );
}
static function delete_2fa( $uid, $all = false ) {
if ( ! $uid = absint( $uid ) ) {
return;
}
$cus = cerber_get_set( CRB_USER_SET, $uid );
if ( $cus && isset( $cus['2fa'] ) ) {
if ( $all ) {
unset( $cus['2fa'] );
}
else {
unset( $cus['2fa'][ self::cerber_2fa_session_id() ] );
}
cerber_update_set( CRB_USER_SET, $cus, $uid );
}
}
static function cerber_2fa_session_id() {
if ( self::$token ) {
return self::$token;
}
return crb_get_session_token();
}
static function cerber_2fa_form() {
$max = CERBER_PIN_LENGTH;
$atts = 'pattern="\d{' . $max . '}" maxlength="' . $max . '" size="' . $max . '" title="' . __( 'only digits are allowed', 'wp-cerber' ) . '"';
// Please enter your PIN code to continue
$email = self::get_user_email();
$text = __( "We've sent a verification PIN code to your email", 'wp-cerber' ) . ' ' . cerber_mask_email( $email ) .
'