Commit 39166470 authored by cyeh%bluemartini.com's avatar cyeh%bluemartini.com

fixes for 51184, 51185, 51186: allow for ldap authentication. patches

by jmrobins@tgix.com (Joe Robins). LDAP sections haven't been tested yet, but the code is arranged such that it shouldn't disturb existing user authentication system.
parent c89c74e3
......@@ -19,6 +19,7 @@
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# Dan Mosedale <dmose@mozilla.org>
# Joe Robins <jmrobins@tgix.com>
# Contains some global routines used throughout the CGI scripts of Bugzilla.
......@@ -27,6 +28,9 @@ use strict;
# use Carp; # for confess
# Shut up misguided -w warnings about "used only once". For some reason,
# "use vars" chokes on me when I try it here.
# We want to check for the existence of the LDAP modules here.
eval "use Mozilla::LDAP::Conn";
my $have_ldap = $@ ? 0 : 1;
sub CGI_pl_sillyness {
my $zz;
......@@ -623,60 +627,179 @@ sub confirm_login {
# print "Content-type: text/plain\n\n";
ConnectToDatabase();
# 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 = "";
if (defined $::FORM{"Bugzilla_login"} &&
defined $::FORM{"Bugzilla_password"}) {
my $enteredlogin = $::FORM{"Bugzilla_login"};
my $enteredpwd = $::FORM{"Bugzilla_password"};
CheckEmailSyntax($enteredlogin);
my $realcryptpwd = PasswordForLogin($::FORM{"Bugzilla_login"});
if (defined $::FORM{"PleaseMailAPassword"}) {
my $realpwd;
if ($realcryptpwd eq "") {
$realpwd = InsertNewUser($enteredlogin, "");
} else {
SendSQL("select password from profiles where login_name = " .
SqlQuote($enteredlogin));
$realpwd = FetchOneColumn();
}
print "Content-type: text/html\n\n";
PutHeader("Password has been emailed");
MailPassword($enteredlogin, $realpwd);
PutFooter();
exit;
}
SendSQL("SELECT encrypt(" . SqlQuote($enteredpwd) . ", " .
SqlQuote(substr($realcryptpwd, 0, 2)) . ")");
my $enteredcryptpwd = FetchOneColumn();
if ($realcryptpwd eq "" || $enteredcryptpwd ne $realcryptpwd) {
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;
}
$::COOKIE{"Bugzilla_login"} = $enteredlogin;
if (!defined $ENV{'REMOTE_HOST'}) {
$ENV{'REMOTE_HOST'} = $ENV{'REMOTE_ADDR'};
}
SendSQL("insert into logincookies (userid,cryptpassword,hostname) values (@{[DBNameToIdAndCheck($enteredlogin)]}, @{[SqlQuote($realcryptpwd)]}, @{[SqlQuote($ENV{'REMOTE_HOST'})]})");
SendSQL("select LAST_INSERT_ID()");
my $logincookie = FetchOneColumn();
$::COOKIE{"Bugzilla_logincookie"} = $logincookie;
print "Set-Cookie: Bugzilla_login=$enteredlogin ; path=/; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
print "Set-Cookie: Bugzilla_logincookie=$logincookie ; path=/; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
# This next one just cleans out any old bugzilla passwords that may
# be sitting around in the cookie files, from the bad old days when
# we actually stored the password there.
print "Set-Cookie: Bugzilla_password= ; path=/; expires=Sun, 30-Jun-80 00:00:00 GMT\n";
$enteredlogin = $::FORM{"Bugzilla_login"};
my $enteredpwd = $::FORM{"Bugzilla_password"};
CheckEmailSyntax($enteredlogin);
$realcryptpwd = PasswordForLogin($::FORM{"Bugzilla_login"});
if (defined $::FORM{"PleaseMailAPassword"}) {
my $realpwd;
if ($realcryptpwd eq "") {
$realpwd = InsertNewUser($enteredlogin, "");
} else {
SendSQL("select password from profiles where login_name = " .
SqlQuote($enteredlogin));
$realpwd = FetchOneColumn();
}
print "Content-type: text/html\n\n";
PutHeader("Password has been emailed");
MailPassword($enteredlogin, $realpwd);
PutFooter();
exit;
}
SendSQL("SELECT encrypt(" . SqlQuote($enteredpwd) . ", " .
SqlQuote(substr($realcryptpwd, 0, 2)) . ")");
my $enteredcryptpwd = FetchOneColumn();
if ($realcryptpwd eq "" || $enteredcryptpwd ne $realcryptpwd) {
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;
}
} 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.
# 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;
}
# 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;
if (!defined $ENV{'REMOTE_HOST'}) {
$ENV{'REMOTE_HOST'} = $ENV{'REMOTE_ADDR'};
}
SendSQL("insert into logincookies (userid,cryptpassword,hostname) values (@{[DBNameToIdAndCheck($enteredlogin)]}, @{[SqlQuote($realcryptpwd)]}, @{[SqlQuote($ENV{'REMOTE_HOST'})]})");
SendSQL("select LAST_INSERT_ID()");
my $logincookie = FetchOneColumn();
$::COOKIE{"Bugzilla_logincookie"} = $logincookie;
print "Set-Cookie: Bugzilla_login=$enteredlogin ; path=/; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
print "Set-Cookie: Bugzilla_logincookie=$logincookie ; path=/; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
# This next one just cleans out any old bugzilla passwords that may
# be sitting around in the cookie files, from the bad old days when
# we actually stored the password there.
print "Set-Cookie: Bugzilla_password= ; path=/; expires=Sun, 30-Jun-80 00:00:00 GMT\n";
}
......@@ -701,7 +824,11 @@ Content-type: text/html
}
print "Content-type: text/html\n\n";
PutHeader("Login", undef, undef, undef, 1);
print "I need a legitimate e-mail address and password to continue.\n";
if(Param("useLDAP")) {
print "I need a legitimate LDAP username and password to continue.\n";
} else {
print "I need a legitimate e-mail address and password to continue.\n";
}
if (!defined $nexturl || $nexturl eq "") {
# Sets nexturl to be argv0, stripping everything up to and
# including the last slash.
......@@ -715,13 +842,25 @@ Content-type: text/html
print "
<FORM action=$nexturl method=$method>
<table>
<tr>";
if(Param("useLDAP")) {
print "
<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 {
print "
<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>
<td><input type=password size=35 name=Bugzilla_password></td>";
}
print "
</tr>
</table>
";
......@@ -733,11 +872,16 @@ Content-type: text/html
}
print "
<input type=submit value=Login name=GoAheadAndLogIn><hr>
";
# If we're using LDAP, we can't request that a password be mailed...
unless(Param("useLDAP")) {
print "
If you don't have a password, or have forgotten it, then please fill in the
e-mail address above and click
here:<input type=submit value=\"E-mail me a password\"
name=PleaseMailAPassword>
</form>\n";
}
# 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
......
......@@ -20,6 +20,7 @@
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# David Gardiner <david.gardiner@unisa.edu.au>
# Joe Robins <jmrobins@tgix.com>
use diagnostics;
use strict;
......@@ -42,6 +43,14 @@ Content-type: text/html
";
# If we're using LDAP for login, then we can't create a new account here.
if(Param('useLDAP')) {
PutHeader("Can't create LDAP accounts");
print "This site is using LDAP for authentication. Please contact an LDAP ";
print "administrator to get a new account created.\n";
PutFooter();
exit;
}
my $login = $::FORM{'login'};
my $realname = $::FORM{'realname'};
......
......@@ -203,6 +203,36 @@ sub check_despotbaseurl {
}
# Adding in four parameters for LDAP authentication. -JMR, 7/28/00
DefParam("useLDAP",
"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.)",
"b",
0);
DefParam("LDAPserver",
"The name (and optionally port) of your LDAP server. (e.g. ldap.company.com, or ldap.company.com:portnum)",
"t",
"");
DefParam("LDAPBaseDN",
"The BaseDN for authenticating users against. (e.g. \"ou=People,o=Company\")",
"t",
"");
DefParam("LDAPmailattribute",
"The name of the attribute of a user in your directory that ".
"contains the email address.",
"t",
"mail");
#End of LDAP parameters
DefParam("headerhtml",
"Additional HTML to add to the HEAD area of documents, eg. links to stylesheets.",
"l",
......
......@@ -20,6 +20,7 @@
#
# Contributor(s): Holger Schurig <holgerschurig@nikocity.de>
# Dave Miller <dave@intrec.com>
# Joe Robins <jmrobins@tgix.com>
#
# Direct any questions on this source code to
#
......@@ -109,8 +110,11 @@ sub EmitFormElements ($$$$$$$)
if ($editall) {
print "</TR><TR>\n";
print " <TH ALIGN=\"right\">Password:</TH>\n";
print " <TD><INPUT TYPE=\"PASSWORD\" SIZE=16 MAXLENGTH=16 NAME=\"password\" VALUE=\"$password\"></TD>\n";
if(Param('useLDAP')) {
print " <TD><FONT COLOR=RED>This site is using LDAP for authentication!</FONT></TD>\n";
} else {
print " <TD><INPUT TYPE=\"PASSWORD\" SIZE=16 MAXLENGTH=16 NAME=\"password\" VALUE=\"$password\"></TD>\n";
}
print "</TR><TR>\n";
print " <TH ALIGN=\"right\">Email notification:</TH>\n";
print qq{<TD><SELECT NAME="emailnotification">};
......@@ -341,7 +345,7 @@ if ($action eq 'list') {
}
print "</TR>";
}
if ($editall) {
if ($editall && !Param('useLDAP')) {
print "<TR>\n";
my $span = $candelete ? 3 : 2;
print qq{
......@@ -375,6 +379,13 @@ 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.";
PutTrailer();
exit;
}
print "<FORM METHOD=POST ACTION=editusers.cgi>\n";
print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n";
......@@ -406,6 +417,13 @@ 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.";
PutTrailer();
exit;
}
# Cleanups and valididy checks
my $realname = trim($::FORM{realname} || '');
my $password = trim($::FORM{password} || '');
......@@ -667,7 +685,7 @@ if ($action eq 'edit') {
print "</TR></TABLE>\n";
print "<INPUT TYPE=HIDDEN NAME=\"userold\" VALUE=\"$user\">\n";
if ($editall) {
if ($editall && !Param('useLDAP')) {
print "<INPUT TYPE=HIDDEN NAME=\"passwordold\" VALUE=\"$password\">\n";
}
print "<INPUT TYPE=HIDDEN NAME=\"realnameold\" VALUE=\"$realname\">\n";
......@@ -764,13 +782,14 @@ if ($action eq 'update') {
WHERE login_name=" . SqlQuote($userold));
print "Updated email notification.<BR>\n";
}
if ($editall && $password ne $passwordold) {
if(!Param('useLDAP')) {
if ($editall && $password ne $passwordold) {
my $q = SqlQuote($password);
SendSQL("UPDATE profiles
SET password= $q, cryptpassword = ENCRYPT($q)
WHERE login_name=" . SqlQuote($userold));
print "Updated password.<BR>\n";
}
}
if ($editall && $realname ne $realnameold) {
SendSQL("UPDATE profiles
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment