# Rights Reserved.
#
# Contributor(s): Bradley Baetz <bbaetz@student.usyd.edu.au>
+# Erik Stambaugh <erik@dasbistro.com>
#
package Bugzilla;
use strict;
use Bugzilla::Auth;
+use Bugzilla::Auth::Login::WWW;
use Bugzilla::CGI;
use Bugzilla::Config;
use Bugzilla::Constants;
sub login {
my ($class, $type) = @_;
-
- # Avoid double-logins, which may confuse the auth code
- # (double cookies, odd compat code settings, etc)
- # This is particularly important given the munging for
- # $::COOKIE{'Bugzilla_login'} from a userid to a loginname
- # (for backwards compat)
- if (defined $_user) {
- return $_user;
- }
-
- $type = LOGIN_NORMAL unless defined $type;
-
- # For now, we can only log in from a cgi
- # One day, we'll be able to log in via apache auth, an email message's
- # PGP signature, and so on
-
- use Bugzilla::Auth::CGI;
- my $userid = Bugzilla::Auth::CGI->login($type);
- if ($userid) {
- $_user = new Bugzilla::User($userid);
-
- # Compat stuff
- $::userid = $userid;
-
- # Evil compat hack. The cookie stores the id now, not the name, but
- # old code still looks at this to get the current user's email
- # so it needs to be set.
- $::COOKIE{'Bugzilla_login'} = $_user->login;
- } else {
- logout_request();
- }
-
- return $_user;
+ $_user = Bugzilla::Auth::Login::WWW->login($type);
}
sub logout {
}
$option = LOGOUT_CURRENT unless defined $option;
- use Bugzilla::Auth::CGI;
- Bugzilla::Auth::CGI->logout($_user, $option);
- if ($option != LOGOUT_KEEP_CURRENT) {
- Bugzilla::Auth::CGI->clear_browser_cookies();
- logout_request();
- }
+ Bugzilla::Auth::Login::WWW->logout($_user, $option);
}
sub logout_user {
my ($class, $user) = @_;
# When we're logging out another user we leave cookies alone, and
- # therefore avoid calling logout() directly.
- use Bugzilla::Auth::CGI;
- Bugzilla::Auth::CGI->logout($user, LOGOUT_ALL);
+ # therefore avoid calling Bugzilla->logout() directly.
+ Bugzilla::Auth::Login::WWW->logout($user, LOGOUT_ALL);
}
# just a compatibility front-end to logout_user that gets a user by id
=item C<login>
Logs in a user, returning a C<Bugzilla::User> object, or C<undef> if there is
-no logged in user. See L<Bugzilla::Auth|Bugzilla::Auth> and
+no logged in user. See L<Bugzilla::Auth|Bugzilla::Auth>, and
L<Bugzilla::User|Bugzilla::User>.
=item C<logout($option)>
Essentially, causes calls to C<Bugzilla->user> to return C<undef>. This has the
effect of logging out a user for the current request only; cookies and
-database sessions are left intact.
+database sessions are left intact.
=item C<dbh>
# Rights Reserved.
#
# Contributor(s): Bradley Baetz <bbaetz@acm.org>
+# Erik Stambaugh <erik@dasbistro.com>
package Bugzilla::Auth;
use Bugzilla::Config;
use Bugzilla::Constants;
-# 'inherit' from the main loginmethod
+# The verification method that was successfully used upon login, if any
+my $current_verify_class = undef;
+
+# 'inherit' from the main verify method
BEGIN {
- my $loginmethod = Param("loginmethod");
- if ($loginmethod =~ /^([A-Za-z0-9_\.\-]+)$/) {
- $loginmethod = $1;
- }
- else {
- die "Badly-named loginmethod '$loginmethod'";
+ 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";
}
- require "Bugzilla/Auth/" . $loginmethod . ".pm";
-
- our @ISA;
- push (@ISA, "Bugzilla::Auth::" . $loginmethod);
}
# 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;
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 = ();
+ for my $method (split /,\s*/, Param("user_verify_class")) {
+ $method = "Bugzilla::Auth::Verify::" . $method;
+ @result = $method->authenticate(@args);
+ @firstresult = @result unless @firstresult;
+
+ if (($result[0] != AUTH_NODATA)&&($result[0] != AUTH_LOGINFAILED)) {
+ $current_verify_class = $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
+
+ for my $method (split /,\s*/, Param("user_verify_class")) {
+ $method = "Bugzilla::Auth::Verify::" . $method;
+ if ($method->can_edit('new')) {
+ $current_verify_class = $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__
this data to authenticate against the datasource (the Bugzilla DB, LDAP,
cookies, etc).
-The handlers for the various types of authentication
-(DB/LDAP/cookies/etc) provide the actual code for each specific method
-of authentication.
-
-The source modules (currently, only
-L<Bugzilla::Auth::CGI|Bugzilla::Auth::CGI>) then use those methods to do
-the authentication.
-
-I<Bugzilla::Auth> itself inherits from the default authentication handler,
-identified by the I<loginmethod> param.
+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
=head1 AUTHENTICATION
Authentication modules check a user's credentials (username, password,
-etc) to verify who the user is.
+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
=back
+=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. If this
-method returns a C<true> value, then accounts can be created and
-modified through the Bugzilla user interface. Forgotten passwords can
-also be retrieved through the L<Token interface|Bugzilla::Token>.
+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::CGI|Bugzilla::Auth::CGI>
+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.
=head1 SEE ALSO
-L<Bugzilla::Auth::CGI>, L<Bugzilla::Auth::Cookie>, L<Bugzilla::Auth::DB>
+L<Bugzilla::Auth::Login::WWW::CGI>, L<Bugzilla::Auth::Login::WWW::CGI::Cookie>, L<Bugzilla::Auth::Verify::DB>
--- /dev/null
+# -*- 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 <erik@dasbistro.com>
+
+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;
+}
+
+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)
+ # This is particularly important given the munging for
+ # $::COOKIE{'Bugzilla_login'} from a userid to a loginname
+ # (for backwards compat)
+ if (defined $user) {
+ return $user;
+ }
+
+ $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);
+
+ # Compat stuff
+ $::userid = $userid;
+
+ # Evil compat hack. The cookie stores the id now, not the name, but
+ # old code still looks at this to get the current user's email
+ # so it needs to be set.
+ $::COOKIE{'Bugzilla_login'} = $user->login;
+ } else {
+ Bugzilla->logout_request();
+ }
+ return $user;
+}
+
+sub logout {
+ my ($class, $user, $option) = @_;
+ if ($class->login_class) {
+ $class->login_class->logout($user, $option);
+ }
+}
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Bugzilla::Auth::Login::WWW - WWW login information gathering module
+
+=head1 METHODS
+
+=item C<login>
+
+Passes C<login> calls to each class defined in the param C<user_info_class>
+and returns a C<Bugzilla::User> object from the first one that successfully
+gathers user login information.
+
+
# Gervase Markham <gerv@gerv.net>
# Christian Reis <kiko@async.com.br>
# Bradley Baetz <bbaetz@acm.org>
+# Erik Stambaugh <erik@dasbistro.com>
-package Bugzilla::Auth::CGI;
+package Bugzilla::Auth::Login::WWW::CGI;
use strict;
my $username = $cgi->param("Bugzilla_login");
my $passwd = $cgi->param("Bugzilla_password");
- my $authmethod = Param("loginmethod");
+ my $authmethod = Param("user_verify_class");
my ($authres, $userid, $extra, $info) =
Bugzilla::Auth->authenticate($username, $passwd);
$username = $cgi->cookie("Bugzilla_login");
$passwd = $cgi->cookie("Bugzilla_logincookie");
- require Bugzilla::Auth::Cookie;
+ require Bugzilla::Auth::Login::WWW::CGI::Cookie;
my $authmethod = "Cookie";
($authres, $userid, $extra) =
- Bugzilla::Auth::Cookie->authenticate($username, $passwd);
+ 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.
{ 'target' => $cgi->url(-relative=>1),
'form' => \%::FORM,
'mform' => \%::MFORM,
- 'caneditaccount' => Bugzilla::Auth->can_edit,
+ 'caneditaccount' => Bugzilla::Auth->can_edit('new'),
+ 'has_db' => Bugzilla::Auth->has_db,
}
)
|| ThrowTemplateError($template->error());
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 {
=head1 NAME
-Bugzilla::Auth::CGI - CGI-based logins for Bugzilla
+Bugzilla::Auth::Login::WWW::CGI - CGI-based logins for Bugzilla
=head1 SUMMARY
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::Cookie>.
+L<Bugzilla::Auth::Login::WWW::CGI::Cookie>.
=head1 SEE ALSO
# Christian Reis <kiko@async.com.br>
# Bradley Baetz <bbaetz@acm.org>
-package Bugzilla::Auth::Cookie;
+package Bugzilla::Auth::Login::WWW::CGI::Cookie;
use strict;
=head1 NAME
-Bugzilla::Cookie - cookie authentication for Bugzilla
+Bugzilla::Auth::Login::WWW::CGI::Cookie - cookie authentication for Bugzilla
=head1 SUMMARY
restriction can be specified by the admin via the C<loginnetmask> parameter.
This module does not ever send a cookie (It has no way of knowing when a user
-is successfully logged in). Instead L<Bugzilla::Auth::CGI> handles this.
+is successfully logged in). Instead L<Bugzilla::Auth::Login::WWW::CGI> handles this.
=head1 SEE ALSO
-L<Bugzilla::Auth>, L<Bugzilla::Auth::CGI>
+L<Bugzilla::Auth>, L<Bugzilla::Auth::Login::WWW::CGI>
--- /dev/null
+How Auth Works
+==============
+Christian Reis <kiko@async.com.br>
+
+Overview
+--------
+
+Authentication in Bugzilla is handled by a collection of modules that live in
+the Bugzilla::Auth package. These modules are organized hierarchically based
+upon their responsibility.
+
+The authentication scheme is divided in two tasks: Login and Verify. Login
+involves gathering credentials from a user, while Verify validates them
+against an authentication service.
+
+The Bugzilla parameters user_info_class and user_verify_class contain a
+list of Login and Verify modules, respectively.
+
+Task: Login
+-----------
+
+This task obtains user credentials based on a request. Examples of requests
+include CGI access from the Bugzilla web interface, email submissions and
+credentials supplied by standalone scripts.
+
+Each type of Bugzilla front-end should have its own package. For instance,
+access via the Bugzilla web pages should go through Bugzilla::Auth::WWW.
+These packages would contain modules of their own to perform whatever extra
+functions are needed, like the CGI and Cookie modules in the case of WWW.
+
+Task: Verify
+------------
+
+This task validates user credentials against a user authentication service.
+
+The default service in Bugzilla has been the database, which stores the
+login_name and cryptpasswd fields in the profiles table. An alternative means
+of validation, LDAP, is already supported, and other contributions would be
+appreciated.
+
+The module layout is similar to the Login package, but there is no need for a
+sub-level as there is with Login request types.
+
+Params
+------
+
+There are two params that define behaviour for each authentication task. Each
+of them defines a comma-separated list of modules to be tried in order.
+
+ - user_info_class determines the module(s) used to obtain user
+ credentials. This param is specific to the requests from Bugzilla web
+ pages, so all of the listed modules live under
+ Bugzilla::Auth::Login::WWW
+
+ - user_verify_class determines the module(s) used to verify credentials.
+ This param is general and concerns the whole Bugzilla instance, since
+ the same back end should be used regardless of what front end is used.
+
+Responsibilities
+----------------
+
+Bugzilla::Auth
+
+ This module is responsible for abstracting away as much as possible the
+ login and logout tasks in Bugzilla.
+
+ It offers login() and logout() methods that are proxied to the selected
+ login and verify packages.
+
+Bugzilla::Auth::Login
+
+ This is a container to hold the various modules for each request type.
+
+Bugzilla::Auth::Login::WWW
+
+ This module is responsible for abstracting away details of which web-based
+ login modules exist and are in use. It offers login() and logout() methods
+ that proxy through to whatever specific modules
+
+Bugzilla::Auth::Verify
+
+ This module is responsible for abstracting away details of which
+ credential verification modules exist, and should proxy calls through to
+ them. There is a method that is particularly important, and which should
+ be proxied through to the specific:
+
+ can_edit($type)
+
+ This method takes an argument that specifies what sort of change
+ is being requested; the specific module should return 1 or 0 based
+ on the fact that it implements or not the required change.
+
+ Current values for $type are "new" for new accounts, and "userid",
+ "login_name", "realname" for their respective fields.
+
+Specific Login Modules
+----------------------
+
+ WWW
+
+ The main authentication frontend; regular pages (CGIs) should use only
+ this module. It offers a convenient frontend to the main functionality
+ that CGIs need, using form parameters and cookies.
+
+ - Cookie
+
+ Implements part of the backend code that deals with browser
+ cookies. It's actually tied in to DB.pm, so Cookie logins that use
+ LDAP won't work at all.
+
+ LDAP
+
+ The other authentication module is LDAP-based; it is *only* used for
+ password authentication and not for any other login-related task (it
+ actually relies on the database to handle the profile information).
+
+Legacy
+------
+
+Bugzilla.pm
+
+ There is glue code that currently lives in the top-level module
+ Bugzilla.pm; this module handles backwards-compatibility data that is used
+ in a number of CGIs. This data has been slowly removed from the Bugzilla
+ pages and eventually should go away completely, at which point Bugzilla.pm
+ will be just a wrapper to conveniently offer template, cgi, dbh and user
+ variables.
+
+ This module is meant to be used only by Bugzilla pages, and in the case of
+ a reorganization which moves CGI-specific code to a subdirectory,
+ Bugzilla.pm should go with it.
+
+$::COOKIE
+
+ There are still instances of use of $::COOKIE to obtain Logincookie
+ information; these should be removed as well.
+
+
# Gervase Markham <gerv@gerv.net>
# Christian Reis <kiko@async.com.br>
# Bradley Baetz <bbaetz@acm.org>
+# Erik Stambaugh <erik@dasbistro.com>
-package Bugzilla::Auth::DB;
+package Bugzilla::Auth::Verify::DB;
use strict;
use Bugzilla::Constants;
use Bugzilla::Util;
+my $edit_options = {
+ 'new' => 1,
+ 'userid' => 0,
+ 'login_name' => 1,
+ 'realname' => 1,
+};
+
+sub can_edit {
+ my ($class, $type) = @_;
+ return $edit_options->{$type};
+}
+
sub authenticate {
my ($class, $username, $passwd) = @_;
return (AUTH_OK, $userid);
}
-sub can_edit { return 1; }
-
sub get_id_from_username {
my ($class, $username) = @_;
my $dbh = Bugzilla->dbh;
=head1 NAME
-Bugzilla::Auth::DB - database authentication for Bugzilla
+Bugzilla::Auth::Verify::DB - database authentication for Bugzilla
=head1 SUMMARY
# Gervase Markham <gerv@gerv.net>
# Christian Reis <kiko@async.com.br>
# Bradley Baetz <bbaetz@acm.org>
+# Erik Stambaugh <erik@dasbistro.com>
-package Bugzilla::Auth::LDAP;
+package Bugzilla::Auth::Verify::LDAP;
use strict;
use Net::LDAP;
+my $edit_options = {
+ 'new' => 0,
+ 'userid' => 0,
+ 'login_name' => 0,
+ 'realname' => 0,
+};
+
+sub can_edit {
+ my ($class, $type) = @_;
+ return $edit_options->{$type};
+}
+
sub authenticate {
my ($class, $username, $passwd) = @_;
return (AUTH_OK, $userid);
}
-sub can_edit { return 0; }
-
1;
__END__
=head1 NAME
-Bugzilla::Auth::LDAP - LDAP based authentication for Bugzilla
+Bugzilla::Auth::Verify::LDAP - LDAP based authentication for Bugzilla
This is an L<authentication module|Bugzilla::Auth/"AUTHENTICATION"> for
Bugzilla, which logs the user in using an LDAP directory.
# J. Paul Reed <preed@sigkill.com>
# Bradley Baetz <bbaetz@student.usyd.edu.au>
# Christopher Aillon <christopher@aillon.com>
+# Erik Stambaugh <erik@dasbistro.com>
package Bugzilla::Config;
$param{'loginmethod'} = $param{'useLDAP'} ? "LDAP" : "DB";
}
+ # set verify method to whatever loginmethod was
+ if (exists $param{'loginmethod'} && !exists $param{'user_verify_class'}) {
+ $param{'user_verify_class'} = $param{'loginmethod'};
+ delete $param{'loginmethod'};
+ }
+
# --- DEFAULTS FOR NEW PARAMS ---
foreach my $item (@param_list) {
# Bradley Baetz <bbaetz@student.usyd.edu.au>
# Tobias Burnus <burnus@net-b.de>
# Gervase Markham <gerv@gerv.net>
+# Erik Stambaugh <erik@dasbistro.com>
#
#
# Direct any questions on this source code to
# Check for LDAP
###########################################################################
-if (Param('loginmethod') eq 'LDAP') {
- my $netLDAP = have_vers("Net::LDAP", 0);
- if (!$netLDAP && !$silent) {
- print "If you wish to use LDAP authentication, then you must install Net::LDAP\n\n";
+for my $verifymethod (split /,\s*/, Param('user_verify_class')) {
+ if ($verifymethod eq 'LDAP') {
+ my $netLDAP = have_vers("Net::LDAP", 0);
+ if (!$netLDAP && !$silent) {
+ print "If you wish to use LDAP authentication, then you must install Net::LDAP\n\n";
+ }
}
}
);
# If we're using LDAP for login, then we can't create a new account here.
-unless (Bugzilla::Auth->can_edit) {
+unless (Bugzilla::Auth->can_edit('new')) {
# Just in case someone already has an account, let them get the correct
# footer on the error message
Bugzilla->login();
# J. Paul Reed <preed@sigkill.com>
# Bradley Baetz <bbaetz@student.usyd.edu.au>
# Joseph Heenan <joseph@heenan.me.uk>
+# Erik Stambaugh <erik@dasbistro.com>
#
# This file defines all the parameters that we have a GUI to edit within
return "";
}
-sub check_loginmethod {
+sub check_user_verify_class {
# doeditparams traverses the list of params, and for each one it checks,
# then updates. This means that if one param checker wants to look at
# other params, it must be below that other one. So you can't have two
# the login method as LDAP, we won't notice, but all logins will fail.
# So don't do that.
- my ($method, $entry) = @_;
- my $res = check_multi($method, $entry);
- return $res if $res;
- if ($method eq 'DB') {
- # No params
- } elsif ($method eq 'LDAP') {
- eval "require Net::LDAP";
- return "Error requiring Net::LDAP: '$@'" if $@;
- return "LDAP servername is missing" unless Param("LDAPserver");
- return "LDAPBaseDN is empty" unless Param("LDAPBaseDN");
- } else {
- return "Unknown loginmethod '$method' in check_loginmethod";
+ my ($list, $entry) = @_;
+ for my $class (split /,\s*/, $list) {
+ my $res = check_multi($class, $entry);
+ return $res if $res;
+ if ($class eq 'DB') {
+ # No params
+ } elsif ($class eq 'LDAP') {
+ eval "require Net::LDAP";
+ return "Error requiring Net::LDAP: '$@'" if $@;
+ return "LDAP servername is missing" unless Param("LDAPserver");
+ return "LDAPBaseDN is empty" unless Param("LDAPBaseDN");
+ } else {
+ return "Unknown user_verify_class '$class' in check_user_verify_class";
+ }
}
return "";
}
default => '',
},
+ # XXX in the future:
+ #
+ # user_verify_class and user_info_class should have choices gathered from
+ # whatever sits in their respective directories
+ #
+ # rather than comma-separated lists, these two should eventually become
+ # arrays, but that requires alterations to editparams first
+
+ {
+ name => 'user_info_class',
+ desc => 'Mechanism(s) to be used for gathering a user\'s login information.
+ <add>
+ More than one may be selected. If the first one returns nothing,
+ the second is tried, and so on.<br />
+ The types are:
+ <dl>
+ <dt>CGI</dt>
+ <dd>
+ Asks for username and password via CGI form interface.
+ </dd>
+ </dl>',
+ type => 's',
+ choices => [ 'CGI' ],
+ default => 'CGI',
+ checker => \&check_multi
+ },
+
{
- name => 'loginmethod',
- desc => 'The type of login authentication to use:
+ name => 'user_verify_class',
+ desc => 'Mechanism(s) to be used for verifying (authenticating) information
+ gathered by user_info_class.
+ More than one may be selected. If the first one cannot find the
+ user, the second is tried, and so on.<br />
+ The types are:
<dl>
<dt>DB</dt>
<dd>
</dd>
</dl>',
type => 's',
- choices => [ 'DB', 'LDAP' ],
+ choices => [ 'DB', 'LDAP', 'DB,LDAP', 'LDAP,DB' ],
default => 'DB',
- checker => \&check_loginmethod
+ checker => \&check_user_verify_class
},
{
# Joe Robins <jmrobins@tgix.com>
# Dan Mosedale <dmose@mozilla.org>
# Joel Peshkin <bugreport@peshkin.net>
+# Erik Stambaugh <erik@dasbistro.com>
#
# Direct any questions on this source code to
#
if ($editall) {
print "</TR><TR>\n";
print " <TH ALIGN=\"right\">Password:</TH>\n";
- if(!Bugzilla::Auth->can_edit) {
- print " <TD><FONT COLOR=RED>This site's authentication method does not allow password changes through Bugzilla!</FONT></TD>\n";
- } else {
print qq|
<TD><INPUT TYPE="PASSWORD" SIZE="16" MAXLENGTH="16" NAME="password" VALUE=""><br>
(enter new password to change)
</TD>
|;
- }
print "</TR><TR>\n";
print " <TH ALIGN=\"right\">Disable text:</TH>\n";
sub PutTrailer (@)
{
my (@links) = ("Back to the <a href=\"./\">index</a>");
- if($editall && Bugzilla::Auth->can_edit) {
+ if($editall) {
push(@links,
"<a href=\"editusers.cgi?action=add\">add</a> a new user");
}
}
print "</TR>";
}
- if ($editall && Bugzilla::Auth->can_edit) {
+ if ($editall) {
print "<TR>\n";
my $span = $candelete ? 3 : 2;
print qq{
exit;
}
- if(!Bugzilla::Auth->can_edit) {
- print "The authentication mechanism you are using does not permit accounts to be created from Bugzilla";
- PutTrailer();
- exit;
- }
-
print "<FORM METHOD=POST ACTION=editusers.cgi>\n";
print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n";
exit;
}
- if (!Bugzilla::Auth->can_edit) {
- print "This site's authentication mechanism does not allow new users to be added.";
- PutTrailer();
- exit;
- }
-
# Cleanups and valididy checks
my $realname = trim($::FORM{realname} || '');
# We don't trim the password since that could falsely lead the user
# Update the database with the user's new password if they changed it.
- if ( Bugzilla::Auth->can_edit && $editall && $password ) {
+ if ( $editall && $password ) {
my $passworderror = ValidatePassword($password);
if ( !$passworderror ) {
my $cryptpassword = SqlQuote(Crypt($password));
@additional_files = ();
%exclude_deps = (
'XML::Parser' => ['importxml.pl'],
- 'Net::LDAP' => ['Bugzilla/Auth/LDAP.pm'],
+ 'Net::LDAP' => ['Bugzilla/Auth/Verify/LDAP.pm'],
);
# form: hash; the form values which need to be submitted to the target script
# mform: hash; the form values with multiple values which need to be
# submitted to the target script
+ # has_db: true if DB is one of the available authentication mechanisms
#%]
[% PROCESS global/variables.none.tmpl %]
#%]
[% IF caneditaccount %]
- <hr>
[% IF Param("createemailregexp") %]
+ <hr>
+
<p>
If you don't have a [% terms.Bugzilla %] account, you can
<a href="createaccount.cgi">create a new account</a>.
</p>
[% END %]
- <form method="get" action="token.cgi">
- <input type="hidden" name="a" value="reqpw">
- If you have an account, but have forgotten your password,
- enter your login name below and submit a request
- to change your password.<br>
- <input size="35" name="loginname">
- <input type="submit" value="Submit Request">
- </form>
+ [%# For now, password change requests only apply to the DB
+ # verification method #%]
+
+ [% IF has_db != 0 %]
+ <hr>
+
+ <form method="get" action="token.cgi">
+ <input type="hidden" name="a" value="reqpw">
+ If you have an account, but have forgotten your password,
+ enter your login name below and submit a request
+ to change your password.<br>
+ <input size="35" name="loginname">
+ <input type="submit" value="Submit Request">
+ </form>
+
+ [% END %]
<hr>
[% END %]
[% title = "Old Password Required" %]
You must enter your old password to change your email address.
+ [% ELSIF error == "password_change_requests_not_allowed" %]
+ [% title = "Password Change Requests Not Allowed" %]
+ The system is not configured to allow password change requests.
+
[% ELSIF error == "passwords_dont_match" %]
[% title = "Passwords Don't Match" %]
The two passwords you entered did not match.
}
}
+
# If the user is requesting a password change, make sure they submitted
-# their login name and it exists in the database.
+# their login name and it exists in the database, and that the DB module is in
+# the list of allowed verification methids.
if ( $::action eq 'reqpw' ) {
defined $cgi->param('loginname')
|| ThrowUserError("login_needed_for_password_change");
+ # check verification methods
+ unless (Bugzilla::Auth->has_db) {
+ ThrowUserError("password_change_requests_not_allowed");
+ }
+
# Make sure the login name looks like an email address. This function
# displays its own error and stops execution if the login name looks wrong.
CheckEmailSyntax($cgi->param('loginname'));