summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Auth/Login/CGI.pm
diff options
context:
space:
mode:
authorbugreport%peshkin.net <>2004-07-12 08:36:42 +0200
committerbugreport%peshkin.net <>2004-07-12 08:36:42 +0200
commitce983f5d751e61c5500eac45e5db29eee7309520 (patch)
tree6ad5cbd3cec6177abf3d69e97baa761359885b61 /Bugzilla/Auth/Login/CGI.pm
parentf5b60b13b9ebe135498421680b8d7b0166d6cb36 (diff)
downloadbugzilla-ce983f5d751e61c5500eac45e5db29eee7309520.tar.gz
bugzilla-ce983f5d751e61c5500eac45e5db29eee7309520.tar.xz
Bug 241900: Allow Bugzilla::Auth to have multiple login and validation styles
patch by erik r=joel a=justdave
Diffstat (limited to 'Bugzilla/Auth/Login/CGI.pm')
-rw-r--r--Bugzilla/Auth/Login/CGI.pm254
1 files changed, 254 insertions, 0 deletions
diff --git a/Bugzilla/Auth/Login/CGI.pm b/Bugzilla/Auth/Login/CGI.pm
new file mode 100644
index 000000000..2f8ca071d
--- /dev/null
+++ b/Bugzilla/Auth/Login/CGI.pm
@@ -0,0 +1,254 @@
+# -*- 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 <terry@mozilla.org>
+# Dan Mosedale <dmose@mozilla.org>
+# Joe Robins <jmrobins@tgix.com>
+# Dave Miller <justdave@syndicomm.com>
+# Christopher Aillon <christopher@aillon.com>
+# Gervase Markham <gerv@gerv.net>
+# Christian Reis <kiko@async.com.br>
+# Bradley Baetz <bbaetz@acm.org>
+# Erik Stambaugh <erik@dasbistro.com>
+
+package Bugzilla::Auth::Login::CGI;
+
+use strict;
+
+use Bugzilla::Config;
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Util;
+
+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;
+
+ # First, try the actual login method against form variables
+ my $username = $cgi->param("Bugzilla_login");
+ my $passwd = $cgi->param("Bugzilla_password");
+
+ my $authmethod = Param("user_verify_method");
+ my ($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 $dbh = Bugzilla->dbh;
+ $dbh->do("INSERT INTO logincookies (userid, ipaddr) VALUES (?, ?)",
+ undef,
+ $userid, $ipaddr);
+ my $logincookie = $dbh->selectrow_array("SELECT LAST_INSERT_ID()");
+
+ # 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') 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::CGI::Cookie;
+ my $authmethod = "Cookie";
+
+ ($authres, $userid, $extra) =
+ Bugzilla::Auth::Login::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) {
+ # 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),
+ 'form' => \%::FORM,
+ 'mform' => \%::MFORM,
+ 'caneditaccount' => Bugzilla::Auth->can_edit->{'new'},
+ }
+ )
+ || 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.
+ Bugzilla->dbh->do("DELETE FROM logincookies " .
+ "WHERE TO_DAYS(NOW()) - 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 the cookie
+
+ $cgi->send_cookie(-name => 'Bugzilla_login',
+ -expires => "Tue, 15-Sep-1998 21:49:00 GMT");
+ $cgi->send_cookie(-name => 'Bugzilla_logincookie',
+ -expires => "Tue, 15-Sep-1998 21:49:00 GMT");
+
+ # 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, });
+}
+
+# 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;
+ $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 a cookie
+ my $cookie = Bugzilla->cgi->cookie("Bugzilla_logincookie");
+ detaint_natural($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()");
+ }
+}
+
+sub clear_browser_cookies {
+ my $cgi = Bugzilla->cgi;
+ $cgi->send_cookie(-name => "Bugzilla_login",
+ -expires => "Tue, 15-Sep-1998 21:49:00 GMT");
+ $cgi->send_cookie(-name => "Bugzilla_logincookie",
+ -expires => "Tue, 15-Sep-1998 21:49:00 GMT");
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Bugzilla::Auth::Login::CGI - CGI-based logins for Bugzilla
+
+=head1 SUMMARY
+
+This is a L<login module|Bugzilla::Auth/"LOGIN"> 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<Bugzilla_login> and I<Bugzilla_password>.
+
+If no data is present for that, then cookies are tried, using
+L<Bugzilla::Auth::Login::CGI::Cookie>.
+
+=head1 SEE ALSO
+
+L<Bugzilla::Auth>