]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
fixes for 51184, 51185, 51186: allow for ldap authentication. patches
authorcyeh%bluemartini.com <>
Sat, 16 Sep 2000 01:35:16 +0000 (01:35 +0000)
committercyeh%bluemartini.com <>
Sat, 16 Sep 2000 01:35:16 +0000 (01:35 +0000)
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.

CGI.pl
createaccount.cgi
defparams.pl
editusers.cgi

diff --git a/CGI.pl b/CGI.pl
index 4b85caec67e1bd020f5ebaa8c3aba9f6566823e7..21f5c8c77fb5e50c94141339c0e6645c51966e5c 100644 (file)
--- a/CGI.pl
+++ b/CGI.pl
@@ -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
index 8a905c4657113f0a89710e5f152f3ff3a2eee14a..2ff2c0b1ff5cb87c2103114949ab6f1c7f070fd0 100755 (executable)
@@ -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'};
index 695bd2c9c964d6b11c8434d630b1baba3943a56c..3a767f84f3a44d7db79ac793fd7c9130e59d7858 100644 (file)
@@ -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",
index 73ee8f1315fcb7d6772d80439e922629a34e6e8a..3af80a86aaed8ebe30c0b5681e99d52a772f0f96 100755 (executable)
@@ -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