From 05fed61671067cb6a750d41909ccb5692ba43808 Mon Sep 17 00:00:00 2001 From: Byron Jones Date: Tue, 29 Sep 2015 22:57:02 +0800 Subject: Bug 1199090 - add printable recovery 2fa codes --- Bugzilla/Auth.pm | 4 ++-- Bugzilla/MFA.pm | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- Bugzilla/MFA/TOTP.pm | 4 ++-- 3 files changed, 51 insertions(+), 7 deletions(-) (limited to 'Bugzilla') diff --git a/Bugzilla/Auth.pm b/Bugzilla/Auth.pm index b39bb827b..50e892914 100644 --- a/Bugzilla/Auth.pm +++ b/Bugzilla/Auth.pm @@ -133,8 +133,8 @@ sub mfa_verified { my $params = Bugzilla->input_params; $self->{_info_getter}->{successful} = Bugzilla::Auth::Login::CGI->new(); - $params->{Bugzilla_restrictlogin} = $event->{restrictlogin}; - $params->{Bugzilla_remember} = $event->{remember}; + $params->{Bugzilla_restrictlogin} = !!$event->{restrictlogin}; + $params->{Bugzilla_remember} = !!$event->{remember}; $self->_handle_login_result({ user => $user }, $event->{type}); } diff --git a/Bugzilla/MFA.pm b/Bugzilla/MFA.pm index 21f42fbfb..4f0d8a547 100644 --- a/Bugzilla/MFA.pm +++ b/Bugzilla/MFA.pm @@ -8,7 +8,9 @@ package Bugzilla::MFA; use strict; +use Bugzilla::RNG qw( irand ); use Bugzilla::Token qw( issue_short_lived_session_token set_token_extra_data get_token_extra_data delete_token ); +use Bugzilla::Util qw( trick_taint); sub new { my ($class, $user) = @_; @@ -46,15 +48,15 @@ sub verify_prompt { exit; } -sub verify_check { +sub verify_token { my ($self, $token) = @_; # check token my ($user_id) = Bugzilla::Token::GetTokenData($token); my $user = Bugzilla::User->check({ id => $user_id, cache => 1 }); - # mfa verification - $self->check(Bugzilla->input_params); + # verify mfa + $self->verify_check(Bugzilla->input_params); # return event data my $event = get_token_extra_data($token); @@ -66,10 +68,49 @@ sub verify_check { return $event; } +sub verify_check { + my ($self, $params) = @_; + $params->{code} //= ''; + + # recovery code verification + if (length($params->{code}) == 9) { + my $code = $params->{code}; + foreach my $i (1..10) { + my $key = "recovery.$i"; + if (($self->property_get($key) // '') eq $code) { + $self->property_delete($key); + return; + } + } + } + + # mfa verification + $self->check($params); +} + +# methods + +sub generate_recovery_codes { + my ($self) = @_; + + my @codes; + foreach my $i (1..10) { + # generate 9 digit code + my $code; + $code .= irand(10) for 1..9; + push @codes, $code; + # store (replacing existing) + $self->property_set("recovery.$i", $code); + } + + return \@codes; +} + # helpers sub property_get { my ($self, $name) = @_; + trick_taint($name); return scalar Bugzilla->dbh->selectrow_array( "SELECT value FROM profile_mfa WHERE user_id = ? AND name = ?", undef, $self->{user}->id, $name); @@ -77,6 +118,8 @@ sub property_get { sub property_set { my ($self, $name, $value) = @_; + trick_taint($name); + trick_taint($value); Bugzilla->dbh->do( "INSERT INTO profile_mfa (user_id, name, value) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = ?", undef, $self->{user}->id, $name, $value, $value); @@ -84,6 +127,7 @@ sub property_set { sub property_delete { my ($self, $name) = @_; + trick_taint($name); Bugzilla->dbh->do( "DELETE FROM profile_mfa WHERE user_id = ? AND name = ?", undef, $self->{user}->id, $name); diff --git a/Bugzilla/MFA/TOTP.pm b/Bugzilla/MFA/TOTP.pm index 859ca4b8d..64efcfc8d 100644 --- a/Bugzilla/MFA/TOTP.pm +++ b/Bugzilla/MFA/TOTP.pm @@ -58,10 +58,10 @@ sub prompt { sub check { my ($self, $params) = @_; - my $code = $params->{code} // ''; + my $code = $params->{code}; return if $self->_auth()->verify($code, 1); - if (exists $params->{mfa_action}) { + if ($params->{mfa_action} && $params->{mfa_action} eq 'enable') { ThrowUserError('mfa_totp_bad_enrolment_code'); } else { -- cgit v1.2.3-24-g4f1b