Horde LDAP hook file

Bonsoir,
I installed NS 7 on a private home server with LDAP not with an AD.
Now I’m back in the old story that users can login but only the username is displayed instead of the fullname and the primary mail address.
Can anybody provide a “hooks.local.php” file that works with LDAP?
That would save me a lot of research and experiments.

The Howto shows a correct hook file for AD. Now, which parameters have to be exchanged to make it work with the NS LDAP directory? I guess it should bei “uid” instead of “samaccountname”. But this is not enough. “Userprincipalname”, “displayname” and “givenname” are missing as well. What are the equivalents? Can anybody help, please?

Look at the Domain accounts page: it should display the ldap db dump, with the full structure and attributes

Yes, I saw that before. But it does not really help me with the Horde hook file.

Hi Ralph,

I adapted the hook file from the horde howto for LDAP. To check the AD/LDAP fields you may use phpldapadmin or lam. I am going to integrate this into the horde module so AD/LDAP fullname instead of username will be used.

<?php
class Horde_Hooks
{
    public function prefs_init($pref, $value, $username, $scope_ob)
    {
        // LDAP connection parameters
        $ldapServer = 'localhost';
        $ldapPort = 389;
        $searchBase = 'ou=People,dc=directory,dc=nh';
        $binddn = 'cn=ldapservice,dc=directory,dc=nh';
        $bindpw = 'YOURBINDPW';

        switch ($pref)  {

            case 'from_addr':

                if (is_null($username)) {
                    return $value;
                }

                $ds = @ldap_connect($ldapServer, $ldapPort);
                if (ldap_start_tls($ds)) {
                   if (@ldap_bind($ds, $binddn, $bindpw)) {
                      $searchResult = @ldap_search($ds, $searchBase, 'uid=' . $username);
                      $information = @ldap_get_entries($ds, $searchResult);
                      if (($information === false) || ($information['count'] == 0)) {
                          $user = $username . '@domain.local';
                      } else {
                          $user = ($information[0]['Email'][0] != '')
                          ? $information[0]['Email'][0]
                          : $information[0]['mail'][0];
                      }
                  }
                }

                ldap_close($ds);
                return empty($user) ? $username : $user;


            case 'fullname':

                if (is_null($username)) {
                    return $value;
                }
                $ds = @ldap_connect($ldapServer, $ldapPort);

                if (ldap_start_tls($ds)) {
                  if (@ldap_bind($ds, $binddn, $bindpw)) {
                      $searchResult = @ldap_search($ds, $searchBase, 'uid=' . $username);
                      $information = @ldap_get_entries($ds, $searchResult);
                      if (($information === false) || ($information['count'] == 0)) {
                          $name = '';
                      } else {
                          $name = ($information[0]['cn'][0] != '')
                          ? $information[0]['cn'][0]
                          : $information[0]['gecos'][0];
                      }
                  }
                }
                ldap_close($ds);
                return empty($name) ? $username : $name;
        }
    }
}
3 Likes

Oh yeah, that’s it! Thanks, Markus! Like that Horde and Nethserver can also be used in a family scale (with mostly Linux computers). An Active Directory would be a bit too fat for that purpose.
One more question: how can I use the NS reverse proxy GUI to be able to address Horde as “sub.domain.de” instead of “domain.de/horde”. I’m quite familiar with the Nginx way to handle subdomains but not with Apache.

For me it didn’t work with a reverse proxy so I put the horde httpd conf in a virtualhost.
Here is a /etc/httpd/conf.d/php-horde-horde.conf to work with sub.domain.com:

Reload httpd with systemctl reload httpd to apply the config.

# Include default vhosts
<VirtualHost *:80>
    IncludeOptional conf.d/default-virtualhost.inc
</VirtualHost>

# Make letsencrypt work
<VirtualHost *:80>
   ServerName sub.domain.com
   RedirectMatch 301 ^(?!/\.well-known/acme-challenge/).* https://sub.domain.com
</VirtualHost>

# Horde vhost
<Virtualhost *:443>
   ServerName sub.domain.com
   SSLEngine on
   Documentroot /usr/share/horde

<Directory /usr/share/horde>

   Options +FollowSymLinks

   <IfModule mod_authz_core.c>
     # Apache 2.4
     Require local
     Require all granted

   </IfModule>
   <IfModule !mod_authz_core.c>
     # Apache 2.2
     Order Deny,Allow
     Deny from All
     Allow from 127.0.0.1
     Allow from ::1
   </IfModule>

   <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteBase   /horde
      RewriteCond   %{REQUEST_FILENAME}  !-d
      RewriteCond   %{REQUEST_FILENAME}  !-f
      RewriteRule ^(.*)$ rampage.php [QSA,L]
   </IfModule>
</Directory>

<Directory /usr/share/horde/config>
     Deny from all
</Directory>

<Directory /usr/share/horde/scripts>
     Deny from all
</Directory>

<Directory /usr/share/horde/locale>
     Deny from all
</Directory>

<Directory /usr/share/horde/lib>
     Deny from all
</Directory>

<Directory /usr/share/horde/templates>
     Deny from all
</Directory>

<Directory /usr/share/horde/rpc>
  <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond   %{REQUEST_FILENAME}  !-d
    RewriteCond   %{REQUEST_FILENAME}  !-f
    RewriteRule   ^(.*)$ index.php/$1 [QSA,L]
  </IfModule>
</Directory>

</Virtualhost>
1 Like

Thanks. I’ll try that.
Unfortunately it turned out that your hooks file is not as efficient as it looked like. In fact the Horde Administrator sees the fullname and the mail address of the users in the configuration. But the user should find both in the general preferences as his standard identity as well. That is not the case. And it leads to problems with sending mails - maybe from different identities.
I checked this Howto in the Horde wiki:
https://wiki.horde.org/LDAPHooksHorde5
The command “escapeshellcmd($username)” seems to be outdated. With just “$username” like in your file it delivers the correct results.
Maybe this approach can be optimized to avoid the double ldapsearch but at least it works.