136 lines
4.2 KiB
PHP
136 lines
4.2 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Tiny Tiny RSS plugin for LDAP authentication
|
||
|
* @author hydrian (ben.tyger@tygerclan.net)
|
||
|
* @copyright GPL2
|
||
|
* Requires php-ldap and PEAR Net::LDAP2
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* 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_BINDDN', 'cn=serviceaccount,dc=example,dc=com');
|
||
|
* define('LDAP_AUTH_BINDPW', 'ServiceAccountsPassword');
|
||
|
* define('LDAP_AUTH_BASEDN', 'dc=example,dc=com');
|
||
|
* // ??? will be replaced with the entered username(escaped) at login
|
||
|
* define('LDAP_AUTH_SEARCHFILTER', '(&(objectClass=person)(uid=???))');
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* 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;
|
||
|
|
||
|
function about() {
|
||
|
return array(0.01,
|
||
|
"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) {
|
||
|
trigger_error($msg, E_USER_WARN);
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
if (!require_once('Net/LDAP2.php')) {
|
||
|
trigger_error('auth_ldap requires the PEAR package Net::LDAP2');
|
||
|
return FALSE;
|
||
|
}
|
||
|
$parsedURI=parse_url(LDAP_AUTH_SERVER_URI);
|
||
|
if ($parsedURI === FALSE) {
|
||
|
$this->_log('Could not parse LDAP_AUTH_SERVER_URI in config.php');
|
||
|
return FALSE;
|
||
|
}
|
||
|
$ldapConnParams=array(
|
||
|
'host'=>$parsedURI['scheme'].'://'.$parsedURI['host'],
|
||
|
'basedn'=>LDAP_AUTH_BASEDN,
|
||
|
'options' => array('LDAP_OPT_REFERRALS' => 0)
|
||
|
);
|
||
|
$ldapConnParams['starttls']= defined('LDAP_AUTH_USETLS') ?
|
||
|
LDAP_AUTH_USETLS : FALSE;
|
||
|
|
||
|
if (is_int($parsedURI['port'])) {
|
||
|
$ldapConnParams['port']=$parsedURI['port'];
|
||
|
}
|
||
|
// Making connection to LDAP server
|
||
|
if (LDAP_AUTH_ALLOW_UNTRUSTED_CERT === TRUE) {
|
||
|
putenv('LDAPTLS_REQCERT=never');
|
||
|
}
|
||
|
$ldapConn = Net_LDAP2::connect($ldapConnParams);
|
||
|
if (Net_LDAP2::isError($ldapConn)) {
|
||
|
$this->_log('Could not connect to LDAP Server: '.$ldapConn->getMessage());
|
||
|
return FALSE;
|
||
|
}
|
||
|
// Bind with service account
|
||
|
$binding=$ldapConn->bind(LDAP_AUTH_BINDDN, LDAP_AUTH_BINDPW);
|
||
|
if (Net_LDAP2::isError($binding)) {
|
||
|
$this->_log('Cound not bind service account: '.$binding->getMessage());
|
||
|
return FALSE;
|
||
|
}
|
||
|
//Searching for user
|
||
|
$completedSearchFiler=str_replace('???',$login,LDAP_AUTH_SEARCHFILTER);
|
||
|
$filterObj=Net_LDAP2_Filter::parse($completedSearchFiler);
|
||
|
$searchResults=$ldapConn->search(LDAP_AUTH_BASEDN, $filterObj);
|
||
|
if (Net_LDAP2::isError($searchResults)) {
|
||
|
$this->_log('LDAP Search Failed: '.$searchResults->getMessage());
|
||
|
return FALSE;
|
||
|
} elseif ($searchResults->count() === 0) {
|
||
|
return FALSE;
|
||
|
} elseif ($searchResults->count() > 1 ) {
|
||
|
$this->_log('Multiple DNs found for username '.$login);
|
||
|
return FALSE;
|
||
|
}
|
||
|
//Getting user's DN from search
|
||
|
$userEntry=$searchResults->shiftEntry();
|
||
|
$userDN=$userEntry->dn();
|
||
|
//Binding with user's DN.
|
||
|
$loginAttempt=$ldapConn->bind($userDN, $password);
|
||
|
$ldapConn->disconnect();
|
||
|
if ($loginAttempt === TRUE) {
|
||
|
return $this->base->auto_create_user($login);
|
||
|
} elseif ($loginAttempt->getCode() == 49) {
|
||
|
return FALSE;
|
||
|
} else {
|
||
|
$this->_log('Unknown Error: Code: '.$loginAttempt->getCode().
|
||
|
' Message: '.$loginAttempt->getMessage());
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
?>
|