From c23eeb54be298793aba5ebb7c304c9fa63f2efe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 00:42:38 +0200 Subject: [PATCH 01/11] [ldap-contacts-suggestions] Fix allowed emails The configuration interface allows a list of allowed emails to be set, but the configuration parameter is never used. --- .../LdapContactsSuggestions.php | 14 ++------------ plugins/ldap-contacts-suggestions/index.php | 3 ++- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index 9e8a45982..8f69d425d 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -66,10 +66,11 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges * @param string $sObjectClass * @param string $sNameField * @param string $sEmailField + * @param string $sAllowedEmails * * @return \LdapContactsSuggestions */ - public function SetConfig($sHostName, $iHostPort, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sUidField, $sNameField, $sEmailField) + public function SetConfig($sHostName, $iHostPort, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails) { $this->sHostName = $sHostName; $this->iHostPort = $iHostPort; @@ -83,17 +84,6 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges $this->sUidField = $sUidField; $this->sNameField = $sNameField; $this->sEmailField = $sEmailField; - - return $this; - } - - /** - * @param string $sAllowedEmails - * - * @return \LdapContactsSuggestions - */ - public function SetAllowedEmails($sAllowedEmails) - { $this->sAllowedEmails = $sAllowedEmails; return $this; diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 97aa4177b..7bc36c7c1 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -50,13 +50,14 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin $sSearchField = \trim($this->Config()->Get('plugin', 'search_field', '')); $sNameField = \trim($this->Config()->Get('plugin', 'name_field', '')); $sEmailField = \trim($this->Config()->Get('plugin', 'mail_field', '')); + $sAllowedEmails = \trim($this->Config()->Get('plugin', 'allowed_emails', '')); if (0 < \strlen($sUsersDn) && 0 < \strlen($sObjectClass) && 0 < \strlen($sEmailField)) { include_once __DIR__.'/LdapContactsSuggestions.php'; $oProvider = new LdapContactsSuggestions(); - $oProvider->SetConfig($sHostName, $iHostPort, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sSearchField, $sNameField, $sEmailField); + $oProvider->SetConfig($sHostName, $iHostPort, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sSearchField, $sNameField, $sEmailField, $sAllowedEmails); $mResult[] = $oProvider; } From 11294a8f8b2bf91c1005742369b3778b515b7ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 10:48:33 +0200 Subject: [PATCH 02/11] [ldap-contacts-suggestions] Add support for StartTLS The plugin currently supports SSL (by using a ldaps:// URI as the hostname of the LDAP server) and unencrypted LDAP. This patch also adds StartTLS support, which is used by many LDAP servers. --- .../LdapContactsSuggestions.php | 15 ++++++++++++++- plugins/ldap-contacts-suggestions/index.php | 6 +++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index 8f69d425d..c0a21f925 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -12,6 +12,11 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges */ private $iHostPort = 389; + /** + * @var bool + */ + private $bUseStartTLS = True; + /** * @var string */ @@ -60,6 +65,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @param string $sHostName * @param int $iHostPort + * @param bool $bUseStartTLS * @param string $sAccessDn * @param string $sAccessPassword * @param string $sUsersDn @@ -70,10 +76,11 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges * * @return \LdapContactsSuggestions */ - public function SetConfig($sHostName, $iHostPort, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails) + public function SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails) { $this->sHostName = $sHostName; $this->iHostPort = $iHostPort; + $this->bUseStartTLS = $bUseStartTLS; if (0 < \strlen($sAccessDn)) { $this->sAccessDn = $sAccessDn; @@ -190,6 +197,12 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges @\ldap_set_option($oCon, LDAP_OPT_PROTOCOL_VERSION, 3); + if ($this->bUseStartTLS && !@\ldap_start_tls($oCon)) + { + $this->logLdapError($oCon, 'ldap_start_tls'); + return $aResult; + } + if (!@\ldap_bind($oCon, $this->sAccessDn, $this->sAccessPassword)) { if (is_null($this->sAccessDn)) diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 7bc36c7c1..8b1178098 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -43,6 +43,7 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin $sHostName = \trim($this->Config()->Get('plugin', 'hostname', '')); $iHostPort = (int) $this->Config()->Get('plugin', 'port', 389); + $bUseStartTLS = (bool) $this->Config()->Get('plugin', 'use_start_tls', True); $sAccessDn = \trim($this->Config()->Get('plugin', 'access_dn', '')); $sAccessPassword = \trim($this->Config()->Get('plugin', 'access_password', '')); $sUsersDn = \trim($this->Config()->Get('plugin', 'users_dn_format', '')); @@ -57,7 +58,7 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin include_once __DIR__.'/LdapContactsSuggestions.php'; $oProvider = new LdapContactsSuggestions(); - $oProvider->SetConfig($sHostName, $iHostPort, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sSearchField, $sNameField, $sEmailField, $sAllowedEmails); + $oProvider->SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sSearchField, $sNameField, $sEmailField, $sAllowedEmails); $mResult[] = $oProvider; } @@ -77,6 +78,9 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin \RainLoop\Plugins\Property::NewInstance('port')->SetLabel('LDAP port') ->SetType(\RainLoop\Enumerations\PluginPropertyType::INT) ->SetDefaultValue(389), + \RainLoop\Plugins\Property::NewInstance('use_start_tls')->SetLabel('Use StartTLS') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) + ->SetDefaultValue(True), \RainLoop\Plugins\Property::NewInstance('access_dn')->SetLabel('Access dn (login)') ->SetDescription('LDAP bind DN to authentifcate with. If left blank, anonymous bind will be tried and Access password will be ignored') ->SetDefaultValue(''), From 725f21777877a3dd5c853b13bc6505264df2ca54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 11:03:56 +0200 Subject: [PATCH 03/11] [ldap-contacts-suggestions] Better handling of mixed case attributes While the LDAP search is case insensitive, the array which is returned from ldap_get_entries() will only use lowercase. This means that if one configures the plugin to look for e.g. "givenName", no results will be returned. --- .../ldap-contacts-suggestions/LdapContactsSuggestions.php | 5 ++++- plugins/ldap-contacts-suggestions/index.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index c0a21f925..9e6bd29d2 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -45,7 +45,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sNameField = 'givenname'; + private $sNameField = 'givenName'; /** * @var string @@ -141,6 +141,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges { foreach ($aEmailFields as $sField) { + $sField = \strtolower($sField); if (!empty($aLdapItem[$sField][0])) { $sEmail = \trim($aLdapItem[$sField][0]); @@ -153,6 +154,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges foreach ($aNameFields as $sField) { + $sField = \strtolower($sField); if (!empty($aLdapItem[$sField][0])) { $sName = \trim($aLdapItem[$sField][0]); @@ -165,6 +167,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges foreach ($aUidFields as $sField) { + $sField = \strtolower($sField); if (!empty($aLdapItem[$sField][0])) { $sUid = \trim($aLdapItem[$sField][0]); diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 8b1178098..253128158 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -95,7 +95,7 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin \RainLoop\Plugins\Property::NewInstance('search_field')->SetLabel('Search field') ->SetDefaultValue('uid'), \RainLoop\Plugins\Property::NewInstance('name_field')->SetLabel('Name field') - ->SetDefaultValue('givenname'), + ->SetDefaultValue('givenName'), \RainLoop\Plugins\Property::NewInstance('mail_field')->SetLabel('Mail field') ->SetDefaultValue('mail'), \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') From a53d7383db862efe073fe780766c4b120b1922b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 11:48:21 +0200 Subject: [PATCH 04/11] [ldap-contacts-suggestions] Update option documentation Use common LDAP terminology and update comments to reflect how the configuration options work (e.g. that all the LDAP attribute options are multivalued). --- plugins/ldap-contacts-suggestions/index.php | 25 ++++++++++++--------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 253128158..15bdcaf2c 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -48,7 +48,7 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin $sAccessPassword = \trim($this->Config()->Get('plugin', 'access_password', '')); $sUsersDn = \trim($this->Config()->Get('plugin', 'users_dn_format', '')); $sObjectClass = \trim($this->Config()->Get('plugin', 'object_class', '')); - $sSearchField = \trim($this->Config()->Get('plugin', 'search_field', '')); + $sUidField = \trim($this->Config()->Get('plugin', 'uid_field', '')); $sNameField = \trim($this->Config()->Get('plugin', 'name_field', '')); $sEmailField = \trim($this->Config()->Get('plugin', 'mail_field', '')); $sAllowedEmails = \trim($this->Config()->Get('plugin', 'allowed_emails', '')); @@ -58,7 +58,7 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin include_once __DIR__.'/LdapContactsSuggestions.php'; $oProvider = new LdapContactsSuggestions(); - $oProvider->SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sSearchField, $sNameField, $sEmailField, $sAllowedEmails); + $oProvider->SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails); $mResult[] = $oProvider; } @@ -81,25 +81,28 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin \RainLoop\Plugins\Property::NewInstance('use_start_tls')->SetLabel('Use StartTLS') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(True), - \RainLoop\Plugins\Property::NewInstance('access_dn')->SetLabel('Access dn (login)') - ->SetDescription('LDAP bind DN to authentifcate with. If left blank, anonymous bind will be tried and Access password will be ignored') + \RainLoop\Plugins\Property::NewInstance('access_dn')->SetLabel('Bind DN') + ->SetDescription('DN to bind (login) with. If left blank, anonymous bind will be tried and the password will be ignored') ->SetDefaultValue(''), - \RainLoop\Plugins\Property::NewInstance('access_password')->SetLabel('Access password') + \RainLoop\Plugins\Property::NewInstance('access_password')->SetLabel('Bind password') ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD) ->SetDefaultValue(''), - \RainLoop\Plugins\Property::NewInstance('users_dn_format')->SetLabel('Users DN format') - ->SetDescription('LDAP users dn format. Supported tokens: {email}, {login}, {domain}, {domain:dc}, {imap:login}, {imap:host}, {imap:port}') + \RainLoop\Plugins\Property::NewInstance('users_dn_format')->SetLabel('Search base DN') + ->SetDescription('DN to use as the search base. Supported tokens: {domain}, {domain:dc}, {email}, {email:user}, {email:domain}, {login}, {imap:login}, {imap:host}, {imap:port}') ->SetDefaultValue('ou=People,dc=domain,dc=com'), \RainLoop\Plugins\Property::NewInstance('object_class')->SetLabel('objectClass value') ->SetDefaultValue('inetOrgPerson'), - \RainLoop\Plugins\Property::NewInstance('search_field')->SetLabel('Search field') + \RainLoop\Plugins\Property::NewInstance('uid_field')->SetLabel('uid attributes') + ->SetDescription('LDAP attributes for userids, comma separated list in order of preference') ->SetDefaultValue('uid'), - \RainLoop\Plugins\Property::NewInstance('name_field')->SetLabel('Name field') + \RainLoop\Plugins\Property::NewInstance('name_field')->SetLabel('Name attributes') + ->SetDescription('LDAP attributes for user names, comma separated list in order of preference') ->SetDefaultValue('givenName'), - \RainLoop\Plugins\Property::NewInstance('mail_field')->SetLabel('Mail field') + \RainLoop\Plugins\Property::NewInstance('mail_field')->SetLabel('Mail attributes') + ->SetDescription('LDAP attributes for user email addresses, comma separated list in order of preference') ->SetDefaultValue('mail'), \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') - ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') + ->SetDescription('Email addresses of users which should be allowed to do LDAP lookups, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') ->SetDefaultValue('*') ); } From 1841688b5f2f068b5558059422d28734b854ce71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 12:01:43 +0200 Subject: [PATCH 05/11] [ldap-contacts-suggestions] Rename some variables Rename some variables to use common LDAP terminology and to make their purpose clearer. --- .../LdapContactsSuggestions.php | 32 +++++++++---------- plugins/ldap-contacts-suggestions/index.php | 16 +++++----- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index 9e6bd29d2..f30973227 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -20,17 +20,17 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sAccessDn = null; + private $sBindDn = null; /** * @var string */ - private $sAccessPassword = null; + private $sBindPassword = null; /** * @var string */ - private $sUsersDn = ''; + private $sBaseDn = ''; /** * @var string @@ -66,9 +66,9 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges * @param string $sHostName * @param int $iHostPort * @param bool $bUseStartTLS - * @param string $sAccessDn - * @param string $sAccessPassword - * @param string $sUsersDn + * @param string $sBindDn + * @param string $sBindPassword + * @param string $sBaseDn * @param string $sObjectClass * @param string $sNameField * @param string $sEmailField @@ -76,17 +76,17 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges * * @return \LdapContactsSuggestions */ - public function SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails) + public function SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails) { $this->sHostName = $sHostName; $this->iHostPort = $iHostPort; $this->bUseStartTLS = $bUseStartTLS; - if (0 < \strlen($sAccessDn)) + if (0 < \strlen($sBindDn)) { - $this->sAccessDn = $sAccessDn; - $this->sAccessPassword = $sAccessPassword; + $this->sBindDn = $sBindDn; + $this->sBindPassword = $sBindPassword; } - $this->sUsersDn = $sUsersDn; + $this->sBaseDn = $sBaseDn; $this->sObjectClass = $sObjectClass; $this->sUidField = $sUidField; $this->sNameField = $sNameField; @@ -206,9 +206,9 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges return $aResult; } - if (!@\ldap_bind($oCon, $this->sAccessDn, $this->sAccessPassword)) + if (!@\ldap_bind($oCon, $this->sBindDn, $this->sBindPassword)) { - if (is_null($this->sAccessDn)) + if (is_null($this->sBindDn)) { $this->logLdapError($oCon, 'ldap_bind (anonymous)'); } @@ -221,7 +221,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges } $sDomain = \MailSo\Base\Utils::GetDomainFromEmail($oAccount->Email()); - $sSearchDn = \strtr($this->sUsersDn, array( + $sBaseDn = \strtr($this->sBaseDn, array( '{domain}' => $sDomain, '{domain:dc}' => 'dc='.\strtr($sDomain, array('.' => ',dc=')), '{email}' => $oAccount->Email(), @@ -258,8 +258,8 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges $sFilter .= (1 < count($aItems) ? '(|' : '').$sSubFilter.(1 < count($aItems) ? ')' : ''); $sFilter .= ')'; - $this->oLogger->Write('ldap_search: start: '.$sSearchDn.' / '.$sFilter, \MailSo\Log\Enumerations\Type::INFO, 'LDAP'); - $oS = @\ldap_search($oCon, $sSearchDn, $sFilter, $aItems, 0, 30, 30); + $this->oLogger->Write('ldap_search: start: '.$sBaseDn.' / '.$sFilter, \MailSo\Log\Enumerations\Type::INFO, 'LDAP'); + $oS = @\ldap_search($oCon, $sBaseDn, $sFilter, $aItems, 0, 30, 30); if ($oS) { $aEntries = @\ldap_get_entries($oCon, $oS); diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 15bdcaf2c..8efa7e498 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -44,21 +44,21 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin $sHostName = \trim($this->Config()->Get('plugin', 'hostname', '')); $iHostPort = (int) $this->Config()->Get('plugin', 'port', 389); $bUseStartTLS = (bool) $this->Config()->Get('plugin', 'use_start_tls', True); - $sAccessDn = \trim($this->Config()->Get('plugin', 'access_dn', '')); - $sAccessPassword = \trim($this->Config()->Get('plugin', 'access_password', '')); - $sUsersDn = \trim($this->Config()->Get('plugin', 'users_dn_format', '')); + $sBindDn = \trim($this->Config()->Get('plugin', 'bind_dn', '')); + $sBindPassword = \trim($this->Config()->Get('plugin', 'bind_password', '')); + $sBaseDn = \trim($this->Config()->Get('plugin', 'base_dn', '')); $sObjectClass = \trim($this->Config()->Get('plugin', 'object_class', '')); $sUidField = \trim($this->Config()->Get('plugin', 'uid_field', '')); $sNameField = \trim($this->Config()->Get('plugin', 'name_field', '')); $sEmailField = \trim($this->Config()->Get('plugin', 'mail_field', '')); $sAllowedEmails = \trim($this->Config()->Get('plugin', 'allowed_emails', '')); - if (0 < \strlen($sUsersDn) && 0 < \strlen($sObjectClass) && 0 < \strlen($sEmailField)) + if (0 < \strlen($sBaseDn) && 0 < \strlen($sObjectClass) && 0 < \strlen($sEmailField)) { include_once __DIR__.'/LdapContactsSuggestions.php'; $oProvider = new LdapContactsSuggestions(); - $oProvider->SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sAccessDn, $sAccessPassword, $sUsersDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails); + $oProvider->SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails); $mResult[] = $oProvider; } @@ -81,13 +81,13 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin \RainLoop\Plugins\Property::NewInstance('use_start_tls')->SetLabel('Use StartTLS') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(True), - \RainLoop\Plugins\Property::NewInstance('access_dn')->SetLabel('Bind DN') + \RainLoop\Plugins\Property::NewInstance('bind_dn')->SetLabel('Bind DN') ->SetDescription('DN to bind (login) with. If left blank, anonymous bind will be tried and the password will be ignored') ->SetDefaultValue(''), - \RainLoop\Plugins\Property::NewInstance('access_password')->SetLabel('Bind password') + \RainLoop\Plugins\Property::NewInstance('bind_password')->SetLabel('Bind password') ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD) ->SetDefaultValue(''), - \RainLoop\Plugins\Property::NewInstance('users_dn_format')->SetLabel('Search base DN') + \RainLoop\Plugins\Property::NewInstance('base_dn')->SetLabel('Search base DN') ->SetDescription('DN to use as the search base. Supported tokens: {domain}, {domain:dc}, {email}, {email:user}, {email:domain}, {login}, {imap:login}, {imap:host}, {imap:port}') ->SetDefaultValue('ou=People,dc=domain,dc=com'), \RainLoop\Plugins\Property::NewInstance('object_class')->SetLabel('objectClass value') From 8e9cef4f78bffd282714af3ca4808d22e601a4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 12:17:05 +0200 Subject: [PATCH 06/11] [ldap-contacts-suggestions] Use LDAP URI for connecting ldap_connect(, ) is deprecated and ldap_connect() is more expressive (for example, by allowing the use of SSL to be mandatory using a ldaps:// URL). --- .../LdapContactsSuggestions.php | 17 +++++------------ plugins/ldap-contacts-suggestions/index.php | 15 ++++++--------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index f30973227..288122fde 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -5,12 +5,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sHostName = '127.0.0.1'; - - /** - * @var int - */ - private $iHostPort = 389; + private $sLdapUri = 'ldap://127.0.0.1:389'; /** * @var bool @@ -63,8 +58,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges private $sAllowedEmails = ''; /** - * @param string $sHostName - * @param int $iHostPort + * @param string $sLdapUri * @param bool $bUseStartTLS * @param string $sBindDn * @param string $sBindPassword @@ -76,10 +70,9 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges * * @return \LdapContactsSuggestions */ - public function SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails) + public function SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails) { - $this->sHostName = $sHostName; - $this->iHostPort = $iHostPort; + $this->sLdapUri = $sLdapUri; $this->bUseStartTLS = $bUseStartTLS; if (0 < \strlen($sBindDn)) { @@ -193,7 +186,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges $sSearchEscaped = $this->escape($sQuery); $aResult = array(); - $oCon = @\ldap_connect($this->sHostName, $this->iHostPort); + $oCon = @\ldap_connect($this->sLdapUri); if ($oCon) { $this->oLogger->Write('ldap_connect: connected', \MailSo\Log\Enumerations\Type::INFO, 'LDAP'); diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 8efa7e498..217d2971f 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -41,8 +41,7 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin $mResult = array(); } - $sHostName = \trim($this->Config()->Get('plugin', 'hostname', '')); - $iHostPort = (int) $this->Config()->Get('plugin', 'port', 389); + $sLdapUri = \trim($this->Config()->Get('plugin', 'ldap_uri', '')); $bUseStartTLS = (bool) $this->Config()->Get('plugin', 'use_start_tls', True); $sBindDn = \trim($this->Config()->Get('plugin', 'bind_dn', '')); $sBindPassword = \trim($this->Config()->Get('plugin', 'bind_password', '')); @@ -53,12 +52,12 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin $sEmailField = \trim($this->Config()->Get('plugin', 'mail_field', '')); $sAllowedEmails = \trim($this->Config()->Get('plugin', 'allowed_emails', '')); - if (0 < \strlen($sBaseDn) && 0 < \strlen($sObjectClass) && 0 < \strlen($sEmailField)) + if (0 < \strlen($sLdapUri) && 0 < \strlen($sBaseDn) && 0 < \strlen($sObjectClass) && 0 < \strlen($sEmailField)) { include_once __DIR__.'/LdapContactsSuggestions.php'; $oProvider = new LdapContactsSuggestions(); - $oProvider->SetConfig($sHostName, $iHostPort, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails); + $oProvider->SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails); $mResult[] = $oProvider; } @@ -73,11 +72,9 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin protected function configMapping() : array { return array( - \RainLoop\Plugins\Property::NewInstance('hostname')->SetLabel('LDAP hostname') - ->SetDefaultValue('127.0.0.1'), - \RainLoop\Plugins\Property::NewInstance('port')->SetLabel('LDAP port') - ->SetType(\RainLoop\Enumerations\PluginPropertyType::INT) - ->SetDefaultValue(389), + \RainLoop\Plugins\Property::NewInstance('ldap_uri')->SetLabel('LDAP URI') + ->SetDescription('LDAP server URI(s), space separated') + ->SetDefaultValue('ldap://127.0.0.1:389'), \RainLoop\Plugins\Property::NewInstance('use_start_tls')->SetLabel('Use StartTLS') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(True), From f3b6cd08f03e11704cb91da6c574b094ccb691f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 12:54:02 +0200 Subject: [PATCH 07/11] [ldap-contacts-suggestions] Update defaults Since multiple LDAP attributes are supported for the user name/email, there's no harm in having defaults that are a bit more flexible (for example, "givenName" is commonly only the users first name, while a full name is usually preferable as an email recipient). --- .../ldap-contacts-suggestions/LdapContactsSuggestions.php | 8 ++++---- plugins/ldap-contacts-suggestions/index.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index 288122fde..ae891a4c5 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -25,7 +25,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sBaseDn = ''; + private $sBaseDn = 'ou=People,dc=example,dc=com'; /** * @var string @@ -40,12 +40,12 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sNameField = 'givenName'; + private $sNameField = 'displayName,cn,givenName,sn'; /** * @var string */ - private $sEmailField = 'mail'; + private $sEmailField = 'mailAddress,mail,mailAlternateAddress,mailAlias'; /** * @var \MailSo\Log\Logger @@ -55,7 +55,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sAllowedEmails = ''; + private $sAllowedEmails = '*'; /** * @param string $sLdapUri diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 217d2971f..a36b2a47b 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -86,7 +86,7 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin ->SetDefaultValue(''), \RainLoop\Plugins\Property::NewInstance('base_dn')->SetLabel('Search base DN') ->SetDescription('DN to use as the search base. Supported tokens: {domain}, {domain:dc}, {email}, {email:user}, {email:domain}, {login}, {imap:login}, {imap:host}, {imap:port}') - ->SetDefaultValue('ou=People,dc=domain,dc=com'), + ->SetDefaultValue('ou=People,dc=example,dc=com'), \RainLoop\Plugins\Property::NewInstance('object_class')->SetLabel('objectClass value') ->SetDefaultValue('inetOrgPerson'), \RainLoop\Plugins\Property::NewInstance('uid_field')->SetLabel('uid attributes') @@ -94,10 +94,10 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin ->SetDefaultValue('uid'), \RainLoop\Plugins\Property::NewInstance('name_field')->SetLabel('Name attributes') ->SetDescription('LDAP attributes for user names, comma separated list in order of preference') - ->SetDefaultValue('givenName'), + ->SetDefaultValue('displayName,cn,givenName,sn'), \RainLoop\Plugins\Property::NewInstance('mail_field')->SetLabel('Mail attributes') ->SetDescription('LDAP attributes for user email addresses, comma separated list in order of preference') - ->SetDefaultValue('mail'), + ->SetDefaultValue('mailAddress,mail,mailAlternateAddress,mailAlias'), \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') ->SetDescription('Email addresses of users which should be allowed to do LDAP lookups, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net') ->SetDefaultValue('*') From 8eec9d4a8fba7fc122ae83b74f4b088850578b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 13:10:40 +0200 Subject: [PATCH 08/11] [ldap-contacts-suggestions] Clarify some more variables Make it clearer that these variables take several attributes. --- .../LdapContactsSuggestions.php | 38 ++++++++++--------- plugins/ldap-contacts-suggestions/index.php | 16 ++++---- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index ae891a4c5..4169ce763 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -35,17 +35,17 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sUidField = 'uid'; + private $sUidAttributes = 'uid'; /** * @var string */ - private $sNameField = 'displayName,cn,givenName,sn'; + private $sNameAttributes = 'displayName,cn,givenName,sn'; /** * @var string */ - private $sEmailField = 'mailAddress,mail,mailAlternateAddress,mailAlias'; + private $sEmailAttributes = 'mailAddress,mail,mailAlternateAddress,mailAlias'; /** * @var \MailSo\Log\Logger @@ -64,13 +64,14 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges * @param string $sBindPassword * @param string $sBaseDn * @param string $sObjectClass - * @param string $sNameField - * @param string $sEmailField + * @param string $sNameAttributes + * @param string $sEmailAttributes + * @param string $sUidAttributes * @param string $sAllowedEmails * * @return \LdapContactsSuggestions */ - public function SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails) + public function SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidAttributes, $sNameAttributes, $sEmailAttributes, $sAllowedEmails) { $this->sLdapUri = $sLdapUri; $this->bUseStartTLS = $bUseStartTLS; @@ -81,9 +82,9 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges } $this->sBaseDn = $sBaseDn; $this->sObjectClass = $sObjectClass; - $this->sUidField = $sUidField; - $this->sNameField = $sNameField; - $this->sEmailField = $sEmailField; + $this->sUidAttributes = $sUidAttributes; + $this->sNameAttributes = $sNameAttributes; + $this->sEmailAttributes = $sEmailAttributes; $this->sAllowedEmails = $sAllowedEmails; return $this; @@ -122,17 +123,18 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @param array $aLdapItem - * @param array $aEmailFields - * @param array $aNameFields + * @param array $aEmailAttributes + * @param array $aNameAttributes + * @param array $aUidAttributes * * @return array */ - private function findNameAndEmail($aLdapItem, $aEmailFields, $aNameFields, $aUidFields) + private function findNameAndEmail($aLdapItem, $aEmailAttributes, $aNameAttributes, $aUidAttributes) { $sEmail = $sName = $sUid = ''; if ($aLdapItem) { - foreach ($aEmailFields as $sField) + foreach ($aEmailAttributes as $sField) { $sField = \strtolower($sField); if (!empty($aLdapItem[$sField][0])) @@ -145,7 +147,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges } } - foreach ($aNameFields as $sField) + foreach ($aNameAttributes as $sField) { $sField = \strtolower($sField); if (!empty($aLdapItem[$sField][0])) @@ -158,7 +160,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges } } - foreach ($aUidFields as $sField) + foreach ($aUidAttributes as $sField) { $sField = \strtolower($sField); if (!empty($aLdapItem[$sField][0])) @@ -226,9 +228,9 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges '{imap:port}' => $oAccount->DomainIncPort() )); - $aEmails = empty($this->sEmailField) ? array() : \explode(',', $this->sEmailField); - $aNames = empty($this->sNameField) ? array() : \explode(',', $this->sNameField); - $aUIDs = empty($this->sUidField) ? array() : \explode(',', $this->sUidField); + $aEmails = empty($this->sEmailAttributes) ? array() : \explode(',', $this->sEmailAttributes); + $aNames = empty($this->sNameAttributes) ? array() : \explode(',', $this->sNameAttributes); + $aUIDs = empty($this->sUidAttributes) ? array() : \explode(',', $this->sUidAttributes); $aEmails = \array_map('trim', $aEmails); $aNames = \array_map('trim', $aNames); diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index a36b2a47b..2d3e6692c 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -47,17 +47,17 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin $sBindPassword = \trim($this->Config()->Get('plugin', 'bind_password', '')); $sBaseDn = \trim($this->Config()->Get('plugin', 'base_dn', '')); $sObjectClass = \trim($this->Config()->Get('plugin', 'object_class', '')); - $sUidField = \trim($this->Config()->Get('plugin', 'uid_field', '')); - $sNameField = \trim($this->Config()->Get('plugin', 'name_field', '')); - $sEmailField = \trim($this->Config()->Get('plugin', 'mail_field', '')); + $sUidAttributes = \trim($this->Config()->Get('plugin', 'uid_attributes', '')); + $sNameAttributes = \trim($this->Config()->Get('plugin', 'name_attributes', '')); + $sEmailAttributes = \trim($this->Config()->Get('plugin', 'mail_attributes', '')); $sAllowedEmails = \trim($this->Config()->Get('plugin', 'allowed_emails', '')); - if (0 < \strlen($sLdapUri) && 0 < \strlen($sBaseDn) && 0 < \strlen($sObjectClass) && 0 < \strlen($sEmailField)) + if (0 < \strlen($sLdapUri) && 0 < \strlen($sBaseDn) && 0 < \strlen($sObjectClass) && 0 < \strlen($sEmailAttributes)) { include_once __DIR__.'/LdapContactsSuggestions.php'; $oProvider = new LdapContactsSuggestions(); - $oProvider->SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidField, $sNameField, $sEmailField, $sAllowedEmails); + $oProvider->SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidAttributes, $sNameAttributes, $sEmailAttributes, $sAllowedEmails); $mResult[] = $oProvider; } @@ -89,13 +89,13 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin ->SetDefaultValue('ou=People,dc=example,dc=com'), \RainLoop\Plugins\Property::NewInstance('object_class')->SetLabel('objectClass value') ->SetDefaultValue('inetOrgPerson'), - \RainLoop\Plugins\Property::NewInstance('uid_field')->SetLabel('uid attributes') + \RainLoop\Plugins\Property::NewInstance('uid_attributes')->SetLabel('uid attributes') ->SetDescription('LDAP attributes for userids, comma separated list in order of preference') ->SetDefaultValue('uid'), - \RainLoop\Plugins\Property::NewInstance('name_field')->SetLabel('Name attributes') + \RainLoop\Plugins\Property::NewInstance('name_attributes')->SetLabel('Name attributes') ->SetDescription('LDAP attributes for user names, comma separated list in order of preference') ->SetDefaultValue('displayName,cn,givenName,sn'), - \RainLoop\Plugins\Property::NewInstance('mail_field')->SetLabel('Mail attributes') + \RainLoop\Plugins\Property::NewInstance('mail_attributes')->SetLabel('Mail attributes') ->SetDescription('LDAP attributes for user email addresses, comma separated list in order of preference') ->SetDefaultValue('mailAddress,mail,mailAlternateAddress,mailAlias'), \RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails') From 3beef5a789d93993cc92d2a09b587e2dc3419a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 13:32:20 +0200 Subject: [PATCH 09/11] [ldap-contacts-suggestions] Support multiple objectClasses This is mostly for consistency with the other LDAP attributes. --- .../LdapContactsSuggestions.php | 25 +++++++++++++++---- plugins/ldap-contacts-suggestions/index.php | 9 ++++--- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index 4169ce763..f7134ab10 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -30,7 +30,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sObjectClass = 'inetOrgPerson'; + private $sObjectClasses = 'inetOrgPerson'; /** * @var string @@ -63,7 +63,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges * @param string $sBindDn * @param string $sBindPassword * @param string $sBaseDn - * @param string $sObjectClass + * @param string $sObjectClasses * @param string $sNameAttributes * @param string $sEmailAttributes * @param string $sUidAttributes @@ -71,7 +71,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges * * @return \LdapContactsSuggestions */ - public function SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidAttributes, $sNameAttributes, $sEmailAttributes, $sAllowedEmails) + public function SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClasses, $sUidAttributes, $sNameAttributes, $sEmailAttributes, $sAllowedEmails) { $this->sLdapUri = $sLdapUri; $this->bUseStartTLS = $bUseStartTLS; @@ -81,7 +81,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges $this->sBindPassword = $sBindPassword; } $this->sBaseDn = $sBaseDn; - $this->sObjectClass = $sObjectClass; + $this->sObjectClasses = $sObjectClasses; $this->sUidAttributes = $sUidAttributes; $this->sNameAttributes = $sNameAttributes; $this->sEmailAttributes = $sEmailAttributes; @@ -228,16 +228,30 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges '{imap:port}' => $oAccount->DomainIncPort() )); + $aObjectClasses = empty($this->sObjectClasses) ? array() : \explode(',', $this->sObjectClasses); $aEmails = empty($this->sEmailAttributes) ? array() : \explode(',', $this->sEmailAttributes); $aNames = empty($this->sNameAttributes) ? array() : \explode(',', $this->sNameAttributes); $aUIDs = empty($this->sUidAttributes) ? array() : \explode(',', $this->sUidAttributes); + $aObjectClasses = \array_map('trim', $aObjectClasses); $aEmails = \array_map('trim', $aEmails); $aNames = \array_map('trim', $aNames); $aUIDs = \array_map('trim', $aUIDs); $aFields = \array_merge($aEmails, $aNames, $aUIDs); + $iObjCount = 0; + $sObjFilter = ''; + foreach ($aObjectClasses as $sItem) + { + if (!empty($sItem)) + { + $iObjCount++; + $sObjFilter .= '(objectClass='.$sItem.')'; + } + } + + $aItems = array(); $sSubFilter = ''; foreach ($aFields as $sItem) @@ -249,7 +263,8 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges } } - $sFilter = '(&(objectclass='.$this->sObjectClass.')'; + $sFilter = '(&'; + $sFilter .= (1 < $iObjCount ? '(|' : '').$sObjFilter.(1 < $iObjCount ? ')' : ''); $sFilter .= (1 < count($aItems) ? '(|' : '').$sSubFilter.(1 < count($aItems) ? ')' : ''); $sFilter .= ')'; diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 2d3e6692c..8ad39ae3b 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -46,18 +46,18 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin $sBindDn = \trim($this->Config()->Get('plugin', 'bind_dn', '')); $sBindPassword = \trim($this->Config()->Get('plugin', 'bind_password', '')); $sBaseDn = \trim($this->Config()->Get('plugin', 'base_dn', '')); - $sObjectClass = \trim($this->Config()->Get('plugin', 'object_class', '')); + $sObjectClasses = \trim($this->Config()->Get('plugin', 'object_classes', '')); $sUidAttributes = \trim($this->Config()->Get('plugin', 'uid_attributes', '')); $sNameAttributes = \trim($this->Config()->Get('plugin', 'name_attributes', '')); $sEmailAttributes = \trim($this->Config()->Get('plugin', 'mail_attributes', '')); $sAllowedEmails = \trim($this->Config()->Get('plugin', 'allowed_emails', '')); - if (0 < \strlen($sLdapUri) && 0 < \strlen($sBaseDn) && 0 < \strlen($sObjectClass) && 0 < \strlen($sEmailAttributes)) + if (0 < \strlen($sLdapUri) && 0 < \strlen($sBaseDn) && 0 < \strlen($sObjectClasses) && 0 < \strlen($sEmailAttributes)) { include_once __DIR__.'/LdapContactsSuggestions.php'; $oProvider = new LdapContactsSuggestions(); - $oProvider->SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClass, $sUidAttributes, $sNameAttributes, $sEmailAttributes, $sAllowedEmails); + $oProvider->SetConfig($sLdapUri, $bUseStartTLS, $sBindDn, $sBindPassword, $sBaseDn, $sObjectClasses, $sUidAttributes, $sNameAttributes, $sEmailAttributes, $sAllowedEmails); $mResult[] = $oProvider; } @@ -87,7 +87,8 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin \RainLoop\Plugins\Property::NewInstance('base_dn')->SetLabel('Search base DN') ->SetDescription('DN to use as the search base. Supported tokens: {domain}, {domain:dc}, {email}, {email:user}, {email:domain}, {login}, {imap:login}, {imap:host}, {imap:port}') ->SetDefaultValue('ou=People,dc=example,dc=com'), - \RainLoop\Plugins\Property::NewInstance('object_class')->SetLabel('objectClass value') + \RainLoop\Plugins\Property::NewInstance('object_classes')->SetLabel('objectClasses to use') + ->SetDescription('LDAP objectClasses to search for, comma separated list') ->SetDefaultValue('inetOrgPerson'), \RainLoop\Plugins\Property::NewInstance('uid_attributes')->SetLabel('uid attributes') ->SetDescription('LDAP attributes for userids, comma separated list in order of preference') From 9876597542cd1bffad903dffe6ec561f58293ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 22 Aug 2021 13:36:05 +0200 Subject: [PATCH 10/11] [ldap-contacts-suggestions] Bump version number --- plugins/ldap-contacts-suggestions/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 8ad39ae3b..3a5c06c1e 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -4,9 +4,9 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin { const NAME = 'Contacts suggestions (LDAP)', - VERSION = '2.0', + VERSION = '2.1', CATEGORY = 'Security', - DESCRIPTION = 'Plugin that adds functionality to get contacts from LDAP on compose page.'; + DESCRIPTION = 'Plugin to get contacts suggestions from LDAP.'; public function Init() : void { From 5cbc3ed3f97e22cb91023103b6f8c4e8257f313a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Mon, 23 Aug 2021 10:14:42 +0200 Subject: [PATCH 11/11] [ldap-contacts-suggestions] Default to localhost instead of 127.0.0.1 No need to default to IPv4 only. --- plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php | 2 +- plugins/ldap-contacts-suggestions/index.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php index f7134ab10..8a10443b2 100644 --- a/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php +++ b/plugins/ldap-contacts-suggestions/LdapContactsSuggestions.php @@ -5,7 +5,7 @@ class LdapContactsSuggestions implements \RainLoop\Providers\Suggestions\ISugges /** * @var string */ - private $sLdapUri = 'ldap://127.0.0.1:389'; + private $sLdapUri = 'ldap://localhost:389'; /** * @var bool diff --git a/plugins/ldap-contacts-suggestions/index.php b/plugins/ldap-contacts-suggestions/index.php index 3a5c06c1e..67ad954de 100644 --- a/plugins/ldap-contacts-suggestions/index.php +++ b/plugins/ldap-contacts-suggestions/index.php @@ -74,7 +74,7 @@ class LdapContactsSuggestionsPlugin extends \RainLoop\Plugins\AbstractPlugin return array( \RainLoop\Plugins\Property::NewInstance('ldap_uri')->SetLabel('LDAP URI') ->SetDescription('LDAP server URI(s), space separated') - ->SetDefaultValue('ldap://127.0.0.1:389'), + ->SetDefaultValue('ldap://localhost:389'), \RainLoop\Plugins\Property::NewInstance('use_start_tls')->SetLabel('Use StartTLS') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(True),