Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 233 |
ldap | |
0.00% |
0 / 1 |
|
0.00% |
0 / 7 |
1722.00 | |
0.00% |
0 / 233 |
__construct | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 6 |
|||
init | |
0.00% |
0 / 1 |
182.00 | |
0.00% |
0 / 53 |
|||
login | |
0.00% |
0 / 1 |
380.00 | |
0.00% |
0 / 142 |
|||
acp | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 5 |
|||
get_acp_template | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 15 |
|||
ldap_user_filter | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 9 |
|||
ldap_escape | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 3 |
<?php | |
/** | |
* | |
* This file is part of the phpBB Forum Software package. | |
* | |
* @copyright (c) phpBB Limited <https://www.phpbb.com> | |
* @license GNU General Public License, version 2 (GPL-2.0) | |
* | |
* For full copyright and license information, please see | |
* the docs/CREDITS.txt file. | |
* | |
*/ | |
namespace phpbb\auth\provider; | |
use phpbb\config\config; | |
use phpbb\db\driver\driver_interface; | |
use phpbb\language\language; | |
use phpbb\user; | |
/** | |
* Database authentication provider for phpBB3 | |
* This is for authentication via the integrated user table | |
*/ | |
class ldap extends base | |
{ | |
/** @var config phpBB config */ | |
protected $config; | |
/** @var driver_interface DBAL driver interface */ | |
protected $db; | |
/** @var language phpBB language class */ | |
protected $language; | |
/** @var user phpBB user */ | |
protected $user; | |
/** | |
* LDAP Authentication Constructor | |
* | |
* @param config $config Config object | |
* @param driver_interface $db DBAL driver interface | |
* @param language $language Language object | |
* @param user $user User object | |
*/ | |
public function __construct(config $config, driver_interface $db, language $language, user $user) | |
{ | |
$this->config = $config; | |
$this->db = $db; | |
$this->language = $language; | |
$this->user = $user; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function init() | |
{ | |
if (!@extension_loaded('ldap')) | |
{ | |
return $this->language->lang('LDAP_NO_LDAP_EXTENSION'); | |
} | |
$this->config['ldap_port'] = (int) $this->config['ldap_port']; | |
if ($this->config['ldap_port']) | |
{ | |
$ldap = @ldap_connect($this->config['ldap_server'], $this->config['ldap_port']); | |
} | |
else | |
{ | |
$ldap = @ldap_connect($this->config['ldap_server']); | |
} | |
if (!$ldap) | |
{ | |
return $this->language->lang('LDAP_NO_SERVER_CONNECTION'); | |
} | |
@ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); | |
@ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); | |
if ($this->config['ldap_user'] || $this->config['ldap_password']) | |
{ | |
if (!@ldap_bind($ldap, html_entity_decode($this->config['ldap_user'], ENT_COMPAT), html_entity_decode($this->config['ldap_password'], ENT_COMPAT))) | |
{ | |
return $this->language->lang('LDAP_INCORRECT_USER_PASSWORD'); | |
} | |
} | |
// ldap_connect only checks whether the specified server is valid, so the connection might still fail | |
$search = @ldap_search( | |
$ldap, | |
html_entity_decode($this->config['ldap_base_dn'], ENT_COMPAT), | |
$this->ldap_user_filter($this->user->data['username']), | |
(empty($this->config['ldap_email'])) ? | |
array(html_entity_decode($this->config['ldap_uid'], ENT_COMPAT)) : | |
array(html_entity_decode($this->config['ldap_uid'], ENT_COMPAT), html_entity_decode($this->config['ldap_email'], ENT_COMPAT)), | |
0, | |
1 | |
); | |
if ($search === false) | |
{ | |
return $this->language->lang('LDAP_SEARCH_FAILED'); | |
} | |
$result = @ldap_get_entries($ldap, $search); | |
@ldap_close($ldap); | |
if (!is_array($result) || count($result) < 2) | |
{ | |
return $this->language->lang('LDAP_NO_IDENTITY', $this->user->data['username']); | |
} | |
if (!empty($this->config['ldap_email']) && !isset($result[0][html_entity_decode($this->config['ldap_email'])])) | |
{ | |
return $this->language->lang('LDAP_NO_EMAIL'); | |
} | |
return false; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function login($username, $password) | |
{ | |
// do not allow empty password | |
if (!$password) | |
{ | |
return array( | |
'status' => LOGIN_ERROR_PASSWORD, | |
'error_msg' => 'NO_PASSWORD_SUPPLIED', | |
'user_row' => array('user_id' => ANONYMOUS), | |
); | |
} | |
if (!$username) | |
{ | |
return array( | |
'status' => LOGIN_ERROR_USERNAME, | |
'error_msg' => 'LOGIN_ERROR_USERNAME', | |
'user_row' => array('user_id' => ANONYMOUS), | |
); | |
} | |
if (!@extension_loaded('ldap')) | |
{ | |
return array( | |
'status' => LOGIN_ERROR_EXTERNAL_AUTH, | |
'error_msg' => 'LDAP_NO_LDAP_EXTENSION', | |
'user_row' => array('user_id' => ANONYMOUS), | |
); | |
} | |
$this->config['ldap_port'] = (int) $this->config['ldap_port']; | |
if ($this->config['ldap_port']) | |
{ | |
$ldap = @ldap_connect($this->config['ldap_server'], $this->config['ldap_port']); | |
} | |
else | |
{ | |
$ldap = @ldap_connect($this->config['ldap_server']); | |
} | |
if (!$ldap) | |
{ | |
return array( | |
'status' => LOGIN_ERROR_EXTERNAL_AUTH, | |
'error_msg' => 'LDAP_NO_SERVER_CONNECTION', | |
'user_row' => array('user_id' => ANONYMOUS), | |
); | |
} | |
@ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); | |
@ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); | |
if ($this->config['ldap_user'] || $this->config['ldap_password']) | |
{ | |
if (!@ldap_bind($ldap, html_entity_decode($this->config['ldap_user'], ENT_COMPAT), html_entity_decode($this->config['ldap_password'], ENT_COMPAT))) | |
{ | |
return array( | |
'status' => LOGIN_ERROR_EXTERNAL_AUTH, | |
'error_msg' => 'LDAP_NO_SERVER_CONNECTION', | |
'user_row' => array('user_id' => ANONYMOUS), | |
); | |
} | |
} | |
$search = @ldap_search( | |
$ldap, | |
html_entity_decode($this->config['ldap_base_dn'], ENT_COMPAT), | |
$this->ldap_user_filter($username), | |
(empty($this->config['ldap_email'])) ? | |
array(html_entity_decode($this->config['ldap_uid'], ENT_COMPAT)) : | |
array(html_entity_decode($this->config['ldap_uid'], ENT_COMPAT), html_entity_decode($this->config['ldap_email'], ENT_COMPAT)), | |
0, | |
1 | |
); | |
$ldap_result = @ldap_get_entries($ldap, $search); | |
if (is_array($ldap_result) && count($ldap_result) > 1) | |
{ | |
if (@ldap_bind($ldap, $ldap_result[0]['dn'], html_entity_decode($password, ENT_COMPAT))) | |
{ | |
@ldap_close($ldap); | |
$sql ='SELECT user_id, username, user_password, user_passchg, user_email, user_type | |
FROM ' . USERS_TABLE . " | |
WHERE username_clean = '" . $this->db->sql_escape(utf8_clean_string($username)) . "'"; | |
$result = $this->db->sql_query($sql); | |
$row = $this->db->sql_fetchrow($result); | |
$this->db->sql_freeresult($result); | |
if ($row) | |
{ | |
unset($ldap_result); | |
// User inactive... | |
if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) | |
{ | |
return array( | |
'status' => LOGIN_ERROR_ACTIVE, | |
'error_msg' => 'ACTIVE_ERROR', | |
'user_row' => $row, | |
); | |
} | |
// Successful login... set user_login_attempts to zero... | |
return array( | |
'status' => LOGIN_SUCCESS, | |
'error_msg' => false, | |
'user_row' => $row, | |
); | |
} | |
else | |
{ | |
// retrieve default group id | |
$sql = 'SELECT group_id | |
FROM ' . GROUPS_TABLE . " | |
WHERE group_name = '" . $this->db->sql_escape('REGISTERED') . "' | |
AND group_type = " . GROUP_SPECIAL; | |
$result = $this->db->sql_query($sql); | |
$row = $this->db->sql_fetchrow($result); | |
$this->db->sql_freeresult($result); | |
if (!$row) | |
{ | |
trigger_error('NO_GROUP'); | |
} | |
// generate user account data | |
$ldap_user_row = array( | |
'username' => $username, | |
'user_password' => '', | |
'user_email' => (!empty($this->config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][html_entity_decode($this->config['ldap_email'], ENT_COMPAT)][0]) : '', | |
'group_id' => (int) $row['group_id'], | |
'user_type' => USER_NORMAL, | |
'user_ip' => $this->user->ip, | |
'user_new' => ($this->config['new_member_post_limit']) ? 1 : 0, | |
); | |
unset($ldap_result); | |
// this is the user's first login so create an empty profile | |
return array( | |
'status' => LOGIN_SUCCESS_CREATE_PROFILE, | |
'error_msg' => false, | |
'user_row' => $ldap_user_row, | |
); | |
} | |
} | |
else | |
{ | |
unset($ldap_result); | |
@ldap_close($ldap); | |
// Give status about wrong password... | |
return array( | |
'status' => LOGIN_ERROR_PASSWORD, | |
'error_msg' => 'LOGIN_ERROR_PASSWORD', | |
'user_row' => array('user_id' => ANONYMOUS), | |
); | |
} | |
} | |
@ldap_close($ldap); | |
return array( | |
'status' => LOGIN_ERROR_USERNAME, | |
'error_msg' => 'LOGIN_ERROR_USERNAME', | |
'user_row' => array('user_id' => ANONYMOUS), | |
); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function acp() | |
{ | |
// These are fields required in the config table | |
return array( | |
'ldap_server', 'ldap_port', 'ldap_base_dn', 'ldap_uid', 'ldap_user_filter', 'ldap_email', 'ldap_user', 'ldap_password', | |
); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function get_acp_template($new_config) | |
{ | |
return array( | |
'TEMPLATE_FILE' => 'auth_provider_ldap.html', | |
'TEMPLATE_VARS' => array( | |
'AUTH_LDAP_BASE_DN' => $new_config['ldap_base_dn'], | |
'AUTH_LDAP_EMAIL' => $new_config['ldap_email'], | |
'AUTH_LDAP_PASSORD' => $new_config['ldap_password'] !== '' ? '********' : '', | |
'AUTH_LDAP_PORT' => $new_config['ldap_port'], | |
'AUTH_LDAP_SERVER' => $new_config['ldap_server'], | |
'AUTH_LDAP_UID' => $new_config['ldap_uid'], | |
'AUTH_LDAP_USER' => $new_config['ldap_user'], | |
'AUTH_LDAP_USER_FILTER' => $new_config['ldap_user_filter'], | |
), | |
); | |
} | |
/** | |
* Generates a filter string for ldap_search to find a user | |
* | |
* @param $username string Username identifying the searched user | |
* | |
* @return string A filter string for ldap_search | |
*/ | |
private function ldap_user_filter($username) | |
{ | |
$filter = '(' . $this->config['ldap_uid'] . '=' . $this->ldap_escape(html_entity_decode($username, ENT_COMPAT)) . ')'; | |
if ($this->config['ldap_user_filter']) | |
{ | |
$_filter = ($this->config['ldap_user_filter'][0] == '(' && substr($this->config['ldap_user_filter'], -1) == ')') ? $this->config['ldap_user_filter'] : "({$this->config['ldap_user_filter']})"; | |
$filter = "(&{$filter}{$_filter})"; | |
} | |
return $filter; | |
} | |
/** | |
* Escapes an LDAP AttributeValue | |
* | |
* @param string $string The string to be escaped | |
* @return string The escaped string | |
*/ | |
private function ldap_escape($string) | |
{ | |
return str_replace(array('*', '\\', '(', ')'), array('\\*', '\\\\', '\\(', '\\)'), $string); | |
} | |
} |