/** * Test escaping of filter values */ public function testEscape_filter_value() { $expected = 't\\28e,s\\29t\\2av\\5cal\\1eue'; $filterval = 't(e,s)t*v\\al' . chr(30) . 'ue'; // string call $this->assertEquals(array($expected), Net_LDAP2_Util::escape_filter_value($filterval)); // array call $this->assertEquals(array($expected), Net_LDAP2_Util::escape_filter_value(array($filterval))); // multiple arrays $this->assertEquals(array($expected, $expected, $expected), Net_LDAP2_Util::escape_filter_value(array($filterval, $filterval, $filterval))); }
/** * This can be used to escape a string to provide a valid LDAP-Filter. * * LDAP will only recognise certain characters as the * character istself if they are properly escaped. This is * what this method does. * The method can be called statically, so you can use it outside * for your own purposes (eg for escaping only parts of strings) * * In fact, this is just a shorthand to {@link Net_LDAP2_Util::escape_filter_value()}. * For upward compatibiliy reasons you are strongly encouraged to use the escape * methods provided by the Net_LDAP2_Util class. * * @param string $value Any string who should be escaped * * @static * @return string The string $string, but escaped * @deprecated Do not use this method anymore, instead use Net_LDAP2_Util::escape_filter_value() directly */ public static function escape($value) { $return = Net_LDAP2_Util::escape_filter_value(array($value)); return $return[0]; }
/** * Execute a LDAP query stement and fetch all results. * * @param mixed $query The SQL query as a string or an array. * @param string $configPath The config path; used for exception messages. * * @return array An array of records. * @throws XML_Query2XML_LDAP2Exception If Net_LDAP2::search() returns an error. * @see XML_Query2XML_Driver::getAllRecords() */ public function getAllRecords($query, $configPath) { $base = null; $filter = null; $options = array(); if (isset($query['base'])) { $base = $query['base']; } if (isset($query['filter'])) { $filter = $query['filter']; } if (isset($query['options'])) { $options = $query['options']; } if (isset($options['query2xml_placeholder'])) { $placeholder = $options['query2xml_placeholder']; } else { $placeholder = '?'; } unset($options['query2xml_placeholder']); if (isset($query['data']) && is_array($query['data'])) { $data = Net_LDAP2_Util::escape_filter_value($query['data']); $base = self::_replacePlaceholders($base, $data, $placeholder); if (is_string($filter)) { $filter = self::_replacePlaceholders($filter, $data, $placeholder); } } $search = $this->_ldap->search($base, $filter, $options); if (PEAR::isError($search)) { /* * unit test: getXML/throwLDAPException_queryError.phpt */ throw new XML_Query2XML_LDAP2Exception($configPath . ': Could not run LDAP search query: ' . $search->toString()); } $records = array(); $entries = $search->entries(); foreach ($entries as $key => $entry) { $records[] = $entry->getValues(); } $search->done(); $records = self::_processMultiValueAttributes($records); // set missing attriubtes to null if (isset($options['attributes']) && is_array($options['attributes'])) { foreach ($options['attributes'] as $attribute) { for ($i = 0; $i < count($records); $i++) { if (!array_key_exists($attribute, $records[$i])) { $records[$i][$attribute] = null; } } } } return $records; }
/** * Main Authentication method * Required for plugin interface * @param unknown $login User's username * @param unknown $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; } if (!(require_once 'Net/LDAP2.php')) { trigger_error('auth_ldap requires the PEAR package Net::LDAP2'); 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->_allowUntrustedCerts = defined('LDAP_AUTH_ALLOW_UNTRUSTED_CERT') ? LDAP_AUTH_ALLOW_UNTRUSTED_CERT : FALSE; $this->_schemaCacheEnable = defined('LDAP_AUTH_SCHEMA_CACHE_ENABLE') ? LDAP_AUTH_SCHEMA_CACHE_ENABLE : TRUE; $this->_schemaCacheTimeout = defined('LDAP_AUTH_SCHEMA_CACHE_TIMEOUT') ? LDAP_AUTH_SCHEMA_CACHE_TIMEOUT : 86400; $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->_scheme . '://' . $this->_host, 'options' => array('LDAP_OPT_REFERRALS' => 0), 'basedn' => $this->_baseDN, 'port' => $this->_port, 'starttls' => $this->_useTLS); if (!$this->_anonBeforeBind) { $ldapConnParams['binddn'] = $this->_serviceBindDN; $ldapConnParams['bindpw'] = $this->_serviceBindPass; } if ($this->_allowUntrustedCerts) { putenv('LDAPTLS_REQCERT=never'); } if ($this->_debugMode) { $this->_log(print_r($ldapConnParams, TRUE), E_USER_NOTICE); } $ldapConn = Net_LDAP2::connect($ldapConnParams); if (get_class($ldapConn) !== 'Net_LDAP2') { $this->_log('Could not connect to LDAP Server: ' . $ldapConn->getMessage() . ' with ' . $this->_getBindDNWord(), E_USER_ERROR); return FALSE; } else { $this->ldapObj = $ldapConn; $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); } } //Cache LDAP Schema if ($ldapSchemaCacheEnable) { $this->_getSchemaCache(); } //Validate BaseDN $baseDNObj = $this->ldapObj->getEntry($this->_baseDN); if (get_class($baseDNObj) !== 'Net_LDAP2_Entry') { $this->_log('Cound not get LDAP_AUTH_BASEDN. Please check config.php', E_USER_ERROR); //return FALSE; } //Searching for user $escapedUserName = Net_LDAP2_Util::escape_filter_value(array($login)); $completedSearchFilter = str_replace('???', $escapedUserName[0], LDAP_AUTH_SEARCHFILTER); $filterObj = Net_LDAP2_Filter::parse($completedSearchFilter); if (get_class($filterObj) !== 'Net_LDAP2_Filter') { $this->_log('Could not parse LDAP Search filter', E_USER_ERROR); return FALSE; } if ($this->_debugMode) { $this->_log("Seaching for user {$login} with this query " . $filterObj->asString() . ' within ' . $this->_baseDN); } $searchResults = $this->ldapObj->search($this->_baseDN, $filterObj); if (get_class($searchResults) !== 'Net_LDAP2_Search') { $this->_log('LDAP Search Failed: ' . $searchResults->getMessage(), E_USER_ERROR); return FALSE; } elseif ($searchResults->count() === 0) { $this->_log((string) $login, 'Unknown User', E_USER_NOTICE); return FALSE; } elseif ($searchResults->count() > 1) { $this->_log('Multiple DNs found for username ' . (string) $login, E_USER_WARNING); return FALSE; } //Getting user's DN from search $userEntry = $searchResults->shiftEntry(); $userDN = $userEntry->dn(); //Binding with user's DN. if ($this->_debugMode) { $this->_log('Try to bind with user\'s DN: ' . $userDN); } $loginAttempt = $this->ldapObj->bind($userDN, $password); if ($loginAttempt === TRUE) { $this->_log('User: '******' authentication successful'); if (strlen($this->_ldapLoginAttrib) > 0) { if ($this->_debugMode) { $this->_log('Looking up TT-RSS username attribute in ' . $this->_ldapLoginAttrib); } $ttrssUsername = $userEntry->getValue($this->_ldapLoginAttrib, 'single'); $this->ldapObj->disconnect(); 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 { $this->ldapObj->disconnect(); return $this->base->auto_create_user($login); } } elseif ($loginAttempt->getCode() == 49) { $this->ldapObj->disconnect(); $this->_log('User: '******' authentication failed'); return FALSE; } else { $this->ldapObj->disconnect(); $this->_log('Unknown Error: Code: ' . $loginAttempt->getCode() . ' Message: ' . $loginAttempt->getMessage() . ' user(' . (string) $login . ')', E_USER_WARNING); return FALSE; } } return false; }