diff --git a/wp-content/plugins/authldap/.phive/phars.xml b/wp-content/plugins/authldap/.phive/phars.xml
index 2825dbbc..34099137 100644
--- a/wp-content/plugins/authldap/.phive/phars.xml
+++ b/wp-content/plugins/authldap/.phive/phars.xml
@@ -3,4 +3,6 @@
+
+
diff --git a/wp-content/plugins/authldap/authLdap.php b/wp-content/plugins/authldap/authLdap.php
index 542ea85e..cbe009d3 100644
--- a/wp-content/plugins/authldap/authLdap.php
+++ b/wp-content/plugins/authldap/authLdap.php
@@ -4,7 +4,7 @@
Plugin Name: AuthLDAP
Plugin URI: https://github.com/heiglandreas/authLdap
Description: This plugin allows you to use your existing LDAP as authentication base for WordPress
-Version: 2.5.9
+Version: 2.6.0
Author: Andreas Heigl
Author URI: http://andreas.heigl.org
License: MIT
@@ -373,10 +373,10 @@ function authLdap_login($user, $username, $password, $already_md5 = false)
// we only need this if either LDAP groups are disabled or
// if the WordPress role of the user overrides LDAP groups
- if (!$authLDAPGroupEnable || !$authLDAPGroupOverUser) {
- $role = authLdap_user_role($uid);
- if ($role !== '') {
- $roles[] = $role;
+ if (!$authLDAPGroupEnable || $authLDAPGroupOverUser) {
+ $userRoles = authLdap_user_role($uid);
+ if ($userRoles !== []) {
+ $roles = array_merge($roles, $userRoles);
}
// TODO, this needs to be revised, it seems, like authldap is taking only the first role
// even if in WP there are assigned multiple.
@@ -430,23 +430,23 @@ function authLdap_login($user, $username, $password, $already_md5 = false)
$user_info['user_nicename'] = '';
// first name
- if (isset($attribs[0][strtolower($authLDAPNameAttr)][0])) {
- $user_info['first_name'] = $attribs[0][strtolower($authLDAPNameAttr)][0];
+ if (isset($attribs[0][strtolower((string) $authLDAPNameAttr)][0])) {
+ $user_info['first_name'] = $attribs[0][strtolower((string) $authLDAPNameAttr)][0];
}
// last name
- if (isset($attribs[0][strtolower($authLDAPSecName)][0])) {
- $user_info['last_name'] = $attribs[0][strtolower($authLDAPSecName)][0];
+ if (isset($attribs[0][strtolower((string) $authLDAPSecName)][0])) {
+ $user_info['last_name'] = $attribs[0][strtolower((string) $authLDAPSecName)][0];
}
// mail address
- if (isset($attribs[0][strtolower($authLDAPMailAttr)][0])) {
- $user_info['user_email'] = $attribs[0][strtolower($authLDAPMailAttr)][0];
+ if (isset($attribs[0][strtolower((string) $authLDAPMailAttr)][0])) {
+ $user_info['user_email'] = $attribs[0][strtolower((string) $authLDAPMailAttr)][0];
}
// website
- if (isset($attribs[0][strtolower($authLDAPWebAttr)][0])) {
- $user_info['user_url'] = $attribs[0][strtolower($authLDAPWebAttr)][0];
+ if (isset($attribs[0][strtolower((string) $authLDAPWebAttr)][0])) {
+ $user_info['user_url'] = $attribs[0][strtolower((string) $authLDAPWebAttr)][0];
}
// display name, nickname, nicename
if (array_key_exists('first_name', $user_info)) {
@@ -556,20 +556,20 @@ function authLdap_get_uid($username)
* Returns empty string if not found.
*
* @param int $uid wordpress user id
- * @return string role, empty if none found
+ * @return array roles, empty if none found
*/
function authLdap_user_role($uid)
{
global $wpdb, $wp_roles;
if (!$uid) {
- return '';
+ return [];
}
/** @var array $usercapabilities */
$usercapabilities = get_user_meta($uid, "{$wpdb->prefix}capabilities", true);
if (!is_array($usercapabilities)) {
- return '';
+ return [];
}
/** @var array} $editable_roles */
@@ -578,10 +578,10 @@ function authLdap_user_role($uid)
// By using this approach we are now using the order of the roles from the WP_Roles object
// and not from the capabilities any more.
$userroles = array_keys(array_intersect_key($editable_roles, $usercapabilities));
- $role = ($userroles !== []) ? $userroles[0] : '';
- authLdap_debug("Existing user's role: {$role}");
- return $role;
+ authLdap_debug(sprintf("Existing user's roles: %s", implode(', ', $userroles)));
+
+ return $userroles;
}
/**
diff --git a/wp-content/plugins/authldap/behat.yml.dist b/wp-content/plugins/authldap/behat.yml.dist
new file mode 100644
index 00000000..0f63330a
--- /dev/null
+++ b/wp-content/plugins/authldap/behat.yml.dist
@@ -0,0 +1 @@
+default:
diff --git a/wp-content/plugins/authldap/features/bootstrap/FeatureContext.php b/wp-content/plugins/authldap/features/bootstrap/FeatureContext.php
new file mode 100644
index 00000000..1e495b2c
--- /dev/null
+++ b/wp-content/plugins/authldap/features/bootstrap/FeatureContext.php
@@ -0,0 +1,289 @@
+set(Options::URI, 'ldap://cn=admin,dc=example,dc=org:insecure@openldap:389/dc=example,dc=org');
+ $options->set(Options::ENABLED, true);
+ $options->set(Options::FILTER, 'uid=%1$s');
+ $options->set(Options::DEFAULT_ROLE, 'subscriber');
+ $options->set(Options::DEBUG, true);
+ $options->set(Options::NAME_ATTR, 'cn');
+
+ exec(sprintf(
+ 'wp --allow-root option update --format=json authLDAPOptions \'%1$s\'',
+ json_encode($options->toArray())
+ ));
+ }
+
+ /**
+ * @Given configuration value :arg1 is set to :arg2
+ */
+ public function configurationValueIsSetTo($arg1, $arg2)
+ {
+ exec(sprintf(
+ 'wp --allow-root option patch update authLDAPOptions %1$s %2$s --format=json',
+ $arg1,
+ "'" . json_encode($arg2) . "'"
+ ));
+ }
+
+ /**
+ * @Given an LDAP user :arg1 with name :arg2, password :arg3 and email :arg4 exists
+ */
+ public function anLdapUserWithNamePasswordAndEmailExists($arg1, $arg2, $arg3, $arg4)
+ {
+ exec(sprintf(
+ 'ldapadd -x -H %1$s -D "%2$s" -w %3$s <res = $client->post('http://wp/wp-login.php', [
+ 'cookies' => CookieJar::fromArray([
+ 'wordpress_test_cookie' => 'test',
+ 'XDEBUG_SESSION' => 'PHPSTORM',
+ ], 'http://wp'),
+ 'form_params' => [
+ 'log' => $arg1,
+ 'pwd' => $arg2,
+ ],
+ 'allow_redirects' => false
+ ]);
+ }
+
+ /**
+ * @Then the login suceeds
+ */
+ public function theLoginSuceeds()
+ {
+ Assert::isInstanceOf($this->res, Response::class);
+ Assert::eq( $this->res->getStatusCode(), 302);
+ Assert::startsWith($this->res->getHeader('Location')[0], 'http://localhost/wp-admin');
+ }
+
+ /**
+ * @Then a new WordPress user :arg1 was created with name :arg2 and email :arg3
+ */
+ public function aNewWordpressUserWasCreatedWithNameAndEmail($arg1, $arg2, $arg3)
+ {
+ exec(sprintf(
+ 'wp --allow-root user get %1$s --format=json 2> /dev/null',
+ $arg1,
+ ), $output, $result);
+ Assert::eq(0, $result);
+ $user = json_decode($output[0], true);
+ Assert::eq($user['user_email'], $arg3);
+ Assert::eq($user['display_name'], $arg2);
+ Assert::greaterThan(
+ new DateTimeImmutable($user['user_registered']),
+ (new DateTimeImmutable())->sub(new DateInterval('PT1M')),
+ );
+ }
+
+ /**
+ * @Then the WordPress user :arg1 is member of role :arg2
+ */
+ public function theWordpressUserIsMemberOfRole($arg1, $arg2)
+ {
+ exec(sprintf(
+ 'wp --allow-root user get %1$s --format=json 2> /dev/null',
+ $arg1,
+ ), $output, $result);
+ Assert::eq(0, $result);
+ $user = json_decode($output[0], true);
+ $roles = array_map(function($item): string {
+ return trim($item);
+ }, explode(',', $user['roles']));
+ Assert::inArray($arg2, $roles);
+ }
+
+ /**
+ * @Given LDAP user :arg1 is member of LDAP group :arg2
+ */
+ public function ldapUserIsMemberOfLdapGroup($arg1, $arg2)
+ {
+ exec(sprintf(
+ 'ldapmodify -x -H %1$s -D "%2$s" -w %3$s 2>&1 < /dev/null',
+ $arg1,
+ ), $output, $result);
+ Assert::eq(0, $result);
+ $user = json_decode($output[0], true);
+ $roles = array_map(function($item): string {
+ return trim($item);
+ }, explode(',', $user['roles']));
+ Assert::false(in_array($arg2, $roles));
+
+ }
+}
diff --git a/wp-content/plugins/authldap/features/log in using no groups at all.feature b/wp-content/plugins/authldap/features/log in using no groups at all.feature
new file mode 100644
index 00000000..b8515c84
--- /dev/null
+++ b/wp-content/plugins/authldap/features/log in using no groups at all.feature
@@ -0,0 +1,63 @@
+Feature: Log in without group assignment
+ Scenario: Login without group assignment with
+ Given a default configuration
+ And configuration value "GroupEnable" is set to "false"
+ And configuration value "DefaultRole" is set to "subscriber"
+ And an LDAP user "ldapuser" with name "LDAP User", password "P@ssw0rd" and email "ldapuser@example.com" exists
+ And an LDAP group "ldapgroup" exists
+ And LDAP user "ldapuser" is member of LDAP group "ldapgroup"
+ And a WordPress user "wordpressuser" with name "WordPress_User" and email "wordpressuser@example.com" exists
+ And a WordPress role "wordpressrole" exists
+ And WordPress user "wordpressuser" has role "wordpressrole"
+ And a WordPress user "ldapuser" does not exist
+ When LDAP user "ldapuser" logs in with password "P@ssw0rd"
+ Then the login suceeds
+ And a new WordPress user "ldapuser" was created with name "LDAP User" and email "ldapuser@example.com"
+ And the WordPress user "ldapuser" is member of role "subscriber"
+
+ Scenario: Login with group assignment to multiple groups where only first wordpress group is used
+ Given a default configuration
+ And configuration value "GroupEnable" is set to "true"
+ And configuration value "DefaultRole" is set to "subscriber"
+ And configuration value "Groups" is set to "administrator=ldapgroup" and "editor=ldapgroup"
+ And configuration value "GroupAttr" is set to "cn"
+ And configuration value "GroupFilter" is set to "uniquemember=%dn%"
+ And configuration value "GroupOverUser" is set to "true"
+ And an LDAP user "ldapuser" with name "LDAP User", password "P@ssw0rd" and email "ldapuser@example.com" exists
+ And an LDAP group "ldapgroup" exists
+ And LDAP user "ldapuser" is member of LDAP group "ldapgroup"
+ And a WordPress user "wordpressuser" with name "WordPress_User" and email "wordpressuser@example.com" exists
+ And a WordPress role "wordpressrole" exists
+ And WordPress user "wordpressuser" has role "wordpressrole"
+ And a WordPress user "ldapuser" does not exist
+ When LDAP user "ldapuser" logs in with password "P@ssw0rd"
+ Then the login suceeds
+ And a new WordPress user "ldapuser" was created with name "LDAP User" and email "ldapuser@example.com"
+ And the WordPress user "ldapuser" is member of role "administrator"
+ And the WordPress user "ldapuser" is not member of role "editor"
+ And the WordPress user "ldapuser" is not member of role "subscriber"
+
+ Scenario: Second Login with group assignment to multiple groups where only first wordpress group is used.
+ Given a default configuration
+ And configuration value "GroupEnable" is set to "true"
+ And configuration value "DefaultRole" is set to "subscriber"
+ And configuration value "Groups" is set to "administrator=ldapgroup" and "editor=ldapgroup"
+ And configuration value "GroupAttr" is set to "cn"
+ And configuration value "GroupFilter" is set to "uniquemember=%dn%"
+ And configuration value "GroupOverUser" is set to "false"
+ And an LDAP user "ldapuser" with name "LDAP User", password "P@ssw0rd" and email "ldapuser@example.com" exists
+ And an LDAP group "ldapgroup" exists
+ And LDAP user "ldapuser" is member of LDAP group "ldapgroup"
+ And a WordPress user "wordpressuser" with name "WordPress_User" and email "wordpressuser@example.com" exists
+ And a WordPress role "wordpressrole" exists
+ And WordPress user "wordpressuser" has role "wordpressrole"
+ And a WordPress user "ldapuser" does not exist
+ And LDAP user "ldapuser" logs in with password "P@ssw0rd"
+ And WordPress user "ldapuser" has role "wordpressrole"
+ And the WordPress user "ldapuser" is member of role "wordpressrole"
+ When LDAP user "ldapuser" logs in with password "P@ssw0rd"
+ Then the login suceeds
+ And the WordPress user "ldapuser" is member of role "administrator"
+ And the WordPress user "ldapuser" is member of role "wordpressrole"
+ And the WordPress user "ldapuser" is not member of role "editor"
+ And the WordPress user "ldapuser" is not member of role "subscriber"
diff --git a/wp-content/plugins/authldap/readme.txt b/wp-content/plugins/authldap/readme.txt
index 1c6084da..00476fe6 100644
--- a/wp-content/plugins/authldap/readme.txt
+++ b/wp-content/plugins/authldap/readme.txt
@@ -2,7 +2,7 @@
Contributors: heiglandreas
Tags: ldap, auth, authentication, active directory, AD, openLDAP, Open Directory
Requires at least: 2.5.0
-Tested up to: 6.3.0
+Tested up to: 6.4.0
Requires PHP: 7.4
Stable tag: trunk
License: MIT
@@ -47,6 +47,11 @@ Please see https://github.com/heiglandreas/authLdap/blob/master/SECURITY.md for
== Changelog ==
+= 2.6.0 =
+
+* Fix reducing assigned WordPress roles to single role on login when WordPress roles shall be kept
+* Add Behavioural testing and first 3 scenarios
+
= 2.5.9 =
* Adds information about security-contacts
diff --git a/wp-content/plugins/authldap/src/Exception/UnknownOption.php b/wp-content/plugins/authldap/src/Exception/UnknownOption.php
new file mode 100644
index 00000000..b2737b19
--- /dev/null
+++ b/wp-content/plugins/authldap/src/Exception/UnknownOption.php
@@ -0,0 +1,24 @@
+
+ *
+ * Licensed under the MIT-license. For details see the included file LICENSE.md
+ */
+
+namespace Org_Heigl\AuthLdap\Exception;
+
+use RuntimeException;
+
+class UnknownOption extends RuntimeException
+{
+ public static function withKey(string $key): self
+ {
+ return new self(sprintf(
+ 'An option "%1$s" is not known',
+ $key
+ ));
+ }
+}
diff --git a/wp-content/plugins/authldap/src/LdapUri.php b/wp-content/plugins/authldap/src/LdapUri.php
index 2d2169fc..265ec96e 100644
--- a/wp-content/plugins/authldap/src/LdapUri.php
+++ b/wp-content/plugins/authldap/src/LdapUri.php
@@ -116,7 +116,7 @@ final class LdapUri
if (isset($url['pass'])) {
$this->password = $url['pass'];
}
- if ($this->scheme === 'ldaps' && $this->port = 389) {
+ if ($this->scheme === 'ldaps' && $this->port === 389) {
$this->port = 636;
}
diff --git a/wp-content/plugins/authldap/src/OptionFactory.php b/wp-content/plugins/authldap/src/OptionFactory.php
new file mode 100644
index 00000000..aa2955e4
--- /dev/null
+++ b/wp-content/plugins/authldap/src/OptionFactory.php
@@ -0,0 +1,27 @@
+
+ *
+ * Licensed under the MIT-license. For details see the included file LICENSE.md
+ */
+
+namespace Org_Heigl\AuthLdap;
+
+use function json_decode;
+
+class OptionFactory
+{
+ public function fromJson(string $json): Options
+ {
+ $option = new Options();
+ $content = json_decode($json, true);
+ foreach ($content as $key => $value) {
+ $option->set($key, $value);
+ }
+
+ return $option;
+ }
+}
diff --git a/wp-content/plugins/authldap/src/Options.php b/wp-content/plugins/authldap/src/Options.php
new file mode 100644
index 00000000..ee7b969c
--- /dev/null
+++ b/wp-content/plugins/authldap/src/Options.php
@@ -0,0 +1,90 @@
+
+ *
+ * Licensed under the MIT-license. For details see the included file LICENSE.md
+ */
+
+namespace Org_Heigl\AuthLdap;
+
+use Org_Heigl\AuthLdap\Exception\UnknownOption;
+use function array_key_exists;
+
+class Options
+{
+ public const ENABLED = 'Enabled';
+ public const CACHE_PW = 'CachePW';
+ public const URI = 'URI';
+ public const URI_SEPARATOR = 'URISeparator';
+ public const FILTER = 'Filter';
+ public const NAME_ATTR = 'NameAttr';
+ public const SEC_NAME = 'SecName';
+ public const UID_ATTR = 'UidAttr';
+ public const MAIL_ATTR = 'MailAttr';
+ public const WEB_ATTR = 'WebAttr';
+ public const GROUPS = 'Groups';
+ public const DEBUG = 'Debug';
+ public const GROUP_ATTR = 'GroupAttr';
+ public const GROUP_FILTER = 'GroupFilter';
+ public const DEFAULT_ROLE = 'DefaultRole';
+ public const GROUP_ENABLE = 'GroupEnable';
+ public const GROUP_OVER_USER = 'GroupOverUser';
+ public const VERSION = 'Version';
+ public const DO_NOT_OVERWRITE_NON_LDAP_USERS = 'DoNotOverwriteNonLdapUsers';
+
+ private array $settings = [
+ 'Enabled' => false,
+ 'CachePW' => false,
+ 'URI' => '',
+ 'URISeparator' => ' ',
+ 'Filter' => '', // '(uid=%s)'
+ 'NameAttr' => '', // 'name'
+ 'SecName' => '',
+ 'UidAttr' => '', // 'uid'
+ 'MailAttr' => '', // 'mail'
+ 'WebAttr' => '',
+ 'Groups' => [],
+ 'Debug' => false,
+ 'GroupAttr' => '', // 'gidNumber'
+ 'GroupFilter' => '', // '(&(objectClass=posixGroup)(memberUid=%s))'
+ 'DefaultRole' => '',
+ 'GroupEnable' => true,
+ 'GroupOverUser' => true,
+ 'Version' => 1,
+ 'DoNotOverwriteNonLdapUsers' => false,
+ ];
+
+ public function get(string $key)
+ {
+ if (! array_key_exists($key, $this->settings)) {
+ throw UnknownOption::withKey($key);
+ }
+
+ return $this->settings[$key];
+ }
+
+ public function has(string $key): bool
+ {
+ return array_key_exists($key, $this->settings);
+ }
+
+ /**
+ * @param mixed $value
+ */
+ public function set(string $key, $value): void
+ {
+ if (! array_key_exists($key, $this->settings)) {
+ throw UnknownOption::withKey($key);
+ }
+
+ $this->settings[$key] = $value;
+ }
+
+ public function toArray(): array
+ {
+ return $this->settings;
+ }
+}
diff --git a/wp-content/plugins/authldap/src/Wrapper/Ldap.php b/wp-content/plugins/authldap/src/Wrapper/Ldap.php
index 530de8e8..48b01d34 100644
--- a/wp-content/plugins/authldap/src/Wrapper/Ldap.php
+++ b/wp-content/plugins/authldap/src/Wrapper/Ldap.php
@@ -18,6 +18,7 @@ use function ldap_get_entries;
use function ldap_set_option;
use function ldap_start_tls;
use function ldap_unbind;
+use function var_dump;
final class Ldap implements LdapInterface
{