芝麻web文件管理V1.00
编辑当前文件:/home/sditechnicalteam/ppclaunchers.com/wp-content/plugins/sg-security/core/Sg_2fa/Sg_2fa.php
encryption_key_file = defined( 'SGS_ENCRYPTION_KEY_FILE_PATH' ) ? SGS_ENCRYPTION_KEY_FILE_PATH : WP_CONTENT_DIR . '/sgs_encrypt_key.php'; $this->google_authenticator = new PHPGangsta_GoogleAuthenticator(); $this->recovery = new Recovery(); $this->encryption = new Encryption_Service( $this->encryption_key_file ); } /** * Get the singleton instance. * * @since 1.1.1 * * @return \Sg_2fa The singleton instance. */ public static function get_instance() { if ( null == self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Generate QR code for specific user. * * @since 1.0.0 * * @param int $user_id WordPress user ID. * * @return string The QR code URL. */ public function generate_qr_code( $user_id ) { // Get the user by ID. $user = get_user_by( 'ID', $user_id ); // Build the title for the authenticator. $title = get_home_url() . ' (' . $user->user_email . ')'; // Get the user secret code. $secret = $this->get_user_secret( $user->ID ); // phpcs:ignore // Return the URL. return $this->google_authenticator->getQRCodeGoogleUrl( $title, $secret ); } /** * Verify the authenticaion code. * * @since 1.0.0 * * @param string $code One time code from the authenticator app. * @param int $user_id The user ID. * * @return bool True if the code is valid, false otherwise. */ public function check_authentication_code( $code, $user_id ) { // Get the user secret. $secret = $this->get_user_secret( $user_id ); // phpcs:ignore // Verify the code. return $this->google_authenticator->verifyCode( $secret, $code, 2 ); } /** * Enable 2FA. * * @since 1.0.0 * * @return bool True on success, false on failure. */ public function enable_2fa() { // Remove admin notice for file creation. delete_option( 'sg_security_2fa_encryption_file_notice' ); // Get all users which needs to have 2FA enabled. $users = get_users( array( 'role__in' => $this->get_admin_user_roles(), ) ); // Bail if there are no such users found. if ( empty( $users ) ) { return true; } foreach ( $users as $user ) { // Get the user by the user id. $user = get_userdata( $user->data->ID ); if ( empty( array_intersect( $this->get_admin_user_roles(), $user->roles ) ) ) { continue; } $session_tokens = WP_Session_Tokens::get_instance( $user->data->ID ); $session_tokens->destroy_all(); } return true; } /** * Handle 2FA option change. * * @since 1.0.0 * * @param mixed $new_value New option value. * @param mixed $old_value Old option value. */ public function handle_option_change( $new_value, $old_value ) { if ( 1 === intval( $new_value ) && false === $this->encryption->generate_encryption_file() ) { return $old_value; } if ( 1 == $new_value ) { $this->enable_2fa(); } return $new_value; } /** * Generate the user secret. * * @since 1.0.0 * * @param int $user_id WordPress user ID. * * @return mixed True on success, false on failure, user ID if the secret exists. */ public function generate_user_secret( $user_id ) { // Check if the user has secret code. $secret = $this->get_user_secret( $user_id ); // phpcs:ignore // Bail if the user already has a secret code. if ( ! empty( $secret ) ) { return $user_id; } // Add the user secret meta. return update_user_meta( // phpcs:ignore $user_id, 'sg_security_2fa_secret', $this->encryption->sgs_encrypt( $this->google_authenticator->createSecret() ) // Generate and encrypt the secret code. ); } /** * Generate the user backup codes. * * @since 1.1.0 * * @param int $user_id WordPress user ID. * * @return mixed True on success, false on failure, user ID if the backup codes exists. */ public function generate_user_backup_codes( $user_id ) { // Check if the user has backup codes. $backup_codes = get_user_meta( $user_id, 'sg_security_2fa_backup_codes', true ); // phpcs:ignore // Bail if the user already has a backup codes. if ( ! empty( $backup_codes ) ) { return array(); } // Generate the backup codes. $generated_backup_codes = $this->recovery->numeric()->setCount( 8 )->setBlocks( 1 )->setChars( 8 )->toArray(); // Store the backup codes hashed. $this->store_hashed_user_meta( $user_id, 'sg_security_2fa_backup_codes', $generated_backup_codes ); // Return the codes so we can show them to the user once. return $generated_backup_codes; } /** * Validate the backup codes 2Fa login. * * @since 1.1.0 * * @param string $code The backup login code. * @param int $user The user id. * * @return bool True if the code is correct, false on failure. */ public function validate_backup_login( $code, $user ) { $codes = get_user_meta( $user, 'sg_security_2fa_backup_codes', true ); // phpcs:ignore // Bail if the user doesn't have backup codes. if ( empty( $codes ) ) { return false; } // Validate the backup code. foreach ( $codes as $index => $hashed_code ) { if ( wp_check_password( $code, $hashed_code ) ) { // Remove the used key. unset( $codes[ $index ] ); // Update user meta with the removed code data. update_user_meta( $user, 'sg_security_2fa_backup_codes', $codes ); return true; } } // Bail if the code doesn't exists in the user backup codes. return false; } /** * Display the two factor authentication forms. * * @since 1.0.0 * * @param array $args Additional args. */ public function load_form( $args ) { // Bail if template is not provided. if ( empty( $args['template'] ) ) { return; } // Path to the form template. $path = SG_Security\DIR . '/templates/' . $args['template']; // Bail if there is no such file. if ( ! file_exists( $path ) ) { return; } $args = $this->get_args_for_template( $args ); // Check if the referer matches wp-login url. if ( strtok( wp_get_raw_referer(), '?' ) === wp_login_url() ) { $args['is_wp_login'] = true; } if ( ! empty( $this->get_2fa_nonce_cookie() ) ) { $args['is_wp_login'] = true; } // Include the login header if the function doesn't exists. if ( ! function_exists( 'login_header' ) ) { include_once ABSPATH . 'wp-login.php'; } // Include the template.php if the function doesn't exists. if ( ! function_exists( 'submit_button' ) ) { require_once ABSPATH . '/wp-admin/includes/template.php'; } // JetPack SSO Hiding 2FA form. if ( class_exists( 'Automattic\Jetpack\Connection\SSO' ) ) { remove_filter( 'login_body_class', array( \Automattic\Jetpack\Connection\SSO::get_instance(), 'login_body_class' ) ); } login_header(); // Include the template. include_once $path; login_footer(); exit; } /** * Reset the 2FA for specific user ID. * * @since 1.1.1 * * @param int $user_id WordPress user ID. * * @return array $response Responce to react app. */ public function reset_user_2fa( $user_id ) { // Bail if there is no such user. if ( false === get_user_by( 'ID', $user_id ) ) { return false; } // Delete the 2FA user meta and reset the 2FA configuration setting. foreach ( $this->user_2fa_meta as $meta ) { delete_user_meta( $user_id, 'sg_security_2fa_' . $meta ); // phpcs:ignore } return array( 'message' => __( 'User 2FA reset!', 'sg-security' ), 'result' => 1, ); } /** * Default arguments passed to the form. * * @since 1.1.1 * * @param array $args Аrguments passed. * * @return array Аrguments merged with the default ones. */ public function get_args_for_template( $args ) { return array_merge( $args, array( 'interim_login' => ( isset( $_REQUEST['interim-login'] ) ) ? filter_var( wp_unslash( $_REQUEST['interim-login'] ), FILTER_VALIDATE_BOOLEAN ) : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended 'redirect_to' => isset( $_REQUEST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_REQUEST['redirect_to'] ) ) : admin_url(), // phpcs:ignore WordPress.Security.NonceVerification.Recommended 'rememberme' => ( ! empty( $_REQUEST['rememberme'] ) ) ? true : false, // phpcs:ignore WordPress.Security.NonceVerification.Recommended 'is_wp_login' => false, ) ); } /** * Load the backup codes form. * * @since 1.1.0 */ public function load_backup_codes_form() { // Get cookie data. $cookie_data = $this->get_2fa_nonce_cookie(); // Bail if cookie data is empty. if ( empty( $cookie_data ) ) { return; } // Load the backup code login form. $this->load_form( array( 'template' => '2fa-login-backup-code.php', 'action' => esc_url( add_query_arg( 'action', 'sgs2fabc', wp_login_url() ) ), 'error' => '', ) ); } /** * Set 30 days 2FA auth cookie. * * @since 1.2.6 * * @param int $user_id WordPress user ID. */ public function set_2fa_dnc_cookie( $user_id ) { // Generate random token. $token = bin2hex( random_bytes( 22 ) ); // Assign the token to the user. update_user_meta( $user_id, 'sgs_2fa_dnc_token', $token ); $difference = ''; $domain = $_SERVER['SERVER_NAME']; $domain_with_subfolder = get_home_url(); $protocol = isset( $_SERVER['HTTPS'] ) && ! empty( $_SERVER['HTTPS'] ) ? 'https://' : 'http://'; $escaped_domain = preg_quote( $protocol . $domain, '/' ); if ( get_site_url() !== get_home_url() ) { $domain = get_home_url(); $domain_with_subfolder = get_site_url(); $escaped_domain = preg_quote( $domain, '/' ); } if ( preg_match( '/^' . $escaped_domain . '(.*)$/', $domain_with_subfolder, $matches ) ) { $difference = $matches[1]; } $domain = empty( COOKIE_DOMAIN ) ? $_SERVER['SERVER_NAME'] : COOKIE_DOMAIN; // Set the 2FA auth cookie. setcookie( 'sg_security_2fa_dnc_cookie', $user_id . '|' . $token, time() + 2592000, $difference . '/wp-login.php', $domain, true, true ); // phpcs:ignore } /** * Check if there is a valid 2FA cookie. * * @since 1.1.1 * * @param string $user_login The username. * @param object $user WP_User object. * * @return bool True if there is a 2FA cookie, false if not. */ public function check_2fa_cookie( $user_login, $user ) { // 2FA user cookie name. $sg_2fa_user_cookie = 'sg_security_2fa_dnc_cookie'; // Bail if the cookie doesn't exists. if ( ! isset( $_COOKIE[ $sg_2fa_user_cookie ] ) ) { return false; } // Parse the cookie. $cookie_data = explode( '|', $_COOKIE[ $sg_2fa_user_cookie ] ); if ( // If the 2FA is configured for the user. 1 == get_user_meta( $cookie_data[0], 'sg_security_2fa_configured', true ) && // phpcs:ignore get_user_meta( $cookie_data[0], 'sgs_2fa_dnc_token', true ) === $cookie_data[1] // If there is already a cookie with that name and the name matches. ) { return true; } return false; } /** * Show the backup codes form to the user if this is the initial 2fa setup. * * @since 1.1.1 * * @param int $user_id WordPress user ID. */ public function show_backup_codes( $user_id ) { $this->load_form( array( 'template' => 'backup-codes.php', 'backup_codes' => $this->generate_user_backup_codes( $user_id ), 'redirect_to' => ! empty( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : get_admin_url(), // phpcs:ignore ) ); } /** * Show QR code to the user if backup code is used. * * @since 1.1.1 * * @param int $id WordPress user ID. */ public function show_qr_backup_code_used() { $this->load_form( array( 'template' => 'backup-code-used.php', 'redirect_to' => ! empty( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : get_admin_url(), // phpcs:ignore ) ); } /** * Interim WordPress login. * * @since 1.1.1 */ public function interim_check() { global $interim_login; $interim_login = ( isset( $_REQUEST['interim-login'] ) ) ? filter_var( $_REQUEST['interim-login'], FILTER_VALIDATE_BOOLEAN ) : false; // phpcs:ignore // Bail if $interim_login is false. if ( false === $interim_login ) { return; } $interim_login = 'success'; // WPCS: override ok. login_header( '', '
' . __( 'You have logged in successfully.', 'sg-security' ) . '
' ); ?>