diff options
Diffstat (limited to 'Bugzilla/Auth/Login/Cookie.pm')
-rw-r--r-- | Bugzilla/Auth/Login/Cookie.pm | 221 |
1 files changed, 112 insertions, 109 deletions
diff --git a/Bugzilla/Auth/Login/Cookie.pm b/Bugzilla/Auth/Login/Cookie.pm index 9a94fe019..79456c383 100644 --- a/Bugzilla/Auth/Login/Cookie.pm +++ b/Bugzilla/Auth/Login/Cookie.pm @@ -23,145 +23,148 @@ use List::Util qw(first); use constant requires_persistence => 0; use constant requires_verification => 0; -use constant can_login => 0; +use constant can_login => 0; sub is_automatic { return $_[0]->login_token ? 0 : 1; } # Note that Cookie never consults the Verifier, it always assumes # it has a valid DB account or it fails. sub get_login_info { - my ($self) = @_; - my $cgi = Bugzilla->cgi; - my $dbh = Bugzilla->dbh; - my ($user_id, $login_cookie, $is_internal); - - if (!Bugzilla->request_cache->{auth_no_automatic_login}) { - $login_cookie = $cgi->cookie("Bugzilla_logincookie"); - $user_id = $cgi->cookie("Bugzilla_login"); - - # If cookies cannot be found, this could mean that they haven't - # been made available yet. In this case, look at Bugzilla_cookie_list. - unless ($login_cookie) { - my $cookie = first {$_->name eq 'Bugzilla_logincookie'} - @{$cgi->{'Bugzilla_cookie_list'}}; - $login_cookie = $cookie->value if $cookie; - } - unless ($user_id) { - my $cookie = first {$_->name eq 'Bugzilla_login'} - @{$cgi->{'Bugzilla_cookie_list'}}; - $user_id = $cookie->value if $cookie; - } - trick_taint($login_cookie) if $login_cookie; - $self->cookie($login_cookie); - - # If the call is for a web service, and an api token is provided, check - # it is valid. - if (i_am_webservice()) { - if (exists Bugzilla->input_params->{Bugzilla_api_token}) { - my $api_token = Bugzilla->input_params->{Bugzilla_api_token}; - my ($token_user_id, undef, undef, $token_type) - = Bugzilla::Token::GetTokenData($api_token); - if (!defined $token_type - || $token_type ne 'api_token' - || $user_id != $token_user_id) - { - ThrowUserError('auth_invalid_token', { token => $api_token }); - } - $is_internal = 1; - } - elsif ($login_cookie && Bugzilla->usage_mode == USAGE_MODE_REST) { - # REST requires an api-token when using cookie authentication - # fall back to a non-authenticated request - $login_cookie = ''; - } + my ($self) = @_; + my $cgi = Bugzilla->cgi; + my $dbh = Bugzilla->dbh; + my ($user_id, $login_cookie, $is_internal); + + if (!Bugzilla->request_cache->{auth_no_automatic_login}) { + $login_cookie = $cgi->cookie("Bugzilla_logincookie"); + $user_id = $cgi->cookie("Bugzilla_login"); + + # If cookies cannot be found, this could mean that they haven't + # been made available yet. In this case, look at Bugzilla_cookie_list. + unless ($login_cookie) { + my $cookie = first { $_->name eq 'Bugzilla_logincookie' } + @{$cgi->{'Bugzilla_cookie_list'}}; + $login_cookie = $cookie->value if $cookie; + } + unless ($user_id) { + my $cookie = first { $_->name eq 'Bugzilla_login' } + @{$cgi->{'Bugzilla_cookie_list'}}; + $user_id = $cookie->value if $cookie; + } + trick_taint($login_cookie) if $login_cookie; + $self->cookie($login_cookie); + + # If the call is for a web service, and an api token is provided, check + # it is valid. + if (i_am_webservice()) { + if (exists Bugzilla->input_params->{Bugzilla_api_token}) { + my $api_token = Bugzilla->input_params->{Bugzilla_api_token}; + my ($token_user_id, undef, undef, $token_type) + = Bugzilla::Token::GetTokenData($api_token); + if ( !defined $token_type + || $token_type ne 'api_token' + || $user_id != $token_user_id) + { + ThrowUserError('auth_invalid_token', {token => $api_token}); } + $is_internal = 1; + } + elsif ($login_cookie && Bugzilla->usage_mode == USAGE_MODE_REST) { + + # REST requires an api-token when using cookie authentication + # fall back to a non-authenticated request + $login_cookie = ''; + } } + } - # If no cookies were provided, we also look for a login token - # passed in the parameters of a webservice - my $token = $self->login_token; - if ($token && (!$login_cookie || !$user_id)) { - ($user_id, $login_cookie) = ($token->{'user_id'}, $token->{'login_token'}); - } + # If no cookies were provided, we also look for a login token + # passed in the parameters of a webservice + my $token = $self->login_token; + if ($token && (!$login_cookie || !$user_id)) { + ($user_id, $login_cookie) = ($token->{'user_id'}, $token->{'login_token'}); + } + + my $ip_addr = remote_ip(); - my $ip_addr = remote_ip(); + if ($login_cookie && $user_id) { - if ($login_cookie && $user_id) { - # Anything goes for these params - they're just strings which - # we're going to verify against the db - trick_taint($ip_addr); - trick_taint($login_cookie); - detaint_natural($user_id); + # Anything goes for these params - they're just strings which + # we're going to verify against the db + trick_taint($ip_addr); + trick_taint($login_cookie); + detaint_natural($user_id); - my $db_cookie = - $dbh->selectrow_array('SELECT cookie + my $db_cookie = $dbh->selectrow_array( + 'SELECT cookie FROM logincookies WHERE cookie = ? AND userid = ? AND (restrict_ipaddr = 0 OR ipaddr = ?)', - undef, ($login_cookie, $user_id, $ip_addr)); - - # If the cookie is valid, return a valid username. - if (defined $db_cookie && $login_cookie eq $db_cookie) { - - # forbid logging in with a cookie if only api-keys are allowed - if (i_am_webservice() && !$is_internal) { - my $user = Bugzilla::User->new({ id => $user_id, cache => 1 }); - if ($user->settings->{api_key_only}->{value} eq 'on') { - ThrowUserError('invalid_cookies_or_token'); - } - } - - # If we logged in successfully, then update the lastused - # time on the login cookie - $dbh->do("UPDATE logincookies SET lastused = NOW() - WHERE cookie = ?", undef, $login_cookie); - return { user_id => $user_id }; - } - elsif (i_am_webservice()) { - ThrowUserError('invalid_cookies_or_token'); + undef, ($login_cookie, $user_id, $ip_addr) + ); + + # If the cookie is valid, return a valid username. + if (defined $db_cookie && $login_cookie eq $db_cookie) { + + # forbid logging in with a cookie if only api-keys are allowed + if (i_am_webservice() && !$is_internal) { + my $user = Bugzilla::User->new({id => $user_id, cache => 1}); + if ($user->settings->{api_key_only}->{value} eq 'on') { + ThrowUserError('invalid_cookies_or_token'); } + } + + # If we logged in successfully, then update the lastused + # time on the login cookie + $dbh->do( + "UPDATE logincookies SET lastused = NOW() + WHERE cookie = ?", undef, $login_cookie + ); + return {user_id => $user_id}; } - - # Either the cookie or token is invalid and we are not authenticating - # via a webservice, or we did not receive a cookie or token. We don't - # want to ever return AUTH_LOGINFAILED, because we don't want Bugzilla to - # actually throw an error when it gets a bad cookie or token. It should just - # look like there was no cookie or token to begin with. - return { failure => AUTH_NODATA }; + elsif (i_am_webservice()) { + ThrowUserError('invalid_cookies_or_token'); + } + } + + # Either the cookie or token is invalid and we are not authenticating + # via a webservice, or we did not receive a cookie or token. We don't + # want to ever return AUTH_LOGINFAILED, because we don't want Bugzilla to + # actually throw an error when it gets a bad cookie or token. It should just + # look like there was no cookie or token to begin with. + return {failure => AUTH_NODATA}; } sub login_token { - my ($self) = @_; - my $input = Bugzilla->input_params; - my $usage_mode = Bugzilla->usage_mode; + my ($self) = @_; + my $input = Bugzilla->input_params; + my $usage_mode = Bugzilla->usage_mode; - return $self->{'_login_token'} if exists $self->{'_login_token'}; + return $self->{'_login_token'} if exists $self->{'_login_token'}; - if (!i_am_webservice()) { - return $self->{'_login_token'} = undef; - } + if (!i_am_webservice()) { + return $self->{'_login_token'} = undef; + } - # Check if a token was passed in via requests for WebServices - my $token = trim(delete $input->{'Bugzilla_token'}); - return $self->{'_login_token'} = undef if !$token; + # Check if a token was passed in via requests for WebServices + my $token = trim(delete $input->{'Bugzilla_token'}); + return $self->{'_login_token'} = undef if !$token; - my ($user_id, $login_token) = split('-', $token, 2); - if (!detaint_natural($user_id) || !$login_token) { - return $self->{'_login_token'} = undef; - } + my ($user_id, $login_token) = split('-', $token, 2); + if (!detaint_natural($user_id) || !$login_token) { + return $self->{'_login_token'} = undef; + } - return $self->{'_login_token'} = { - user_id => $user_id, - login_token => $login_token - }; + return $self->{'_login_token'} + = {user_id => $user_id, login_token => $login_token}; } sub cookie { - my ($self, $val) = @_; - $self->{_cookie} = $val if @_ > 1; + my ($self, $val) = @_; + $self->{_cookie} = $val if @_ > 1; - return $self->{_cookie}; + return $self->{_cookie}; } 1; |