Merge pull request #1454 from S-A-L13/master

Added function for ldap-identities plugin to filter by mail prefixes (allow compatibility for e.g. Exchange and others)
This commit is contained in:
Maarten 2024-02-27 22:34:48 +01:00 committed by GitHub
commit 1722d88f1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 62 additions and 6 deletions

View file

@ -8,6 +8,7 @@ class LdapConfig
public const CONFIG_SERVER = "server"; public const CONFIG_SERVER = "server";
public const CONFIG_PROTOCOL_VERSION = "server_version"; public const CONFIG_PROTOCOL_VERSION = "server_version";
public const CONFIG_STARTTLS = "starttls"; public const CONFIG_STARTTLS = "starttls";
public const CONFIG_MAIL_PREFIX = "mail_prefix";
public const CONFIG_BIND_USER = "bind_user"; public const CONFIG_BIND_USER = "bind_user";
public const CONFIG_BIND_PASSWORD = "bind_password"; public const CONFIG_BIND_PASSWORD = "bind_password";
@ -30,6 +31,7 @@ class LdapConfig
public $server; public $server;
public $protocol; public $protocol;
public $starttls; public $starttls;
public $mail_prefix;
public $bind_user; public $bind_user;
public $bind_password; public $bind_password;
public $user_base; public $user_base;
@ -51,6 +53,7 @@ class LdapConfig
$ldap->server = trim($config->Get("plugin", self::CONFIG_SERVER)); $ldap->server = trim($config->Get("plugin", self::CONFIG_SERVER));
$ldap->protocol = (int)trim($config->Get("plugin", self::CONFIG_PROTOCOL_VERSION, 3)); $ldap->protocol = (int)trim($config->Get("plugin", self::CONFIG_PROTOCOL_VERSION, 3));
$ldap->starttls = (bool)trim($config->Get("plugin", self::CONFIG_STARTTLS)); $ldap->starttls = (bool)trim($config->Get("plugin", self::CONFIG_STARTTLS));
$ldap->mail_prefix = trim($config->Get("plugin", self::CONFIG_MAIL_PREFIX));
$ldap->bind_user = trim($config->Get("plugin", self::CONFIG_BIND_USER)); $ldap->bind_user = trim($config->Get("plugin", self::CONFIG_BIND_USER));
$ldap->bind_password = trim($config->Get("plugin", self::CONFIG_BIND_PASSWORD)); $ldap->bind_password = trim($config->Get("plugin", self::CONFIG_BIND_PASSWORD));
$ldap->user_base = trim($config->Get("plugin", self::CONFIG_USER_BASE)); $ldap->user_base = trim($config->Get("plugin", self::CONFIG_USER_BASE));

View file

