HEX
Server: Apache/2.4.54 (Unix) OpenSSL/1.0.2k-fips
System: Linux f17.eelserver.com 3.10.0-1160.80.1.el7.x86_64 #1 SMP Tue Nov 8 15:48:59 UTC 2022 x86_64
User: zulfiqar (1155)
PHP: 8.2.0
Disabled: mail, exec, system, popen, proc_open, shell_exec, passthru, show_source
Upload Files
File: /home/zulfiqar/public_html/wp-content/plugins/stream/connectors/class-connector-two-factor.php
<?php
/**
 * Connector for Two Factor
 *
 * @package WP_Stream
 */

namespace WP_Stream;

/**
 * Class - Connector_Two_Factor
 */
class Connector_Two_Factor extends Connector {
	/**
	 * Connector slug
	 *
	 * @var string
	 */
	public $name = 'twofactor';

	/**
	 * Actions registered for this connector
	 *
	 * @var array
	 */
	public $actions = array(
		'update_user_meta', // Before user meta changes.
		'updated_user_meta', // After user meta changes.
		'added_user_meta', // After user meta is added.

		'two_factor_user_authenticated', // Authenticate via 2FA.
		'wp_login_failed', // Failed login.
	);

	/**
	 * Tracked option keys
	 *
	 * @var array
	 */
	public $options = array();

	/**
	 * Record the user_meta meta_value before updates.
	 *
	 * @var array
	 */
	public $user_meta = array();

