From d9cbb0f0a62bba345ed26ac68364bb441f41d35d Mon Sep 17 00:00:00 2001 From: "mkanat%bugzilla.org" <> Date: Fri, 12 May 2006 09:40:56 +0000 Subject: Bug 300410: Bugzilla::Auth needs to be restructured to not require a BEGIN block Patch By Max Kanat-Alexander r=LpSolit, a=myk --- Bugzilla/Auth/Login/CGI.pm | 73 +++++++++ Bugzilla/Auth/Login/Cookie.pm | 83 ++++++++++ Bugzilla/Auth/Login/Env.pm | 54 +++++++ Bugzilla/Auth/Login/Stack.pm | 87 +++++++++++ Bugzilla/Auth/Login/WWW.pm | 111 -------------- Bugzilla/Auth/Login/WWW/CGI.pm | 275 ---------------------------------- Bugzilla/Auth/Login/WWW/CGI/Cookie.pm | 113 -------------- Bugzilla/Auth/Login/WWW/Env.pm | 156 ------------------- 8 files changed, 297 insertions(+), 655 deletions(-) create mode 100644 Bugzilla/Auth/Login/CGI.pm create mode 100644 Bugzilla/Auth/Login/Cookie.pm create mode 100644 Bugzilla/Auth/Login/Env.pm create mode 100644 Bugzilla/Auth/Login/Stack.pm delete mode 100644 Bugzilla/Auth/Login/WWW.pm delete mode 100644 Bugzilla/Auth/Login/WWW/CGI.pm delete mode 100644 Bugzilla/Auth/Login/WWW/CGI/Cookie.pm delete mode 100644 Bugzilla/Auth/Login/WWW/Env.pm (limited to 'Bugzilla/Auth/Login') diff --git a/Bugzilla/Auth/Login/CGI.pm b/Bugzilla/Auth/Login/CGI.pm new file mode 100644 index 000000000..14b64ee79 --- /dev/null +++ b/Bugzilla/Auth/Login/CGI.pm @@ -0,0 +1,73 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Netscape Communications +# Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): Terry Weissman +# Dan Mosedale +# Joe Robins +# Dave Miller +# Christopher Aillon +# Gervase Markham +# Christian Reis +# Bradley Baetz +# Erik Stambaugh +# Max Kanat-Alexander + +package Bugzilla::Auth::Login::CGI; +use strict; +use base qw(Bugzilla::Auth::Login); +use constant user_can_create_account => 1; + +use Bugzilla::Config; +use Bugzilla::Constants; +use Bugzilla::Util; +use Bugzilla::User; + +sub get_login_info { + my ($self) = @_; + my $cgi = Bugzilla->cgi; + + my $username = trim($cgi->param("Bugzilla_login")); + my $password = $cgi->param("Bugzilla_password"); + + $cgi->delete('Bugzilla_login', 'Bugzilla_password'); + + if (!defined $username || !defined $password) { + return { failure => AUTH_NODATA }; + } + + return { username => $username, password => $password }; +} + +sub fail_nodata { + my ($self) = @_; + my $cgi = Bugzilla->cgi; + my $template = Bugzilla->template; + + # Redirect to SSL if required + if (Param('sslbase') ne '' and Param('ssl') ne 'never') { + $cgi->require_https(Param('sslbase')); + } + print $cgi->header(); + $template->process("account/auth/login.html.tmpl", + { 'target' => $cgi->url(-relative=>1) }) + || ThrowTemplateError($template->error()); + exit; +} + +1; diff --git a/Bugzilla/Auth/Login/Cookie.pm b/Bugzilla/Auth/Login/Cookie.pm new file mode 100644 index 000000000..e4cc0daac --- /dev/null +++ b/Bugzilla/Auth/Login/Cookie.pm @@ -0,0 +1,83 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# Contributor(s): Bradley Baetz +# Max Kanat-Alexander + +package Bugzilla::Auth::Login::Cookie; +use strict; +use base qw(Bugzilla::Auth::Login); + +use Bugzilla::Auth; +use Bugzilla::Constants; +use Bugzilla::User; +use Bugzilla::Util; + +use constant requires_persistence => 0; +use constant requires_verification => 0; +use constant can_login => 0; + +# 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 $ip_addr = $cgi->remote_addr(); + my $net_addr = Bugzilla::Auth::get_netaddr($ip_addr); + my $login_cookie = $cgi->cookie("Bugzilla_logincookie"); + my $user_id = $cgi->cookie("Bugzilla_login"); + + 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); + + my $query = "SELECT userid + FROM logincookies + WHERE logincookies.cookie = ? + AND logincookies.userid = ? + AND (logincookies.ipaddr = ?"; + + # If we have a network block that's allowed to use this cookie, + # as opposed to just a single IP. + my @params = ($login_cookie, $user_id, $ip_addr); + if (defined $net_addr) { + trick_taint($net_addr); + $query .= " OR logincookies.ipaddr = ?"; + push(@params, $net_addr); + } + $query .= ")"; + + # If the cookie is valid, return a valid username. + if ($dbh->selectrow_array($query, undef, @params)) { + # 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 he cookie is invalid, or we got no cookie. 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. It should just + # look like there was no cokie to begin with. + return { failure => AUTH_NODATA }; +} + +1; diff --git a/Bugzilla/Auth/Login/Env.pm b/Bugzilla/Auth/Login/Env.pm new file mode 100644 index 000000000..fda71bf35 --- /dev/null +++ b/Bugzilla/Auth/Login/Env.pm @@ -0,0 +1,54 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Netscape Communications +# Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): Erik Stambaugh +# Max Kanat-Alexander + +package Bugzilla::Auth::Login::Env; +use strict; +use base qw(Bugzilla::Auth::Login); + +use Bugzilla::Config; +use Bugzilla::Constants; +use Bugzilla::Error; +use Bugzilla::User; + +use constant can_logout => 0; +use constant can_login => 0; +use constant requires_verification => 0; + +sub get_login_info { + my ($self) = @_; + my $dbh = Bugzilla->dbh; + + my $env_id = $ENV{Param("auth_env_id")} || ''; + my $env_email = $ENV{Param("auth_env_email")} || ''; + my $env_realname = $ENV{Param("auth_env_realname")} || ''; + + return { failure => AUTH_NODATA } if !$env_email; + + return { username => $env_email, extern_id => $env_id, + realname => $env_realname }; +} + +sub fail_nodata { + ThrowCodeError('env_no_email'); +} + +1; diff --git a/Bugzilla/Auth/Login/Stack.pm b/Bugzilla/Auth/Login/Stack.pm new file mode 100644 index 000000000..d51003861 --- /dev/null +++ b/Bugzilla/Auth/Login/Stack.pm @@ -0,0 +1,87 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Netscape Communications +# Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): Max Kanat-Alexander + +package Bugzilla::Auth::Login::Stack; +use strict; +use base qw(Bugzilla::Auth::Login); +use fields qw( + _stack + successful +); + +sub new { + my $class = shift; + my $self = $class->SUPER::new(@_); + my $list = shift; + $self->{_stack} = []; + foreach my $login_method (split(',', $list)) { + require "Bugzilla/Auth/Login/${login_method}.pm"; + push(@{$self->{_stack}}, + "Bugzilla::Auth::Login::$login_method"->new(@_)); + } + return $self; +} + +sub get_login_info { + my $self = shift; + my $result; + foreach my $object (@{$self->{_stack}}) { + $result = $object->get_login_info(@_); + $self->{successful} = $object; + last if !$result->{failure}; + # So that if none of them succeed, it's undef. + $self->{successful} = undef; + } + return $result; +} + +sub fail_nodata { + my $self = shift; + # We fail from the bottom of the stack. + my @reverse_stack = reverse @{$self->{_stack}}; + foreach my $object (@reverse_stack) { + # We pick the first object that actually has the method + # implemented. + if ($object->can('fail_nodata')) { + $object->fail_nodata(@_); + } + } +} + +sub can_login { + my ($self) = @_; + # We return true if any method can log in. + foreach my $object (@{$self->{_stack}}) { + return 1 if $object->can_login; + } + return 0; +} + +sub user_can_create_account { + my ($self) = @_; + # We return true if any method allows users to create accounts. + foreach my $object (@{$self->{_stack}}) { + return 1 if $object->user_can_create_account; + } + return 0; +} + +1; diff --git a/Bugzilla/Auth/Login/WWW.pm b/Bugzilla/Auth/Login/WWW.pm deleted file mode 100644 index 29cc7fced..000000000 --- a/Bugzilla/Auth/Login/WWW.pm +++ /dev/null @@ -1,111 +0,0 @@ -# -*- Mode: perl; indent-tabs-mode: nil -*- -# -# The contents of this file are subject to the Mozilla Public -# License Version 1.1 (the "License"); you may not use this file -# except in compliance with the License. You may obtain a copy of -# the License at http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS -# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -# implied. See the License for the specific language governing -# rights and limitations under the License. -# -# The Original Code is the Bugzilla Bug Tracking System. -# -# The Initial Developer of the Original Code is Netscape Communications -# Corporation. Portions created by Netscape are -# Copyright (C) 1998 Netscape Communications Corporation. All -# Rights Reserved. -# -# Contributor(s): Erik Stambaugh - -package Bugzilla::Auth::Login::WWW; - -use strict; - -use Bugzilla::Constants; -use Bugzilla::Config; - -# $current_login_class stores the name of the login style that succeeded. -my $current_login_class = undef; -sub login_class { - my ($class, $type) = @_; - if ($type) { - $current_login_class = $type; - } - return $current_login_class; -} - -# can_logout determines if a user may log out -sub can_logout { - return 1 if (login_class && login_class->can_logout); - return 0; -} - -sub login { - my ($class, $type) = @_; - - my $user = Bugzilla->user; - - # Avoid double-logins, which may confuse the auth code - # (double cookies, odd compat code settings, etc) - return $user if $user->id; - - $type = LOGIN_REQUIRED if Bugzilla->cgi->param('GoAheadAndLogIn'); - $type = LOGIN_NORMAL unless defined $type; - - # Log in using whatever methods are defined in user_info_class. - # Please note the particularly strange way require() and the function - # calls are being done, because we're calling a module that's named in - # a string. I assure you it works, and it avoids the need for an eval(). - my $userid; - for my $login_class (split(/,\s*/, Param('user_info_class'))) { - require "Bugzilla/Auth/Login/WWW/" . $login_class . ".pm"; - $userid = "Bugzilla::Auth::Login::WWW::$login_class"->login($type); - if ($userid) { - $class->login_class("Bugzilla::Auth::Login::WWW::$login_class"); - last; - } - } - - if ($userid) { - $user = new Bugzilla::User($userid); - - # Redirect to SSL if required - if (Param('sslbase') ne '' and Param('ssl') ne 'never') { - Bugzilla->cgi->require_https(Param('sslbase')); - } - $user->set_flags('can_logout' => $class->can_logout); - } else { - Bugzilla->logout_request(); - } - return $user; -} - -sub logout { - my ($class, $user, $option) = @_; - if (can_logout) { - $class->login_class->logout($user, $option); - } -} - -1; - - -__END__ - -=head1 NAME - -Bugzilla::Auth::Login::WWW - WWW login information gathering module - -=head1 METHODS - -=over - -=item C - -Passes C calls to each class defined in the param C -and returns a C object from the first one that successfully -gathers user login information. - -=back diff --git a/Bugzilla/Auth/Login/WWW/CGI.pm b/Bugzilla/Auth/Login/WWW/CGI.pm deleted file mode 100644 index 5030691e3..000000000 --- a/Bugzilla/Auth/Login/WWW/CGI.pm +++ /dev/null @@ -1,275 +0,0 @@ -# -*- Mode: perl; indent-tabs-mode: nil -*- -# -# The contents of this file are subject to the Mozilla Public -# License Version 1.1 (the "License"); you may not use this file -# except in compliance with the License. You may obtain a copy of -# the License at http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS -# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -# implied. See the License for the specific language governing -# rights and limitations under the License. -# -# The Original Code is the Bugzilla Bug Tracking System. -# -# The Initial Developer of the Original Code is Netscape Communications -# Corporation. Portions created by Netscape are -# Copyright (C) 1998 Netscape Communications Corporation. All -# Rights Reserved. -# -# Contributor(s): Terry Weissman -# Dan Mosedale -# Joe Robins -# Dave Miller -# Christopher Aillon -# Gervase Markham -# Christian Reis -# Bradley Baetz -# Erik Stambaugh - -package Bugzilla::Auth::Login::WWW::CGI; - -use strict; - -use Bugzilla::Config; -use Bugzilla::Constants; -use Bugzilla::Error; -use Bugzilla::Util; -use Bugzilla::Token; - -sub login { - my ($class, $type) = @_; - - # 'NORMAL' logins depend on the 'requirelogin' param - if ($type == LOGIN_NORMAL) { - $type = Param('requirelogin') ? LOGIN_REQUIRED : LOGIN_OPTIONAL; - } - - my $cgi = Bugzilla->cgi; - my $dbh = Bugzilla->dbh; - - # First, try the actual login method against form variables - my $username = trim($cgi->param("Bugzilla_login")); - my $passwd = $cgi->param("Bugzilla_password"); - - $cgi->delete('Bugzilla_login', 'Bugzilla_password'); - - # Perform the actual authentication, get the method name from the class name - my ($authmethod, $authres, $userid, $extra, $info) = - Bugzilla::Auth->authenticate($username, $passwd); - - if ($authres == AUTH_OK) { - # Login via username/password was correct and valid, so create - # and send out the login cookies - my $ipaddr = $cgi->remote_addr; - unless ($cgi->param('Bugzilla_restrictlogin') || - Param('loginnetmask') == 32) { - $ipaddr = Bugzilla::Auth::get_netaddr($ipaddr); - } - - # The IP address is valid, at least for comparing with itself in a - # subsequent login - trick_taint($ipaddr); - - my $logincookie = Bugzilla::Token::GenerateUniqueToken('logincookies', 'cookie'); - - $dbh->do("INSERT INTO logincookies (cookie, userid, ipaddr, lastused) - VALUES (?, ?, ?, NOW())", - undef, - $logincookie, $userid, $ipaddr); - - # Remember cookie only if admin has told so - # or admin didn't forbid it and user told to remember. - if ((Param('rememberlogin') eq 'on') || - ((Param('rememberlogin') ne 'off') && - $cgi->param('Bugzilla_remember') && - ($cgi->param('Bugzilla_remember') eq 'on'))) { - $cgi->send_cookie(-name => 'Bugzilla_login', - -value => $userid, - -expires => 'Fri, 01-Jan-2038 00:00:00 GMT'); - $cgi->send_cookie(-name => 'Bugzilla_logincookie', - -value => $logincookie, - -expires => 'Fri, 01-Jan-2038 00:00:00 GMT'); - - } - else { - $cgi->send_cookie(-name => 'Bugzilla_login', - -value => $userid); - $cgi->send_cookie(-name => 'Bugzilla_logincookie', - -value => $logincookie); - } - } - elsif ($authres == AUTH_NODATA) { - # No data from the form, so try to login via cookies - $username = $cgi->cookie("Bugzilla_login"); - $passwd = $cgi->cookie("Bugzilla_logincookie"); - - require Bugzilla::Auth::Login::WWW::CGI::Cookie; - my $authmethod = "Cookie"; - - ($authres, $userid, $extra) = - Bugzilla::Auth::Login::WWW::CGI::Cookie->authenticate($username, $passwd); - - # If the data for the cookie was incorrect, then treat that as - # NODATA. This could occur if the user's IP changed, for example. - # Give them un-loggedin access if allowed (checked below) - $authres = AUTH_NODATA if $authres == AUTH_LOGINFAILED; - } - - # Now check the result - - # An error may have occurred with the login mechanism - if ($authres == AUTH_ERROR) { - ThrowCodeError("auth_err", - { authmethod => lc($authmethod), - userid => $userid, - auth_err_tag => $extra, - info => $info - }); - } - - # We can load the page if the login was ok, or there was no data - # but a login wasn't required - if ($authres == AUTH_OK || - ($authres == AUTH_NODATA && $type == LOGIN_OPTIONAL)) { - - # login succeded, so we're done - return $userid; - } - - # No login details were given, but we require a login if the - # page does - if ($authres == AUTH_NODATA && $type == LOGIN_REQUIRED) { - - # Redirect to SSL if required - if (Param('sslbase') ne '' and Param('ssl') ne 'never') { - $cgi->require_https(Param('sslbase')); - } - - # Throw up the login page - - print Bugzilla->cgi->header(); - - my $template = Bugzilla->template; - $template->process("account/auth/login.html.tmpl", - { 'target' => $cgi->url(-relative=>1), - 'caneditaccount' => Bugzilla::Auth->can_edit('new'), - 'has_db' => Bugzilla::Auth->has_db, - } - ) - || ThrowTemplateError($template->error()); - - # This seems like as good as time as any to get rid of old - # crufty junk in the logincookies table. Get rid of any entry - # that hasn't been used in a month. - $dbh->do("DELETE FROM logincookies WHERE " . - $dbh->sql_to_days('NOW()') . " - " . - $dbh->sql_to_days('lastused') . " > 30"); - - exit; - } - - # The username/password may be wrong - # Don't let the user know whether the username exists or whether - # the password was just wrong. (This makes it harder for a cracker - # to find account names by brute force) - if ($authres == AUTH_LOGINFAILED) { - ThrowUserError("invalid_username_or_password"); - } - - # The account may be disabled - if ($authres == AUTH_DISABLED) { - clear_browser_cookies(); - # and throw a user error - ThrowUserError("account_disabled", - {'disabled_reason' => $extra}); - } - - # If we get here, then we've run out of options, which shouldn't happen - ThrowCodeError("authres_unhandled", { authres => $authres, - type => $type }); -} - -# This auth style allows the user to log out. -sub can_logout { return 1; } - -# Logs user out, according to the option provided; this consists of -# removing entries from logincookies for the specified $user. -sub logout { - my ($class, $user, $option) = @_; - my $dbh = Bugzilla->dbh; - my $cgi = Bugzilla->cgi; - $option = LOGOUT_ALL unless defined $option; - - if ($option == LOGOUT_ALL) { - $dbh->do("DELETE FROM logincookies WHERE userid = ?", - undef, $user->id); - return; - } - - # The LOGOUT_*_CURRENT options require the current login cookie. - # If a new cookie has been issued during this run, that's the current one. - # If not, it's the one we've received. - my $cookie; - foreach (@{$cgi->{'Bugzilla_cookie_list'}}) { - if ($_->name() eq 'Bugzilla_logincookie') { - $cookie = $_->value(); - last; - } - } - $cookie ||= $cgi->cookie("Bugzilla_logincookie"); - trick_taint($cookie); - - # These queries use both the cookie ID and the user ID as keys. Even - # though we know the userid must match, we still check it in the SQL - # as a sanity check, since there is no locking here, and if the user - # logged out from two machines simultaneously, while someone else - # logged in and got the same cookie, we could be logging the other - # user out here. Yes, this is very very very unlikely, but why take - # chances? - bbaetz - if ($option == LOGOUT_KEEP_CURRENT) { - $dbh->do("DELETE FROM logincookies WHERE cookie != ? AND userid = ?", - undef, $cookie, $user->id); - } elsif ($option == LOGOUT_CURRENT) { - $dbh->do("DELETE FROM logincookies WHERE cookie = ? AND userid = ?", - undef, $cookie, $user->id); - } else { - die("Invalid option $option supplied to logout()"); - } - - if ($option != LOGOUT_KEEP_CURRENT) { - clear_browser_cookies(); - Bugzilla->logout_request(); - } -} - -sub clear_browser_cookies { - my $cgi = Bugzilla->cgi; - $cgi->remove_cookie('Bugzilla_login'); - $cgi->remove_cookie('Bugzilla_logincookie'); -} - -1; - -__END__ - -=head1 NAME - -Bugzilla::Auth::Login::WWW::CGI - CGI-based logins for Bugzilla - -=head1 SUMMARY - -This is a L for Bugzilla. Users connecting -from a CGI script use this module to authenticate. Logouts are also handled here. - -=head1 BEHAVIOUR - -Users are first authenticated against the default authentication handler, -using the CGI parameters I and I. - -If no data is present for that, then cookies are tried, using -L. - -=head1 SEE ALSO - -L diff --git a/Bugzilla/Auth/Login/WWW/CGI/Cookie.pm b/Bugzilla/Auth/Login/WWW/CGI/Cookie.pm deleted file mode 100644 index c2244d15d..000000000 --- a/Bugzilla/Auth/Login/WWW/CGI/Cookie.pm +++ /dev/null @@ -1,113 +0,0 @@ -# -*- Mode: perl; indent-tabs-mode: nil -*- -# -# The contents of this file are subject to the Mozilla Public -# License Version 1.1 (the "License"); you may not use this file -# except in compliance with the License. You may obtain a copy of -# the License at http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS -# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -# implied. See the License for the specific language governing -# rights and limitations under the License. -# -# The Original Code is the Bugzilla Bug Tracking System. -# -# The Initial Developer of the Original Code is Netscape Communications -# Corporation. Portions created by Netscape are -# Copyright (C) 1998 Netscape Communications Corporation. All -# Rights Reserved. -# -# Contributor(s): Terry Weissman -# Dan Mosedale -# Joe Robins -# Dave Miller -# Christopher Aillon -# Gervase Markham -# Christian Reis -# Bradley Baetz - -package Bugzilla::Auth::Login::WWW::CGI::Cookie; - -use strict; - -use Bugzilla::Auth; -use Bugzilla::Config; -use Bugzilla::Constants; -use Bugzilla::Util; - -sub authenticate { - my ($class, $login, $login_cookie) = @_; - - return (AUTH_NODATA) unless defined $login && defined $login_cookie; - - my $cgi = Bugzilla->cgi; - - my $ipaddr = $cgi->remote_addr(); - my $netaddr = Bugzilla::Auth::get_netaddr($ipaddr); - - # Anything goes for these params - they're just strings which - # we're going to verify against the db - trick_taint($login); - trick_taint($login_cookie); - trick_taint($ipaddr); - - my $query = "SELECT profiles.userid, profiles.disabledtext " . - "FROM logincookies, profiles " . - "WHERE logincookies.cookie=? AND " . - " logincookies.userid=profiles.userid AND " . - " logincookies.userid=? AND " . - " (logincookies.ipaddr=?"; - my @params = ($login_cookie, $login, $ipaddr); - if (defined $netaddr) { - trick_taint($netaddr); - $query .= " OR logincookies.ipaddr=?"; - push(@params, $netaddr); - } - $query .= ")"; - - my $dbh = Bugzilla->dbh; - my ($userid, $disabledtext) = $dbh->selectrow_array($query, undef, @params); - - return (AUTH_DISABLED, $userid, $disabledtext) - if ($disabledtext); - - if ($userid) { - # 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 (AUTH_OK, $userid); - } - - # If we get here, then the login failed. - return (AUTH_LOGINFAILED); -} - -1; - -__END__ - -=head1 NAME - -Bugzilla::Auth::Login::WWW::CGI::Cookie - cookie authentication for Bugzilla - -=head1 SUMMARY - -This is an L for -Bugzilla, which logs the user in using a persistent cookie stored in the -C table. - -The actual password is not stored in the cookie; only the userid and a -I (which is used to reverify the login without requiring the -password to be sent over the network) are. These I are -restricted to certain IP addresses as a security meaure. The exact -restriction can be specified by the admin via the C parameter. - -This module does not ever send a cookie (It has no way of knowing when a user -is successfully logged in). Instead L handles this. - -=head1 SEE ALSO - -L, L diff --git a/Bugzilla/Auth/Login/WWW/Env.pm b/Bugzilla/Auth/Login/WWW/Env.pm deleted file mode 100644 index f437bf06f..000000000 --- a/Bugzilla/Auth/Login/WWW/Env.pm +++ /dev/null @@ -1,156 +0,0 @@ -# -*- Mode: perl; indent-tabs-mode: nil -*- -# -# The contents of this file are subject to the Mozilla Public -# License Version 1.1 (the "License"); you may not use this file -# except in compliance with the License. You may obtain a copy of -# the License at http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS -# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -# implied. See the License for the specific language governing -# rights and limitations under the License. -# -# The Original Code is the Bugzilla Bug Tracking System. -# -# The Initial Developer of the Original Code is Netscape Communications -# Corporation. Portions created by Netscape are -# Copyright (C) 1998 Netscape Communications Corporation. All -# Rights Reserved. -# -# Contributor(s): Erik Stambaugh - -package Bugzilla::Auth::Login::WWW::Env; - -use strict; - -use Bugzilla::Config; -use Bugzilla::Error; -use Bugzilla::Util; -use Bugzilla::User; - -sub login { - my ($class, $type) = @_; - my $dbh = Bugzilla->dbh; - - # XXX This does not currently work correctly with Param('requirelogin'). - # Bug 253636 will hopefully see that param's needs taken care of in a - # parent module, but for the time being, this module does not honor - # the param in the way that CGI.pm does. - - my $matched_userid; - my $matched_extern_id; - my $disabledtext; - - # Gather the environment variables - my $env_id = $ENV{Param("auth_env_id")} || ''; - my $env_email = $ENV{Param("auth_env_email")} || ''; - my $env_realname = $ENV{Param("auth_env_realname")} || ''; - - # make sure the email field contains only a valid email address - my $emailregexp = Param("emailregexp"); - if ($env_email =~ /($emailregexp)/) { - $env_email = $1; - } - else { - $env_email = ''; - } - - return undef unless $env_email; - - # untaint the remaining values - trick_taint($env_id); - trick_taint($env_realname); - - # Look in the DB for the extern_id - if ($env_id) { - ($matched_userid, $disabledtext) = - $dbh->selectrow_array('SELECT userid, disabledtext - FROM profiles WHERE extern_id = ?', - undef, $env_id); - } - - unless ($matched_userid) { - # There was either no match for the external ID given, or one was - # not present. - # - # Check to see if the email address is in there and has no - # external id assigned. We test for both the login name (which we - # also sent), and the id, so that we have a way of telling that we - # got something instead of a bunch of NULLs - ($matched_extern_id, $matched_userid, $disabledtext) = - $dbh->selectrow_array('SELECT extern_id, userid, disabledtext - FROM profiles WHERE ' . - $dbh->sql_istrcmp('login_name', '?'), - undef, $env_email); - - if ($matched_userid) { - if ($matched_extern_id) { - # someone with a different external ID has that address! - ThrowUserError("extern_id_conflict"); - } - else { - # someone with no external ID used that address, time to - # add the ID! - $dbh->do('UPDATE profiles SET extern_id = ? WHERE userid = ?', - undef,($env_id, $matched_userid)); - } - } - else { - # Need to create a new user with that email address. Note - # that cryptpassword has been filled in with '*', since the - # user has no DB password. - insert_new_user($env_email, $env_realname, '*'); - my $new_user = Bugzilla::User->new_from_login($env_email); - $matched_userid = $new_user->id; - } - } - - # now that we hopefully have a username, we need to see if the data - # has to be updated. If we just created this account, then the data - # is already up to date. - my ($username, $this_realname) = - $dbh->selectrow_array('SELECT login_name, realname - FROM profiles WHERE userid = ?', - undef, $matched_userid); - - if (($username ne $env_email) || ($this_realname ne $env_realname)) { - $dbh->do('UPDATE profiles SET login_name = ?, realname = ? - WHERE userid = ?', undef, - ($env_email, ($env_realname || $this_realname), $matched_userid)); - - # If the login name may be new, make sure the regexp groups are current - my $userprofile = new Bugzilla::User($matched_userid); - $userprofile->derive_regexp_groups; - } - - # Now we throw an error if the user has been disabled - if ($disabledtext) { - ThrowUserError("account_disabled", - {'disabled_reason' => $disabledtext}); - } - - return $matched_userid; -} - -# This auth style does not allow the user to log out. -sub can_logout { return 0; } - -1; - -__END__ - -=head1 NAME - -Bugzilla::Auth::Env - Environment Variable Authentication - -=head1 DESCRIPTION - -Many external user authentication systems supply login information to CGI -programs via environment variables. This module checks to see if those -variables are populated and, if so, assumes authentication was successful and -returns the user's ID, having automatically created a new profile if -necessary. - -=head1 SEE ALSO - -L -- cgit v1.2.3-24-g4f1b