updated plugin AuthLDAP
version 2.5.9
This commit is contained in:
parent
5a3dd4cf21
commit
052743ea8a
6
wp-content/plugins/authldap/.phive/phars.xml
Normal file
6
wp-content/plugins/authldap/.phive/phars.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?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"/>
|
||||
</phive>
|
@ -4,12 +4,12 @@
|
||||
|
||||
Use your existing LDAP as authentication-backend for your wordpress!
|
||||
|
||||
[![Build Status](https://travis-ci.org/heiglandreas/authLdap.svg?branch=master)](https://travis-ci.org/heiglandreas/authLdap)
|
||||
[![Build Status](https://github.com/heiglandreas/authLdap/actions/workflows/tests.yml/badge.svg)](https://github.com/heiglandreas/authLdap/actions/workflows/tests.yml)
|
||||
[![WordPress Stats](https://img.shields.io/wordpress/plugin/dt/authldap.svg)](https://wordpress.org/plugins/authldap/stats/)
|
||||
[![WordPress Version](https://img.shields.io/wordpress/plugin/v/authldap.svg)](https://wordpress.org/plugins/authldap/)
|
||||
[![WordPress testet](https://img.shields.io/wordpress/v/authldap.svg)](https://wordpress.org/plugins/authldap/)
|
||||
[![Code Climate](https://codeclimate.com/github/heiglandreas/authLdap/badges/gpa.svg)](https://codeclimate.com/github/heiglandreas/authLdap)
|
||||
[![Test Coverage](https://codeclimate.com/github/heiglandreas/authLdap/badges/coverage.svg)](https://codeclimate.com/github/heiglandreas/authLdap)
|
||||
[![codecov](https://codecov.io/gh/heiglandreas/authLdap/branch/master/graph/badge.svg?token=AYAhEeWtRQ)](https://codecov.io/gh/heiglandreas/authLdap)
|
||||
|
||||
So what are the differences to other Wordpress-LDAP-Authentication-Plugins?
|
||||
|
||||
|
18
wp-content/plugins/authldap/SECURITY.md
Normal file
18
wp-content/plugins/authldap/SECURITY.md
Normal file
@ -0,0 +1,18 @@
|
||||
# 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.
|
File diff suppressed because it is too large
Load Diff
@ -1,275 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* $Id: ldap.php 2676679 2022-02-10 18:26:37Z heiglandreas $
|
||||
*
|
||||
* authLdap - Authenticate Wordpress against an LDAP-Backend.
|
||||
* Copyright (c) 2008 Andreas Heigl<andreas@heigl.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* This file handles the basic LDAP-Tasks
|
||||
*
|
||||
* @author Andreas Heigl<andreas@heigl.org>
|
||||
* @package authLdap
|
||||
* @category authLdap
|
||||
* @since 2008
|
||||
*/
|
||||
namespace Org_Heigl\AuthLdap;
|
||||
|
||||
use Exception;
|
||||
use Org_Heigl\AuthLdap\Exception\Error;
|
||||
use function ldap_escape;
|
||||
|
||||
class LDAP
|
||||
{
|
||||
private $server = '';
|
||||
|
||||
private $scheme = 'ldap';
|
||||
|
||||
private $port = 389;
|
||||
|
||||
private $baseDn = '';
|
||||
|
||||
private $debug = false;
|
||||
/**
|
||||
* This property contains the connection handle to the ldap-server
|
||||
*
|
||||
* @var Ressource|Connection|null
|
||||
*/
|
||||
private $ch = null;
|
||||
|
||||
private $username = '';
|
||||
|
||||
private $password = '';
|
||||
|
||||
private $starttls = false;
|
||||
|
||||
public function __construct(LdapUri $URI, $debug = false, $starttls = false)
|
||||
{
|
||||
$this->debug=$debug;
|
||||
$array = parse_url($URI->toString());
|
||||
if (! is_array($array)) {
|
||||
throw new Exception($URI . ' seems not to be a valid URI');
|
||||
}
|
||||
$url = array_map(function ($item) {
|
||||
return urldecode($item);
|
||||
}, $array);
|
||||
|
||||
if (false === $url) {
|
||||
throw new Exception($URI . ' is an invalid URL');
|
||||
}
|
||||
if (! isset($url['scheme'])) {
|
||||
throw new Exception($URI . ' does not provide a scheme');
|
||||
}
|
||||
if (0 !== strpos($url['scheme'], 'ldap')) {
|
||||
throw new Exception($URI . ' is an invalid LDAP-URI');
|
||||
}
|
||||
if (! isset($url['host'])) {
|
||||
throw new Exception($URI . ' does not provide a server');
|
||||
}
|
||||
if (! isset($url['path'])) {
|
||||
throw new Exception($URI . ' does not provide a search-base');
|
||||
}
|
||||
if (1 == strlen($url['path'])) {
|
||||
throw new Exception($URI . ' does not provide a valid search-base');
|
||||
}
|
||||
$this -> server = $url['host'];
|
||||
$this -> scheme = $url['scheme'];
|
||||
$this -> baseDn = substr($url['path'], 1);
|
||||
if (isset($url['user'])) {
|
||||
$this -> username = $url['user'];
|
||||
}
|
||||
if ('' == trim($this -> username)) {
|
||||
$this -> username = 'anonymous';
|
||||
}
|
||||
if (isset($url['pass'])) {
|
||||
$this -> password = $url['pass'];
|
||||
}
|
||||
if (isset($url['port'])) {
|
||||
$this -> port = $url['port'];
|
||||
}
|
||||
$this->starttls = $starttls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the given LDAP-Server
|
||||
*
|
||||
* @return LDAP
|
||||
* @throws Error
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
$this -> disconnect();
|
||||
if ('ldaps' == $this->scheme && 389 == $this->port) {
|
||||
$this->port = 636;
|
||||
}
|
||||
|
||||
$this->ch = @ldap_connect($this->scheme . '://' . $this->server . ':' . $this -> port);
|
||||
if (false === $this->ch) {
|
||||
$this->ch = null;
|
||||
throw new Error('Could not connect to the server');
|
||||
}
|
||||
ldap_set_option($this->ch, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($this->ch, LDAP_OPT_REFERRALS, 0);
|
||||
//if configured try to upgrade encryption to tls for ldap connections
|
||||
if ($this->starttls) {
|
||||
ldap_start_tls($this->ch);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from a resource if one is available
|
||||
*
|
||||
* @return LDAP
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
if (null !== $this->ch ) {
|
||||
@ldap_unbind($this->ch);
|
||||
}
|
||||
$this->ch = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to an LDAP-Server with the given credentials
|
||||
*
|
||||
* @return LDAP
|
||||
* @throw AuthLdap_Exception
|
||||
*/
|
||||
public function bind()
|
||||
{
|
||||
if (! $this->ch) {
|
||||
$this->connect();
|
||||
}
|
||||
if (null === $this->ch) {
|
||||
throw new Error('No valid LDAP connection available');
|
||||
}
|
||||
$bind = false;
|
||||
if (( ( $this->username )
|
||||
&& ( $this->username != 'anonymous') )
|
||||
&& ( $this->password != '' )) {
|
||||
$bind = @ldap_bind($this->ch, $this->username, $this->password);
|
||||
} else {
|
||||
$bind = @ldap_bind($this->ch);
|
||||
}
|
||||
if (! $bind) {
|
||||
throw new Error('bind was not successfull: ' . ldap_error($this->ch));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getErrorNumber()
|
||||
{
|
||||
return @ldap_errno($this->ch);
|
||||
}
|
||||
|
||||
public function getErrorText()
|
||||
{
|
||||
return @ldap_error($this->ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does the actual ldap-serch.
|
||||
*
|
||||
* This is using the filter <var>$filter</var> for retrieving the attributes
|
||||
* <var>$attributes</var>
|
||||
*
|
||||
*
|
||||
* @param string $filter
|
||||
* @param array $attributes
|
||||
* @param string $base
|
||||
* @return array
|
||||
*/
|
||||
public function search($filter, $attributes = array('uid'), $base = '')
|
||||
{
|
||||
if (null === $this->ch) {
|
||||
throw new Error('No resource handle avbailable');
|
||||
}
|
||||
if (! $base) {
|
||||
$base = $this->baseDn;
|
||||
}
|
||||
$result = ldap_search($this->ch, $base, $filter, $attributes);
|
||||
if ($result === false) {
|
||||
throw new Error('no result found');
|
||||
}
|
||||
$this->_info = @ldap_get_entries($this->ch, $result);
|
||||
if ($this->_info === false) {
|
||||
throw new Error('invalid results found');
|
||||
}
|
||||
return $this -> _info;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets debugging to ON
|
||||
*/
|
||||
public function debugOn()
|
||||
{
|
||||
$this->debug = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets debugging to OFF
|
||||
*/
|
||||
public function debugOff()
|
||||
{
|
||||
$this->debug = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method authenticates the user <var>$username</var> using the
|
||||
* password <var>$password</var>
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $filter OPTIONAL This parameter defines the Filter to be used
|
||||
* when searchin for the username. This MUST contain the string '%s' which
|
||||
* will be replaced by the vaue given in <var>$username</var>
|
||||
* @return boolean true or false depending on successfull authentication or not
|
||||
*/
|
||||
public function authenticate($username, $password, $filter = '(uid=%s)')
|
||||
{
|
||||
//return true;
|
||||
$this->connect();
|
||||
$this->bind();
|
||||
$res = $this->search(sprintf($filter, ldap_escape($username, '', LDAP_ESCAPE_FILTER)));
|
||||
if (! $res || ! is_array($res) || ( $res ['count'] != 1 )) {
|
||||
return false;
|
||||
}
|
||||
$dn = $res[0]['dn'];
|
||||
if ($username && $password) {
|
||||
if (@ldap_bind($this->ch, $dn, $password)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* $this method loggs errors if debugging is set to ON
|
||||
*/
|
||||
public function logError()
|
||||
{
|
||||
if ($this->debug) {
|
||||
$_v = debug_backtrace();
|
||||
throw new Error(
|
||||
'[LDAP_ERROR]' . ldap_errno($this->ch) . ':' . ldap_error($this->ch),
|
||||
$_v[0]['line']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
22
wp-content/plugins/authldap/phpcs.xml
Normal file
22
wp-content/plugins/authldap/phpcs.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="Custom Standard" namespace="MyProject\CS\Standard">
|
||||
<description>authLdap codestyle</description>
|
||||
<file>./src</file>
|
||||
<file>./authLdap.php</file>
|
||||
<file>./tests</file>
|
||||
|
||||
<arg name="colors"/>
|
||||
<arg value="sp"/>
|
||||
|
||||
<autoload>./vendor/autoload.php</autoload>
|
||||
|
||||
<rule ref="PSR12">
|
||||
<exclude name="Generic.WhiteSpace.DisallowTabIndent"/>
|
||||
</rule>
|
||||
<rule ref="Generic.WhiteSpace.ScopeIndent">
|
||||
<properties>
|
||||
<property name="tabIndent" value="true"/>
|
||||
</properties>
|
||||
</rule>
|
||||
|
||||
</ruleset>
|
@ -2,8 +2,8 @@
|
||||
Contributors: heiglandreas
|
||||
Tags: ldap, auth, authentication, active directory, AD, openLDAP, Open Directory
|
||||
Requires at least: 2.5.0
|
||||
Tested up to: 5.9.0
|
||||
Requires PHP: 7.2
|
||||
Tested up to: 6.3.0
|
||||
Requires PHP: 7.4
|
||||
Stable tag: trunk
|
||||
License: MIT
|
||||
License URI: https://opensource.org/licenses/MIT
|
||||
@ -39,8 +39,36 @@ Go to https://github.com/heiglandreas/authLdap
|
||||
|
||||
Please use the issuetracker at https://github.com/heiglandreas/authLdap/issues
|
||||
|
||||
= Where can I report sensitive security issues with the plugin? =
|
||||
|
||||
In essence: Report a security vulnerability at https://github.com/heiglandreas/authLdap/security/advisories/new
|
||||
|
||||
Please see https://github.com/heiglandreas/authLdap/blob/master/SECURITY.md for more details
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 2.5.9 =
|
||||
|
||||
* Adds information about security-contacts
|
||||
* Addresses CVE-2023-41655
|
||||
|
||||
= 2.5.8 =
|
||||
|
||||
* Fix regression from 2.5.7
|
||||
|
||||
= 2.5.7 =
|
||||
|
||||
* Fix regressions from 2.5.4
|
||||
* Fix CI system
|
||||
|
||||
= 2.5.4 =
|
||||
* Update Tested up to
|
||||
|
||||
= 2.5.3 =
|
||||
* Fix issue with broken role-assignement in combination with WooCommerce
|
||||
* Fix spelling issue
|
||||
* Allow DN as role-definition
|
||||
|
||||
= 2.5.0 =
|
||||
* Ignore the order of capabilities to tell the role. In addition the filter `editable_roles` can be used to limit the roles
|
||||
|
||||
|
6
wp-content/plugins/authldap/security.txt
Normal file
6
wp-content/plugins/authldap/security.txt
Normal file
@ -0,0 +1,6 @@
|
||||
Contact: mailto://andreas@heigl.net
|
||||
Contact: https://github.com/heiglandreas/authLdap/security/advisories/new
|
||||
Expires: 2026-09-07T10:00:00.000Z
|
||||
Encryption: https://andreas.heigl.org/publickey/
|
||||
Encryption: https://heigl.org/.well-known/openpgpkey/hu/sfqdema7hgdj146cwzo4rxgsoujxis31
|
||||
Preferred-Languages: en,de
|
@ -1,13 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Copyright Andrea Heigl <andreas@heigl.org>
|
||||
*
|
||||
* Licenses under the MIT-license. For details see the included file LICENSE.md
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap\Exception;
|
||||
|
||||
use Exception;
|
||||
|
@ -1,15 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright Andreas Heigl <andreas@heigl.org>
|
||||
*
|
||||
* Licenses under the MIT-license. For details see the included file LICENSE.md
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class InvalidLdapUri extends RuntimeException
|
||||
{
|
||||
public static function fromLdapUriString(string $ldapUri): InvalidLdapUri
|
||||
{
|
||||
return new self('"%s" is not a valid LDAP-URI.');
|
||||
}
|
||||
public static function cannotparse(string $ldapUri): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'%1$s seems not to be a valid URI',
|
||||
$ldapUri
|
||||
));
|
||||
}
|
||||
|
||||
public static function wrongSchema(string $uri): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'%1$s does not start with a valid schema',
|
||||
$uri
|
||||
));
|
||||
}
|
||||
|
||||
public static function noSchema(string $uri): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'%1$s does not provide a schema',
|
||||
$uri
|
||||
));
|
||||
}
|
||||
|
||||
public static function noEnvironmentVariableSet(string $uri): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The environment variable %1$s does not provide a URI',
|
||||
$uri
|
||||
));
|
||||
}
|
||||
|
||||
public static function noServerProvided(string $uri): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The LDAP-URI %1$s does not provide a server',
|
||||
$uri
|
||||
));
|
||||
}
|
||||
|
||||
public static function noSearchBaseProvided(string $uri): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The LDAP-URI %1$s does not provide a search-base',
|
||||
$uri
|
||||
));
|
||||
}
|
||||
|
||||
public static function invalidSearchBaseProvided(string $uri): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The LDAP-URI %1$s does not provide a valid search-base',
|
||||
$uri
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright Andreas Heigl <andreas@heigl.org>
|
||||
*
|
||||
* Licenses under the MIT-license. For details see the included file LICENSE.md
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class MissingValidLdapConnection extends Error
|
||||
{
|
||||
public static function get(): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'No valid LDAP connection available'
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright Andreas Heigl <andreas@heigl.org>
|
||||
*
|
||||
* Licenses under the MIT-license. For details see the included file LICENSE.md
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class SearchUnsuccessfull extends RuntimeException
|
||||
{
|
||||
public static function fromSearchFilter(string $filter): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Search for %1$s was not successfull',
|
||||
$filter
|
||||
));
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) Andreas Heigl<andreas@heigl.org>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -26,23 +27,26 @@
|
||||
|
||||
namespace Org_Heigl\AuthLdap;
|
||||
|
||||
use Exception;
|
||||
use Org_Heigl\AuthLdap\Exception\Error;
|
||||
use Org_Heigl\AuthLdap\Exception\SearchUnsuccessfull;
|
||||
use Org_Heigl\AuthLdap\Manager\Ldap;
|
||||
|
||||
class LdapList
|
||||
{
|
||||
/**
|
||||
* @var \LDAP[]
|
||||
* @var Ldap[]
|
||||
*/
|
||||
protected $items = [];
|
||||
|
||||
public function addLdap(LDAP $ldap)
|
||||
public function addLdap(Ldap $ldap)
|
||||
{
|
||||
$this->items[] = $ldap;
|
||||
}
|
||||
|
||||
public function authenticate($username, $password, $filter = '(uid=%s)')
|
||||
{
|
||||
/** @var LDAP $item */
|
||||
/** @var Ldap $item */
|
||||
foreach ($this->items as $key => $item) {
|
||||
if (! $item->authenticate($username, $password, $filter)) {
|
||||
unset($this->items[$key]);
|
||||
@ -81,10 +85,9 @@ class LdapList
|
||||
$result = $item->search($filter, $attributes, $base);
|
||||
return $result;
|
||||
} catch (Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
throw new \AuthLDAP_Exception('No Results found');
|
||||
throw SearchUnsuccessfull::fromSearchFilter($filter);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Copyright (c) Andreas Heigl<andreas@heigl.org>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -27,46 +25,155 @@ declare(strict_types=1);
|
||||
* @link http://github.com/heiglandreas/authLDAP
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap;
|
||||
|
||||
use Org_Heigl\AuthLdap\Exception\InvalidLdapUri;
|
||||
|
||||
use function array_map;
|
||||
use function error_get_last;
|
||||
use function getenv;
|
||||
use function preg_replace;
|
||||
use function urlencode;
|
||||
use function is_array;
|
||||
use function is_string;
|
||||
use function parse_url;
|
||||
use function preg_replace_callback;
|
||||
use function rawurlencode;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use function trim;
|
||||
use function urldecode;
|
||||
|
||||
final class LdapUri
|
||||
{
|
||||
private $uri;
|
||||
private $server;
|
||||
|
||||
private function __construct(string $uri)
|
||||
{
|
||||
if (! preg_match('/^(ldap|ldaps|env)/', $uri)) {
|
||||
throw InvalidLdapUri::fromLdapUriString($uri);
|
||||
}
|
||||
$this->uri = $uri;
|
||||
}
|
||||
private $scheme;
|
||||
|
||||
public static function fromString(string $uri): LdapUri
|
||||
{
|
||||
return new LdapUri($uri);
|
||||
}
|
||||
private $port = 389;
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
$uri = $this->uri;
|
||||
if (0 === strpos($uri, 'env:')) {
|
||||
$uri = getenv(substr($this->uri, 4));
|
||||
}
|
||||
private string $baseDn;
|
||||
|
||||
$uri = preg_replace_callback('/%env:([^%]+)%/', function (array $matches) {
|
||||
return rawurlencode(getenv($matches[1]));
|
||||
}, $uri);
|
||||
private $username = '';
|
||||
|
||||
return $uri;
|
||||
}
|
||||
private $password = '';
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
private function __construct(string $uri)
|
||||
{
|
||||
if (!preg_match('/^(ldap|ldaps|env)/', $uri)) {
|
||||
throw InvalidLdapUri::wrongSchema($uri);
|
||||
}
|
||||
|
||||
if (strpos($uri, 'env:') === 0) {
|
||||
$newUri = getenv(substr($uri, 4));
|
||||
if (false === $newUri) {
|
||||
throw InvalidLdapUri::noEnvironmentVariableSet($uri);
|
||||
}
|
||||
$uri = (string) $newUri;
|
||||
}
|
||||
|
||||
$uri = $this->injectEnvironmentVariables($uri);
|
||||
|
||||
$array = parse_url($uri);
|
||||
if (!is_array($array)) {
|
||||
throw InvalidLdapUri::cannotparse($uri);
|
||||
}
|
||||
|
||||
$url = array_map(static function ($item) {
|
||||
if (is_int($item)) {
|
||||
return $item;
|
||||
}
|
||||
return urldecode($item);
|
||||
}, $array);
|
||||
|
||||
|
||||
if (!isset($url['scheme'])) {
|
||||
throw InvalidLdapUri::noSchema($uri);
|
||||
}
|
||||
if (0 !== strpos($url['scheme'], 'ldap')) {
|
||||
throw InvalidLdapUri::wrongSchema($uri);
|
||||
}
|
||||
if (!isset($url['host'])) {
|
||||
throw InvalidLdapUri::noServerProvided($uri);
|
||||
}
|
||||
if (!isset($url['path'])) {
|
||||
throw InvalidLdapUri::noSearchBaseProvided($uri);
|
||||
}
|
||||
if (1 === strlen($url['path'])) {
|
||||
throw InvalidLdapUri::invalidSearchBaseProvided($uri);
|
||||
}
|
||||
|
||||
$this->server = $url['host'];
|
||||
$this->scheme = $url['scheme'];
|
||||
$this->baseDn = substr($url['path'], 1);
|
||||
if (isset($url['user'])) {
|
||||
$this->username = $url['user'];
|
||||
}
|
||||
if ('' === trim($this->username)) {
|
||||
$this->username = 'anonymous';
|
||||
}
|
||||
if (isset($url['pass'])) {
|
||||
$this->password = $url['pass'];
|
||||
}
|
||||
if ($this->scheme === 'ldaps' && $this->port = 389) {
|
||||
$this->port = 636;
|
||||
}
|
||||
|
||||
// When someone sets the port in the URL we overwrite whatever is set.
|
||||
// We have to assume they know what they are doing!
|
||||
if (isset($url['port'])) {
|
||||
$this->port = $url['port'];
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromString(string $uri): LdapUri
|
||||
{
|
||||
return new LdapUri($uri);
|
||||
}
|
||||
|
||||
private function injectEnvironmentVariables(string $base): string
|
||||
{
|
||||
return preg_replace_callback('/%env:([^%]+)%/', static function (array $matches) {
|
||||
return rawurlencode(getenv($matches[1]));
|
||||
}, $base);
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
return $this->scheme . '://' . $this->server . ':' . $this->port;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
|
||||
public function getUsername(): string
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function getPassword(): string
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function getBaseDn(): string
|
||||
{
|
||||
return $this->baseDn;
|
||||
}
|
||||
|
||||
public function isAnonymous(): bool
|
||||
{
|
||||
if ($this->password === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->username === 'anonymous') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
164
wp-content/plugins/authldap/src/Manager/Ldap.php
Normal file
164
wp-content/plugins/authldap/src/Manager/Ldap.php
Normal file
@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* $Id: ldap.php 381646 2011-05-06 09:37:31Z heiglandreas $
|
||||
*
|
||||
* authLdap - Authenticate Wordpress against an LDAP-Backend.
|
||||
* Copyright (c) 2008 Andreas Heigl<andreas@heigl.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* This file handles the basic LDAP-Tasks
|
||||
*
|
||||
* @author Andreas Heigl<andreas@heigl.org>
|
||||
* @package authLdap
|
||||
* @category authLdap
|
||||
* @since 2008
|
||||
*/
|
||||
|
||||
namespace Org_Heigl\AuthLdap\Manager;
|
||||
|
||||
use Org_Heigl\AuthLdap\Exception\Error;
|
||||
use Org_Heigl\AuthLdap\Exception\MissingValidLdapConnection;
|
||||
use Org_Heigl\AuthLdap\LdapUri;
|
||||
use Org_Heigl\AuthLdap\Wrapper\LdapFactory;
|
||||
use Org_Heigl\AuthLdap\Wrapper\LdapInterface;
|
||||
|
||||
class Ldap
|
||||
{
|
||||
/**
|
||||
* This property contains the connection handle to the ldap-server
|
||||
*
|
||||
* @var LdapInterface|null
|
||||
*/
|
||||
private ?LdapInterface $connection;
|
||||
|
||||
private LdapUri $uri;
|
||||
|
||||
private LdapFactory $factory;
|
||||
|
||||
private $starttls;
|
||||
|
||||
public function __construct(LdapFactory $factory, LdapUri $uri, $starttls = false)
|
||||
{
|
||||
$this->starttls = $starttls;
|
||||
$this->uri = $uri;
|
||||
$this->factory = $factory;
|
||||
$this->connection = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the given LDAP-Server
|
||||
*/
|
||||
public function connect(): self
|
||||
{
|
||||
$this->disconnect();
|
||||
|
||||
$this->connection = $this->factory->createFromLdapUri($this->uri->toString());
|
||||
$this->connection->setOption(LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
$this->connection->setOption(LDAP_OPT_REFERRALS, 0);
|
||||
//if configured try to upgrade encryption to tls for ldap connections
|
||||
if ($this->starttls) {
|
||||
$this->connection->startTls();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from a resource if one is available
|
||||
*/
|
||||
public function disconnect(): self
|
||||
{
|
||||
if (null !== $this->connection) {
|
||||
$this->connection->unbind();
|
||||
}
|
||||
$this->connection = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to an LDAP-Server with the given credentials
|
||||
*
|
||||
* @throws Error
|
||||
*/
|
||||
public function bind(): self
|
||||
{
|
||||
if (!$this->connection) {
|
||||
$this->connect();
|
||||
}
|
||||
if (null === $this->connection) {
|
||||
throw MissingValidLdapConnection::get();
|
||||
}
|
||||
if ($this->uri->isAnonymous()) {
|
||||
$bind = $this->connection->bind();
|
||||
} else {
|
||||
$bind = $this->connection->bind($this->uri->getUsername(), $this->uri->getPassword());
|
||||
}
|
||||
if (!$bind) {
|
||||
throw new Error('bind was not successfull: ' . $this->connection->error());
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does the actual ldap-serch.
|
||||
*
|
||||
* This is using the filter <var>$filter</var> for retrieving the attributes
|
||||
* <var>$attributes</var>
|
||||
*
|
||||
* @return array<string|int, mixed>
|
||||
* @throws Error
|
||||
*/
|
||||
public function search(string $filter, array $attributes = ['uid'], ?string $base = ''): array
|
||||
{
|
||||
if (null === $this->connection) {
|
||||
throw new Error('No resource handle available');
|
||||
}
|
||||
if (!$base) {
|
||||
$base = $this->uri->getBaseDn();
|
||||
}
|
||||
$result = $this->connection->search($base, $filter, $attributes);
|
||||
if ($result === false) {
|
||||
throw new Error('no result found');
|
||||
}
|
||||
$info = $this->connection->getEntries($result);
|
||||
if ($info === false) {
|
||||
throw new Error('invalid results found');
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method authenticates the user <var>$username</var> using the
|
||||
* password <var>$password</var>
|
||||
*
|
||||
* @param string $filter OPTIONAL This parameter defines the Filter to be used
|
||||
* when searchin for the username. This MUST contain the string '%s' which
|
||||
* will be replaced by the vaue given in <var>$username</var>
|
||||
* @throws Error
|
||||
*/
|
||||
public function authenticate(string $username, string $password, string $filter = '(uid=%s)'): bool
|
||||
{
|
||||
$this->connect();
|
||||
$this->bind();
|
||||
$res = $this->search(sprintf($filter, $this->factory->escape($username, '', LDAP_ESCAPE_FILTER)));
|
||||
if ($res ['count'] !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$dn = $res[0]['dn'];
|
||||
return $username && $password && $this->connection->bind($dn, $password);
|
||||
}
|
||||
}
|
54
wp-content/plugins/authldap/src/UserRoleHandler.php
Normal file
54
wp-content/plugins/authldap/src/UserRoleHandler.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright Andreas Heigl <andreas@heigl.org>
|
||||
*
|
||||
* Licenses under the MIT-license. For details see the included file LICENSE.md
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap;
|
||||
|
||||
use WP_User;
|
||||
|
||||
use function array_search;
|
||||
use function in_array;
|
||||
use function var_dump;
|
||||
|
||||
class UserRoleHandler
|
||||
{
|
||||
/**
|
||||
* @param WP_User $user
|
||||
* @param string[] $roles
|
||||
* @return void
|
||||
*/
|
||||
public function addRolesToUser(WP_User $user, $roles) : void
|
||||
{
|
||||
if ($roles === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($user->roles == $roles) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove unused roles from existing.
|
||||
foreach ($user->roles as $role) {
|
||||
if (!in_array($role, $roles)) {
|
||||
// Remove unused roles.
|
||||
$user->remove_role($role);
|
||||
continue;
|
||||
}
|
||||
// Remove the existing role from roles.
|
||||
if (($key = array_search($role, $roles)) !== false) {
|
||||
unset($roles[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add new ones if not already assigned.
|
||||
foreach ($roles as $role) {
|
||||
$user->add_role($role);
|
||||
}
|
||||
}
|
||||
}
|
92
wp-content/plugins/authldap/src/Wrapper/Ldap.php
Normal file
92
wp-content/plugins/authldap/src/Wrapper/Ldap.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright Andreas Heigl <andreas@heigl.org>
|
||||
*
|
||||
* Licenses under the MIT-license. For details see the included file LICENSE.md
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap\Wrapper;
|
||||
|
||||
use function ldap_bind;
|
||||
use function ldap_connect;
|
||||
use function ldap_error;
|
||||
use function ldap_escape;
|
||||
use function ldap_get_entries;
|
||||
use function ldap_set_option;
|
||||
use function ldap_start_tls;
|
||||
use function ldap_unbind;
|
||||
|
||||
final class Ldap implements LdapInterface
|
||||
{
|
||||
private $connection;
|
||||
|
||||
public function __construct(string $ldapUri)
|
||||
{
|
||||
$this->connection = ldap_connect($ldapUri);
|
||||
}
|
||||
|
||||
public function bind($dn = null, $password = null)
|
||||
{
|
||||
if (null === $dn && null === $password) {
|
||||
return ldap_bind($this->connection);
|
||||
}
|
||||
return ldap_bind($this->connection, $dn, $password);
|
||||
}
|
||||
|
||||
public function unbind()
|
||||
{
|
||||
return ldap_unbind($this->connection);
|
||||
}
|
||||
|
||||
public function setOption($option, $value)
|
||||
{
|
||||
return ldap_set_option($this->connection, $option, $value);
|
||||
}
|
||||
|
||||
public function startTls()
|
||||
{
|
||||
return ldap_start_tls($this->connection);
|
||||
}
|
||||
|
||||
public function error()
|
||||
{
|
||||
return ldap_error($this->connection);
|
||||
}
|
||||
|
||||
public function errno()
|
||||
{
|
||||
return ldap_errno($this->connection);
|
||||
}
|
||||
|
||||
public function search(
|
||||
$base,
|
||||
$filter,
|
||||
array $attributes = [],
|
||||
$attributes_only = 0,
|
||||
$sizelimit = -1,
|
||||
$timelimit = -1
|
||||
) {
|
||||
return ldap_search(
|
||||
$this->connection,
|
||||
$base,
|
||||
$filter,
|
||||
$attributes,
|
||||
$attributes_only,
|
||||
$sizelimit,
|
||||
$timelimit
|
||||
);
|
||||
}
|
||||
|
||||
public function getEntries($search_result)
|
||||
{
|
||||
return ldap_get_entries($this->connection, $search_result);
|
||||
}
|
||||
|
||||
public static function escape(string $value, string $ignore = '', int $flags = 0): string
|
||||
{
|
||||
return ldap_escape($value, $ignore, $flags);
|
||||
}
|
||||
}
|
24
wp-content/plugins/authldap/src/Wrapper/LdapFactory.php
Normal file
24
wp-content/plugins/authldap/src/Wrapper/LdapFactory.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright Andreas Heigl <andreas@heigl.org>
|
||||
*
|
||||
* Licenses under the MIT-license. For details see the included file LICENSE.md
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap\Wrapper;
|
||||
|
||||
class LdapFactory
|
||||
{
|
||||
public function createFromLdapUri(string $ldapUri): LdapInterface
|
||||
{
|
||||
return new Ldap($ldapUri);
|
||||
}
|
||||
|
||||
public function escape($value, $ignore = '', $flags = 0): string
|
||||
{
|
||||
return Ldap::escape($value, $ignore, $flags);
|
||||
}
|
||||
}
|
39
wp-content/plugins/authldap/src/Wrapper/LdapInterface.php
Normal file
39
wp-content/plugins/authldap/src/Wrapper/LdapInterface.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright Andreas Heigl <andreas@heigl.org>
|
||||
*
|
||||
* Licenses under the MIT-license. For details see the included file LICENSE.md
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Org_Heigl\AuthLdap\Wrapper;
|
||||
|
||||
interface LdapInterface
|
||||
{
|
||||
public function bind($dn = null, $password = null);
|
||||
|
||||
public function unbind();
|
||||
|
||||
public function setOption($option, $value);
|
||||
|
||||
public function startTls();
|
||||
|
||||
public function error();
|
||||
|
||||
public function errno();
|
||||
|
||||
public function search(
|
||||
$base,
|
||||
$filter,
|
||||
array $attributes = [],
|
||||
$attributes_only = 0,
|
||||
$sizelimit = -1,
|
||||
$timelimit = -1
|
||||
);
|
||||
|
||||
public function getEntries($search_result);
|
||||
|
||||
public static function escape(string $value, string $ignore = '', int $flags = 0): string;
|
||||
}
|
@ -37,6 +37,7 @@
|
||||
<?php endif ?>
|
||||
<h2>AuthLDAP Options</h2>
|
||||
<form class="authldap-options" method="post" id="authLDAP_options" action="<?php echo $action;?>">
|
||||
<input name="authLdapNonce" type="hidden" value="<?php echo wp_create_nonce('authLdapNonce'); ?>" />
|
||||
<h3 class="title">General Usage of authLDAP</h3>
|
||||
<fieldset class="options">
|
||||
<table class="form-table">
|
||||
@ -193,7 +194,7 @@
|
||||
<p class="description">
|
||||
If checked the plugin will use the user's account to query their own information. If not it will use the admin account.
|
||||
</p>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
Loading…
Reference in New Issue
Block a user