Bug 180642 - Move authentication code into a module
r=gerv, justdave a=justdave git-svn-id: svn://10.0.0.236/trunk@140041 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
e17d52d583
commit
2b0b42744f
@ -24,10 +24,13 @@ package Bugzilla;
|
||||
|
||||
use strict;
|
||||
|
||||
use Bugzilla::Auth;
|
||||
use Bugzilla::CGI;
|
||||
use Bugzilla::Config;
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::DB;
|
||||
use Bugzilla::Template;
|
||||
use Bugzilla::User;
|
||||
|
||||
my $_template;
|
||||
sub template {
|
||||
@ -43,6 +46,60 @@ sub cgi {
|
||||
return $_cgi;
|
||||
}
|
||||
|
||||
my $_user;
|
||||
sub user {
|
||||
my $class = shift;
|
||||
return $_user;
|
||||
}
|
||||
|
||||
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->{id};
|
||||
}
|
||||
|
||||
$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;
|
||||
&::ConfirmGroup($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->{email};
|
||||
|
||||
$::vars->{'user'} = &::GetUserInfo($userid);
|
||||
} else {
|
||||
# Old compat stuff
|
||||
|
||||
$::userid = 0;
|
||||
delete $::COOKIE{'Bugzilla_login'};
|
||||
delete $::COOKIE{'Bugzilla_logincookie'};
|
||||
# NB - Can't delete from $cgi->cookie, so the cookie data will
|
||||
# remain there
|
||||
# People shouldn't rely on the cookie param for the username
|
||||
# - use Bugzilla->user instead!
|
||||
}
|
||||
|
||||
return $userid || 0;
|
||||
}
|
||||
|
||||
my $_dbh;
|
||||
my $_dbh_main;
|
||||
my $_dbh_shadow;
|
||||
@ -93,6 +150,7 @@ sub switch_to_main_db {
|
||||
# Per process cleanup
|
||||
sub _cleanup {
|
||||
undef $_cgi;
|
||||
undef $_user;
|
||||
|
||||
# See bug 192531. If we don't clear the possibly active statement handles,
|
||||
# then when this is called from the END block, it happens _before_ the
|
||||
@ -192,6 +250,16 @@ The current C<cgi> object. Note that modules should B<not> be using this in
|
||||
general. Not all Bugzilla actions are cgi requests. Its useful as a convenience
|
||||
method for those scripts/templates which are only use via CGI, though.
|
||||
|
||||
=item C<user>
|
||||
|
||||
The current L<Bugzilla::User>. C<undef> if there is no currently logged in user
|
||||
or if the login code has not yet been run.
|
||||
|
||||
=item C<login>
|
||||
|
||||
Logs in a user, returning the userid, or C<0> if there is no logged in user.
|
||||
See L<Bugzilla::Auth>.
|
||||
|
||||
=item C<dbh>
|
||||
|
||||
The current database handle. See L<DBI>.
|
||||
|
||||
214
mozilla/webtools/bugzilla/Bugzilla/Auth.pm
Normal file
214
mozilla/webtools/bugzilla/Bugzilla/Auth.pm
Normal file
@ -0,0 +1,214 @@
|
||||
# -*- 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>
|
||||
|
||||
package Bugzilla::Auth;
|
||||
|
||||
use strict;
|
||||
|
||||
use Bugzilla::Config;
|
||||
use Bugzilla::Constants;
|
||||
|
||||
# 'inherit' from the main loginmethod
|
||||
BEGIN {
|
||||
my $loginmethod = Param("loginmethod");
|
||||
require "Bugzilla/Auth/" . $loginmethod . ".pm";
|
||||
|
||||
our @ISA;
|
||||
push (@ISA, "Bugzilla::Auth::" . $loginmethod);
|
||||
}
|
||||
|
||||
# PRIVATE
|
||||
|
||||
# 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');
|
||||
|
||||
$addr >>= (32-$maskbits);
|
||||
$addr <<= (32-$maskbits);
|
||||
return join(".", unpack("CCCC", pack("N", $addr)));
|
||||
}
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
=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')> at 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 users's credentials (username, password, etc) to
|
||||
verify who the user is.
|
||||
|
||||
=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 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.
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<AUTH_OK>
|
||||
|
||||
Authentication succeeded. The second 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 second return
|
||||
value may contain the Bugzilla userid, but will probably be C<undef>,
|
||||
signifiying that the userid is unknown. The third value is a tag describing
|
||||
the error used by the authentication error templates to print a description
|
||||
to the user. The optional fourth 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 second 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 third 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 fourth 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
|
||||
second argument in the returned array is the userid, and the third 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.
|
||||
|
||||
=back
|
||||
|
||||
=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|Token>.
|
||||
|
||||
=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> logs in users
|
||||
from CGI scripts, first by trying database authentication against the
|
||||
Bugzilla C<profiles> table, and then by trying cookies as a fallback.
|
||||
|
||||
A login module consists of a single method, C<login>, which takes a C<$type>
|
||||
argument, using constants found in C<Bugzilla::Constants>.
|
||||
|
||||
=over 4
|
||||
|
||||
=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.
|
||||
|
||||
=back
|
||||
|
||||
The login module uses various authentication modules to try to authenticate
|
||||
a user, and returns 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
|
||||
module to prompt the user for this data.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Bugzilla::Auth::CGI>, L<Bugzilla::Auth::Cookie>, L<Bugzilla::Auth::DB>
|
||||
195
mozilla/webtools/bugzilla/Bugzilla/Auth/CGI.pm
Normal file
195
mozilla/webtools/bugzilla/Bugzilla/Auth/CGI.pm
Normal file
@ -0,0 +1,195 @@
|
||||
# -*- 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>
|
||||
|
||||
package Bugzilla::Auth::CGI;
|
||||
|
||||
use strict;
|
||||
|
||||
use Bugzilla::Config;
|
||||
use Bugzilla::Constants;
|
||||
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("loginmethod");
|
||||
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 = 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()");
|
||||
my $cookiepath = Param("cookiepath");
|
||||
print "Set-Cookie: Bugzilla_login=$userid ; path=$cookiepath; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
|
||||
print "Set-Cookie: Bugzilla_logincookie=$logincookie ; path=$cookiepath; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
|
||||
|
||||
# compat code. The cookie value is used for logouts, and that
|
||||
# isn't generic yet.
|
||||
$::COOKIE{'Bugzilla_logincookie'} = $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::Cookie;
|
||||
my $authmethod = "Cookie";
|
||||
|
||||
($authres, $userid, $extra) =
|
||||
Bugzilla::Auth::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) {
|
||||
$::vars->{'authmethod'} = lc($authmethod);
|
||||
$::vars->{'userid'} = $userid;
|
||||
$::vars->{'auth_err_tag'} = $extra;
|
||||
$::vars->{'info'} = $info;
|
||||
|
||||
&::ThrowCodeError("auth_err");
|
||||
}
|
||||
|
||||
# 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 "Content-Type: text/html\n\n";
|
||||
|
||||
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,
|
||||
}
|
||||
)
|
||||
|| &::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
|
||||
my $cookiepath = Param("cookiepath");
|
||||
print "Set-Cookie: Bugzilla_login= ; path=$cookiepath; expires=Sun, 30-Jun-80 00:00:00 GMT\n";
|
||||
print "Set-Cookie: Bugzilla_logincookie= ; path=$cookiepath; expires=Sun, 30-Jun-80 00:00:00 GMT\n";
|
||||
# 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,
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Bugzilla::Auth::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.
|
||||
|
||||
=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::Cookie>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Bugzilla::Auth>
|
||||
119
mozilla/webtools/bugzilla/Bugzilla/Auth/Cookie.pm
Normal file
119
mozilla/webtools/bugzilla/Bugzilla/Auth/Cookie.pm
Normal file
@ -0,0 +1,119 @@
|
||||
# -*- 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>
|
||||
|
||||
package Bugzilla::Auth::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=?";
|
||||
if (defined $netaddr) {
|
||||
trick_taint($netaddr);
|
||||
$query .= " OR logincookies.ipaddr=?";
|
||||
}
|
||||
$query .= ")";
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my ($userid, $disabledtext) = $dbh->selectrow_array($query, undef,
|
||||
$login_cookie,
|
||||
$login,
|
||||
$ipaddr,
|
||||
$netaddr);
|
||||
|
||||
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=NULL WHERE cookie=?",
|
||||
undef,
|
||||
$login_cookie);
|
||||
|
||||
# compat code. The cookie value is used for logouts, and that
|
||||
# isn't generic yet. Detaint it so that its usable
|
||||
detaint_natural($::COOKIE{'Bugzilla_logincookie'});
|
||||
|
||||
return (AUTH_OK, $userid);
|
||||
}
|
||||
|
||||
# If we get here, then the login failed.
|
||||
return (AUTH_LOGINFAILED);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Bugzilla::Cookie - cookie authentication for Bugzilla
|
||||
|
||||
=head1 SUMMARY
|
||||
|
||||
This is an L<authentication module|Bugzilla::Auth/"AUTHENTICATION"> for
|
||||
Bugzilla, which logs the user in using a persistent cookie stored in the
|
||||
C<logincookies> table.
|
||||
|
||||
The actual password is not stored in the cookie; only the userid and a
|
||||
I<logincookie> (which is used to reverify the login without requiring the
|
||||
password to be sent over the network) are. These I<logincookies> are
|
||||
restricted to certain IP addresses as a security meaure. The exact
|
||||
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.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Bugzilla::Auth>, L<Bugzilla::Auth::CGI>
|
||||
102
mozilla/webtools/bugzilla/Bugzilla/Auth/DB.pm
Normal file
102
mozilla/webtools/bugzilla/Bugzilla/Auth/DB.pm
Normal file
@ -0,0 +1,102 @@
|
||||
# -*- 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>
|
||||
|
||||
package Bugzilla::Auth::DB;
|
||||
|
||||
use strict;
|
||||
|
||||
use Bugzilla::Config;
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Util;
|
||||
|
||||
sub authenticate {
|
||||
my ($class, $username, $passwd) = @_;
|
||||
|
||||
return (AUTH_NODATA) unless defined $username && defined $passwd;
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
# We're just testing against the db, so any value is ok
|
||||
trick_taint($username);
|
||||
|
||||
# Retrieve the user's ID and crypted password from the database.
|
||||
my $sth = $dbh->prepare_cached("SELECT userid,cryptpassword,disabledtext " .
|
||||
"FROM profiles " .
|
||||
"WHERE login_name=?");
|
||||
my ($userid, $realcryptpwd, $disabledtext) =
|
||||
$dbh->selectrow_array($sth,
|
||||
undef,
|
||||
$username);
|
||||
|
||||
# If the user doesn't exist, return now
|
||||
return (AUTH_LOGINFAILED) unless defined $userid;
|
||||
|
||||
# OK, now authenticate the user
|
||||
|
||||
# Get the salt from the user's crypted password.
|
||||
my $salt = $realcryptpwd;
|
||||
|
||||
# Using the salt, crypt the password the user entered.
|
||||
my $enteredCryptedPassword = crypt($passwd, $salt);
|
||||
|
||||
# Make sure the passwords match or return an error
|
||||
return (AUTH_LOGINFAILED, $userid) unless
|
||||
($enteredCryptedPassword eq $realcryptpwd);
|
||||
|
||||
# Now we know that the user has logged in successfully,
|
||||
# so delete any password tokens for them
|
||||
require Token;
|
||||
Token::DeletePasswordTokens("user logged in");
|
||||
|
||||
# The user may have had their account disabled
|
||||
return (AUTH_DISABLED, $userid, $disabledtext)
|
||||
if $disabledtext ne '';
|
||||
|
||||
# If we get to here, then the user is allowed to login, so we're done!
|
||||
return (AUTH_OK, $userid);
|
||||
}
|
||||
|
||||
sub can_edit { return 1; }
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Bugzilla::DB - database authentication for Bugzilla
|
||||
|
||||
=head1 SUMMARY
|
||||
|
||||
This is an L<authentication module|Bugzilla::Auth/"AUTHENTICATION"> for
|
||||
Bugzilla, which logs the user in using the password stored in the C<profiles>
|
||||
table. This is the most commonly used authentication module.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Bugzilla::Auth>
|
||||
185
mozilla/webtools/bugzilla/Bugzilla/Auth/LDAP.pm
Normal file
185
mozilla/webtools/bugzilla/Bugzilla/Auth/LDAP.pm
Normal file
@ -0,0 +1,185 @@
|
||||
# -*- 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>
|
||||
|
||||
package Bugzilla::Auth::LDAP;
|
||||
|
||||
use strict;
|
||||
|
||||
use Bugzilla::Config;
|
||||
use Bugzilla::Constants;
|
||||
|
||||
use Net::LDAP;
|
||||
|
||||
sub authenticate {
|
||||
my ($class, $username, $passwd) = @_;
|
||||
|
||||
# If no password was provided, then fail the authentication.
|
||||
# While it may be valid to not have an LDAP password, when you
|
||||
# bind without a password (regardless of the binddn value), you
|
||||
# will get an anonymous bind. I do not know of a way to determine
|
||||
# whether a bind is anonymous or not without making changes to the
|
||||
# LDAP access control settings
|
||||
return (AUTH_NODATA) unless $username && $passwd;
|
||||
|
||||
# We need to bind anonymously to the LDAP server. This is
|
||||
# because we need to get the Distinguished Name of the user trying
|
||||
# to log in. Some servers (such as iPlanet) allow you to have unique
|
||||
# uids spread out over a subtree of an area (such as "People"), so
|
||||
# just appending the Base DN to the uid isn't sufficient to get the
|
||||
# user's DN. For servers which don't work this way, there will still
|
||||
# be no harm done.
|
||||
my $LDAPserver = Param("LDAPserver");
|
||||
if ($LDAPserver eq "") {
|
||||
return (AUTH_ERROR, undef, "server_not_defined");
|
||||
}
|
||||
|
||||
my $LDAPport = "389"; # default LDAP port
|
||||
if($LDAPserver =~ /:/) {
|
||||
($LDAPserver, $LDAPport) = split(":",$LDAPserver);
|
||||
}
|
||||
my $LDAPconn = Net::LDAP->new($LDAPserver, port => $LDAPport, version => 3);
|
||||
if(!$LDAPconn) {
|
||||
return (AUTH_ERROR, undef, "connect_failed");
|
||||
}
|
||||
|
||||
my $mesg;
|
||||
if (Param("LDAPbinddn")) {
|
||||
my ($LDAPbinddn,$LDAPbindpass) = split(":",Param("LDAPbinddn"));
|
||||
$mesg = $LDAPconn->bind($LDAPbinddn, password => $LDAPbindpass);
|
||||
}
|
||||
else {
|
||||
$mesg = $LDAPconn->bind();
|
||||
}
|
||||
if($mesg->code) {
|
||||
return (AUTH_ERROR, undef,
|
||||
"connect_failed",
|
||||
{ errstr => $mesg->err });
|
||||
}
|
||||
|
||||
# We've got our anonymous bind; let's look up this user.
|
||||
$mesg = $LDAPconn->search( base => Param("LDAPBaseDN"),
|
||||
scope => "sub",
|
||||
filter => Param("LDAPuidattribute") . "=$username",
|
||||
attrs => ['dn'],
|
||||
);
|
||||
return (AUTH_LOGINFAILED, undef, "lookup_failure")
|
||||
unless $mesg->count;
|
||||
|
||||
# Now we get the DN from this search.
|
||||
my $userDN = $mesg->shift_entry->dn;
|
||||
|
||||
# Now we attempt to bind as the specified user.
|
||||
$mesg = $LDAPconn->bind( $userDN, password => $passwd);
|
||||
|
||||
return (AUTH_LOGINFAILED) if $mesg->code;
|
||||
|
||||
# And now we're going to repeat the search, so that we can get the
|
||||
# mail attribute for this user.
|
||||
$mesg = $LDAPconn->search( base => Param("LDAPBaseDN"),
|
||||
scope => "sub",
|
||||
filter => Param("LDAPuidattribute") . "=$username",
|
||||
);
|
||||
my $user_entry = $mesg->shift_entry if !$mesg->code && $mesg->count;
|
||||
if(!$user_entry || !$user_entry->exists(Param("LDAPmailattribute"))) {
|
||||
return (AUTH_ERROR, undef,
|
||||
"cannot_retreive_attr",
|
||||
{ attr => Param("LDAPmailattribute") });
|
||||
}
|
||||
|
||||
# get the mail attribute
|
||||
$username = $user_entry->get_value(Param("LDAPmailattribute"));
|
||||
# OK, so now we know that the user is valid. Lets try finding them in the
|
||||
# Bugzilla database
|
||||
|
||||
# XXX - should this part be made more generic, and placed in
|
||||
# Bugzilla::Auth? Lots of login mechanisms may have to do this, although
|
||||
# until we actually get some more, its hard to know - BB
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $sth = $dbh->prepare_cached("SELECT userid, disabledtext " .
|
||||
"FROM profiles " .
|
||||
"WHERE login_name=?");
|
||||
my ($userid, $disabledtext) =
|
||||
$dbh->selectrow_array($sth,
|
||||
undef,
|
||||
$username);
|
||||
|
||||
# If the user doesn't exist, then they need to be added
|
||||
unless ($userid) {
|
||||
# We'll want the user's name for this.
|
||||
my $userRealName = $user_entry->get_value("displayName");
|
||||
if($userRealName eq "") {
|
||||
$userRealName = $user_entry->get_value("cn");
|
||||
}
|
||||
&::InsertNewUser($username, $userRealName);
|
||||
|
||||
my ($userid, $disabledtext) = $dbh->selectrow_array($sth,
|
||||
undef,
|
||||
$username);
|
||||
return (AUTH_ERROR, $userid, "no_userid")
|
||||
unless $userid;
|
||||
}
|
||||
|
||||
# we're done, so disconnect
|
||||
$LDAPconn->unbind;
|
||||
|
||||
# Test for disabled account
|
||||
return (AUTH_DISABLED, $userid, $disabledtext)
|
||||
if $disabledtext ne '';
|
||||
|
||||
# If we get to here, then the user is allowed to login, so we're done!
|
||||
return (AUTH_OK, $userid);
|
||||
}
|
||||
|
||||
sub can_edit { return 0; }
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Bugzilla::Auth::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.
|
||||
|
||||
=head1 DISCLAIMER
|
||||
|
||||
B<This module is experimental>. It is poorly documented, and not very flexible.
|
||||
Search L<http://bugzilla.mozilla.org/> for a list of known LDAP bugs.
|
||||
|
||||
None of the core Bugzilla developers, nor any of the large installations, use
|
||||
this module, and so it has received less testing. (In fact, this iteration
|
||||
hasn't been tested at all)
|
||||
|
||||
Patches are accepted.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Bugzilla::Auth>
|
||||
@ -186,6 +186,11 @@ sub UpdateParams {
|
||||
$param{'useentrygroupdefault'} = $param{'usebuggroupsentry'};
|
||||
}
|
||||
|
||||
# Modularise auth code
|
||||
if (exists $param{'useLDAP'} && !exists $param{'loginmethod'}) {
|
||||
$param{'loginmethod'} = $param{'useLDAP'} ? "LDAP" : "DB";
|
||||
}
|
||||
|
||||
# --- DEFAULTS FOR NEW PARAMS ---
|
||||
|
||||
foreach my $item (@param_list) {
|
||||
|
||||
@ -36,7 +36,17 @@ use base qw(Exporter);
|
||||
CONTROLMAPSHOWN
|
||||
CONTROLMAPDEFAULT
|
||||
CONTROLMAPMANDATORY
|
||||
);
|
||||
|
||||
AUTH_OK
|
||||
AUTH_NODATA
|
||||
AUTH_ERROR
|
||||
AUTH_LOGINFAILED
|
||||
AUTH_DISABLED
|
||||
|
||||
LOGIN_OPTIONAL
|
||||
LOGIN_NORMAL
|
||||
LOGIN_REQUIRED
|
||||
);
|
||||
|
||||
|
||||
# CONSTANTS
|
||||
@ -72,5 +82,16 @@ use constant CONTROLMAPSHOWN => 1;
|
||||
use constant CONTROLMAPDEFAULT => 2;
|
||||
use constant CONTROLMAPMANDATORY => 3;
|
||||
|
||||
1;
|
||||
# See Bugzilla::Auth for docs for these
|
||||
|
||||
use constant AUTH_OK => 0;
|
||||
use constant AUTH_NODATA => 1;
|
||||
use constant AUTH_ERROR => 2;
|
||||
use constant AUTH_LOGINFAILED => 3;
|
||||
use constant AUTH_DISABLED => 4;
|
||||
|
||||
use constant LOGIN_OPTIONAL => 0;
|
||||
use constant LOGIN_NORMAL => 1;
|
||||
use constant LOGIN_REQUIRED => 2;
|
||||
|
||||
1;
|
||||
|
||||
@ -61,8 +61,6 @@ our @SQLStateStack = ();
|
||||
sub SendSQL {
|
||||
my ($str) = @_;
|
||||
|
||||
require Bugzilla;
|
||||
|
||||
$_current_sth = Bugzilla->dbh->prepare($str);
|
||||
|
||||
$_current_sth->execute;
|
||||
@ -79,8 +77,6 @@ sub SqlQuote {
|
||||
# Backwards compat code
|
||||
return "''" if not defined $str;
|
||||
|
||||
require Bugzilla;
|
||||
|
||||
my $res = Bugzilla->dbh->quote($str);
|
||||
|
||||
trick_taint($res);
|
||||
@ -156,6 +152,7 @@ sub _connect {
|
||||
$db_pass,
|
||||
{ RaiseError => 1,
|
||||
PrintError => 0,
|
||||
ShowErrorStatement => 1,
|
||||
HandleError => \&_handle_error,
|
||||
FetchHashKeyName => 'NAME_lc',
|
||||
TaintIn => 1,
|
||||
|
||||
@ -237,16 +237,17 @@ sub Cancel {
|
||||
&::SendSQL("UNLOCK TABLES");
|
||||
}
|
||||
|
||||
sub HasPasswordToken {
|
||||
# Returns a password token if the user has one.
|
||||
sub DeletePasswordTokens {
|
||||
my ($userid, $reason) = @_;
|
||||
|
||||
my ($userid) = @_;
|
||||
|
||||
&::SendSQL("SELECT token FROM tokens
|
||||
WHERE userid = $userid AND tokentype = 'password' LIMIT 1");
|
||||
my ($token) = &::FetchSQLData();
|
||||
|
||||
return $token;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $sth = $dbh->prepare("SELECT token " .
|
||||
"FROM tokens " .
|
||||
"WHERE userid=? AND tokentype='password'");
|
||||
$sth->execute($userid);
|
||||
while (my $token = $sth->fetchrow_array) {
|
||||
Token::Cancel($token, "user_logged_in");
|
||||
}
|
||||
}
|
||||
|
||||
sub HasEmailChangeToken {
|
||||
|
||||
@ -34,12 +34,7 @@ use lib ".";
|
||||
|
||||
use Bugzilla::Util;
|
||||
use Bugzilla::Config;
|
||||
|
||||
# commented out the following snippet of code. this tosses errors into the
|
||||
# CGI if you are perl 5.6, and doesn't if you have perl 5.003.
|
||||
# We want to check for the existence of the LDAP modules here.
|
||||
# eval "use Mozilla::LDAP::Conn";
|
||||
# my $have_ldap = $@ ? 0 : 1;
|
||||
use Bugzilla::Constants;
|
||||
|
||||
# Shut up misguided -w warnings about "used only once". For some reason,
|
||||
# "use vars" chokes on me when I try it here.
|
||||
@ -202,82 +197,8 @@ sub PasswordForLogin {
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub get_netaddr {
|
||||
my ($ipaddr) = @_;
|
||||
|
||||
# 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');
|
||||
|
||||
$addr >>= (32-$maskbits);
|
||||
$addr <<= (32-$maskbits);
|
||||
return join(".", unpack("CCCC", pack("N", $addr)));
|
||||
}
|
||||
|
||||
my $login_cookie_set = 0;
|
||||
# If quietly_check_login is called with no arguments and logins are
|
||||
# required, it will prompt for a login.
|
||||
sub quietly_check_login {
|
||||
if (Param('requirelogin') && !(@_)) {
|
||||
return confirm_login();
|
||||
}
|
||||
$::disabledreason = '';
|
||||
my $userid = 0;
|
||||
my $ipaddr = $ENV{'REMOTE_ADDR'};
|
||||
my $netaddr = get_netaddr($ipaddr);
|
||||
if (defined $::COOKIE{"Bugzilla_login"} &&
|
||||
defined $::COOKIE{"Bugzilla_logincookie"}) {
|
||||
my $query = "SELECT profiles.userid," .
|
||||
" profiles.login_name, " .
|
||||
" profiles.disabledtext " .
|
||||
" FROM profiles, logincookies WHERE logincookies.cookie = " .
|
||||
SqlQuote($::COOKIE{"Bugzilla_logincookie"}) .
|
||||
" AND profiles.userid = logincookies.userid AND" .
|
||||
" profiles.login_name = " .
|
||||
SqlQuote($::COOKIE{"Bugzilla_login"}) .
|
||||
" AND (logincookies.ipaddr = " .
|
||||
SqlQuote($ipaddr);
|
||||
if (defined $netaddr) {
|
||||
$query .= " OR logincookies.ipaddr = " . SqlQuote($netaddr);
|
||||
}
|
||||
$query .= ")";
|
||||
SendSQL($query);
|
||||
|
||||
my @row;
|
||||
if (MoreSQLData()) {
|
||||
($userid, my $loginname, my $disabledtext) = FetchSQLData();
|
||||
if ($userid > 0) {
|
||||
if ($disabledtext eq '') {
|
||||
$::COOKIE{"Bugzilla_login"} = $loginname; # Makes sure case
|
||||
# is in
|
||||
# canonical form.
|
||||
# We've just verified that this is ok
|
||||
detaint_natural($::COOKIE{"Bugzilla_logincookie"});
|
||||
} else {
|
||||
$::disabledreason = $disabledtext;
|
||||
$userid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# if 'who' is passed in, verify that it's a good value
|
||||
if ($::FORM{'who'}) {
|
||||
my $whoid = DBname_to_id($::FORM{'who'});
|
||||
delete $::FORM{'who'} unless $whoid;
|
||||
}
|
||||
if (!$userid) {
|
||||
delete $::COOKIE{"Bugzilla_login"};
|
||||
}
|
||||
|
||||
$::userid = $userid;
|
||||
ConfirmGroup($userid);
|
||||
$vars->{'user'} = GetUserInfo($::userid);
|
||||
return $userid;
|
||||
return Bugzilla->login($_[0] ? LOGIN_OPTIONAL : LOGIN_NORMAL);
|
||||
}
|
||||
|
||||
# Populate a hash with information about this user.
|
||||
@ -351,281 +272,7 @@ sub MailPassword {
|
||||
}
|
||||
|
||||
sub confirm_login {
|
||||
my ($nexturl) = (@_);
|
||||
|
||||
# Uncommenting the next line can help debugging...
|
||||
# print "Content-type: text/plain\n\n";
|
||||
|
||||
# I'm going to reorganize some of this stuff a bit. Since we're adding
|
||||
# a second possible validation method (LDAP), we need to move some of this
|
||||
# to a later section. -Joe Robins, 8/3/00
|
||||
my $enteredlogin = "";
|
||||
my $realcryptpwd = "";
|
||||
my $userid;
|
||||
|
||||
# If the form contains Bugzilla login and password fields, use Bugzilla's
|
||||
# built-in authentication to authenticate the user (otherwise use LDAP below).
|
||||
if (defined $::FORM{"Bugzilla_login"} && defined $::FORM{"Bugzilla_password"}) {
|
||||
# Make sure the user's login name is a valid email address.
|
||||
$enteredlogin = $::FORM{"Bugzilla_login"};
|
||||
CheckEmailSyntax($enteredlogin);
|
||||
|
||||
# Retrieve the user's ID and crypted password from the database.
|
||||
SendSQL("SELECT userid, cryptpassword FROM profiles
|
||||
WHERE login_name = " . SqlQuote($enteredlogin));
|
||||
($userid, $realcryptpwd) = FetchSQLData();
|
||||
|
||||
# Make sure the user exists or throw an error (but do not admit it was a username
|
||||
# error to make it harder for a cracker to find account names by brute force).
|
||||
$userid || ThrowUserError("invalid_username_or_password");
|
||||
|
||||
# If this is a new user, generate a password, insert a record
|
||||
# into the database, and email their password to them.
|
||||
if ( defined $::FORM{"PleaseMailAPassword"} && !$userid ) {
|
||||
# Ensure the new login is valid
|
||||
if(!ValidateNewUser($enteredlogin)) {
|
||||
ThrowUserError("account_exists");
|
||||
}
|
||||
|
||||
my $password = InsertNewUser($enteredlogin, "");
|
||||
MailPassword($enteredlogin, $password);
|
||||
|
||||
$vars->{'login'} = $enteredlogin;
|
||||
|
||||
print "Content-Type: text/html\n\n";
|
||||
$template->process("account/created.html.tmpl", $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
}
|
||||
|
||||
# Otherwise, authenticate the user.
|
||||
else {
|
||||
# Get the salt from the user's crypted password.
|
||||
my $salt = $realcryptpwd;
|
||||
|
||||
# Using the salt, crypt the password the user entered.
|
||||
my $enteredCryptedPassword = crypt( $::FORM{"Bugzilla_password"} , $salt );
|
||||
|
||||
# Make sure the passwords match or throw an error.
|
||||
($enteredCryptedPassword eq $realcryptpwd)
|
||||
|| ThrowUserError("invalid_username_or_password");
|
||||
|
||||
# If the user has successfully logged in, delete any password tokens
|
||||
# lying around in the system for them.
|
||||
use Token;
|
||||
my $token = Token::HasPasswordToken($userid);
|
||||
while ( $token ) {
|
||||
Token::Cancel($token, 'user_logged_in');
|
||||
$token = Token::HasPasswordToken($userid);
|
||||
}
|
||||
}
|
||||
|
||||
} elsif (Param("useLDAP") &&
|
||||
defined $::FORM{"LDAP_login"} &&
|
||||
defined $::FORM{"LDAP_password"}) {
|
||||
# If we're using LDAP for login, we've got an entirely different
|
||||
# set of things to check.
|
||||
|
||||
# see comment at top of file near eval
|
||||
# First, if we don't have the LDAP modules available to us, we can't
|
||||
# do this.
|
||||
# if(!$have_ldap) {
|
||||
# print "Content-type: text/html\n\n";
|
||||
# PutHeader("LDAP not enabled");
|
||||
# print "The necessary modules for LDAP login are not installed on ";
|
||||
# print "this machine. Please send mail to ".Param("maintainer");
|
||||
# print " and notify him of this problem.\n";
|
||||
# PutFooter();
|
||||
# exit;
|
||||
# }
|
||||
|
||||
# Next, we need to bind anonymously to the LDAP server. This is
|
||||
# because we need to get the Distinguished Name of the user trying
|
||||
# to log in. Some servers (such as iPlanet) allow you to have unique
|
||||
# uids spread out over a subtree of an area (such as "People"), so
|
||||
# just appending the Base DN to the uid isn't sufficient to get the
|
||||
# user's DN. For servers which don't work this way, there will still
|
||||
# be no harm done.
|
||||
my $LDAPserver = Param("LDAPserver");
|
||||
if ($LDAPserver eq "") {
|
||||
print "Content-type: text/html\n\n";
|
||||
PutHeader("LDAP server not defined");
|
||||
print "The LDAP server for authentication has not been defined. ";
|
||||
print "Please contact ".Param("maintainer")." ";
|
||||
print "and notify him of this problem.\n";
|
||||
PutFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
my $LDAPport = "389"; #default LDAP port
|
||||
if($LDAPserver =~ /:/) {
|
||||
($LDAPserver, $LDAPport) = split(":",$LDAPserver);
|
||||
}
|
||||
my $LDAPconn = new Mozilla::LDAP::Conn($LDAPserver,$LDAPport);
|
||||
if(!$LDAPconn) {
|
||||
print "Content-type: text/html\n\n";
|
||||
PutHeader("Unable to connect to LDAP server");
|
||||
print "I was unable to connect to the LDAP server for user ";
|
||||
print "authentication. Please contact ".Param("maintainer");
|
||||
print " and notify him of this problem.\n";
|
||||
PutFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
# if no password was provided, then fail the authentication
|
||||
# while it may be valid to not have an LDAP password, when you
|
||||
# bind without a password (regardless of the binddn value), you
|
||||
# will get an anonymous bind. I do not know of a way to determine
|
||||
# whether a bind is anonymous or not without making changes to the
|
||||
# LDAP access control settings
|
||||
if ( ! $::FORM{"LDAP_password"} ) {
|
||||
print "Content-type: text/html\n\n";
|
||||
PutHeader("Login Failed");
|
||||
print "You did not provide a password.\n";
|
||||
print "Please click <b>Back</b> and try again.\n";
|
||||
PutFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
# We've got our anonymous bind; let's look up this user.
|
||||
my $dnEntry = $LDAPconn->search(Param("LDAPBaseDN"),"subtree","uid=".$::FORM{"LDAP_login"});
|
||||
if(!$dnEntry) {
|
||||
print "Content-type: text/html\n\n";
|
||||
PutHeader("Login Failed");
|
||||
print "The username or password you entered is not valid.\n";
|
||||
print "Please click <b>Back</b> and try again.\n";
|
||||
PutFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
# Now we get the DN from this search. Once we've got that, we're
|
||||
# done with the anonymous bind, so we close it.
|
||||
my $userDN = $dnEntry->getDN;
|
||||
$LDAPconn->close;
|
||||
|
||||
# Now we attempt to bind as the specified user.
|
||||
$LDAPconn = new Mozilla::LDAP::Conn($LDAPserver,$LDAPport,$userDN,$::FORM{"LDAP_password"});
|
||||
if(!$LDAPconn) {
|
||||
print "Content-type: text/html\n\n";
|
||||
PutHeader("Login Failed");
|
||||
print "The username or password you entered is not valid.\n";
|
||||
print "Please click <b>Back</b> and try again.\n";
|
||||
PutFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
# And now we're going to repeat the search, so that we can get the
|
||||
# mail attribute for this user.
|
||||
my $userEntry = $LDAPconn->search(Param("LDAPBaseDN"),"subtree","uid=".$::FORM{"LDAP_login"});
|
||||
if(!$userEntry->exists(Param("LDAPmailattribute"))) {
|
||||
print "Content-type: text/html\n\n";
|
||||
PutHeader("LDAP authentication error");
|
||||
print "I was unable to retrieve the ".Param("LDAPmailattribute");
|
||||
print " attribute from the LDAP server. Please contact ";
|
||||
print Param("maintainer")." and notify him of this error.\n";
|
||||
PutFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
# Mozilla::LDAP::Entry->getValues returns an array for the attribute
|
||||
# requested, even if there's only one entry.
|
||||
$enteredlogin = ($userEntry->getValues(Param("LDAPmailattribute")))[0];
|
||||
|
||||
# We're going to need the cryptpwd for this user from the database
|
||||
# so that we can set the cookie below, even though we're not going
|
||||
# to use it for authentication.
|
||||
$realcryptpwd = PasswordForLogin($enteredlogin);
|
||||
|
||||
# If we don't get a result, then we've got a user who isn't in
|
||||
# Bugzilla's database yet, so we've got to add them.
|
||||
if($realcryptpwd eq "") {
|
||||
# We'll want the user's name for this.
|
||||
my $userRealName = ($userEntry->getValues("displayName"))[0];
|
||||
if($userRealName eq "") {
|
||||
$userRealName = ($userEntry->getValues("cn"))[0];
|
||||
}
|
||||
InsertNewUser($enteredlogin, $userRealName);
|
||||
$realcryptpwd = PasswordForLogin($enteredlogin);
|
||||
}
|
||||
} # end LDAP authentication
|
||||
|
||||
# And now, if we've logged in via either method, then we need to set
|
||||
# the cookies.
|
||||
if($enteredlogin ne "") {
|
||||
$::COOKIE{"Bugzilla_login"} = $enteredlogin;
|
||||
my $ipaddr = $ENV{'REMOTE_ADDR'};
|
||||
|
||||
# Unless we're restricting the login, or restricting would have no
|
||||
# effect, loosen the IP which we record in the table
|
||||
unless ($::FORM{'Bugzilla_restrictlogin'} ||
|
||||
Param('loginnetmask') == 32) {
|
||||
$ipaddr = get_netaddr($ipaddr);
|
||||
$ipaddr = $ENV{'REMOTE_ADDR'} unless defined $ipaddr;
|
||||
}
|
||||
SendSQL("insert into logincookies (userid,ipaddr) values (@{[DBNameToIdAndCheck($enteredlogin)]}, @{[SqlQuote($ipaddr)]})");
|
||||
SendSQL("select LAST_INSERT_ID()");
|
||||
my $logincookie = FetchOneColumn();
|
||||
|
||||
$::COOKIE{"Bugzilla_logincookie"} = $logincookie;
|
||||
my $cookiepath = Param("cookiepath");
|
||||
if ($login_cookie_set == 0) {
|
||||
$login_cookie_set = 1;
|
||||
print "Set-Cookie: Bugzilla_login= " . url_quote($enteredlogin) . " ; path=$cookiepath; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
|
||||
print "Set-Cookie: Bugzilla_logincookie=$logincookie ; path=$cookiepath; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
|
||||
}
|
||||
}
|
||||
|
||||
# If anonymous logins are disabled, quietly_check_login will force
|
||||
# the user to log in by calling confirm_login() when called by any
|
||||
# code that does not call it with an argument. When confirm_login
|
||||
# calls quietly_check_login, it must not result in confirm_login
|
||||
# being called back.
|
||||
$userid = quietly_check_login('do_not_recurse_here');
|
||||
|
||||
if (!$userid) {
|
||||
if ($::disabledreason) {
|
||||
my $cookiepath = Param("cookiepath");
|
||||
print "Set-Cookie: Bugzilla_login= ; path=$cookiepath; expires=Sun, 30-Jun-80 00:00:00 GMT
|
||||
Set-Cookie: Bugzilla_logincookie= ; path=$cookiepath; expires=Sun, 30-Jun-80 00:00:00 GMT
|
||||
Content-type: text/html
|
||||
|
||||
";
|
||||
$vars->{'disabled_reason'} = $::disabledreason;
|
||||
ThrowUserError("account_disabled");
|
||||
}
|
||||
|
||||
if (!defined $nexturl || $nexturl eq "") {
|
||||
# Sets nexturl to be argv0, stripping everything up to and
|
||||
# including the last slash (or backslash on Windows).
|
||||
$0 =~ m:([^/\\]*)$:;
|
||||
$nexturl = $1;
|
||||
}
|
||||
|
||||
$vars->{'target'} = $nexturl;
|
||||
$vars->{'form'} = \%::FORM;
|
||||
$vars->{'mform'} = \%::MFORM;
|
||||
|
||||
print "Content-type: text/html\n\n";
|
||||
$template->process("account/login.html.tmpl", $vars)
|
||||
|| 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.
|
||||
if (Bugzilla->dbwritesallowed) {
|
||||
SendSQL("DELETE FROM logincookies " .
|
||||
"WHERE TO_DAYS(NOW()) - TO_DAYS(lastused) > 30");
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
# Update the timestamp on our logincookie, so it'll keep on working.
|
||||
if (Bugzilla->dbwritesallowed) {
|
||||
SendSQL("UPDATE logincookies SET lastused = null " .
|
||||
"WHERE cookie = $::COOKIE{'Bugzilla_logincookie'}");
|
||||
}
|
||||
ConfirmGroup($userid);
|
||||
return $userid;
|
||||
return Bugzilla->login(LOGIN_REQUIRED);
|
||||
}
|
||||
|
||||
sub PutHeader {
|
||||
@ -660,13 +307,18 @@ sub ThrowCodeError {
|
||||
|
||||
SendSQL("UNLOCK TABLES") if $unlock_tables;
|
||||
|
||||
# Copy the extra_vars into the vars hash
|
||||
foreach my $var (keys %$extra_vars) {
|
||||
$vars->{$var} = $extra_vars->{$var};
|
||||
}
|
||||
# If we don't have this test here, then the %@extra_vars vivifies
|
||||
# the hashref, and then setting $vars->{'variables'} uses an empty hashref
|
||||
# so the error template prints out a bogus header for the empty hash
|
||||
if (defined $extra_vars) {
|
||||
# Copy the extra_vars into the vars hash
|
||||
foreach my $var (keys %$extra_vars) {
|
||||
$vars->{$var} = $extra_vars->{$var};
|
||||
}
|
||||
|
||||
# We may one day log something to file here also.
|
||||
$vars->{'variables'} = $extra_vars;
|
||||
# We may one day log something to file here also.
|
||||
$vars->{'variables'} = $extra_vars;
|
||||
}
|
||||
|
||||
print "Content-type: text/html\n\n" if !$vars->{'header_done'};
|
||||
$template->process("global/code-error.html.tmpl", $vars)
|
||||
|
||||
@ -237,16 +237,17 @@ sub Cancel {
|
||||
&::SendSQL("UNLOCK TABLES");
|
||||
}
|
||||
|
||||
sub HasPasswordToken {
|
||||
# Returns a password token if the user has one.
|
||||
sub DeletePasswordTokens {
|
||||
my ($userid, $reason) = @_;
|
||||
|
||||
my ($userid) = @_;
|
||||
|
||||
&::SendSQL("SELECT token FROM tokens
|
||||
WHERE userid = $userid AND tokentype = 'password' LIMIT 1");
|
||||
my ($token) = &::FetchSQLData();
|
||||
|
||||
return $token;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $sth = $dbh->prepare("SELECT token " .
|
||||
"FROM tokens " .
|
||||
"WHERE userid=? AND tokentype='password'");
|
||||
$sth->execute($userid);
|
||||
while (my $token = $sth->fetchrow_array) {
|
||||
Token::Cancel($token, "user_logged_in");
|
||||
}
|
||||
}
|
||||
|
||||
sub HasEmailChangeToken {
|
||||
|
||||
@ -674,28 +674,6 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Global Utility Library
|
||||
###########################################################################
|
||||
|
||||
# globals.pl clears the PATH, but File::Find uses Cwd::cwd() instead of
|
||||
# Cwd::getcwd(), which we need to do because `pwd` isn't in the path - see
|
||||
# http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2001-09/msg00115.html
|
||||
# As a workaround, since we only use File::Find in checksetup, which doesn't
|
||||
# run in taint mode anyway, preserve the path...
|
||||
my $origPath = $::ENV{'PATH'};
|
||||
|
||||
# Use the Bugzilla utility library for various functions. We do this
|
||||
# here rather than at the top of the file so globals.pl doesn't define
|
||||
# localconfig variables for us before we get a chance to check for
|
||||
# their existence and create them if they don't exist. Also, globals.pl
|
||||
# removes $ENV{'path'}, which we need in order to run `which mysql` above.
|
||||
require "globals.pl";
|
||||
|
||||
# ...and restore it. This doesn't change tainting, so this will still cause
|
||||
# errors if this script ever does run with -T.
|
||||
$::ENV{'PATH'} = $origPath;
|
||||
|
||||
###########################################################################
|
||||
# Check data directory
|
||||
###########################################################################
|
||||
@ -1215,6 +1193,33 @@ if ($my_webservergroup) {
|
||||
chmod 01777, 'graphs';
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Global Utility Library
|
||||
###########################################################################
|
||||
|
||||
# This is done here, because some modules require params to be set up, which
|
||||
# won't have happened earlier.
|
||||
|
||||
# The only use for loading globals.pl is for Crypt(), which should at some
|
||||
# point probably be factored out into Bugzilla::Auth::*
|
||||
|
||||
# globals.pl clears the PATH, but File::Find uses Cwd::cwd() instead of
|
||||
# Cwd::getcwd(), which we need to do because `pwd` isn't in the path - see
|
||||
# http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2001-09/msg00115.html
|
||||
# As a workaround, since we only use File::Find in checksetup, which doesn't
|
||||
# run in taint mode anyway, preserve the path...
|
||||
my $origPath = $::ENV{'PATH'};
|
||||
|
||||
# Use the Bugzilla utility library for various functions. We do this
|
||||
# here rather than at the top of the file so globals.pl doesn't define
|
||||
# localconfig variables for us before we get a chance to check for
|
||||
# their existence and create them if they don't exist. Also, globals.pl
|
||||
# removes $ENV{'path'}, which we need in order to run `which mysql` above.
|
||||
require "globals.pl";
|
||||
|
||||
# ...and restore it. This doesn't change tainting, so this will still cause
|
||||
# errors if this script ever does run with -T.
|
||||
$::ENV{'PATH'} = $origPath;
|
||||
|
||||
###########################################################################
|
||||
# Check MySQL setup
|
||||
@ -1300,6 +1305,16 @@ my $dbh = DBI->connect($connectstring, $my_db_user, $my_db_pass)
|
||||
|
||||
END { $dbh->disconnect if $dbh }
|
||||
|
||||
###########################################################################
|
||||
# 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";
|
||||
}
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Check GraphViz setup
|
||||
|
||||
@ -40,11 +40,11 @@ use vars qw(
|
||||
ConnectToDatabase();
|
||||
|
||||
# If we're using LDAP for login, then we can't create a new account here.
|
||||
if(Param('useLDAP')) {
|
||||
unless (Bugzilla::Auth->can_edit) {
|
||||
# Just in case someone already has an account, let them get the correct
|
||||
# footer on the error message
|
||||
quietly_check_login();
|
||||
ThrowUserError("ldap_cant_create_account");
|
||||
ThrowUserError("auth_cant_create_account");
|
||||
}
|
||||
|
||||
# Clear out the login cookies. Make people log in again if they create an
|
||||
|
||||
@ -123,6 +123,31 @@ sub check_netmask {
|
||||
return "";
|
||||
}
|
||||
|
||||
sub check_loginmethod {
|
||||
# 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
|
||||
# params mutually dependant on each other.
|
||||
# This means that if someone clears the LDAP config params after setting
|
||||
# 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";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
# OK, here are the parameter definitions themselves.
|
||||
#
|
||||
# Each definition is a hash with keys:
|
||||
@ -322,16 +347,6 @@ sub check_netmask {
|
||||
checker => \&check_shadowdb
|
||||
},
|
||||
|
||||
{
|
||||
name => 'useLDAP',
|
||||
desc => 'Turn this on to use an LDAP directory for user authentication ' .
|
||||
'instead of the Bugzilla database. (User profiles will still be ' .
|
||||
'stored in the database, and will match against the LDAP user by ' .
|
||||
'email address.)',
|
||||
type => 'b',
|
||||
default => 0
|
||||
},
|
||||
|
||||
{
|
||||
name => 'LDAPserver',
|
||||
desc => 'The name (and optionally port) of your LDAP server. (e.g. ' .
|
||||
@ -340,6 +355,16 @@ sub check_netmask {
|
||||
default => ''
|
||||
},
|
||||
|
||||
{
|
||||
name => 'LDAPbinddn',
|
||||
desc => 'If your LDAP server requires that you use a binddn and password ' .
|
||||
'instead of binding anonymously, enter it here ' .
|
||||
'(e.g. cn=default,cn=user:password). ' .
|
||||
'Leave this empty for the normal case of an anonymous bind.',
|
||||
type => 't',
|
||||
default => ''
|
||||
},
|
||||
|
||||
{
|
||||
name => 'LDAPBaseDN',
|
||||
desc => 'The BaseDN for authenticating users against. (e.g. ' .
|
||||
@ -348,6 +373,13 @@ sub check_netmask {
|
||||
default => ''
|
||||
},
|
||||
|
||||
{
|
||||
name => 'LDAPuidattribute',
|
||||
desc => 'The name of the attribute containing the user\'s login name.',
|
||||
type => 't',
|
||||
default => 'uid'
|
||||
},
|
||||
|
||||
{
|
||||
name => 'LDAPmailattribute',
|
||||
desc => 'The name of the attribute of a user in your directory that ' .
|
||||
@ -356,6 +388,29 @@ sub check_netmask {
|
||||
default => 'mail'
|
||||
},
|
||||
|
||||
{
|
||||
name => 'loginmethod',
|
||||
desc => 'The type of login authentication to use:
|
||||
<dl>
|
||||
<dt>DB</dt>
|
||||
<dd>
|
||||
Bugzilla\'s builtin authentication. This is the most common
|
||||
choice.
|
||||
</dd>
|
||||
<dt>LDAP</dt>
|
||||
<dd>
|
||||
LDAP authentication using an LDAP server. This method is
|
||||
experimental; please see the Bugzilla documentation for more
|
||||
information. Using this method requires additional parameters
|
||||
to be set above.
|
||||
</dd>
|
||||
</dl>',
|
||||
type => 's',
|
||||
choices => [ 'DB', 'LDAP' ],
|
||||
default => 'DB',
|
||||
checker => \&check_loginmethod
|
||||
},
|
||||
|
||||
{
|
||||
name => 'mostfreqthreshold',
|
||||
desc => 'The minimum number of duplicates a bug needs to show up on the ' .
|
||||
|
||||
@ -110,8 +110,8 @@ sub EmitFormElements ($$$$)
|
||||
if ($editall) {
|
||||
print "</TR><TR>\n";
|
||||
print " <TH ALIGN=\"right\">Password:</TH>\n";
|
||||
if(Param('useLDAP')) {
|
||||
print " <TD><FONT COLOR=RED>This site is using LDAP for authentication!</FONT></TD>\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>
|
||||
@ -357,7 +357,7 @@ if ($action eq 'list') {
|
||||
}
|
||||
print "</TR>";
|
||||
}
|
||||
if ($editall && !Param('useLDAP')) {
|
||||
if ($editall && Bugzilla::Auth->can_edit) {
|
||||
print "<TR>\n";
|
||||
my $span = $candelete ? 3 : 2;
|
||||
print qq{
|
||||
@ -391,9 +391,8 @@ if ($action eq 'add') {
|
||||
exit;
|
||||
}
|
||||
|
||||
if(Param('useLDAP')) {
|
||||
print "This site is using LDAP for authentication. To add a new user, ";
|
||||
print "please contact the LDAP administrators.";
|
||||
if(!Bugzilla::Auth->can_edit) {
|
||||
print "The authentication mechanism you are using does not permit accounts to be created from Bugzilla";
|
||||
PutTrailer();
|
||||
exit;
|
||||
}
|
||||
@ -429,9 +428,8 @@ if ($action eq 'new') {
|
||||
exit;
|
||||
}
|
||||
|
||||
if(Param('useLDAP')) {
|
||||
print "This site is using LDAP for authentication. To add a new user, ";
|
||||
print "please contact the LDAP administrators.";
|
||||
if (!Bugzilla::Auth->can_edit) {
|
||||
print "This site's authentication mechanism does not allow new users to be added.";
|
||||
PutTrailer();
|
||||
exit;
|
||||
}
|
||||
@ -791,7 +789,7 @@ if ($action eq 'update') {
|
||||
|
||||
|
||||
# Update the database with the user's new password if they changed it.
|
||||
if ( !Param('useLDAP') && $editall && $password ) {
|
||||
if ( Bugzilla::Auth->can_edit && $editall && $password ) {
|
||||
my $passworderror = ValidatePassword($password);
|
||||
if ( !$passworderror ) {
|
||||
my $cryptpassword = SqlQuote(Crypt($password));
|
||||
|
||||
@ -29,12 +29,13 @@ package Support::Files;
|
||||
@additional_files = ();
|
||||
%exclude_deps = (
|
||||
'XML::Parser' => ['importxml.pl'],
|
||||
'Net::LDAP' => ['Bugzilla/Auth/LDAP.pm'],
|
||||
);
|
||||
|
||||
|
||||
# XXX - this file should be rewritten to use File::Find or similar
|
||||
# XXX - this file should really be rewritten to use File::Find or similar
|
||||
$file = '*';
|
||||
@files = (glob($file), glob('Bugzilla/*.pm'));
|
||||
@files = (glob($file), glob('Bugzilla/*.pm'), glob('Bugzilla/*/*.pm'));
|
||||
|
||||
sub have_pkg {
|
||||
my ($pkg) = @_;
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
[%# 1.0@bugzilla.org %]
|
||||
[%# 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>
|
||||
#%]
|
||||
|
||||
[%# INTERFACE:
|
||||
# auth_err_tag: string. The tag for the error
|
||||
# info: hash. Additional variables which may be used when printing details
|
||||
# of the error.
|
||||
#%]
|
||||
|
||||
[% SWITCH auth_err_tag %]
|
||||
[% CASE "cannot_retreive_attr" %]
|
||||
The specified LDAP attribute [% info.attr FILTER html %] was not found.
|
||||
|
||||
[% CASE "connect_failed" %]
|
||||
An error occurred while trying to connect to the LDAP server.
|
||||
[% IF info.errstr %]
|
||||
The error from the server was: <tt>[% info.errstr FILTER html %]</tt>.
|
||||
[% END %]
|
||||
|
||||
[% CASE "no_userid" %]
|
||||
Bugzilla created a new account for you, but then could not find the
|
||||
new userid.
|
||||
|
||||
[% CASE "server_not_defined" %]
|
||||
The LDAP server for authentication has not been defined.
|
||||
|
||||
[% CASE %]
|
||||
Unhandled authentication error: [% auth_err_tag FILTER html %]
|
||||
|
||||
[% END %]
|
||||
@ -31,45 +31,26 @@
|
||||
%]
|
||||
|
||||
<p>
|
||||
I need a legitimate
|
||||
[% Param('useLDAP') ? "LDAP username" : "email address" %]
|
||||
and password to continue.
|
||||
I need a legitimate login and password to continue.
|
||||
</p>
|
||||
|
||||
<form action="[% target %]" method="POST">
|
||||
<table>
|
||||
<tr>
|
||||
[% IF Param("useLDAP") %]
|
||||
<td align="right">
|
||||
<b>Username:</b>
|
||||
</td>
|
||||
<td>
|
||||
<input size="10" name="LDAP_login">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<b>Password:</b>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" size="10" name="LDAP_password">
|
||||
</td>
|
||||
[% ELSE %]
|
||||
<td align="right">
|
||||
<b>E-mail address:</b>
|
||||
</td>
|
||||
<td>
|
||||
<input size="35" name="Bugzilla_login">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<b>Password:</b>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" size="35" name="Bugzilla_password">
|
||||
</td>
|
||||
[% END %]
|
||||
<td align="right">
|
||||
<b>Login:</b>
|
||||
</td>
|
||||
<td>
|
||||
<input size="35" name="Bugzilla_login">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<b>Password:</b>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" size="35" name="Bugzilla_password">
|
||||
</td>
|
||||
[% IF Param('loginnetmask') < 32 %]
|
||||
<tr>
|
||||
<td align="right">
|
||||
@ -89,17 +70,16 @@
|
||||
</table>
|
||||
|
||||
[% PROCESS "global/hidden-fields.html.tmpl"
|
||||
exclude="^(Bugzilla|LDAP)_(login|password)$" %]
|
||||
exclude="^Bugzilla_(login|password|restrictlogin)$" %]
|
||||
|
||||
<input type="submit" name="GoAheadAndLogIn" value="Login">
|
||||
</form>
|
||||
|
||||
[%# Allow the user to create a new account, or request a token to change
|
||||
# their password (unless we are using LDAP, in which case the user must
|
||||
# use LDAP to change it).
|
||||
# their password, assuming that our auth method allows that.
|
||||
#%]
|
||||
|
||||
[% UNLESS Param("useLDAP") %]
|
||||
[% IF caneditaccount %]
|
||||
<hr>
|
||||
|
||||
[% IF Param("createemailregexp") %]
|
||||
@ -36,7 +36,7 @@ group '[% group.name FILTER html %]' impacts [% group.count %] bugs for which th
|
||||
[% END %]
|
||||
<form method="post" >
|
||||
|
||||
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^(Bugzilla|LDAP)_(login|password)$" %]
|
||||
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^Bugzilla_(login|password)$" %]
|
||||
|
||||
<br>
|
||||
Click "Continue" to proceed with the change including the changes
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
|
||||
<form method="post" action="process_bug.cgi">
|
||||
|
||||
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^(Bugzilla|LDAP)_(login|password)$" %]
|
||||
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^Bugzilla_(login|password)$" %]
|
||||
|
||||
<p>
|
||||
<input type="radio" name="confirm_add_duplicate" value="1">
|
||||
|
||||
@ -65,7 +65,7 @@ You have the following choices:
|
||||
<ul>
|
||||
<li>
|
||||
<form method="post" action="process_bug.cgi">
|
||||
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^(Bugzilla|LDAP)_(login|password)$" %]
|
||||
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^Bugzilla_(login|password)$" %]
|
||||
<input type="submit" value="Submit my changes anyway">
|
||||
This will cause all of the above changes to be overwritten
|
||||
[% ", except for the added comment(s)" IF comments.size > start_at %].
|
||||
|
||||
@ -48,6 +48,16 @@
|
||||
Attachment #[% attachid FILTER html %] ([% description FILTER html %])
|
||||
is already obsolete.
|
||||
|
||||
[% ELSIF error == "auth_err" %]
|
||||
[% title = "Internal Authentication Error" %]
|
||||
[%# Authentication errors are in a template depending on the auth method,
|
||||
for pluggability.
|
||||
#%]
|
||||
[% INCLUDE "account/auth/$authmethod-error.html.tmpl" %]
|
||||
|
||||
[% ELSIF error == "authres_unhandled" %]
|
||||
An authorization handler return value was not handled by the login code.
|
||||
|
||||
[% ELSIF error == "bug_error" %]
|
||||
Trying to retrieve bug [% bug.bug_id %] returned the error
|
||||
[% bug.error FILTER html %]
|
||||
|
||||
@ -155,7 +155,7 @@
|
||||
|
||||
[% IF matchsuccess == 1 %]
|
||||
|
||||
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^(Bugzilla|LDAP)_(login|password)$" %]
|
||||
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^Bugzilla_(login|password)$" %]
|
||||
|
||||
<p>
|
||||
<input type="submit" value="Continue">
|
||||
|
||||
@ -92,6 +92,12 @@
|
||||
Bug aliases cannot be longer than 20 characters.
|
||||
Please choose a shorter alias.
|
||||
|
||||
[% ELSIF error == "auth_cant_create_account" %]
|
||||
[% title = "Can't create accounts" %]
|
||||
This site is using an authentication scheme which does not permit
|
||||
account creation. Please contact an administrator to get a new account
|
||||
created.
|
||||
|
||||
[% ELSIF error == "authorization_failure" %]
|
||||
[% title = "Authorization Failed" %]
|
||||
You are not allowed to [% action %].
|
||||
@ -313,11 +319,6 @@
|
||||
[% title = "Invalid Username Or Password" %]
|
||||
The username or password you entered is not valid.
|
||||
|
||||
[% ELSIF error == "ldap_cant_create_account" %]
|
||||
[% title = "Can't create LDAP accounts" %]
|
||||
This site is using LDAP for authentication. Please contact
|
||||
an LDAP administrator to get a new account created.
|
||||
|
||||
[% ELSIF error == "login_needed_for_password_change" %]
|
||||
[% title = "Login Name Required" %]
|
||||
You must enter a login name when requesting to change your password.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user