[dev] hook in the Auth class [PATCH]

Etienne Goyer etienne.goyer at linuxquebec.com
Tue Sep 30 08:40:57 PDT 2003


You asked for it !

I really hope this get commited.  I think my example functions are 
pretty spiffy and could actually be very useful in some situation.

Feedback welcome.

On Tue, Sep 30, 2003 at 12:34:47PM +0100, Nuno Loureiro wrote:
> 
> It might be of some use to me too...
> Pleae submit the patch to the list when ready...
> 
> On Sun, 2003-09-28 at 21:40, Etienne Goyer wrote:
> > Hi list,
> > 
> > I am requesting comments on a feature I would like to implement.  I
> > would like to add two hooks to the Auth class authenticate() function.
> > I suggest calling them _authenticate_hook_pre and
> > _authenticate_hook_post.  If either of these function return false,
> > authentication fail.  There could be only one of these function, but two
> > would be more flexible IMHO.
> > 
> > The reason I need these is that, although my users are authenticated
> > thru IMP (IMAP), I would like to consult an LDAP directory for
> > membership to a specific group before giving them access to Horde.  I
> > suppose similar requirement to mine could also happen to other people.
> > 
> > If that feature seem interesting to maintainer, I would code and send a
> > patch in the coming days.
> > 
> > Thanks !
> > 
> > -- 
> > Etienne Goyer                    Linux Québec Technologies Inc.
> > http://www.LinuxQuebec.com       etienne.goyer at linuxquebec.com
> -- 
> Nuno Loureiro <nuno at co.sapo.pt>
> PTM.com - http://www.sapo.pt/
> PGP fingerprint = 8A32 5174 E80C 2D40 9075 405E C107 6592 054A 4D05
> 
> 
> -- 
> Horde developers mailing list
> Frequently Asked Questions: http://horde.org/faq/
> To unsubscribe, mail: dev-unsubscribe at lists.horde.org

-- 
Etienne Goyer                    Linux Québec Technologies Inc.
http://www.LinuxQuebec.com       etienne.goyer at linuxquebec.com
-------------- next part --------------
--- lib/Auth.php.orig	Mon Sep 29 16:57:37 2003
+++ lib/Auth.php	Tue Sep 30 10:14:27 2003
@@ -170,19 +170,38 @@
         global $conf;
 
         $userID = trim($userID);
+	$auth = false;
+
+        if (!empty($conf['hooks']['preauthenticate'])) {
+            @include_once HORDE_BASE . '/config/hooks.php';
+            if (function_exists('_horde_hook_preauthenticate')) {
+                if (!call_user_func('_horde_hook_preauthenticate', $userID, $credentials, $realm)) {
+                    return false;
+		}
+	    }
+	}
 
         if ($this->_authenticate($userID, $credentials)) {
             if ($login) {
                 $this->clearAuth();
                 $this->setAuth($userID, $credentials, $realm);
-                return true;
+                $auth = true;
             } elseif (empty($conf['auth']['checkip']) ||
                       ($_SESSION['__auth']['remote_addr'] == $_SERVER['REMOTE_ADDR'])) {
-                return true;
+                $auth = true;
             }
         }
+        
+	if (!empty($conf['hooks']['postauthenticate'])) {
+            @include_once HORDE_BASE . '/config/hooks.php';
+            if (function_exists('_horde_hook_postauthenticate')) {
+                if (!call_user_func('_horde_hook_postauthenticate', $userID, $credentials, $realm)) {
+                    return false;
+		}
+	    }
+	}
 
-        return false;
+        return $auth;
     }
 
     /**
--- config/conf.php.dist.orig	Tue Sep 30 11:28:01 2003
+++ config/conf.php.dist	Tue Sep 30 11:31:27 2003
@@ -509,3 +509,13 @@
 // example when showing name lists to the user.
 // There are examples for such functions in horde/config/hooks.php.dist.
 $conf['hooks']['username'] = false;
+
+// If this is set to true and the function _horde_hook_preauthenticate() return 
+// false, authentication will fail.
+// There are examples for such functions in horde/config/hooks.php.dist.
+$conf['hooks']['preauthenticate'] = false;
+
+// If this is set to true and the function _horde_hook_postauthenticate() return
+// false, authentication will fail.
+// There are examples for such functions in horde/config/hooks.php.dist.
+$conf['hooks']['postauthenticate'] = false;
--- config/hooks.php.dist.orig	Tue Sep 30 11:18:56 2003
+++ config/hooks.php.dist	Tue Sep 30 11:27:36 2003
@@ -203,6 +203,59 @@
     }
 }
 
+// Here is an example _horde_hook_preauthenticate that make Horde respect the
+// Unix convention of not allowing login when a file named /etc/nologin exist.
+// This function get passed the username, credential and realm information but
+// they are not used in this example.
+if (!function_exists('_horde_hook_preauthenticate')) {
+    function _horde_hook_preauthenticate($userID, $credential, $realm)
+    {
+        return !file_exists('/etc/nologin');
+    }
+}
+
+// Here is an example of validating the user's right to login to Horde by
+// consulting group membership in an LDAP directory.  That way, if your Horde
+// installation is configured to authenticate against IMP which in turn
+// authenticate via IMAP, it is still possible to limit access to Horde by group
+// membership.  The following example had been made with an MS Active Directory 
+// in mind.  Note that if the LDAP directory is unavailable or some other error 
+// occur, authentication will fail.
+if (!function_exists('_horde_hook_postauthenticate')) {
+    function _horde_hook_postauthenticate($userID, $credential, $realm)
+    {
+        $ldapServer = 'ad.example.com';
+        $ldapPort = '389';
+        // Note that credential is sent plain-text in this case, so don't use
+        // privileged account here or setup SSL (by using port 636 above).
+        $binddn = "cn=WithoutPrivilege,dc=ulaval-dev,dc=ca";
+        $bindpw = "Remember this is sent in the clear unless SSL is used";
+        $searchBase = 'ou=People,dc=example,dc=com';
+        $userAttr = "sAMAccountName"; // Attribute to match $userID against in search
+        $groupAttr = "memberof"; // Group membership attribute, need to be all lowercase
+        $groupdn = "cn=HordeUser,ou=People,dc=example,dc=com"; // Attribute to check for right to use Horde
+        $ret = true;
+
+        $ds = @ldap_connect($ldapServer, $ldapPort);
+
+        if (@ldap_bind($ds, $binddn, $bindpw)) {
+            $searchResult = @ldap_search($ds, $searchBase, $userAttr . '=' . $userID, array($groupAttr), 0, 1, 5);
+            if ($information = @ldap_get_entries($ds, $searchResult)) {
+                $pattern = '/' . $groupdn . '/i'; // make pattern case-insensitive
+                foreach ($information[0][$groupAttr] as $group) {
+                    if (preg_match($pattern, $group)) {
+                        $ret = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+        ldap_close($ds);
+        return $ret;
+    }
+}
+
 // Here is an example fullname hook function to set the fullname from the GECOS
 // information in the passwd file.
 if (!function_exists('_prefs_hook_fullname')) {


More information about the dev mailing list