mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-06 09:05:45 +00:00
326 lines
10 KiB
Perl
326 lines
10 KiB
Perl
# -*- 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): Bradley Baetz <bbaetz@acm.org>
|
|
# Erik Stambaugh <erik@dasbistro.com>
|
|
|
|
package Bugzilla::Auth;
|
|
|
|
use strict;
|
|
|
|
use Bugzilla::Config;
|
|
use Bugzilla::Constants;
|
|
|
|
# The verification method that was successfully used upon login, if any
|
|
my $current_verify_class = undef;
|
|
|
|
# 'inherit' from the main verify method
|
|
BEGIN {
|
|
for my $verifyclass (split /,\s*/, Param("user_verify_class")) {
|
|
if ($verifyclass =~ /^([A-Za-z0-9_\.\-]+)$/) {
|
|
$verifyclass = $1;
|
|
} else {
|
|
die "Badly-named user_verify_class '$verifyclass'";
|
|
}
|
|
require "Bugzilla/Auth/Verify/" . $verifyclass . ".pm";
|
|
}
|
|
}
|
|
|
|
# PRIVATE
|
|
|
|
# A number of features, like password change requests, require the DB
|
|
# verification method to be on the list.
|
|
sub has_db {
|
|
for (split (/[\s,]+/, Param("user_verify_class"))) {
|
|
if (/^DB$/) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
# Returns the network address for a given IP
|
|
sub get_netaddr {
|
|
my $ipaddr = shift;
|
|
|
|
# Check for a valid IPv4 addr which we know how to parse
|
|
if (!$ipaddr || $ipaddr !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
|
|
return undef;
|
|
}
|
|
|
|
my $addr = unpack("N", pack("CCCC", split(/\./, $ipaddr)));
|
|
|
|
my $maskbits = Param('loginnetmask');
|
|
|
|
# Make Bugzilla ignore the IP address if loginnetmask is set to 0
|
|
return "0.0.0.0" if ($maskbits == 0);
|
|
|
|
$addr >>= (32-$maskbits);
|
|
$addr <<= (32-$maskbits);
|
|
return join(".", unpack("CCCC", pack("N", $addr)));
|
|
}
|
|
|
|
# This is a replacement for the inherited authenticate function
|
|
# go through each of the available methods for each function
|
|
sub authenticate {
|
|
my $class = shift;
|
|
my @args = @_;
|
|
my @firstresult = ();
|
|
my @result = ();
|
|
my $current_verify_method;
|
|
for my $method (split /,\s*/, Param("user_verify_class")) {
|
|
$current_verify_method = $method;
|
|
$method = "Bugzilla::Auth::Verify::" . $method;
|
|
@result = $method->authenticate(@args);
|
|
@firstresult = @result unless @firstresult;
|
|
|
|
if (($result[0] != AUTH_NODATA)&&($result[0] != AUTH_LOGINFAILED)) {
|
|
unshift @result, ($current_verify_method);
|
|
return @result;
|
|
}
|
|
}
|
|
@result = @firstresult;
|
|
# no auth match
|
|
|
|
# see if we can set $current to the first verify method that
|
|
# will allow a new login
|
|
|
|
my $chosen_verify_method;
|
|
for my $method (split /,\s*/, Param("user_verify_class")) {
|
|
$current_verify_method = $method;
|
|
$method = "Bugzilla::Auth::Verify::" . $method;
|
|
if ($method->can_edit('new')) {
|
|
$chosen_verify_method = $method;
|
|
}
|
|
}
|
|
|
|
unshift @result, $chosen_verify_method;
|
|
return @result;
|
|
}
|
|
|
|
sub can_edit {
|
|
my ($class, $type) = @_;
|
|
if ($current_verify_class) {
|
|
return $current_verify_class->can_edit($type);
|
|
}
|
|
# $current_verify_class will not be set if the user isn't logged in. That
|
|
# happens when the user is trying to create a new account, which (for now)
|
|
# is hard-coded to work with DB.
|
|
elsif (has_db) {
|
|
return Bugzilla::Auth::Verify::DB->can_edit($type);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
=head1 NAME
|
|
|
|
Bugzilla::Auth - Authentication handling for Bugzilla users
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Handles authentication for Bugzilla users.
|
|
|
|
Authentication from Bugzilla involves two sets of modules. One set is
|
|
used to obtain the data (from CGI, email, etc), and the other set uses
|
|
this data to authenticate against the datasource (the Bugzilla DB, LDAP,
|
|
cookies, etc).
|
|
|
|
Modules for obtaining the data are located under L<Bugzilla::Auth::Login>, and
|
|
modules for authenticating are located in L<Bugzilla::Auth::Verify>.
|
|
|
|
=head1 METHODS
|
|
|
|
C<Bugzilla::Auth> contains several helper methods to be used by
|
|
authentication or login modules.
|
|
|
|
=over 4
|
|
|
|
=item C<Bugzilla::Auth::get_netaddr($ipaddr)>
|
|
|
|
Given an ip address, this returns the associated network address, using
|
|
C<Param('loginnetmask')> as the netmask. This can be used to obtain data
|
|
in order to restrict weak authentication methods (such as cookies) to
|
|
only some addresses.
|
|
|
|
=back
|
|
|
|
=head1 AUTHENTICATION
|
|
|
|
Authentication modules check a user's credentials (username, password,
|
|
etc) to verify who the user is. The methods that C<Bugzilla::Auth> uses for
|
|
authentication are wrappers that check all configured modules (via the
|
|
C<Param('user_info_class')> and C<Param('user_verify_class')>) in sequence.
|
|
|
|
=head2 METHODS
|
|
|
|
=over 4
|
|
|
|
=item C<authenticate($username, $pass)>
|
|
|
|
This method is passed a username and a password, and returns a list
|
|
containing up to four return values, depending on the results of the
|
|
authentication.
|
|
|
|
The first return value is the name of the class that generated the results
|
|
constined in the remaining return values. The second return value is one of
|
|
the status codes defined in L<Bugzilla::Constants|Bugzilla::Constants> and
|
|
described below. The rest of the return values are status code-specific
|
|
and are explained in the status code descriptions.
|
|
|
|
=item C<AUTH_OK>
|
|
|
|
Authentication succeeded. The third variable is the userid of the new
|
|
user.
|
|
|
|
=item C<AUTH_NODATA>
|
|
|
|
Insufficient login data was provided by the user. This may happen in several
|
|
cases, such as cookie authentication when the cookie is not present.
|
|
|
|
=item C<AUTH_ERROR>
|
|
|
|
An error occurred when trying to use the login mechanism. The third return
|
|
value may contain the Bugzilla userid, but will probably be C<undef>,
|
|
signifiying that the userid is unknown. The fourth value is a tag describing
|
|
the error used by the authentication error templates to print a description
|
|
to the user. The optional fifth argument is a hashref of values used as part
|
|
of the tag's error descriptions.
|
|
|
|
This error template must have a name/location of
|
|
I<account/auth/C<lc(authentication-type)>-error.html.tmpl>.
|
|
|
|
=item C<AUTH_LOGINFAILED>
|
|
|
|
An incorrect username or password was given. Note that for security reasons,
|
|
both cases return the same error code. However, in the case of a valid
|
|
username, the third argument may be the userid. The authentication
|
|
mechanism may not always be able to discover the userid if the password is
|
|
not known, so whether or not this argument is present is implementation
|
|
specific. For security reasons, the presence or lack of a userid value should
|
|
not be communicated to the user.
|
|
|
|
The fourth argument is an optional tag from the authentication server
|
|
describing the error. The tag can be used by a template to inform the user
|
|
about the error. Similar to C<AUTH_ERROR>, an optional hashref may be
|
|
present as a fifth argument, to be used by the tag to give more detailed
|
|
information.
|
|
|
|
=item C<AUTH_DISABLED>
|
|
|
|
The user successfully logged in, but their account has been disabled.
|
|
The third argument in the returned array is the userid, and the fourth
|
|
is some text explaining why the account was disabled. This text would
|
|
typically come from the C<disabledtext> field in the C<profiles> table.
|
|
Note that this argument is a string, not a tag.
|
|
|
|
=item C<current_verify_class>
|
|
|
|
This scalar gets populated with the full name (eg.,
|
|
C<Bugzilla::Auth::Verify::DB>) of the verification method being used by the
|
|
current user. If no user is logged in, it will contain the name of the first
|
|
method that allows new users, if any. Otherwise, it carries an undefined
|
|
value.
|
|
|
|
=item C<can_edit>
|
|
|
|
This determines if the user's account details can be modified. It returns a
|
|
reference to a hash with the keys C<userid>, C<login_name>, and C<realname>,
|
|
which determine whether their respective profile values may be altered, and
|
|
C<new>, which determines if new accounts may be created.
|
|
|
|
Each user verification method (chosen with C<Param('user_verify_class')> has
|
|
its own set of can_edit values. Calls to can_edit return the appropriate
|
|
values for the current user's login method.
|
|
|
|
If a user is not logged in, C<can_edit> will contain the values of the first
|
|
verify method that allows new users to be created, if available. Otherwise it
|
|
returns an empty hash.
|
|
|
|
=back
|
|
|
|
=head1 LOGINS
|
|
|
|
A login module can be used to try to log in a Bugzilla user in a
|
|
particular way. For example,
|
|
L<Bugzilla::Auth::Login::WWW::CGI|Bugzilla::Auth::Login::WWW::CGI>
|
|
logs in users from CGI scripts, first by using form variables, and then
|
|
by trying cookies as a fallback.
|
|
|
|
The login interface consists of the following methods:
|
|
|
|
=over 4
|
|
|
|
=item C<login>, which takes a C<$type> argument, using constants found in
|
|
C<Bugzilla::Constants>.
|
|
|
|
The login method may use various authentication modules (described
|
|
above) to try to authenticate a user, and should return the userid on
|
|
success, or C<undef> on failure.
|
|
|
|
When a login is required, but data is not present, it is the job of the
|
|
login method to prompt the user for this data.
|
|
|
|
The constants accepted by C<login> include the following:
|
|
|
|
=item C<LOGIN_OPTIONAL>
|
|
|
|
A login is never required to access this data. Attempting to login is
|
|
still useful, because this allows the page to be personalised. Note that
|
|
an incorrect login will still trigger an error, even though the lack of
|
|
a login will be OK.
|
|
|
|
=item C<LOGIN_NORMAL>
|
|
|
|
A login may or may not be required, depending on the setting of the
|
|
I<requirelogin> parameter.
|
|
|
|
=item C<LOGIN_REQUIRED>
|
|
|
|
A login is always required to access this data.
|
|
|
|
=item C<logout>, which takes a C<Bugzilla::User> argument for the user
|
|
being logged out, and an C<$option> argument. Possible values for
|
|
C<$option> include:
|
|
|
|
=item C<LOGOUT_CURRENT>
|
|
|
|
Log out the user and invalidate his currently registered session.
|
|
|
|
=item C<LOGOUT_ALL>
|
|
|
|
Log out the user, and invalidate all sessions the user has registered in
|
|
Bugzilla.
|
|
|
|
=item C<LOGOUT_KEEP_CURRENT>
|
|
|
|
Invalidate all sessions the user has registered excluding his current
|
|
session; this option should leave the user logged in. This is useful for
|
|
user-performed password changes.
|
|
|
|
=back
|
|
|
|
=head1 SEE ALSO
|
|
|
|
L<Bugzilla::Auth::Login::WWW::CGI>, L<Bugzilla::Auth::Login::WWW::CGI::Cookie>, L<Bugzilla::Auth::Verify::DB>
|
|
|