Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 34 additions & 29 deletions class-two-factor-core.php
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ public static function maybe_show_last_login_failure_notice( $user ) {
* They were also sent an email notification in `send_password_reset_email()`, but email sent from a typical
* web server is not reliable enough to trust completely.
*
* @param WP_Error $errors
* @param WP_Error $errors Error object.
*/
public static function maybe_show_reset_password_notice( $errors ) {
if ( 'incorrect_password' !== $errors->get_error_code() ) {
Expand Down Expand Up @@ -904,7 +904,7 @@ public static function maybe_show_reset_password_notice( $errors ) {
/**
* Clear the password reset notice after the user resets their password.
*
* @param WP_User $user
* @param WP_User $user User object.
*/
public static function clear_password_reset_notice( $user ) {
delete_user_meta( $user->ID, self::USER_PASSWORD_WAS_RESET_KEY );
Expand All @@ -920,6 +920,7 @@ public static function clear_password_reset_notice( $user ) {
* @param string $redirect_to The URL to which the user would like to be redirected.
* @param string $error_msg Optional. Login error message.
* @param string|object $provider An override to the provider.
* @param string $action Action to perform.
*/
public static function login_html( $user, $login_nonce, $redirect_to, $error_msg = '', $provider = null, $action = 'validate_2fa' ) {
$provider = self::get_provider_for_user( $user, $provider );
Expand Down Expand Up @@ -965,7 +966,8 @@ public static function login_html( $user, $login_nonce, $redirect_to, $error_msg
<?php $provider->authentication_page( $user ); ?>
</form>

<?php if ( $backup_providers ) :
<?php
if ( $backup_providers ) :
$backup_link_args = array(
'action' => $action,
'wp-auth-id' => $user->ID,
Expand Down Expand Up @@ -1371,10 +1373,10 @@ public static function rest_api_can_edit_user_and_update_two_factor_options( $us
* @since 0.1-dev
*/
public static function login_form_validate_2fa() {
$wp_auth_id = ! empty( $_REQUEST['wp-auth-id'] ) ? absint( $_REQUEST['wp-auth-id'] ) : 0;
$wp_auth_id = ! empty( $_REQUEST['wp-auth-id'] ) ? absint( $_REQUEST['wp-auth-id'] ) : 0;
$nonce = ! empty( $_REQUEST['wp-auth-nonce'] ) ? wp_unslash( $_REQUEST['wp-auth-nonce'] ) : '';
$provider = ! empty( $_REQUEST['provider'] ) ? wp_unslash( $_REQUEST['provider'] ) : '';
$redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? wp_unslash( $_REQUEST['redirect_to'] ) : '';
$provider = ! empty( $_REQUEST['provider'] ) ? wp_unslash( $_REQUEST['provider'] ) : '';
$redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? wp_unslash( $_REQUEST['redirect_to'] ) : '';
$is_post_request = ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) );
$user = get_user_by( 'id', $wp_auth_id );

Expand Down Expand Up @@ -1441,7 +1443,7 @@ public static function _login_form_validate_2fa( $user, $nonce = '', $provider =
$rememberme = true;
}

$session_information_callback = static function( $session, $user_id ) use( $provider, $user ) {
$session_information_callback = static function ( $session, $user_id ) use ( $provider, $user ) {
if ( $user->ID === $user_id ) {
$session['two-factor-login'] = time();
$session['two-factor-provider'] = $provider->get_key();
Expand Down Expand Up @@ -1502,9 +1504,9 @@ public static function _login_form_validate_2fa( $user, $nonce = '', $provider =
* @since 0.9.0
*/
public static function login_form_revalidate_2fa() {
$nonce = ! empty( $_REQUEST['wp-auth-nonce'] ) ? wp_unslash( $_REQUEST['wp-auth-nonce'] ) : '';
$provider = ! empty( $_REQUEST['provider'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['provider'] ) ) : false;
$redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? wp_unslash( $_REQUEST['redirect_to'] ) : admin_url();
$nonce = ! empty( $_REQUEST['wp-auth-nonce'] ) ? wp_unslash( $_REQUEST['wp-auth-nonce'] ) : '';
$provider = ! empty( $_REQUEST['provider'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['provider'] ) ) : false;
$redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? wp_unslash( $_REQUEST['redirect_to'] ) : admin_url();
$is_post_request = ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) );

self::_login_form_revalidate_2fa( $nonce, $provider, $redirect_to, $is_post_request );
Expand All @@ -1519,10 +1521,10 @@ public static function login_form_revalidate_2fa() {
*
* @since 0.9.0
*
* @param string $nonce The nonce passed with the request.
* @param string $provider The provider to use, if known.
* @param string $redirect_to The redirection location.
* @param bool $is_post_request Whether the incoming request was a POST request or not.
* @param string $nonce The nonce passed with the request.
* @param string $provider The provider to use, if known.
* @param string $redirect_to The redirection location.
* @param bool $is_post_request Whether the incoming request was a POST request or not.
* @return void
*/
public static function _login_form_revalidate_2fa( $nonce = '', $provider = '', $redirect_to = '', $is_post_request = false ) {
Expand Down Expand Up @@ -1661,7 +1663,7 @@ public static function process_provider( $provider, $user, $is_post_request ) {
/**
* Determine if the user's password should be reset.
*
* @param int $user_id
* @param int $user_id User ID.
*
* @return bool
*/
Expand Down Expand Up @@ -1693,7 +1695,7 @@ public static function should_reset_password( $user_id ) {
* user. `get_user_time_delay()` mitigates brute force attempts, but this acts as an extra layer of defense
* which guarantees that attackers can't brute force it (unless they compromise the new password).
*
* @param WP_User $user The user who failed to login
* @param WP_User $user The user who failed to login.
*/
public static function reset_compromised_password( $user ) {
// Unhook because `wp_password_change_notification()` wouldn't notify the site admin when
Expand All @@ -1711,7 +1713,7 @@ public static function reset_compromised_password( $user ) {
/**
* Notify the user and admin that a password was reset for being compromised.
*
* @param WP_User $user The user whose password should be reset
* @param WP_User $user The user whose password should be reset.
*/
public static function send_password_reset_emails( $user ) {
self::notify_user_password_reset( $user );
Expand All @@ -1733,7 +1735,7 @@ public static function send_password_reset_emails( $user ) {
/**
* Notify the user that their password has been compromised and reset.
*
* @param WP_User $user The user to notify
* @param WP_User $user The user to notify.
*
* @return bool `true` if the email was sent, `false` if it failed.
*/
Expand Down Expand Up @@ -1837,7 +1839,6 @@ public static function manage_users_custom_column( $output, $column_name, $user_
$provider = self::get_primary_provider_for_user( $user_id );
return esc_html( $provider->get_label() );
}

}

/**
Expand Down Expand Up @@ -2054,8 +2055,8 @@ public static function enable_provider_for_user( $user_id, $new_provider ) {
*
* The caller is responsible for checking the user has permission to do this.
*
* @param int $user_id The ID of the user.
* @param string $provider The name of the provider class.
* @param int $user_id The ID of the user.
* @param string $provider_to_delete The name of the provider class.
*
* @return bool True if the provider was disabled, false otherwise.
*/
Expand Down Expand Up @@ -2126,16 +2127,20 @@ public static function user_two_factor_options_update( $user_id ) {

if ( $enabled_providers && ! $existing_providers && ! self::is_current_user_session_two_factor() ) {
// We've enabled two-factor from a non-two-factor session, set the key but not the provider, as no provider has been used yet.
self::update_current_user_session( array(
'two-factor-provider' => '',
'two-factor-login' => time(),
) );
self::update_current_user_session(
array(
'two-factor-provider' => '',
'two-factor-login' => time(),
)
);
} elseif ( $existing_providers && ! $enabled_providers ) {
// We've disabled two-factor, remove session metadata.
self::update_current_user_session( array(
'two-factor-provider' => null,
'two-factor-login' => null,
) );
self::update_current_user_session(
array(
'two-factor-provider' => null,
'two-factor-login' => null,
)
);
}
}

Expand Down
18 changes: 18 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@
<exclude-pattern>tests/providers/*.php</exclude-pattern>
</rule>

<!-- disable input validation on tests -->
<rule ref="WordPress.Security.ValidatedSanitizedInput.InputNotValidated">
<exclude-pattern>tests/*.php</exclude-pattern>
<exclude-pattern>tests/providers/*.php</exclude-pattern>
</rule>

<!-- disable cache constraints on tests -->
<rule ref="WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___COOKIE">
<exclude-pattern>tests/*.php</exclude-pattern>
<exclude-pattern>tests/providers/*.php</exclude-pattern>
</rule>

<!-- disable input sanitization on tests -->
<rule ref="WordPress.Security.ValidatedSanitizedInput.InputNotSanitized">
<exclude-pattern>tests/*.php</exclude-pattern>
<exclude-pattern>tests/providers/*.php</exclude-pattern>
</rule>

<exclude-pattern>*/wordpress/*</exclude-pattern>
<exclude-pattern>*/dist/*</exclude-pattern>
<exclude-pattern>*/includes/*</exclude-pattern>
Expand Down
12 changes: 7 additions & 5 deletions providers/class-two-factor-backup-codes.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ public function register_rest_routes() {
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'rest_generate_codes' ),
'permission_callback' => function( $request ) {
'permission_callback' => function ( $request ) {
return Two_Factor_Core::rest_api_can_edit_user_and_update_two_factor_options( $request['user_id'] );
},
'args' => array(
'user_id' => array(
'user_id' => array(
'required' => true,
'type' => 'integer',
),
Expand Down Expand Up @@ -279,13 +279,15 @@ public function generate_codes( $user, $args = '' ) {
* Generates Backup Codes for returning through the WordPress Rest API.
*
* @since 0.8.0
* @param WP_REST_Request $request Request object.
* @return array|WP_Error
*/
public function rest_generate_codes( $request ) {
$user_id = $request['user_id'];
$user = get_user_by( 'id', $user_id );

// Hardcode these, the user shouldn't be able to choose them.
$args = array(
$args = array(
'number' => self::NUMBER_OF_CODES,
'method' => 'replace',
);
Expand All @@ -306,7 +308,7 @@ public function rest_generate_codes( $request ) {
$i = 1;
foreach ( $codes as $code ) {
$download_link .= rawurlencode( "{$i}. {$code}\r\n" );
$i++;
++$i;
}

$i18n = array(
Expand Down Expand Up @@ -350,7 +352,7 @@ public static function codes_remaining_for_user( $user ) {
public function authentication_page( $user ) {
require_once ABSPATH . '/wp-admin/includes/template.php';

$code_length = $this->get_backup_code_length( $user );
$code_length = $this->get_backup_code_length( $user );
$code_placeholder = str_repeat( 'X', $code_length );

?>
Expand Down
2 changes: 1 addition & 1 deletion providers/class-two-factor-email.php
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public function authentication_page( $user ) {
$this->generate_and_email_token( $user );
}

$token_length = $this->get_token_length();
$token_length = $this->get_token_length();
$token_placeholder = str_repeat( 'X', $token_length );

require_once ABSPATH . '/wp-admin/includes/template.php';
Expand Down
4 changes: 2 additions & 2 deletions providers/class-two-factor-fido-u2f-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ public static function enqueue_assets( $hook ) {

// @todo Ensure that scripts don't fail because of missing u2fL10n.
try {
$data = Two_Factor_FIDO_U2F::$u2f->getRegisterData( $security_keys );
list( $req,$sigs ) = $data;
$data = Two_Factor_FIDO_U2F::$u2f->getRegisterData( $security_keys );
list( $req, $sigs ) = $data;

update_user_meta( $user_id, self::REGISTER_DATA_USER_META_KEY, $req );
} catch ( Exception $e ) {
Expand Down
2 changes: 1 addition & 1 deletion providers/class-two-factor-fido-u2f.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public function get_alternative_provider_label() {
public static function enqueue_scripts() {
wp_register_script(
'fido-u2f-api',
plugins_url( 'includes/Google/u2f-api.js', dirname( __FILE__ ) ),
plugins_url( 'includes/Google/u2f-api.js', __DIR__ ),
null,
self::asset_version(),
true
Expand Down
2 changes: 1 addition & 1 deletion providers/class-two-factor-provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static function get_instance() {
$class_name = static::class;

if ( ! isset( $instances[ $class_name ] ) ) {
$instances[ $class_name ] = new $class_name;
$instances[ $class_name ] = new $class_name();
}

return $instances[ $class_name ];
Expand Down
1 change: 1 addition & 0 deletions providers/class-two-factor-totp.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public function get_alternative_provider_label() {
* Enqueue scripts
*
* @codeCoverageIgnore
* @param string $hook_suffix Hook suffix.
*/
public function enqueue_assets( $hook_suffix ) {
$environment_prefix = file_exists( TWO_FACTOR_DIR . '/dist' ) ? '/dist' : '';
Expand Down
2 changes: 1 addition & 1 deletion tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
// Activate the plugin.
tests_add_filter(
'muplugins_loaded',
function() {
function () {
require_once dirname( __DIR__ ) . '/two-factor.php';
}
);
Expand Down
9 changes: 7 additions & 2 deletions tests/class-secure-dummy.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<?php
/**
* Test Two Factor Dummy Secure.
*
* @package Two_Factor
*/

/**
* Class for creating a dummy provider that never passes.
*
Expand Down Expand Up @@ -26,5 +32,4 @@ public function get_key() {
public function validate_authentication( $user ) {
return false;
}

}
}
Loading
Loading