mirror of
https://github.com/YunoHost-Apps/ttrss_ynh.git
synced 2024-10-01 13:34:46 +02:00
Fix
This commit is contained in:
parent
b1ec247155
commit
716b40abd5
4 changed files with 439 additions and 0 deletions
6
conf/ldap.src
Normal file
6
conf/ldap.src
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
SOURCE_URL=https://git.tt-rss.org/fox/tt-rss/archive/97baf3e8b9be699d972b91a159ccbe0891efe8ae.tar.gz
|
||||||
|
SOURCE_SUM=5810abdde57daa282f470c0bb4c631596f6b6487a41ef8f27b10f0d2ad6407b0
|
||||||
|
SOURCE_SUM_PRG=sha256sum
|
||||||
|
SOURCE_FORMAT=tar.gz
|
||||||
|
SOURCE_IN_SUBDIR=true
|
||||||
|
SOURCE_EXTRACT=true
|
|
@ -81,6 +81,8 @@ ynh_app_setting_set --app=$app --key=final_path --value=$final_path
|
||||||
# Download, check integrity, uncompress and patch the source from app.src
|
# Download, check integrity, uncompress and patch the source from app.src
|
||||||
ynh_setup_source --dest_dir="$final_path"
|
ynh_setup_source --dest_dir="$final_path"
|
||||||
|
|
||||||
|
cp -a ../sources/* $final_path/plugins/
|
||||||
|
|
||||||
chmod 750 "$final_path"
|
chmod 750 "$final_path"
|
||||||
chmod -R o-rwx "$final_path"
|
chmod -R o-rwx "$final_path"
|
||||||
chown -R $app:www-data "$final_path"
|
chown -R $app:www-data "$final_path"
|
||||||
|
|
28
sources/auth_ldap/ChangeLog
Executable file
28
sources/auth_ldap/ChangeLog
Executable file
|
@ -0,0 +1,28 @@
|
||||||
|
2014-08-25 hydrian <ben.tyger@tygerclan.net>
|
||||||
|
|
||||||
|
* init.php: Version 0.5rc2
|
||||||
|
Security Issue: #10
|
||||||
|
Bug Fix: #11
|
||||||
|
|
||||||
|
|
||||||
|
2013-11-22 hydrian <ben.tyger@tygerclan.net>
|
||||||
|
|
||||||
|
* init.php: Version 0.5rc1
|
||||||
|
Bug fixes #5 #6
|
||||||
|
Enhancement #7 #8
|
||||||
|
Major restructure of cache
|
||||||
|
Major restructure of variables
|
||||||
|
|
||||||
|
2013-04-11 hydrian <ben.tyger@tygerclan.net>
|
||||||
|
|
||||||
|
* init.php: version 0.03
|
||||||
|
Fixed Schema file location when sys_get_temp_dir() is not availiable.
|
||||||
|
|
||||||
|
2013-04-08 hydrian <ben.tyger@tygerclan.net>
|
||||||
|
|
||||||
|
* init.php: version 0.02
|
||||||
|
Fixed LDAP over SSL
|
||||||
|
Fixed authentication with anonymous
|
||||||
|
Added LDAP schema cache for performance
|
||||||
|
Added loggging for authentication attempts
|
||||||
|
|
403
sources/auth_ldap/init.php
Executable file
403
sources/auth_ldap/init.php
Executable file
|
@ -0,0 +1,403 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tiny Tiny RSS plugin for LDAP authentication
|
||||||
|
* @author tsmgeek (tsmgeek@gmail.com)
|
||||||
|
* @author hydrian (ben.tyger@tygerclan.net)
|
||||||
|
* @copyright GPL2
|
||||||
|
* Requires php-ldap
|
||||||
|
* @version 2.00
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Configuration
|
||||||
|
* Put the following options in config.php and customize them for your environment
|
||||||
|
*
|
||||||
|
* define('LDAP_AUTH_SERVER_URI', 'ldaps://LDAPServerHostname:port/');
|
||||||
|
* define('LDAP_AUTH_USETLS', FALSE); // Enable TLS Support for ldaps://
|
||||||
|
* define('LDAP_AUTH_ALLOW_UNTRUSTED_CERT', TRUE); // Allows untrusted certificate
|
||||||
|
* define('LDAP_AUTH_BASEDN', 'dc=example,dc=com');
|
||||||
|
* define('LDAP_AUTH_ANONYMOUSBEFOREBIND', FALSE);
|
||||||
|
* // ??? will be replaced with the entered username(escaped) at login
|
||||||
|
* define('LDAP_AUTH_SEARCHFILTER', '(&(objectClass=person)(uid=???))');
|
||||||
|
* // Optional configuration
|
||||||
|
* define('LDAP_AUTH_BINDDN', 'cn=serviceaccount,dc=example,dc=com');
|
||||||
|
* define('LDAP_AUTH_BINDPW', 'ServiceAccountsPassword');
|
||||||
|
* define('LDAP_AUTH_LOGIN_ATTRIB', 'uid');
|
||||||
|
* define('LDAP_AUTH_LOG_ATTEMPTS', FALSE);
|
||||||
|
* Enable Debug Logging
|
||||||
|
* define('LDAP_AUTH_DEBUG', FALSE);
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notes -
|
||||||
|
* LDAP search does not support follow ldap referals. Referals are disabled to
|
||||||
|
* allow proper login. This is particular to Active Directory.
|
||||||
|
*
|
||||||
|
* Also group membership can be supported if the user object contains the
|
||||||
|
* the group membership via attributes. The following LDAP servers can
|
||||||
|
* support this.
|
||||||
|
* * Active Directory
|
||||||
|
* * OpenLDAP support with MemberOf Overlay
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Auth_Ldap extends Plugin implements IAuthModule {
|
||||||
|
|
||||||
|
private $link;
|
||||||
|
private $host;
|
||||||
|
private $base;
|
||||||
|
private $logClass;
|
||||||
|
private $ldapObj = NULL;
|
||||||
|
private $_debugMode;
|
||||||
|
private $_serviceBindDN;
|
||||||
|
private $_serviceBindPass;
|
||||||
|
private $_baseDN;
|
||||||
|
private $_useTLS;
|
||||||
|
private $_host;
|
||||||
|
private $_port;
|
||||||
|
private $_scheme;
|
||||||
|
private $_schemaCacheEnabled;
|
||||||
|
private $_anonBeforeBind;
|
||||||
|
private $_allowUntrustedCerts;
|
||||||
|
private $_ldapLoginAttrib;
|
||||||
|
|
||||||
|
function about() {
|
||||||
|
return array(0.05,
|
||||||
|
"Authenticates against an LDAP server (configured in config.php)",
|
||||||
|
"hydrian",
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function init($host) {
|
||||||
|
$this->link = $host->get_link();
|
||||||
|
$this->host = $host;
|
||||||
|
$this->base = new Auth_Base($this->link);
|
||||||
|
|
||||||
|
$host->add_hook($host::HOOK_AUTH_USER, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _log($msg, $level = E_USER_NOTICE, $file = '', $line = 0, $context = '') {
|
||||||
|
$loggerFunction = Logger::get();
|
||||||
|
if (is_object($loggerFunction)) {
|
||||||
|
$loggerFunction->log_error($level, $msg, $file, $line, $context);
|
||||||
|
} else {
|
||||||
|
trigger_error($msg, $level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs login attempts
|
||||||
|
* @param string $username Given username that attempts to log in to TTRSS
|
||||||
|
* @param string $result "Logging message for type of result. (Success / Fail)"
|
||||||
|
* @return boolean
|
||||||
|
* @deprecated
|
||||||
|
*
|
||||||
|
* Now that _log support syslog and log levels and graceful fallback user.
|
||||||
|
*/
|
||||||
|
private function _logAttempt($username, $result) {
|
||||||
|
|
||||||
|
|
||||||
|
return trigger_error('TT-RSS Login Attempt: user ' . (string) $username .
|
||||||
|
' attempted to login (' . (string) $result . ') from ' . (string) $ip, E_USER_NOTICE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $subject The subject string
|
||||||
|
* @param string $ignore Set of characters to leave untouched
|
||||||
|
* @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the
|
||||||
|
* set(s) of characters to escape.
|
||||||
|
* @return string
|
||||||
|
**/
|
||||||
|
function ldap_escape($subject, $ignore = '', $flags = 0)
|
||||||
|
{
|
||||||
|
if (!function_exists('ldap_escape')) {
|
||||||
|
define('LDAP_ESCAPE_FILTER', 0x01);
|
||||||
|
define('LDAP_ESCAPE_DN', 0x02);
|
||||||
|
|
||||||
|
static $charMaps = array(
|
||||||
|
LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"),
|
||||||
|
LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Pre-process the char maps on first call
|
||||||
|
if (!isset($charMaps[0])) {
|
||||||
|
$charMaps[0] = array();
|
||||||
|
for ($i = 0; $i < 256; $i++) {
|
||||||
|
$charMaps[0][chr($i)] = sprintf('\\%02x', $i);;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) {
|
||||||
|
$chr = $charMaps[LDAP_ESCAPE_FILTER][$i];
|
||||||
|
unset($charMaps[LDAP_ESCAPE_FILTER][$i]);
|
||||||
|
$charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr];
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) {
|
||||||
|
$chr = $charMaps[LDAP_ESCAPE_DN][$i];
|
||||||
|
unset($charMaps[LDAP_ESCAPE_DN][$i]);
|
||||||
|
$charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the base char map to escape
|
||||||
|
$flags = (int)$flags;
|
||||||
|
$charMap = array();
|
||||||
|
if ($flags & LDAP_ESCAPE_FILTER) {
|
||||||
|
$charMap += $charMaps[LDAP_ESCAPE_FILTER];
|
||||||
|
}
|
||||||
|
if ($flags & LDAP_ESCAPE_DN) {
|
||||||
|
$charMap += $charMaps[LDAP_ESCAPE_DN];
|
||||||
|
}
|
||||||
|
if (!$charMap) {
|
||||||
|
$charMap = $charMaps[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any chars to ignore from the list
|
||||||
|
$ignore = (string)$ignore;
|
||||||
|
for ($i = 0, $l = strlen($ignore); $i < $l; $i++) {
|
||||||
|
unset($charMap[$ignore[$i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the main replacement
|
||||||
|
$result = strtr($subject, $charMap);
|
||||||
|
|
||||||
|
// Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed
|
||||||
|
if ($flags & LDAP_ESCAPE_DN) {
|
||||||
|
if ($result[0] === ' ') {
|
||||||
|
$result = '\\20' . substr($result, 1);
|
||||||
|
}
|
||||||
|
if ($result[strlen($result) - 1] === ' ') {
|
||||||
|
$result = substr($result, 0, -1) . '\\20';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}else{
|
||||||
|
return ldap_escape($subject, $ignore, $flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds client's IP address
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function _getClientIP() {
|
||||||
|
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||||
|
//check ip from share internet
|
||||||
|
|
||||||
|
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||||
|
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||||
|
//to check ip is pass from proxy
|
||||||
|
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||||
|
} else {
|
||||||
|
$ip = $_SERVER['REMOTE_ADDR'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _getBindDNWord() {
|
||||||
|
return (strlen($this->_serviceBindDN) > 0 ) ? $this->_serviceBindDN : 'anonymous DN';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _getTempDir() {
|
||||||
|
if (!sys_get_temp_dir()) {
|
||||||
|
$tmpFile = tempnam();
|
||||||
|
$tmpDir = dirname($tmpFile);
|
||||||
|
unlink($tmpFile);
|
||||||
|
unset($tmpFile);
|
||||||
|
return $tmpDir;
|
||||||
|
} else {
|
||||||
|
return sys_get_temp_dir();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Authentication method
|
||||||
|
* Required for plugin interface
|
||||||
|
* @param string $login User's username
|
||||||
|
* @param string $password User's password
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function authenticate($login, $password) {
|
||||||
|
if ($login && $password) {
|
||||||
|
|
||||||
|
if (!function_exists('ldap_connect')) {
|
||||||
|
trigger_error('auth_ldap requires PHP\'s PECL LDAP package installed.');
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Loading configuration
|
||||||
|
$this->_debugMode = defined('LDAP_AUTH_DEBUG') ?
|
||||||
|
LDAP_AUTH_DEBUG : FALSE;
|
||||||
|
|
||||||
|
$this->_anonBeforeBind = defined('LDAP_AUTH_ANONYMOUSBEFOREBIND') ?
|
||||||
|
LDAP_AUTH_ANONYMOUSBEFOREBIND : FALSE;
|
||||||
|
|
||||||
|
$this->_serviceBindDN = defined('LDAP_AUTH_BINDDN') ? LDAP_AUTH_BINDDN : null;
|
||||||
|
$this->_serviceBindPass = defined('LDAP_AUTH_BINDPW') ? LDAP_AUTH_BINDPW : null;
|
||||||
|
$this->_baseDN = defined('LDAP_AUTH_BASEDN') ? LDAP_AUTH_BASEDN : null;
|
||||||
|
if (!defined('LDAP_AUTH_BASEDN')) {
|
||||||
|
$this->_log('LDAP_AUTH_BASEDN is required and not defined.', E_USER_ERROR);
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
$this->_baseDN = LDAP_AUTH_BASEDN;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsedURI = parse_url(LDAP_AUTH_SERVER_URI);
|
||||||
|
if ($parsedURI === FALSE) {
|
||||||
|
$this->_log('Could not parse LDAP_AUTH_SERVER_URI in config.php', E_USER_ERROR);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
$this->_host = $parsedURI['host'];
|
||||||
|
$this->_scheme = $parsedURI['scheme'];
|
||||||
|
|
||||||
|
if (is_int($parsedURI['port'])) {
|
||||||
|
$this->_port = $parsedURI['port'];
|
||||||
|
} else {
|
||||||
|
$this->_port = ($this->_scheme === 'ldaps') ? 636 : 389;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_useTLS = defined('LDAP_AUTH_USETLS') ? LDAP_AUTH_USETLS : FALSE;
|
||||||
|
|
||||||
|
$this->_logAttempts = defined('LDAP_AUTH_LOG_ATTEMPTS') ?
|
||||||
|
LDAP_AUTH_LOG_ATTEMPTS : FALSE;
|
||||||
|
|
||||||
|
$this->_ldapLoginAttrib = defined('LDAP_AUTH_LOGIN_ATTRIB') ?
|
||||||
|
LDAP_AUTH_LOGIN_ATTRIB : null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Building LDAP connection
|
||||||
|
* */
|
||||||
|
$ldapConnParams = array(
|
||||||
|
'host' => $this->_host,
|
||||||
|
'basedn' => $this->_baseDN,
|
||||||
|
'port' => $this->_port,
|
||||||
|
'starttls' => $this->_useTLS
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->_debugMode)
|
||||||
|
$this->_log(print_r($ldapConnParams, TRUE), E_USER_NOTICE);
|
||||||
|
$ldapConn = @ldap_connect($this->_host, $this->_port);
|
||||||
|
if ($ldapConn === FALSE) {
|
||||||
|
$this->_log('Could not connect to LDAP Server: \'' . $this->_host . '\'', E_USER_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable LDAP protocol version 3. */
|
||||||
|
if (!@ldap_set_option($ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3)) {
|
||||||
|
$this->_log('Failed to set LDAP Protocol version (LDAP_OPT_PROTOCOL_VERSION) to 3', E_USER_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set referral option */
|
||||||
|
if (!@ldap_set_option($ldapConn, LDAP_OPT_REFERRALS, FALSE)) {
|
||||||
|
$this->_log('Failed to set LDAP Referrals (LDAP_OPT_REFERRALS) to TRUE', E_USER_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stripos($this->_host, "ldaps:") === FALSE and $this->_useTLS) {
|
||||||
|
if (!@ldap_start_tls($ldapConn)) {
|
||||||
|
$this->_log('Unable to force TLS', E_USER_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$error = @ldap_bind($ldapConn, $this->_serviceBindDN, $this->_serviceBindPass);
|
||||||
|
if ($error === FALSE) {
|
||||||
|
$this->_log(
|
||||||
|
'LDAP bind(): Bind failed (' . $error . ')with DN ' . $this->_serviceBindDN, E_USER_ERROR
|
||||||
|
);
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
$this->_log(
|
||||||
|
'Connected to LDAP Server: ' . LDAP_AUTH_SERVER_URI . ' with ' . $this->_getBindDNWord());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind with service account if orignal connexion was anonymous
|
||||||
|
/* if (($this->_anonBeforeBind) && (strlen($this->_bindDN > 0))) {
|
||||||
|
$binding=$this->ldapObj->bind($this->_serviceBindDN, $this->_serviceBindPass);
|
||||||
|
if (get_class($binding) !== 'Net_LDAP2') {
|
||||||
|
$this->_log(
|
||||||
|
'Cound not bind service account: '.$binding->getMessage(),E_USER_ERROR);
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
$this->_log('Bind with '.$this->_serviceBindDN.' successful.',E_USER_NOTICE);
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
//Searching for user
|
||||||
|
$filterObj = str_replace('???', $this->ldap_escape($login), LDAP_AUTH_SEARCHFILTER);
|
||||||
|
$searchResults = @ldap_search($ldapConn, $this->_baseDN, $filterObj, array('displayName', 'title', 'sAMAccountName', $this->_ldapLoginAttrib), 0, 0, 0);
|
||||||
|
if ($searchResults === FALSE) {
|
||||||
|
$this->_log('LDAP Search Failed on base \'' . $this->_baseDN . '\' for \'' . $filterObj . '\'', E_USER_ERROR);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
$count = @ldap_count_entries($ldapConn, $searchResults);
|
||||||
|
if ($count === FALSE) {
|
||||||
|
|
||||||
|
} elseif ($count > 1) {
|
||||||
|
$this->_log('Multiple DNs found for username ' . (string) $login, E_USER_WARNING);
|
||||||
|
return FALSE;
|
||||||
|
} elseif ($count === 0) {
|
||||||
|
$this->_log('Unknown User ' . (string) $login, E_USER_NOTICE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Getting user's DN from search
|
||||||
|
$userEntry = @ldap_first_entry($ldapConn, $searchResults);
|
||||||
|
if ($userEntry === FALSE) {
|
||||||
|
$this->_log('LDAP search(): Unable to retrieve result after searching base \'' . $this->_baseDN . '\' for \'' . $filterObj . '\'', E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$userAttributes = @ldap_get_attributes($ldapConn, $userEntry);
|
||||||
|
$userDN = @ldap_get_dn($ldapConn, $userEntry);
|
||||||
|
if ($userDN == FALSE) {
|
||||||
|
$this->_log('LDAP search(): Unable to get DN after searching base \'' . $this->_baseDN . '\' for \'' . $filterObj . '\'', E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//Binding with user's DN.
|
||||||
|
if ($this->_debugMode)
|
||||||
|
$this->_log('Try to bind with user\'s DN: ' . $userDN);
|
||||||
|
$loginAttempt = @ldap_bind($ldapConn, $userDN, $password);
|
||||||
|
if ($loginAttempt === TRUE) {
|
||||||
|
$this->_log('User: ' . (string) $login . ' authentication successful');
|
||||||
|
if (strlen($this->_ldapLoginAttrib) > 0) {
|
||||||
|
if ($this->_debugMode)
|
||||||
|
$this->_log('Looking up TT-RSS username attribute in ' . $this->_ldapLoginAttrib);
|
||||||
|
$ttrssUsername = $userAttributes[$this->_ldapLoginAttrib][0];
|
||||||
|
;
|
||||||
|
@ldap_close($ldapConn);
|
||||||
|
if (!is_string($ttrssUsername)) {
|
||||||
|
$this->_log('Could not find user name attribute ' . $this->_ldapLoginAttrib . ' in LDAP entry', E_USER_WARNING);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return $this->base->auto_create_user($ttrssUsername);
|
||||||
|
} else {
|
||||||
|
@ldap_close($ldapConn);
|
||||||
|
return $this->base->auto_create_user($login);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@ldap_close($ldapConn);
|
||||||
|
$this->_log('User: ' . (string) $login . ' authentication failed');
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns plugin API version
|
||||||
|
* Required for plugin interface
|
||||||
|
* @return number
|
||||||
|
*/
|
||||||
|
function api_version() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
Loading…
Add table
Reference in a new issue