enqueue_assets( '' ); } wp_nonce_field( 'user_two_factor_totp_options', '_nonce_user_two_factor_totp_options', false ); $totp_key = $this->get_key( $user ); $this->admin_notices(); ?>
already_active = true; $return->key = get_user_meta( $user->ID, self::SECRET_META_KEY, true ); if ( empty( $return->key ) ) { $return->key = $this->generate_key(); $return->already_active = false; } return $return; } /** * Save the options specified in `::user_two_factor_options()` * * @param integer $user_id The user ID whose options are being updated. */ public function user_two_factor_options_update( $user_id ) { if ( isset( $_POST['_nonce_user_two_factor_totp_options'] ) ) { check_admin_referer( 'user_two_factor_totp_options', '_nonce_user_two_factor_totp_options' ); // If there is no authcode provided if ( empty( $_POST['two-factor-totp-authcode'] ) ) { $two_factor_core = ITSEC_Two_Factor::get_instance(); // Check to see if TOTP is enabled, and if not then go no further if ( ! in_array( 'Two_Factor_Totp', $two_factor_core->get_enabled_providers_for_user() ) ) { return; } } $current_key = get_user_meta( $user_id, self::SECRET_META_KEY, true ); // If the key hasn't changed or is invalid, do nothing. if ( $current_key === $_POST['two-factor-totp-key'] || ! preg_match( '/^[' . $this->_base_32_chars . ']+$/', $_POST['two-factor-totp-key'] ) ) { return; } $notices = array(); if ( empty( $_POST['two-factor-totp-authcode'] ) ) { $notices['error'][] = __( 'Two-Factor Authentication not activated, you must specify authcode to ensure it is properly set up. Please re-scan the QR code and enter the code provided by your application.', 'it-l10n-ithemes-security-pro' ); } else { if ( $this->_is_valid_authcode( $_POST['two-factor-totp-key'], $_POST['two-factor-totp-authcode'] ) ) { if ( ! update_user_meta( $user_id, self::SECRET_META_KEY, $_POST['two-factor-totp-key'] ) ) { $notices['error'][] = __( 'Unable to save Two-Factor Authentication code. Please re-scan the QR code and enter the code provided by your application.', 'it-l10n-ithemes-security-pro' ); } } else { $notices['error'][] = __( 'Two-Factor Authentication not activated, the authentication code you entered was not valid. Please re-scan the QR code and enter the code provided by your application.', 'it-l10n-ithemes-security-pro' ); } } if ( ! empty( $notices ) ) { update_user_meta( $user_id, self::NOTICES_META_KEY, $notices ); } } } public function ajax_new_code() { check_ajax_referer( 'user_two_factor_totp_options', '_nonce_user_two_factor_totp_options' ); $site_name = get_bloginfo( 'name', 'display' ); $return = array(); $return['key'] = $this->generate_key(); $return['qrcode_url'] = $this->get_google_qr_code( $site_name . ':' . $_POST['user_login'], $return['key'], $site_name ); wp_send_json_success( $return ); } public function ajax_verify_code() { check_ajax_referer( 'user_two_factor_totp_options', '_nonce_user_two_factor_totp_options' ); $user_id = (int) $_POST['user_id']; if ( ! $user_id || ! current_user_can( 'edit_user', $user_id ) ) { wp_send_json_error( __( 'You do not have permission to edit this user.', 'it-l10n-ithemes-security-pro' ) ); } if ( $this->_is_valid_authcode( $_POST['key'], $_POST['authcode'] ) ) { if ( ! update_user_meta( $user_id, self::SECRET_META_KEY, $_POST['key'] ) ) { wp_send_json_error( __( 'Unable to save two-factor secret.', 'it-l10n-ithemes-security-pro' ) ); } wp_send_json_success( __( 'Success!', 'it-l10n-ithemes-security-pro' ) ); } else { wp_send_json_error( __( 'The code you supplied is not valid.', 'it-l10n-ithemes-security-pro' ) ); } $site_name = get_bloginfo( 'name', 'display' ); $return = array(); $return['key'] = $this->generate_key(); $return['qrcode_url'] = $this->get_google_qr_code( $site_name . ':' . $_POST['user_login'], $return['key'], $site_name ); wp_send_json( $return ); } /** * Display any available admin notices. * * @param array $notices Keys are CSS class to use, values are an array of messages. */ public function admin_notices( $notices = null ) { if ( ! isset( $notices ) ) { $notices = get_user_meta( get_current_user_id(), self::NOTICES_META_KEY, true ); delete_user_meta( get_current_user_id(), self::NOTICES_META_KEY ); } if ( ! empty( $notices ) ) { foreach ( $notices as $class => $messages ) { ?>
_base_32_chars . ']+$/', $base32_string, $match ) ) { throw new Exception( 'Invalid characters in the base32 string.' ); } $l = strlen( $base32_string ); $n = 0; $j = 0; $binary = ''; for ( $i = 0; $i < $l; $i ++ ) { $n = $n << 5; // Move buffer left by 5 to make room. $n = $n + strpos( $this->_base_32_chars, $base32_string[ $i ] ); // Add value into buffer. $j += 5; // Keep track of number of bits in buffer. if ( $j >= 8 ) { $j -= 8; $binary .= chr( ( $n & ( 0xFF << $j ) ) >> $j ); } } return $binary; } /** * Used with usort to sort an array by distance from 0 * * @param int $a First array element. * @param int $b Second array element. * * @return int -1, 0, or 1 as needed by usort */ private function abssort( $a, $b ) { $a = abs( $a ); $b = abs( $b ); if ( $a === $b ) { return 0; } return ( $a < $b ) ? - 1 : 1; } public function description() { echo '
' . sprintf( wp_kses( __( 'Use a two-factor mobile app such as Authy or Google Authenticator (Android, iOS). The mobile app generates a time-sensitive code that must be supplied when logging in.', 'it-l10n-ithemes-security-pro' ), array( 'a' => array( 'href' => array() ) ) ), esc_url( 'https://www.authy.com/app/mobile/' ), esc_url( 'https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en' ), esc_url( 'https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8' ) ) . '
'; } /** * @inheritDoc */ public function get_on_board_dashicon() { return 'smartphone'; } /** * @inheritDoc */ public function get_on_board_label() { return esc_html__( 'Mobile App', 'it-l10n-ithemes-security-pro' ); } /** * @inheritDoc */ public function get_on_board_description() { return esc_html__( 'Log in to WordPress using a mobile app like Authy or Google Authenticator.', 'it-l10n-ithemes-security-pro' ); } /** * @inheritDoc */ public function has_on_board_configuration() { return true; } /** * @inheritDoc */ public function get_on_board_config( WP_User $user ) { $key = $this->get_key( $user ); $blog = get_bloginfo( 'name', 'display' ); return array( 'secret' => $key->key, 'qr' => $this->get_google_qr_code( $blog . ':' . $user->user_login, $key->key, $blog, array( 'size' => 300 ) ), ); } /** * @inheritDoc */ public function handle_ajax_on_board( WP_User $user, array $data ) { if ( $data['itsec_method'] !== 'verify-totp-code' ) { return; } if ( ! isset( $data['itsec_totp_secret'], $data['itsec_totp_code'] ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid Request Format', 'it-l10n-ithemes-security-pro' ), ) ); } $secret = $data['itsec_totp_secret']; if ( $this->_is_valid_authcode( $secret, $data['itsec_totp_code'] ) ) { if ( $secret !== get_user_meta( $user->ID, self::SECRET_META_KEY, true ) && ! update_user_meta( $user->ID, self::SECRET_META_KEY, $secret ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Unable to save two-factor secret.', 'it-l10n-ithemes-security-pro' ), ) ); } wp_send_json_success( array( 'message' => esc_html__( 'Success!', 'it-l10n-ithemes-security-pro' ), ) ); } else { wp_send_json_error( array( 'message' => esc_html__( 'The code you supplied is not valid.', 'it-l10n-ithemes-security-pro' ), ) ); } } public function configure_via_cli( WP_User $user, array $args ) { $key = $this->generate_key(); if ( ! update_user_meta( $user->ID, self::SECRET_META_KEY, $key ) ) { WP_CLI::error( 'Could not save Totp secret.' ); } if ( empty( $args['porcelain'] ) ) { WP_CLI::log( sprintf( 'Totp Secret: %s', $key ) ); } else { WP_CLI::log( $key ); } } }