@ -69,7 +69,8 @@ class LdapIdentities implements IIdentities
$this->config->user_base, $this->config->user_base,
$this->config->user_objectclass, $this->config->user_objectclass,
$this->config->user_field_name, $this->config->user_field_name,
$this->config->user_field_mail $this->config->user_field_mail,
$this->config->mail_prefix
); );
} catch (LdapException $e) { } catch (LdapException $e) {
return []; // exceptions are only thrown from the handleerror function that does logging already return []; // exceptions are only thrown from the handleerror function that does logging already
@ -104,7 +105,8 @@ class LdapIdentities implements IIdentities
$this->config->group_base, $this->config->group_base,
$this->config->group_objectclass, $this->config->group_objectclass,
$this->config->group_field_name, $this->config->group_field_name,
$this->config->group_field_mail $this->config->group_field_mail,
$this->config->mail_prefix
); );
} catch (LdapException $e) { } catch (LdapException $e) {
return []; // exceptions are only thrown from the handleerror function that does logging already return []; // exceptions are only thrown from the handleerror function that does logging already
@ -241,7 +243,7 @@ class LdapIdentities implements IIdentities
* @return LdapResult[] * @return LdapResult[]
* @throws LdapException * @throws LdapException
*/ */
private function FindLdapResults(string $searchField, string $searchValue, string $searchBase, string $objectClass, string $nameField, string $mailField): array private function FindLdapResults(string $searchField, string $searchValue, string $searchBase, string $objectClass, string $nameField, string $mailField, string $mailPrefix): array
{ {
$this->EnsureBound(); $this->EnsureBound();
@ -261,6 +263,8 @@ class LdapIdentities implements IIdentities
return []; return [];
} }
$entries = $this->CleanupMailAddresses($entries, $mailField, $mailPrefix);
$results = []; $results = [];
for ($i = 0; $i < $entries["count"]; $i++) { for ($i = 0; $i < $entries["count"]; $i++) {
$entry = $entries[$i]; $entry = $entries[$i];
@ -276,6 +280,49 @@ class LdapIdentities implements IIdentities
return $results; return $results;
} }
// Function CleanupMailAddresses(): If a prefix is given this function removes addresses without / with the wrong prefix and then the prefix itself from all remaining values.
// This is usefull for example for importing Active Directory LDAP entry "proxyAddresses" which can hold different address types with prefixes like "X400:", "smtp:" "sip:" and others.
/**
@param array $entries
@param string $mailField
@paraam string $mailPrefix
@return array
*/
private function CleanupMailAddresses(array $entries, string $mailField, string $mailPrefix)
{
if (!empty($mailPrefix)) {
for ($i = 0; $i < $entries["count"]; $i++) {
// Remove addresses without the given prefix
$entries[$i]["$mailField"] = array_filter($entries[$i]["$mailField"],
function($prefixMail)
{
// $mailPrefix can't be used here, because it's nailed to the CleanupMailAddresses function and can't be passed to the array_filter function afaik.
// Ideas to avoid this are welcome.
if (stripos($prefixMail, $this->config->mail_prefix) === 0) {
return TRUE;
}
return FALSE;
}
);
// Set "count" to new value
$newcount = count($entries[$i]["$mailField"]);
if (array_key_exists("count", $entries[$i]["$mailField"])) {
$newcount = $newcount - 1;
}
$entries[$i]["$mailField"]["count"] = $newcount;
// Remove the prefix
for ($j = 0; $j < $entries[$i]["$mailField"]["count"]; $j++) {
$mailPrefixLen = mb_strlen($mailPrefix);
$entries[$i]["$mailField"][$j] = substr($entries[$i]["$mailField"][$j], $mailPrefixLen);
}
}
}
return $entries;
}
/** /**
* @param array $entry * @param array $entry
* @param string $attribute * @param string $attribute

View file

@ -8,10 +8,10 @@ class LdapIdentitiesPlugin extends AbstractPlugin
{ {
const const
NAME = 'LDAP Identities', NAME = 'LDAP Identities',
VERSION = '2.2', VERSION = '2.3',
AUTHOR = 'FWest98', AUTHOR = 'FWest98',
URL = 'https://github.com/FWest98', URL = 'https://github.com/FWest98',
RELEASE = '2024-02-22', RELEASE = '2024-02-27',
REQUIRED = '2.20.0', REQUIRED = '2.20.0',
CATEGORY = 'Accounts', CATEGORY = 'Accounts',
DESCRIPTION = 'Adds functionality to import account identities from LDAP.'; DESCRIPTION = 'Adds functionality to import account identities from LDAP.';
@ -57,13 +57,19 @@ class LdapIdentitiesPlugin extends AbstractPlugin
->SetLabel("LDAP Protocol Version") ->SetLabel("LDAP Protocol Version")
->SetType(PluginPropertyType::SELECTION) ->SetType(PluginPropertyType::SELECTION)
->SetDefaultValue([2, 3]), ->SetDefaultValue([2, 3]),
Property::NewInstance(LdapConfig::CONFIG_STARTTLS) Property::NewInstance(LdapConfig::CONFIG_STARTTLS)
->SetLabel("Use StartTLS") ->SetLabel("Use StartTLS")
->SetType(PluginPropertyType::BOOL) ->SetType(PluginPropertyType::BOOL)
->SetDescription("Whether or not to use TLS encrypted connection") ->SetDescription("Whether or not to use TLS encrypted connection")
->SetDefaultValue(true), ->SetDefaultValue(true),
Property::NewInstance(LdapConfig::CONFIG_MAIL_PREFIX)
->SetLabel("Email prefix")
->SetType(PluginPropertyType::STRING)
->SetDescription("Only addresses with this prefix will be used as identity. The prefix is removed from the identity list.\nThis is useful for example to import identities from Exchange, which stores mail addresses in the ProxyAddresses attribut of Active Directory with \"smtp:\" as prefix. (e.g. \"smtp:john.doe@topsecret.info\")\n-> To use addresses set by Exchange use \"smtp:\" as prefix.")
->SetDefaultValue(""),
Property::NewInstance(LdapConfig::CONFIG_BIND_USER) Property::NewInstance(LdapConfig::CONFIG_BIND_USER)
->SetLabel("Bind User DN") ->SetLabel("Bind User DN")
->SetDescription("The user to use for binding to the LDAP server. Should be a DN or RDN. Leave empty for anonymous bind") ->SetDescription("The user to use for binding to the LDAP server. Should be a DN or RDN. Leave empty for anonymous bind")