--- /dev/null
+<?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;
+ }
+
+}
+
+?>