(Answer) (Category) Faq-O-Matic Faq-O-Matic : (Category) Administrators' Guide : (Category) In Development :
LDAP authentication V2
Here are a 4 patches that provide halfway decent ldap authentication. 
All of the configuration can be done using the FOM Install page.
These patches provide the following:

1.  Authentication using ldap
2.  Recursive user search by doing an anonymous search
3.  Correct E-mail attributions using the 'mail' attribute for an ldap user
4.  Better prompts for authentication via ldap

Note:  $adminAuth must be changed from the administrator's email address to the
administrator's LDAP uid or the administrator will no longer be able to
login.  $adminEmail must also be changed to a valid email address for receiving errors.
--- AuthLocal.pm.dist   Fri Aug 13 13:45:12 2004
+++ AuthLocal.pm        Fri Aug 13 18:39:58 2004
@@ -24,8 +24,27 @@
 # http://www.gnu.org/copyleft/gpl.html                                       #
 #                                                                            #
 ##############################################################################
+# LDAP authentication changes by James Saint-Rossy <jamesATsaint-rossyDOTnet>#
+#   based on an initial patch by Sean Sosik-Hamor <seanATtrunkmonkeyDOTcom>  #
+#                                                                            #
+# Version 0.1
+#
+# This patch requires that authenticate.pm and install.pm also be patched.   #
+#                                                                            #
+# $adminAuth must be changed from the administrator's email address to the   #
+# administrator's LDAP uid or the administrator will no longer be able to    #
+# login.  $adminEmail must also be changed to a valid email address for      #
+# receiving errors.  This can be done by directly modifying the              #
+# cgi-bin/fom-meta/config file or by accessing the "Configuration Main Menu  #
+# (install module)".                                                         #
+#                                                                            #
+##############################################################################
  
 use strict;
+use Net::LDAP;
  
 package FAQ::OMatic::AuthLocal;
  
@@ -40,13 +59,48 @@
        my $id = shift;
        my $pass = shift;
  
-       my ($idf,$passf,@rest) = FAQ::OMatic::Auth::readIDfile($id);
-       if ((defined $idf)
-               and ($idf eq $id)
-               and ($passf ne '__INVALID__')   # avoid the obvious vandal's hole...
-               and FAQ::OMatic::Auth::checkCryptPass($pass, $passf)) {
-               return 'true';
-       }
+  # Do the LDAP authentication if it's enabled
+       if ($FAQ::OMatic::Config::ldapAuth eq 'true') {
+    my $ldapServer = $FAQ::OMatic::Config::ldapServer;
+    my $ldapSearchBase = $FAQ::OMatic::Config::ldapSearchBase;
+    my $ldapUserAttrib = $FAQ::OMatic::Config::ldapUserAttrib;
+    # For future use
+    # my $ldapGroupAttrib = $FAQ::OMatic::Config::ldapGroupAttrib;
+    my $ldapFilter = "$ldapUserAttrib=$id";
+    # Open the ldap connection
+    my $ldap = Net::LDAP->new($ldapServer) or die "$@";
+    # Bind anonymously to search for the user
+    my $mesg = $ldap->bind();
+    # Search for the user DN
+    my $finddn = $ldap->search(
+      'base' => $ldapSearchBase,
+      'filter' => $ldapFilter,
+      'attrs' => [''] # Don't really need anything back
+    );
+    # Make sure if found only one entry before proceeding
+    if ($finddn->count != 1) { return undef; }
+
+    # Get the dn obtained from the anonymous bind
+    my $dn = $finddn->entry->dn;
+    # Try and rebind with the dn and pass
+    # this should work without unbinding the anonymous connection
+    $mesg = $ldap->bind( dn => $dn, password => $pass );
+    unless ($mesg->code ) {
+      # login suceeded
+      return 'true';
+    }
+  }
+  else {
+    my ($idf,$passf,@rest) = FAQ::OMatic::Auth::readIDfile($id);
+    FAQ::OMatic::gripe('problem', "There...\n");
+
+    if ((defined $idf)
+                 and ($idf eq $id)
+                 and ($passf ne '__INVALID__') # avoid the obvious vandal's hole...
+                 and FAQ::OMatic::Auth::checkCryptPass($pass, $passf)) {
+                   return 'true';
+         }
+  }
  
        return undef;
 }
