Compare commits
5 Commits
e73c3de31d
...
e13bab0b76
Author | SHA1 | Date | |
---|---|---|---|
e13bab0b76 | |||
cd379e1d95 | |||
65c751c1d9 | |||
db5f4b72eb | |||
ef209dc569 |
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phive xmlns="https://phar.io/phive">
|
||||
<phar name="phpunit" version="^9.5.21" installed="9.5.21" location="./tools/phpunit" copy="true"/>
|
||||
<phar name="phpcs" version="^3.7.1" installed="3.7.1" location="./tools/phpcs" copy="true"/>
|
||||
<phar name="phpcbf" version="^3.7.1" installed="3.7.1" location="./tools/phpcbf" copy="true"/>
|
||||
<phar name="behat/behat" version="^3.13.0" installed="3.13.0" location="./tools/behat" copy="true"/>
|
||||
<phar name="wp-cli/wp-cli" version="^2.9.0" installed="2.9.0" location="./tools/wp-cli" copy="true"/>
|
||||
</phive>
|
@ -1,7 +0,0 @@
|
||||
Copyright <YEAR> <COPYRIGHT HOLDER>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,95 +0,0 @@
|
||||
# authLDAP
|
||||
|
||||
[](https://gitter.im/heiglandreas/authLdap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Use your existing LDAP as authentication-backend for your wordpress!
|
||||
|
||||
[](https://github.com/heiglandreas/authLdap/actions/workflows/tests.yml)
|
||||
[](https://wordpress.org/plugins/authldap/stats/)
|
||||
[](https://wordpress.org/plugins/authldap/)
|
||||
[](https://wordpress.org/plugins/authldap/)
|
||||
[](https://codeclimate.com/github/heiglandreas/authLdap)
|
||||
[](https://codecov.io/gh/heiglandreas/authLdap)
|
||||
|
||||
So what are the differences to other Wordpress-LDAP-Authentication-Plugins?
|
||||
|
||||
* **Flexible**: You are totaly free in which LDAP-backend to use. Due to the extensive configuration you can
|
||||
freely decide how to do the authentication of your users. It simply depends on your
|
||||
filters
|
||||
* **Independent**: As soon as a user logs in, it is added/updated to the Wordpress' user-database
|
||||
to allow wordpress to always use the correct data. You only have to administer your users once.
|
||||
* **Failsafe**: Due to the users being created in Wordpress' User-database they can
|
||||
also log in when the LDAP-backend currently is gone.
|
||||
* **Role-Aware**: You can map Wordpress' roles to values of an existing LDAP-attribute.
|
||||
|
||||
## How does the plugin work?
|
||||
|
||||
Well, as a matter of fact it is rather simple. The plugin verifies, that the user
|
||||
seeking authentification can bind to the LDAP using the provided password.
|
||||
|
||||
If that is so, the user is either created or updated in the wordpress-user-database.
|
||||
This update includes the provided password (so the wordpress can authenticate users
|
||||
even without the LDAP), the users name according to the authLDAP-preferences and
|
||||
the status of the user depending on the groups-settings of the authLDAP-preferences
|
||||
|
||||
Writing this plugin would not have been as easy as it has been, without the
|
||||
wonderfull plugin of Alistair Young from http://www.weblogs.uhi.ac.uk/sm00ay/?p=45
|
||||
|
||||
## Configuration
|
||||
|
||||
### Usage Settings
|
||||
|
||||
* **Enable Authentication via LDAP** Whether you want to enable authLdap for login or not
|
||||
* **debug authLdap** When you have problems with authentication via LDAP you can enable a debugging mode here.
|
||||
* **Save entered Password** Decide whether passwords will be cached in your wordpress-installation. **Attention:** Without the cache your users will not be able to log into your site when your LDAP is down!
|
||||
|
||||
### Server Settings
|
||||
|
||||
* **LDAP Uri** This is the URI where your ldap-backend can be reached. More information are actually on the Configuration page
|
||||
* **Filter** This is the real McCoy! The filter you define here specifies how a user will be found. Before applying the filter a %s will be replaced with the given username. This means, when a user logs in using ‘foobar’ as username the following happens:
|
||||
|
||||
* **uid=%1$s** check for any LDAP-Entry that has an attribute ‘uid’ with value ‘foobar’
|
||||
* **(&(objectclass=posixAccount)(|(uid=%1$s)(mail=%1$s)))** check for any LDAP-Entry that has an attribute ‘objectclass’ with value ‘posixAccout’ and either a UID- or a mail-attribute with value ‘foobar’
|
||||
|
||||
This filter is rather powerfull if used wisely.
|
||||
|
||||
### Creating Users
|
||||
|
||||
* **Name-Attribute** Which Attribute from the LDAP contains the Full or the First name of the user trying to log in. This defaults to name
|
||||
* **Second Name Attribute** If the above Name-Attribute only contains the First Name of the user you can here specify an Attribute that contains the second name. This field is empty by default
|
||||
* **User-ID Attribute** This field will be used as login-name for wordpress. Please give the Attribute, that is used to identify the user. This should be the same as you used in the above Filter-Option. This field defaults to uid
|
||||
* **Mail Attribute** Which Attribute holds the eMail-Address of the user? If more than one eMail-Address are stored in the LDAP, only the first given is used. This field defaults to mail
|
||||
* **Web-Attribute** If your users have a personal page (URI) stored in the LDAP, it can be provided here. This field is empty by default
|
||||
|
||||
### User-Groups for Roles
|
||||
|
||||
* **Group-Attribute** This is the attribute that defines the Group-ID that can be matched against the Groups defined further down This field defaults to gidNumber.
|
||||
* **Group-Filter** Here you can add the filter for selecting groups for the currentlly logged in user The Filter should contain the string %s which will be replaced by the login-name of the currently logged in
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
<dl>
|
||||
<dt>Can I change a users password with this plugin?</dt>
|
||||
<dd>Short Answer: <strong>No</strong>!<br>Long Answer: As the users credentials are not
|
||||
only used for a wordpress-site when you authenticate against an LDAP but for
|
||||
many other services also chances are great that there is a centralized place
|
||||
where password-changes shall be made. We'll later allow inclusion of a link
|
||||
to such a place but currently it's not available. And as password-hashing and
|
||||
where to store it requires deeper insight into the LDAP-Server then most users
|
||||
have and admins are willing to give, password changes are out of scope of this
|
||||
plugin. If you know exactyl what you do, you might want to have a look at
|
||||
<a href="https://github.com/heiglandreas/authLdap/issues/54#issuecomment-125851029">
|
||||
issue 54</a>
|
||||
wherer a way of adding it is described!
|
||||
</dd>
|
||||
<dt>Can I add a user to the LDAP when she creates a user-account on wordpress?</dt>
|
||||
<dd>Short Answer: <strong>No</strong>!<br>Long Answer: Even though that is technically possible
|
||||
it's not in the scope of this plugin. As creating a user in an LDAP often involves
|
||||
an administrative process that has already been implemented in your departments
|
||||
administration it doesn't make sense to rebuild that - in most cases highly
|
||||
individual - process in this plugin. If you know exactly what you do, have a look at
|
||||
<a href="https://github.com/heiglandreas/authLdap/issues/65">issue 65</a>
|
||||
where <a href="https://github.com/wtfiwtz">wtfiwtz</a> shows how to implement that feature.
|
||||
</dd>
|
||||
</dl>
|
@ -1,18 +0,0 @@
|
||||
# Security-Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- |--------------------|
|
||||
| 2.x | :white_check_mark: |
|
||||
| 1.x | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
* Check our security.txt file for details on how to contact us
|
||||
* Contact us before publicly disclosing the issue anywhere else
|
||||
|
||||
This plugin is developed as OpenSource under the MIT licence.
|
||||
There is no money earned from it. Therefore we are not able to
|
||||
provide any bug-bounties whatsoever. You will be mentioned in the
|
||||
release notes of a fix-release though.
|
@ -1,13 +0,0 @@
|
||||
.row {
|
||||
overflow: hidden;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.element {
|
||||
float: right;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.authldap-options input[type=text] {
|
||||
width: 100%;
|
||||
}
|
@ -1,946 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
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.6.2
|
||||
Author: Andreas Heigl <andreas@heigl.org>
|
||||
Author URI: http://andreas.heigl.org
|
||||
License: MIT
|
||||
License URI: https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
|
||||
use Org_Heigl\AuthLdap\LdapList;
|
||||
use Org_Heigl\AuthLdap\LdapUri;
|
||||
use Org_Heigl\AuthLdap\Manager\Ldap;
|
||||
use Org_Heigl\AuthLdap\UserRoleHandler;
|
||||
use Org_Heigl\AuthLdap\Wrapper\LdapFactory;
|
||||
|
||||
require_once __DIR__ . '/src/Wrapper/LdapInterface.php';
|
||||
require_once __DIR__ . '/src/Exception/Error.php';
|
||||
require_once __DIR__ . '/src/Exception/InvalidLdapUri.php';
|
||||
require_once __DIR__ . '/src/Exception/Error.php';
|
||||
require_once __DIR__ . '/src/Exception/InvalidLdapUri.php';
|
||||
require_once __DIR__ . '/src/Exception/MissingValidLdapConnection.php';
|
||||
require_once __DIR__ . '/src/Exception/SearchUnsuccessfull.php';
|
||||
require_once __DIR__ . '/src/Manager/Ldap.php';
|
||||
require_once __DIR__ . '/src/Wrapper/Ldap.php';
|
||||
require_once __DIR__ . '/src/Wrapper/LdapFactory.php';
|
||||
require_once __DIR__ . '/src/LdapList.php';
|
||||
require_once __DIR__ . '/src/LdapUri.php';
|
||||
require_once __DIR__ . '/src/UserRoleHandler.php';
|
||||
|
||||
function authLdap_debug($message)
|
||||
{
|
||||
if (authLdap_get_option('Debug')) {
|
||||
error_log('[AuthLDAP] ' . $message, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function authLdap_addmenu()
|
||||
{
|
||||
if (!is_multisite()) {
|
||||
add_options_page(
|
||||
'AuthLDAP',
|
||||
'AuthLDAP',
|
||||
'manage_options',
|
||||
basename(__FILE__),
|
||||
'authLdap_options_panel'
|
||||
);
|
||||
} else {
|
||||
add_submenu_page(
|
||||
'settings.php',
|
||||
'AuthLDAP',
|
||||
'AuthLDAP',
|
||||
'manage_options',
|
||||
'authldap',
|
||||
'authLdap_options_panel'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function authLdap_get_post($name, $default = '')
|
||||
{
|
||||
return isset($_POST[$name]) ? $_POST[$name] : $default;
|
||||
}
|
||||
|
||||
function authLdap_options_panel()
|
||||
{
|
||||
// inclusde style sheet
|
||||
wp_enqueue_style('authLdap-style', plugin_dir_url(__FILE__) . 'authLdap.css');
|
||||
|
||||
if (($_SERVER['REQUEST_METHOD'] == 'POST') && array_key_exists('ldapOptionsSave', $_POST)) {
|
||||
if (!isset($_POST['authLdapNonce'])) {
|
||||
die("Go away!");
|
||||
}
|
||||
if (!wp_verify_nonce($_POST['authLdapNonce'], 'authLdapNonce')) {
|
||||
die("Go away!");
|
||||
}
|
||||
|
||||
$new_options = [
|
||||
'Enabled' => authLdap_get_post('authLDAPAuth', false),
|
||||
'CachePW' => authLdap_get_post('authLDAPCachePW', false),
|
||||
'URI' => authLdap_get_post('authLDAPURI'),
|
||||
'URISeparator' => authLdap_get_post('authLDAPURISeparator'),
|
||||
'StartTLS' => authLdap_get_post('authLDAPStartTLS', false),
|
||||
'Filter' => authLdap_get_post('authLDAPFilter'),
|
||||
'NameAttr' => authLdap_get_post('authLDAPNameAttr'),
|
||||
'SecName' => authLdap_get_post('authLDAPSecName'),
|
||||
'UidAttr' => authLdap_get_post('authLDAPUidAttr'),
|
||||
'MailAttr' => authLdap_get_post('authLDAPMailAttr'),
|
||||
'WebAttr' => authLdap_get_post('authLDAPWebAttr'),
|
||||
'Groups' => authLdap_get_post('authLDAPGroups', []),
|
||||
'GroupSeparator' => authLdap_get_post('authLDAPGroupSeparator', ','),
|
||||
'Debug' => authLdap_get_post('authLDAPDebug', false),
|
||||
'GroupBase' => authLdap_get_post('authLDAPGroupBase'),
|
||||
'GroupAttr' => authLdap_get_post('authLDAPGroupAttr'),
|
||||
'GroupFilter' => authLdap_get_post('authLDAPGroupFilter'),
|
||||
'DefaultRole' => authLdap_get_post('authLDAPDefaultRole'),
|
||||
'GroupEnable' => authLdap_get_post('authLDAPGroupEnable', false),
|
||||
'GroupOverUser' => authLdap_get_post('authLDAPGroupOverUser', false),
|
||||
'DoNotOverwriteNonLdapUsers' => authLdap_get_post('authLDAPDoNotOverwriteNonLdapUsers', false),
|
||||
'UserRead' => authLdap_get_post('authLDAPUseUserAccount', false),
|
||||
];
|
||||
if (authLdap_set_options($new_options)) {
|
||||
echo "<div class='updated'><p>Saved Options!</p></div>";
|
||||
} else {
|
||||
echo "<div class='error'><p>Could not save Options!</p></div>";
|
||||
}
|
||||
}
|
||||
|
||||
// Do some initialization for the admin-view
|
||||
$authLDAP = authLdap_get_option('Enabled');
|
||||
$authLDAPCachePW = authLdap_get_option('CachePW');
|
||||
$authLDAPURI = authLdap_get_option('URI');
|
||||
$authLDAPURISeparator = authLdap_get_option('URISeparator');
|
||||
$authLDAPStartTLS = authLdap_get_option('StartTLS');
|
||||
$authLDAPFilter = authLdap_get_option('Filter');
|
||||
$authLDAPNameAttr = authLdap_get_option('NameAttr');
|
||||
$authLDAPSecName = authLdap_get_option('SecName');
|
||||
$authLDAPMailAttr = authLdap_get_option('MailAttr');
|
||||
$authLDAPUidAttr = authLdap_get_option('UidAttr');
|
||||
$authLDAPWebAttr = authLdap_get_option('WebAttr');
|
||||
$authLDAPGroups = authLdap_get_option('Groups');
|
||||
$authLDAPGroupSeparator = authLdap_get_option('GroupSeparator');
|
||||
$authLDAPDebug = authLdap_get_option('Debug');
|
||||
$authLDAPGroupBase = authLdap_get_option('GroupBase');
|
||||
$authLDAPGroupAttr = authLdap_get_option('GroupAttr');
|
||||
$authLDAPGroupFilter = authLdap_get_option('GroupFilter');
|
||||
$authLDAPDefaultRole = authLdap_get_option('DefaultRole');
|
||||
$authLDAPGroupEnable = authLdap_get_option('GroupEnable');
|
||||
$authLDAPGroupOverUser = authLdap_get_option('GroupOverUser');
|
||||
$authLDAPDoNotOverwriteNonLdapUsers = authLdap_get_option('DoNotOverwriteNonLdapUsers');
|
||||
$authLDAPUseUserAccount = authLdap_get_option('UserRead');
|
||||
|
||||
$tChecked = ($authLDAP) ? ' checked="checked"' : '';
|
||||
$tDebugChecked = ($authLDAPDebug) ? ' checked="checked"' : '';
|
||||
$tPWChecked = ($authLDAPCachePW) ? ' checked="checked"' : '';
|
||||
$tGroupChecked = ($authLDAPGroupEnable) ? ' checked="checked"' : '';
|
||||
$tGroupOverUserChecked = ($authLDAPGroupOverUser) ? ' checked="checked"' : '';
|
||||
$tStartTLSChecked = ($authLDAPStartTLS) ? ' checked="checked"' : '';
|
||||
$tDoNotOverwriteNonLdapUsers = ($authLDAPDoNotOverwriteNonLdapUsers) ? ' checked="checked"' : '';
|
||||
$tUserRead = ($authLDAPUseUserAccount) ? ' checked="checked"' : '';
|
||||
|
||||
$roles = new WP_Roles();
|
||||
|
||||
$action = $_SERVER['REQUEST_URI'];
|
||||
if (!extension_loaded('ldap')) {
|
||||
echo '<div class="warning">The LDAP-Extension is not available on your '
|
||||
. 'WebServer. Therefore Everything you can alter here does not '
|
||||
. 'make any sense!</div>';
|
||||
}
|
||||
|
||||
include dirname(__FILE__) . '/view/admin.phtml';
|
||||
}
|
||||
|
||||
/**
|
||||
* get a LDAP server object
|
||||
*
|
||||
* throws exception if there is a problem connecting
|
||||
*
|
||||
* @conf boolean authLDAPDebug true, if debugging should be turned on
|
||||
* @conf string authLDAPURI LDAP server URI
|
||||
*
|
||||
* @return Org_Heigl\AuthLdap\LdapList LDAP server object
|
||||
*/
|
||||
function authLdap_get_server()
|
||||
{
|
||||
static $_ldapserver = null;
|
||||
if (is_null($_ldapserver)) {
|
||||
$authLDAPDebug = authLdap_get_option('Debug');
|
||||
$authLDAPURI = explode(
|
||||
authLdap_get_option('URISeparator', ' '),
|
||||
authLdap_get_option('URI')
|
||||
);
|
||||
$authLDAPStartTLS = authLdap_get_option('StartTLS');
|
||||
|
||||
//$authLDAPURI = 'ldap:/foo:bar@server/trallala';
|
||||
authLdap_debug('connect to LDAP server');
|
||||
require_once dirname(__FILE__) . '/src/LdapList.php';
|
||||
$_ldapserver = new LdapList();
|
||||
foreach ($authLDAPURI as $uri) {
|
||||
$_ldapserver->addLdap(new Ldap(
|
||||
new LdapFactory(),
|
||||
LdapUri::fromString($uri),
|
||||
$authLDAPStartTLS
|
||||
));
|
||||
}
|
||||
}
|
||||
return $_ldapserver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method authenticates a user using either the LDAP or, if LDAP is not
|
||||
* available, the local database
|
||||
*
|
||||
* For this we store the hashed passwords in the WP_Database to ensure working
|
||||
* conditions even without an LDAP-Connection
|
||||
*
|
||||
* @param null|WP_User|WP_Error
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param boolean $already_md5
|
||||
* @return boolean true, if login was successfull or false, if it wasn't
|
||||
* @conf boolean authLDAP true, if authLDAP should be used, false if not. Defaults to false
|
||||
* @conf string authLDAPFilter LDAP filter to use to find correct user, defaults to '(uid=%s)'
|
||||
* @conf string authLDAPNameAttr LDAP attribute containing user (display) name, defaults to 'name'
|
||||
* @conf string authLDAPSecName LDAP attribute containing second name, defaults to ''
|
||||
* @conf string authLDAPMailAttr LDAP attribute containing user e-mail, defaults to 'mail'
|
||||
* @conf string authLDAPUidAttr LDAP attribute containing user id (the username we log on with), defaults to 'uid'
|
||||
* @conf string authLDAPWebAttr LDAP attribute containing user website, defaults to ''
|
||||
* @conf string authLDAPDefaultRole default role for authenticated user, defaults to ''
|
||||
* @conf boolean authLDAPGroupEnable true, if we try to map LDAP groups to Wordpress roles
|
||||
* @conf boolean authLDAPGroupOverUser true, if LDAP Groups have precedence over existing user roles
|
||||
*/
|
||||
function authLdap_login($user, $username, $password, $already_md5 = false)
|
||||
{
|
||||
// don't do anything when authLDAP is disabled
|
||||
if (!authLdap_get_option('Enabled')) {
|
||||
authLdap_debug(
|
||||
'LDAP disabled in AuthLDAP plugin options (use the first option in the AuthLDAP options to enable it)'
|
||||
);
|
||||
return $user;
|
||||
}
|
||||
|
||||
// If the user has already been authenticated (only in that case we get a
|
||||
// WP_User-Object as $user) we skip LDAP-authentication and simply return
|
||||
// the existing user-object
|
||||
if ($user instanceof WP_User) {
|
||||
authLdap_debug(sprintf(
|
||||
'User %s has already been authenticated - skipping LDAP-Authentication',
|
||||
$user->get('nickname')
|
||||
));
|
||||
return $user;
|
||||
}
|
||||
|
||||
authLdap_debug("User '$username' logging in");
|
||||
|
||||
if ($username == 'admin') {
|
||||
authLdap_debug('Doing nothing for possible local user admin');
|
||||
return $user;
|
||||
}
|
||||
|
||||
global $wpdb, $error;
|
||||
try {
|
||||
$authLDAP = authLdap_get_option('Enabled');
|
||||
$authLDAPFilter = authLdap_get_option('Filter');
|
||||
$authLDAPNameAttr = authLdap_get_option('NameAttr');
|
||||
$authLDAPSecName = authLdap_get_option('SecName');
|
||||
$authLDAPMailAttr = authLdap_get_option('MailAttr');
|
||||
$authLDAPUidAttr = authLdap_get_option('UidAttr');
|
||||
$authLDAPWebAttr = authLdap_get_option('WebAttr');
|
||||
$authLDAPDefaultRole = authLdap_get_option('DefaultRole');
|
||||
$authLDAPGroupEnable = filter_var(authLdap_get_option('GroupEnable'), FILTER_VALIDATE_BOOLEAN);
|
||||
$authLDAPGroupOverUser = filter_var(authLdap_get_option('GroupOverUser'), FILTER_VALIDATE_BOOLEAN);
|
||||
$authLDAPUseUserAccount = authLdap_get_option('UserRead');
|
||||
|
||||
if (!$username) {
|
||||
authLdap_debug('Username not supplied: return false');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$password) {
|
||||
authLdap_debug('Password not supplied: return false');
|
||||
$error = __('<strong>Error</strong>: The password field is empty.');
|
||||
return false;
|
||||
}
|
||||
// First check for valid values and set appropriate defaults
|
||||
if (!$authLDAPFilter) {
|
||||
$authLDAPFilter = '(uid=%s)';
|
||||
}
|
||||
if (!$authLDAPNameAttr) {
|
||||
$authLDAPNameAttr = 'name';
|
||||
}
|
||||
if (!$authLDAPMailAttr) {
|
||||
$authLDAPMailAttr = 'mail';
|
||||
}
|
||||
if (!$authLDAPUidAttr) {
|
||||
$authLDAPUidAttr = 'uid';
|
||||
}
|
||||
|
||||
// If already_md5 is TRUE, then we're getting the user/password from the cookie. As we don't want
|
||||
// to store LDAP passwords in any
|
||||
// form, we've already replaced the password with the hashed username and LDAP_COOKIE_MARKER
|
||||
if ($already_md5) {
|
||||
if ($password == md5($username) . md5($ldapCookieMarker)) {
|
||||
authLdap_debug('cookie authentication');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove slashes as noted on https://github.com/heiglandreas/authLdap/issues/108
|
||||
$password = stripslashes_deep($password);
|
||||
|
||||
// No cookie, so have to authenticate them via LDAP
|
||||
$result = false;
|
||||
try {
|
||||
authLdap_debug('about to do LDAP authentication');
|
||||
$result = authLdap_get_server()->Authenticate($username, $password, $authLDAPFilter);
|
||||
} catch (Exception $e) {
|
||||
authLdap_debug('LDAP authentication failed with exception: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make optional querying from the admin account #213
|
||||
if (!authLdap_get_option('UserRead')) {
|
||||
// Rebind with the default credentials after the user has been loged in
|
||||
// Otherwise the credentials of the user trying to login will be used
|
||||
// This fixes #55
|
||||
authLdap_get_server()->bind();
|
||||
}
|
||||
|
||||
if (true !== $result) {
|
||||
authLdap_debug('LDAP authentication failed');
|
||||
// TODO what to return? WP_User object, true, false, even an WP_Error object...
|
||||
// all seem to fall back to normal wp user authentication
|
||||
return;
|
||||
}
|
||||
|
||||
authLdap_debug('LDAP authentication successful');
|
||||
$attributes = array_values(
|
||||
array_filter(
|
||||
apply_filters(
|
||||
'authLdap_filter_attributes',
|
||||
[
|
||||
$authLDAPNameAttr,
|
||||
$authLDAPSecName,
|
||||
$authLDAPMailAttr,
|
||||
$authLDAPWebAttr,
|
||||
$authLDAPUidAttr,
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
$attribs = authLdap_get_server()->search(
|
||||
sprintf($authLDAPFilter, $username),
|
||||
$attributes
|
||||
);
|
||||
// First get all the relevant group informations so we can see if
|
||||
// whether have been changes in group association of the user
|
||||
if (!isset($attribs[0]['dn'])) {
|
||||
authLdap_debug('could not get user attributes from LDAP');
|
||||
throw new UnexpectedValueException('dn has not been returned');
|
||||
}
|
||||
if (!isset($attribs[0][strtolower($authLDAPUidAttr)][0])) {
|
||||
authLdap_debug('could not get user attributes from LDAP');
|
||||
throw new UnexpectedValueException('The user-ID attribute has not been returned');
|
||||
}
|
||||
|
||||
$dn = $attribs[0]['dn'];
|
||||
$realuid = $attribs[0][strtolower($authLDAPUidAttr)][0];
|
||||
} catch (Exception $e) {
|
||||
authLdap_debug('Exception getting LDAP user: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
$uid = authLdap_get_uid($realuid);
|
||||
|
||||
// This fixes #172
|
||||
if (true == authLdap_get_option('DoNotOverwriteNonLdapUsers', false)) {
|
||||
if (!get_user_meta($uid, 'authLDAP')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$roles = [];
|
||||
|
||||
// we only need this if either LDAP groups are disabled or
|
||||
// if the WordPress role of the user overrides LDAP groups
|
||||
if ($authLDAPGroupEnable === false || $authLDAPGroupOverUser === false) {
|
||||
$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.
|
||||
}
|
||||
|
||||
// do LDAP group mapping if needed
|
||||
// (if LDAP groups override wordpress user role, $role is still empty)
|
||||
if ((empty($roles) || $authLDAPGroupOverUser === true) && $authLDAPGroupEnable === true) {
|
||||
$mappedRoles = authLdap_groupmap($realuid, $dn);
|
||||
if ($mappedRoles !== []) {
|
||||
$roles = $mappedRoles;
|
||||
authLdap_debug('role from group mapping: ' . json_encode($roles));
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't have a role yet, use default role
|
||||
if (empty($roles) && !empty($authLDAPDefaultRole)) {
|
||||
authLdap_debug('no role yet, set default role');
|
||||
$roles[] = $authLDAPDefaultRole;
|
||||
}
|
||||
|
||||
if (empty($roles)) {
|
||||
// Sorry, but you are not in any group that is allowed access
|
||||
trigger_error('no group found');
|
||||
authLdap_debug('user is not in any group that is allowed access');
|
||||
return false;
|
||||
} else {
|
||||
$wp_roles = new WP_Roles();
|
||||
// not sure if this is needed, but it can't hurt
|
||||
|
||||
// Get rid of unexisting roles.
|
||||
foreach ($roles as $k => $v) {
|
||||
if (!$wp_roles->is_role($v)) {
|
||||
unset($k);
|
||||
}
|
||||
}
|
||||
|
||||
// check if single role or an empty array provided
|
||||
if (empty($roles)) {
|
||||
trigger_error('no group found');
|
||||
authLdap_debug('role is invalid');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// from here on, the user has access!
|
||||
// now, lets update some user details
|
||||
$user_info = [];
|
||||
$user_info['user_login'] = $realuid;
|
||||
$user_info['user_email'] = '';
|
||||
$user_info['user_nicename'] = '';
|
||||
|
||||
// first name
|
||||
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((string) $authLDAPSecName)][0])) {
|
||||
$user_info['last_name'] = $attribs[0][strtolower((string) $authLDAPSecName)][0];
|
||||
}
|
||||
|
||||
// mail address
|
||||
if (isset($attribs[0][strtolower((string) $authLDAPMailAttr)][0])) {
|
||||
$user_info['user_email'] = $attribs[0][strtolower((string) $authLDAPMailAttr)][0];
|
||||
}
|
||||
|
||||
// website
|
||||
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)) {
|
||||
$user_info['display_name'] = $user_info['first_name'];
|
||||
$user_info['nickname'] = $user_info['first_name'];
|
||||
$user_info['user_nicename'] = sanitize_title_with_dashes($user_info['first_name']);
|
||||
if (array_key_exists('last_name', $user_info)) {
|
||||
$user_info['display_name'] .= ' ' . $user_info['last_name'];
|
||||
$user_info['nickname'] .= ' ' . $user_info['last_name'];
|
||||
$user_info['user_nicename'] .= '_' . sanitize_title_with_dashes($user_info['last_name']);
|
||||
}
|
||||
}
|
||||
$user_info['user_nicename'] = substr($user_info['user_nicename'], 0, 50);
|
||||
|
||||
// optionally store the password into the wordpress database
|
||||
if (authLdap_get_option('CachePW')) {
|
||||
// Password will be hashed inside wp_update_user or wp_insert_user
|
||||
$user_info['user_pass'] = $password;
|
||||
} else {
|
||||
// clear the password
|
||||
$user_info['user_pass'] = '';
|
||||
}
|
||||
|
||||
// add uid if user exists
|
||||
if ($uid) {
|
||||
// found user in the database
|
||||
authLdap_debug('The LDAP user has an entry in the WP-Database');
|
||||
$user_info['ID'] = $uid;
|
||||
unset($user_info['display_name'], $user_info['nickname']);
|
||||
$userid = wp_update_user($user_info);
|
||||
} else {
|
||||
// new wordpress account will be created
|
||||
authLdap_debug('The LDAP user does not have an entry in the WP-Database, a new WP account will be created');
|
||||
|
||||
$userid = wp_insert_user($user_info);
|
||||
}
|
||||
|
||||
// if the user exists, wp_insert_user will update the existing user record
|
||||
if (is_wp_error($userid)) {
|
||||
authLdap_debug('Error creating user : ' . $userid->get_error_message());
|
||||
trigger_error('Error creating user: ' . $userid->get_error_message());
|
||||
return $userid;
|
||||
}
|
||||
|
||||
// Update user roles.
|
||||
$user = new \WP_User($userid);
|
||||
|
||||
/**
|
||||
* Add hook for custom User-Role assignment
|
||||
*
|
||||
* @param WP_User $user This user-object will be returned. Can be modified as necessary in the actions.
|
||||
* @param array $roles
|
||||
*/
|
||||
do_action('authldap_user_roles', $user, $roles);
|
||||
|
||||
/**
|
||||
* Add hook for custom updates
|
||||
*
|
||||
* @param int $userid User ID.
|
||||
* @param array $attribs [0] Attributes retrieved from LDAP for the user.
|
||||
*/
|
||||
do_action('authLdap_login_successful', $userid, $attribs[0]);
|
||||
|
||||
authLdap_debug('user id = ' . $userid);
|
||||
|
||||
// flag the user as an ldap user so we can hide the password fields in the user profile
|
||||
update_user_meta($userid, 'authLDAP', true);
|
||||
|
||||
// return a user object upon positive authorization
|
||||
return $user;
|
||||
} catch (Exception $e) {
|
||||
authLdap_debug($e->getMessage() . '. Exception thrown in line ' . $e->getLine());
|
||||
trigger_error($e->getMessage() . '. Exception thrown in line ' . $e->getLine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's user id
|
||||
*
|
||||
* Returns null if username not found
|
||||
*
|
||||
* @param string $username username
|
||||
* @param string user id, null if not found
|
||||
*/
|
||||
function authLdap_get_uid($username)
|
||||
{
|
||||
global $wpdb;
|
||||
|
||||
// find out whether the user is already present in the database
|
||||
$uid = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID FROM {$wpdb->users} WHERE user_login = %s",
|
||||
$username
|
||||
)
|
||||
);
|
||||
if ($uid) {
|
||||
authLdap_debug("Existing user, uid = {$uid}");
|
||||
return $uid;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's current role
|
||||
*
|
||||
* Returns empty string if not found.
|
||||
*
|
||||
* @param int $uid wordpress user id
|
||||
* @return array roles, empty if none found
|
||||
*/
|
||||
function authLdap_user_role($uid)
|
||||
{
|
||||
global $wpdb, $wp_roles;
|
||||
|
||||
if (!$uid) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var array<string, bool> $usercapabilities */
|
||||
$usercapabilities = get_user_meta($uid, "{$wpdb->prefix}capabilities", true);
|
||||
if (!is_array($usercapabilities)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var array<string, array{name: string, capabilities: array<mixed>} $editable_roles */
|
||||
$editable_roles = $wp_roles->roles;
|
||||
|
||||
// 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));
|
||||
|
||||
authLdap_debug(sprintf("Existing user's roles: %s", implode(', ', $userroles)));
|
||||
|
||||
return $userroles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LDAP groups for user and map to role
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $dn
|
||||
* @return array role, empty array if no mapping found, first or all role(s) found otherwise
|
||||
* @conf array authLDAPGroups, associative array, role => ldap_group
|
||||
* @conf string authLDAPGroupBase, base dn to look up groups
|
||||
* @conf string authLDAPGroupAttr, ldap attribute that holds name of group
|
||||
* @conf string authLDAPGroupFilter, LDAP filter to find groups. can contain %s and %dn% placeholders
|
||||
*/
|
||||
function authLdap_groupmap($username, $dn)
|
||||
{
|
||||
$authLDAPGroups = authLdap_sort_roles_by_capabilities(
|
||||
authLdap_get_option('Groups')
|
||||
);
|
||||
$authLDAPGroupBase = authLdap_get_option('GroupBase');
|
||||
$authLDAPGroupAttr = authLdap_get_option('GroupAttr');
|
||||
$authLDAPGroupFilter = authLdap_get_option('GroupFilter');
|
||||
$authLDAPGroupSeparator = authLdap_get_option('GroupSeparator');
|
||||
if (!$authLDAPGroupAttr) {
|
||||
$authLDAPGroupAttr = 'gidNumber';
|
||||
}
|
||||
if (!$authLDAPGroupFilter) {
|
||||
$authLDAPGroupFilter = '(&(objectClass=posixGroup)(memberUid=%s))';
|
||||
}
|
||||
if (!$authLDAPGroupSeparator) {
|
||||
$authLDAPGroupSeparator = ',';
|
||||
}
|
||||
|
||||
if (!is_array($authLDAPGroups) || count(array_filter(array_values($authLDAPGroups))) == 0) {
|
||||
authLdap_debug('No group names defined');
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
// To allow searches based on the DN instead of the uid, we replace the
|
||||
// string %dn% with the users DN.
|
||||
$authLDAPGroupFilter = str_replace(
|
||||
'%dn%',
|
||||
ldap_escape($dn, '', LDAP_ESCAPE_FILTER),
|
||||
$authLDAPGroupFilter
|
||||
);
|
||||
authLdap_debug('Group Filter: ' . json_encode($authLDAPGroupFilter));
|
||||
authLdap_debug('Group Base: ' . $authLDAPGroupBase);
|
||||
$groups = authLdap_get_server()->search(
|
||||
sprintf($authLDAPGroupFilter, ldap_escape($username, '', LDAP_ESCAPE_FILTER)),
|
||||
[$authLDAPGroupAttr],
|
||||
$authLDAPGroupBase
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
authLdap_debug('Exception getting LDAP group attributes: ' . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
|
||||
$grp = [];
|
||||
for ($i = 0; $i < $groups ['count']; $i++) {
|
||||
if ($authLDAPGroupAttr == "dn") {
|
||||
$grp[] = $groups[$i]['dn'];
|
||||
} else {
|
||||
for ($k = 0; $k < $groups[$i][strtolower($authLDAPGroupAttr)]['count']; $k++) {
|
||||
$grp[] = $groups[$i][strtolower($authLDAPGroupAttr)][$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
authLdap_debug('LDAP groups: ' . json_encode($grp));
|
||||
|
||||
// Check whether the user is member of one of the groups that are
|
||||
// allowed acces to the blog. If the user is not member of one of
|
||||
// The groups throw her out! ;-)
|
||||
$roles = [];
|
||||
foreach ($authLDAPGroups as $key => $val) {
|
||||
$currentGroup = explode($authLDAPGroupSeparator, $val);
|
||||
// Remove whitespaces around the group-ID
|
||||
$currentGroup = array_map('trim', $currentGroup);
|
||||
if (0 < count(array_intersect($currentGroup, $grp))) {
|
||||
$roles[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
// Default: If the user is member of more than one group only the first one
|
||||
// will be taken into account!
|
||||
// This filter allows you to return multiple user roles. WordPress
|
||||
// supports this functionality, but not natively via UI from Users
|
||||
// overview (you need to use a plugin). However, it's still widely used,
|
||||
// for example, by WooCommerce, etc. Use if you know what you're doing.
|
||||
if (apply_filters('authLdap_allow_multiple_roles', false) === false && count($roles) > 1) {
|
||||
$roles = array_slice($roles, 0, 1);
|
||||
}
|
||||
|
||||
authLdap_debug("Roles from LDAP group: " . json_encode($roles));
|
||||
return $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function disables the password-change fields in the users preferences.
|
||||
*
|
||||
* It does not make sense to authenticate via LDAP and then allow the user to
|
||||
* change the password only in the wordpress database. And changing the password
|
||||
* LDAP-wide can not be the scope of Wordpress!
|
||||
*
|
||||
* Whether the user is an LDAP-User or not is determined using the authLDAP-Flag
|
||||
* of the users meta-informations
|
||||
*
|
||||
* @return false, if the user whose prefs are viewed is an LDAP-User, true if
|
||||
* he isn't
|
||||
* @conf boolean authLDAP
|
||||
*/
|
||||
function authLdap_show_password_fields($return, $user)
|
||||
{
|
||||
if (!$user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (get_user_meta($user->ID, 'authLDAP')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function disables the password reset for a user.
|
||||
*
|
||||
* It does not make sense to authenticate via LDAP and then allow the user to
|
||||
* reset the password only in the wordpress database. And changing the password
|
||||
* LDAP-wide can not be the scope of Wordpress!
|
||||
*
|
||||
* Whether the user is an LDAP-User or not is determined using the authLDAP-Flag
|
||||
* of the users meta-informations
|
||||
*
|
||||
* @author chaplina (https://github.com/chaplina)
|
||||
* @conf boolean authLDAP
|
||||
* @return false, if the user is an LDAP-User, true if he isn't
|
||||
*/
|
||||
function authLdap_allow_password_reset($return, $userid)
|
||||
{
|
||||
if (!(isset($userid))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (get_user_meta($userid, 'authLDAP')) {
|
||||
return false;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the given roles by number of capabilities
|
||||
*
|
||||
* @param array $roles
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function authLdap_sort_roles_by_capabilities($roles)
|
||||
{
|
||||
global $wpdb;
|
||||
$myRoles = get_option($wpdb->get_blog_prefix() . 'user_roles');
|
||||
|
||||
authLdap_debug(print_r($roles, true));
|
||||
uasort($myRoles, 'authLdap_sortByCapabilitycount');
|
||||
|
||||
$return = [];
|
||||
|
||||
foreach ($myRoles as $key => $role) {
|
||||
if (isset($roles[$key])) {
|
||||
$return[$key] = $roles[$key];
|
||||
}
|
||||
}
|
||||
|
||||
authLdap_debug(print_r($return, true));
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort according to the number of capabilities
|
||||
*
|
||||
* @param $a
|
||||
* @param $b
|
||||
*/
|
||||
function authLdap_sortByCapabilitycount($a, $b)
|
||||
{
|
||||
if (count($a['capabilities']) > count($b['capabilities'])) {
|
||||
return -1;
|
||||
}
|
||||
if (count($a['capabilities']) < count($b['capabilities'])) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load AuthLDAP Options
|
||||
*
|
||||
* Sets and stores defaults if options are not up to date
|
||||
*/
|
||||
function authLdap_load_options($reload = false)
|
||||
{
|
||||
static $options = null;
|
||||
|
||||
// the current version for options
|
||||
$option_version_plugin = 1;
|
||||
|
||||
$optionFunction = 'get_option';
|
||||
if (is_multisite()) {
|
||||
$optionFunction = 'get_site_option';
|
||||
}
|
||||
if (is_null($options) || $reload) {
|
||||
$options = $optionFunction('authLDAPOptions', []);
|
||||
}
|
||||
|
||||
// check if option version has changed (or if it's there at all)
|
||||
if (!isset($options['Version']) || ($options['Version'] != $option_version_plugin)) {
|
||||
// defaults for all options
|
||||
$options_default = [
|
||||
'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' => $option_version_plugin,
|
||||
'DoNotOverwriteNonLdapUsers' => false,
|
||||
];
|
||||
|
||||
// check if we got a version
|
||||
if (!isset($options['Version'])) {
|
||||
// we just changed to the new option format
|
||||
// read old options, then delete them
|
||||
$old_option_new_option = [
|
||||
'authLDAP' => 'Enabled',
|
||||
'authLDAPCachePW' => 'CachePW',
|
||||
'authLDAPURI' => 'URI',
|
||||
'authLDAPFilter' => 'Filter',
|
||||
'authLDAPNameAttr' => 'NameAttr',
|
||||
'authLDAPSecName' => 'SecName',
|
||||
'authLDAPUidAttr' => 'UidAttr',
|
||||
'authLDAPMailAttr' => 'MailAttr',
|
||||
'authLDAPWebAttr' => 'WebAttr',
|
||||
'authLDAPGroups' => 'Groups',
|
||||
'authLDAPDebug' => 'Debug',
|
||||
'authLDAPGroupAttr' => 'GroupAttr',
|
||||
'authLDAPGroupFilter' => 'GroupFilter',
|
||||
'authLDAPDefaultRole' => 'DefaultRole',
|
||||
'authLDAPGroupEnable' => 'GroupEnable',
|
||||
'authLDAPGroupOverUser' => 'GroupOverUser',
|
||||
];
|
||||
foreach ($old_option_new_option as $old_option => $new_option) {
|
||||
$value = get_option($old_option, null);
|
||||
if (!is_null($value)) {
|
||||
$options[$new_option] = $value;
|
||||
}
|
||||
delete_option($old_option);
|
||||
}
|
||||
delete_option('authLDAPCookieMarker');
|
||||
delete_option('authLDAPCookierMarker');
|
||||
}
|
||||
|
||||
// set default for all options that are missing
|
||||
foreach ($options_default as $key => $default) {
|
||||
if (!isset($options[$key])) {
|
||||
$options[$key] = $default;
|
||||
}
|
||||
}
|
||||
|
||||
// set new version and save
|
||||
$options['Version'] = $option_version_plugin;
|
||||
update_option('authLDAPOptions', $options);
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an individual option
|
||||
*/
|
||||
function authLdap_get_option($optionname, $default = null)
|
||||
{
|
||||
$options = authLdap_load_options();
|
||||
if (isset($options[$optionname]) && $options[$optionname]) {
|
||||
return $options[$optionname];
|
||||
}
|
||||
|
||||
if (null !== $default) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
//authLdap_debug('option name invalid: ' . $optionname);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new options
|
||||
*/
|
||||
function authLdap_set_options($new_options = [])
|
||||
{
|
||||
// initialize the options with what we currently have
|
||||
$options = authLdap_load_options();
|
||||
|
||||
// set the new options supplied
|
||||
foreach ($new_options as $key => $value) {
|
||||
$options[$key] = $value;
|
||||
}
|
||||
|
||||
// store options
|
||||
$optionFunction = 'update_option';
|
||||
if (is_multisite()) {
|
||||
$optionFunction = 'update_site_option';
|
||||
}
|
||||
if ($optionFunction('authLDAPOptions', $options)) {
|
||||
// reload the option cache
|
||||
authLdap_load_options(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// could not set options
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not send an email after changing the password or the email of the user!
|
||||
*
|
||||
* @param boolean $result The initial resturn value
|
||||
* @param array $user The old userdata
|
||||
* @param array $newUserData The changed userdata
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function authLdap_send_change_email($result, $user, $newUserData)
|
||||
{
|
||||
if (get_user_meta($user['ID'], 'authLDAP')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$hook = is_multisite() ? 'network_' : '';
|
||||
add_action($hook . 'admin_menu', 'authLdap_addmenu');
|
||||
add_filter('show_password_fields', 'authLdap_show_password_fields', 10, 2);
|
||||
add_filter('allow_password_reset', 'authLdap_allow_password_reset', 10, 2);
|
||||
add_filter('authenticate', 'authLdap_login', 10, 3);
|
||||
/** This only works from WP 4.3.0 on */
|
||||
add_filter('send_password_change_email', 'authLdap_send_change_email', 10, 3);
|
||||
add_filter('send_email_change_email', 'authLdap_send_change_email', 10, 3);
|
||||
$handler = new UserRoleHandler();
|
||||
add_action('authldap_user_roles', [$handler, 'addRolesToUser'], 10, 2);
|
@ -1 +0,0 @@
|
||||
default:
|
@ -1,308 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Behat\Behat\Tester\Exception\PendingException;
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Gherkin\Node\PyStringNode;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Cookie\CookieJar;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Org_Heigl\AuthLdap\OptionFactory;
|
||||
use Org_Heigl\AuthLdap\Options;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
class FeatureContext implements Context
|
||||
{
|
||||
private ?Response $res = null;
|
||||
/**
|
||||
* Initializes context.
|
||||
*
|
||||
* Every scenario gets its own context instance.
|
||||
* You can also pass arbitrary arguments to the
|
||||
* context constructor through behat.yml.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
exec('wp --allow-root core install --url=localhost --title=Example --admin_user=localadmin --admin_password=P@ssw0rd --admin_email=info@example.com');
|
||||
exec('wp --allow-root plugin activate authldap');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Given a default configuration
|
||||
*/
|
||||
public function aDefaultConfiguration()
|
||||
{
|
||||
$options = new Options();
|
||||
$options->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 <<LDIF
|
||||
%4$s
|
||||
LDIF',
|
||||
'ldap://openldap',
|
||||
'cn=admin,dc=example,dc=org',
|
||||
'insecure',
|
||||
<<<LDIF
|
||||
dn: uid=$arg1,dc=example,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
objectClass: simpleSecurityObject
|
||||
uid: $arg1
|
||||
cn: $arg2
|
||||
sn: $arg2
|
||||
userPassword: $arg3
|
||||
mail: $arg4
|
||||
LDIF
|
||||
));
|
||||
exec(sprintf(
|
||||
'ldappasswd -H ldap://openldap:389 -x -D "uid=admin,dc=example,dc=org" -w "%3$s" -s "%2$s" "uid=%1$s,dc=example,dc=org"',
|
||||
$arg1,
|
||||
$arg3,
|
||||
'insecure'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given an LDAP group :arg1 exists
|
||||
*/
|
||||
public function anLdapGroupExists($arg1)
|
||||
{
|
||||
exec(sprintf(
|
||||
'ldapadd -x -H %1$s -D "%2$s" -w %3$s <<LDIF
|
||||
%4$s
|
||||
LDIF',
|
||||
'ldap://openldap',
|
||||
'cn=admin,dc=example,dc=org',
|
||||
'insecure',
|
||||
<<<LDIF
|
||||
dn: cn=$arg1,dc=example,dc=org
|
||||
objectClass: groupOfUniqueNames
|
||||
cn: $arg1
|
||||
uniqueMember: cn=admin,dc=example,dc=org
|
||||
LDIF
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given a WordPress user :arg1 with name :arg2 and email :arg3 exists
|
||||
*/
|
||||
public function aWordpressUserWithNameAndEmailExists($arg1, $arg2, $arg3)
|
||||
{
|
||||
exec(sprintf(
|
||||
'wp --allow-root user create %1$s %3$s --display_name=%2$s --porcelain',
|
||||
$arg1,
|
||||
$arg2,
|
||||
$arg3
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given a WordPress role :arg1 exists
|
||||
*/
|
||||
public function aWordpressRoleExists($arg1)
|
||||
{
|
||||
exec(sprintf(
|
||||
'wp --allow-root role create %1$s %1$s',
|
||||
$arg1,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given WordPress user :arg1 has role :arg2
|
||||
*/
|
||||
public function wordpressUserHasRole($arg1, $arg2)
|
||||
{
|
||||
exec(sprintf(
|
||||
'wp --allow-root user add-role %1$s %2$s',
|
||||
$arg1,
|
||||
$arg2
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When LDAP user :arg1 logs in with password :arg2
|
||||
*/
|
||||
public function ldapUserLogsInWithPassword($arg1, $arg2)
|
||||
{
|
||||
// curl -i 'http://localhost/wp-login.php' -X POST -H 'Cookie: wordpress_test_cookie=test' --data-raw 'log=localadmin&pwd=P%40ssw0rd'
|
||||
$client = new Client();
|
||||
|
||||
$this->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 <<LDIF
|
||||
%4$s
|
||||
LDIF',
|
||||
'ldap://openldap',
|
||||
'cn=admin,dc=example,dc=org',
|
||||
'insecure',
|
||||
<<<LDIF
|
||||
dn: cn=$arg2,dc=example,dc=org
|
||||
changetype: modify
|
||||
add: uniqueMember
|
||||
uniqueMember: uid=$arg1,dc=example,dc=org
|
||||
LDIF
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given a WordPress user :arg1 does not exist
|
||||
*/
|
||||
public function aWordpressUserDoesNotExist($arg1)
|
||||
{
|
||||
exec(sprintf(
|
||||
'wp --allow-root user delete --yes %1$s',
|
||||
$arg1,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given configuration value :arg1 is set to :arg2 and :arg3
|
||||
*/
|
||||
public function configurationValueIsSetToAnd($arg1, $arg2, $arg3)
|
||||
{
|
||||
$roles = [];
|
||||
foreach ([$arg2, $arg3] as $arg) {
|
||||
$access = explode('=', $arg);
|
||||
$roles[$access[0]] = $access[1];
|
||||
}
|
||||
|
||||
exec(sprintf(
|
||||
'echo %2$s | wp --allow-root option patch update authLDAPOptions %1$s --format=json',
|
||||
$arg1,
|
||||
"'" . json_encode($roles) . "'"
|
||||
), $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the WordPress user :arg1 is not member of role :arg2
|
||||
*/
|
||||
public function theWordpressUserIsNotMemberOfRole($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::false(in_array($arg2, $roles));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given LDAP user :arg1 is not member of LDAP group :arg2
|
||||
*/
|
||||
public function ldapUserIsNotMemberOfLdapGroup($arg1, $arg2)
|
||||
{
|
||||
exec(sprintf(
|
||||
'ldapmodify -x -H %1$s -D "%2$s" -w %3$s 2>&1 <<LDIF
|
||||
%4$s
|
||||
LDIF',
|
||||
'ldap://openldap',
|
||||
'cn=admin,dc=example,dc=org',
|
||||
'insecure',
|
||||
<<<LDIF
|
||||
dn: cn=$arg2,dc=example,dc=org
|
||||
changetype: modify
|
||||
delete: uniqueMember
|
||||
uniqueMember: uid=$arg1,dc=example,dc=org
|
||||
LDIF
|
||||
)); }
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
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 " |