	/**
	 * Check if plugin dependencies are satisfied and add an admin notice if not
	 *
	 * @return bool
	 */
	public function is_dependency_satisfied() {
		if ( class_exists( 'Two_Factor_Core' ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Return translated connector label
	 *
	 * @return string Translated connector label
	 */
	public function get_label() {
		return esc_html__( 'Two Factor', 'stream' );
	}

	/**
	 * Return translated action labels
	 *
	 * @return array Action label translations
	 */
	public function get_action_labels() {
		return array(
			'enabled'       => esc_html_x( 'Enabled', 'two-factor', 'stream' ),
			'disabled'      => esc_html_x( 'Disabled', 'two-factor', 'stream' ),
			'recovered'     => esc_html_x( 'Recovered', 'two-factor', 'stream' ),
			'updated'       => esc_html_x( 'Updated', 'two-factor', 'stream' ),
			'removed'       => esc_html_x( 'Removed', 'two-factor', 'stream' ),
			'added'         => esc_html_x( 'Added', 'two-factor', 'stream' ),
			'authenticated' => esc_html_x( 'Authenticated', 'two-factor', 'stream' ),
		);
	}

	/**
	 * Return translated context labels
	 *
	 * @return array Context label translations
	 */
	public function get_context_labels() {
		return array(
			'user-settings' => esc_html_x( 'User Settings', 'two-factor', 'stream' ),
			'auth'          => esc_html_x( 'Authenticated', 'two-factor', 'stream' ),
		);
	}

	/**
	 * Register the connector
	 */
	public function register() {
		parent::register();

		add_filter( 'wp_stream_log_data', array( $this, 'log_override' ) );
	}

	/**
	 * Modify or prevent logging of some actions.
	 *
	 * @param array $data Record data.
	 *
	 * @return array|bool
	 */
	public function log_override( $data ) {
		if ( ! is_array( $data ) ) {
			return $data;
		}

		// If a login was made but no cookies are being sent (ie. hit the 2FA interstitial), don't log it.
		if (
			'users' === $data['connector'] &&
			'sessions' === $data['context'] &&
			'login' === $data['action'] &&
			\Two_Factor_Core::is_user_using_two_factor( $data['user_id'] ) &&
			has_filter( 'send_auth_cookies', '__return_false' )
		) {
			$data = false;
		}

		return $data;
	}

	/**
	 * Callback to watch for user_meta changes BEFORE it's made.
	 *
	 * @param int    $meta_id        Meta ID.
	 * @param int    $user_id        User ID.
	 * @param string $meta_key       Meta key.
	 * @param mixed  $new_meta_value The NEW meta value.
	 */
	public function callback_update_user_meta( $meta_id, $user_id, $meta_key, $new_meta_value ) {
		unset( $meta_id );
		unset( $new_meta_value );

		switch ( $meta_key ) {
			case '_two_factor_backup_codes':
			case '_two_factor_totp_key':
			case '_two_factor_enabled_providers':
				$this->user_meta[ $user_id ][ $meta_key ] = get_user_meta( $user_id, $meta_key, true );
				break;
		}
	}

	/**
	 * Callback to watch for user_meta changes AFTER it's made.
	 *
	 * @param int    $meta_id        Meta ID.
	 * @param int    $user_id        User ID.
	 * @param string $meta_key       Meta key.
	 * @param mixed  $new_meta_value The NEW meta value.
	 */
	public function callback_updated_user_meta( $meta_id, $user_id, $meta_key, $new_meta_value ) {
		unset( $meta_id );

		$old_meta_value = $this->user_meta[ $user_id ][ $meta_key ] ?? null;
		unset( $this->user_meta[ $user_id ][ $meta_key ] );

		switch ( $meta_key ) {
			case '_two_factor_backup_codes':
				$this->log(
					__( 'Updated backup codes', 'stream' ),
					array(),
					$user_id,
					'user-settings',
					'updated'
				);
				break;
			case '_two_factor_totp_key':
				$this->log(
					__( 'Set TOTP secret key', 'stream' ),
					array(),
					$user_id,
					'user-settings',
					'updated'
				);
				break;
			case '_two_factor_enabled_providers':
				$old_providers = $old_meta_value ?? array();
				$new_providers = $new_meta_value ?? array();

				$enabled_providers  = array_diff( $new_providers, $old_providers );
				$disabled_providers = array_diff( $old_providers, $new_providers );

				foreach ( $enabled_providers as $provider ) {

					/* Translators: %s is the Two Factor provider. */
					$message = __(
						'Enabled provider: %s',
						'stream'
					);

					$this->log(
						$message,
						array(
							'provider' => $provider,
						),
						$user_id,
						'user-settings',
						'enabled'
					);
				}

				foreach ( $disabled_providers as $provider ) {

					/* Translators: %s is the Two Factor provider. */
					$message = __(
						'Disabled provider: %s',
						'stream'
					);

					$this->log(
						$message,
						array(
							'provider' => $provider,
						),
						$user_id,
						'user-settings',
						'disabled'
					);
				}
				break;
		}
	}

	/**
	 * Callback to watch for user_meta changes AFTER it's added.
	 *
	 * @param int    $meta_id        Meta ID.
	 * @param int    $user_id        User ID.
	 * @param string $meta_key       Meta key.
	 * @param mixed  $meta_value     Meta value.
	 */
	public function callback_added_user_meta( $meta_id, $user_id, $meta_key, $meta_value ) {
		unset( $meta_id );

		switch ( $meta_key ) {
			case '_two_factor_backup_codes':
				$this->log(
					__( 'Added backup codes', 'stream' ),
					array(),
					$user_id,
					'user-settings',
					'added'
				);
				break;
			case '_two_factor_totp_key':
				$this->log(
					__( 'Added TOTP secret key', 'stream' ),
					array(),
					$user_id,
					'user-settings',
					'added'
				);
				break;
			case '_two_factor_enabled_providers':
				foreach ( $meta_value as $provider ) {

					/* Translators: %s is the Two Factor provider. */
					$message = __(
						'Enabled provider: %s',
						'stream'
					);

					$this->log(
						$message,
						array(
							'provider' => $provider,
						),
						$user_id,
						'user-settings',
						'enabled'
					);
				}
				break;
		}
	}

	/**
	 * Callback to watch for 2FA authenticated actions.
	 *
	 * @param \WP_User $user     Authenticated user.
	 * @param ?object  $provider The 2FA Provider used, null if unknown (this might happen if using older Two Factor plugin version).
	 */
	public function callback_two_factor_user_authenticated( $user, $provider = null ) {

		/* Translators: %s is the Two Factor provider. */
		$message = __(
			'Authenticated via %s',
			'stream'
		);

		// Get the provider key.
		$provider_key = null === $provider
			? __( 'unknown Two Factor method', 'stream' )
			: $provider->get_key();

		$this->log(
			$message,
			array(
				'provider' => $provider_key,
			),
			$user->ID,
			'auth',
			'authenticated',
			$user->ID
		);
	}

	/**
	 * Callback to watch for failed logins with Two Factor errors.
	 *
	 * @param string    $user_login User login.
	 * @param \WP_Error $error WP_Error object.
	 */
	public function callback_wp_login_failed( $user_login, $error ) {
		if ( ! str_starts_with( $error->get_error_code(), 'two_factor_' ) ) {
			return;
		}

		$user = get_user_by( 'login', $user_login );
		if ( ! $user && is_email( $user_login ) ) {
			$user = get_user_by( 'email', $user_login );
		}

		/* Translators: %1$s is the user display name, %2$s is the error code, %3$s is the error message. */
		$message = __(
			'%1$s Failed 2FA: %2$s %3$s',
			'stream'
		);

		$this->log(
			$message,
			array(
				'display_name' => $this->escape_percentages( $user->display_name ),
				'code'         => $error->get_error_code(),
				'error'        => $error->get_error_message(),
			),
			$user->ID,
			'auth',
			'failed',
			$user->ID
		);
	}
}