--- OMatic.pm.dist      Mon Aug 16 15:02:20 2004
+++ OMatic.pm   Mon Aug 16 15:39:48 2004
@@ -596,6 +596,8 @@
 # THANKS: to steevATtiredDOTcom for suggesting the ability to mangle
 # or disable attributions to reduce the potential for spam address harvesting.
 sub mailtoReference {
+  use Net::LDAP;
+
        my $params = shift||{};
        my $addr = shift || '';
        my $wantarray = shift || '';
@@ -606,6 +608,32 @@
        $addr = entify($addr);
        my $how = $FAQ::OMatic::Config::antiSpam || 'off';
  
+  # Retrieve the E-mail address if LDAP UID's are being used
+  if (($FAQ::OMatic::Config::ldapAuth eq 'true') &&
+    (my $ldapMailAttrib = $FAQ::OMatic::Config::ldapMailAttrib) &&
+    ($addr !~ /\@/)) {
+    # bind anonymously
+    my $ldapServer = $FAQ::OMatic::Config::ldapServer;
+    my $ldapSearchBase = $FAQ::OMatic::Config::ldapSearchBase;
+    my $ldapUserAttrib = $FAQ::OMatic::Config::ldapUserAttrib;
+    # For future use
+    my $ldapFilter = "$ldapUserAttrib=$addr";
+    # Open the ldap connection
+    my $ldap = Net::LDAP->new($ldapServer) or die "$@";
+    # Bind anonymously to search for the user
+    my $mesg = $ldap->bind();
+    # Search for the user DN
+    my $userptr = $ldap->search(
+      'base' => $ldapSearchBase,
+      'filter' => $ldapFilter,
+      'attrs' => $ldapUserAttrib # Don't really need anything back
+    );
+    # Make sure only one entry is returned before proceeding
+    if ($userptr->count != 1) { last; }
+    # If you can't find the mail attribute don't bother
+    $addr = $userptr->entry->get_value($ldapMailAttrib);
+  }
+
        if ($how eq 'cheesy') {
                $addr =~ s#\@#AT#g;
                $addr =~ s#\.#DOT#g;
--- authenticate.pm.dist        Wed Aug 11 17:42:38 2004
+++ authenticate.pm     Wed Aug 11 18:03:43 2004
@@ -117,8 +117,13 @@
                        $rt.=gettexta("The operation you attempted (%0) can only be done by %1.",$what,$whoIsAllowed);
                }
  
-               $rt .= "<ul><li>".gettext("If you have never established a password to use with FAQ-O-Matic, you can")." $newLoginButton.\n";
-               $rt .= "<li>".gettext("If you have forgotten your password, you can")." $newPassButton.\n";
+    # Tab in the bullets
+    $rt .= "<ul>";
+    # Don't use bullets that don't apply to ldap authentication
+    unless ($FAQ::OMatic::Config::ldapAuth eq 'true') {
+                 $rt .= "<li>".gettext("If you have never established a password to use with FAQ-O-Matic, you can")." $newLoginButton.\n";
+                 $rt .= "<li>".gettext("If you have forgotten your password, you can")." $newPassButton.\n";
+    }
                $rt .= "<li>".gettext("If you have already logged in earlier today, it may be that the token I use to identify you has expired. Please log in again.")."\n";
                $rt .= "</ul>\n";
        }
@@ -145,7 +150,12 @@
        $rt .= " checked" if ($reason > 3);
        $rt .= ">\n";
        $rt .= " ".gettext("Authenticated login:")."\n";
-       $rt .= "<br>Email: <input type=text name=\"_pass_id\" value=\"\" size=60>\n";
+  if ($FAQ::OMatic::Config::ldapAuth eq 'true') {
+         $rt .= "<br>Uid: <input type=text name=\"_pass_id\" value=\"\" size=60>\n";
+  }
+  else {
+    $rt .= "<br>Email: <input type=text name=\"_pass_id\" value=\"\" size=60>\n";
+  }
        $rt .= "<br>".gettext("Password:")." <input type=password name=\"_pass_pass\" value=\"\" size=10>\n";
  
        $rt .= "<p><input type=submit name=\"_submit\" value=\"".gettext("Log In")."\">\n";
--- install.pm.dist     Wed Aug 11 15:12:20 2004
+++ install.pm  Mon Aug 16 14:16:35 2004
@@ -731,6 +731,39 @@
        ci('serveURL', '-sort'=>'c-c2', '-free', '-desc'=>
                gettext("The path prefix of the URL needed to access files in <b>\$serveDir</b>. It should be relative to the root of the server (omit http://hostname:port, but include a leading '/'). It should also end with a '/'.") , '-default'=>"''" ),
  
+       ci('sep_d', '-sort'=>'d--sep', '-separator', '-desc'=>
+               gettext("<i>Optional:</i> LDAP Authentication")),
+  ci('ldapAuth',
+    '-sort'=>'d-l1', '-choices'=>["'true'","'false'"],
+    '-desc'=>gettext("Use LDAP for authentication"),
+    '-default'=>gettext("'false'")
+  ),
+  ci('ldapServer',
+    '-sort'=>'d-l2', '-free',
+    '-desc'=>gettext("LDAP Server (if ldapAuth is set)"),
+    '-default'=>gettext("'your.ldap.server'")
+  ),
+  ci('ldapSearchBase',
+    '-sort'=>'d-l3', '-free',
+    '-desc'=>gettext("LDAP Search Base (if ldapAuth is set)"),
+    '-default'=>gettext("'o=foo.com,c=us'")
+  ),
+  ci('ldapUserAttrib',
+    '-sort'=>'d-l4', '-free',
+    '-desc'=>gettext("LDAP User Attribute (if ldapAuth is set).  This is the LDAP attribute that will correspond to what people will enter as their user name"),
+    '-default'=>gettext("'uid'")
+  ),
+  ci('ldapMailAttrib',
+    '-sort'=>'d-l5', '-free',
+    '-desc'=>gettext("LDAP E-Mail Attribute (if ldapAuth is set).  This is the LDAP attribute that contains the E-mail address of an LDAP user"),
+    '-default'=>gettext("'mail'")
+  ),
+  ci('ldapGroupAttrib',
+    '-sort'=>'d-l6', '-free',
+    '-desc'=>gettext("LDAP Group Attribute (if ldapAuth is set).  This is the LDAP attribute that can be used to find ldap groups for authentication"),
+    '-default'=>gettext("'cn'")
+  ),
+
        ci('sep_e', '-sort'=>'e--sep', '-separator', '-desc'=>
                gettext("<i>Optional:</i> Miscellaneous configurations")),
        ci('language',          '-sort'=>'k-m00',
[Append to This Answer]
Previous: (Answer) (missing or broken file)
This document is: http://www.jonh.net/cgi-bin/faqomatic/fom?file=2189
[Search] [Appearance]
This is a Faq-O-Matic 2.718d.
Hosted by SourceForge Logo and jonh.net.