private function _search($base, $filter, $attributes, $sizelimit) { error_log("looking for {$base} {$filter}"); $filter_ = Net_LDAP2_Filter::parse($filter); if ($filter_ instanceof PEAR_Error) { error_log("filter {$filter} invalid (?)"); error_log($filter_->message); } $r = array("count" => 0); foreach ($this->_entries as $branch => $entries) { if ($base && !preg_match("/{$base}\$/", $branch)) { continue; } foreach ($entries as $entry) { if ($filter_->matches($entry)) { $r[] = MyTestLdap::get_one_entry($entry, $attributes); $r["count"] = $r["count"] + 1; if ($r["count"] == $sizelimit) { return $r; } } } } return $r; }
public function LDAP_Filter_factory($ldap, $attr_name, $match, $value = '', $escape = true) { if ($ldap instanceof Net_LDAP2) { return Net_LDAP2_Filter::create($attr_name, $match, $value, $escape); } else { return Net_LDAP_Filter::create($attr_name, $match, $value, $escape); } }
public function getByEmail($usr) { $filter = Net_LDAP2_Filter::create('mail', 'equals', $usr->email); $requested_attributes = array('cn', 'uid', 'mail'); $search = $this->connect()->search($this->basedn, $filter, array('attributes' => $requested_attributes)); if (Misc::isError($search)) { $entry = $search; error_log($entry->getCode() . ': ' . $entry->getMessage()); return null; } if ($search->count() <= 0) { return false; } $entry = $search->current(); $usr->uid = $entry->get_value('uid'); $usr->full_name = $entry->get_value('cn'); return true; }
/** * get an LDAP entry for a user with a given username * * @param string $username * $param array $attributes LDAP attributes to retrieve * @return string DN */ function get_user($username, $attributes = array()) { $ldap = $this->get_ldap_connection(); $filter = Net_LDAP2_Filter::create($this->attributes['username'], 'equals', $username); $options = array('attributes' => $attributes); $search = $ldap->search(null, $filter, $options); if (PEAR::isError($search)) { common_log(LOG_WARNING, 'Error while getting DN for user: '******'Found ' . $search->count() . ' ldap user with the username: ' . $username); return false; } } }
public function get_groups($force_reload = false) { $this->get_user_attributes($force_reload); // ensure we have a connection to the ldap server if ($this->bind() != 'LDAP_SUCCESS') { $this->add_log('ldap', 'Reuse of ldap connection failed: ' . $this->ldaplink->getMessage() . ' at line ' . __LINE__ . ' in ' . __FILE__); return false; } $filter1 = Net_LDAP2_Filter::create('objectClass', 'equals', $this->options['groupoc']); if (!empty($this->options['groupmemberattr'])) { // get membership from group information if ($this->options['groupmemberisdn']) { if ($this->user_attributes['dn'] == null) { return false; } $filter2 = Net_LDAP2_Filter::create($this->options['groupmemberattr'], 'equals', $this->user_dn()); } else { $filter2 = Net_LDAP2_Filter::create($this->options['groupmemberattr'], 'equals', $this->options['username']); } $filter = Net_LDAP2_Filter::combine('and', array($filter1, $filter2)); } else { if (!empty($this->options['usergroupattr'])) { // get membership from user information $ugi =& $this->user_attributes[$this->options['usergroupattr']]; if (!empty($ugi)) { if (!is_array($ugi)) { $ugi = array($ugi); } if (count($ugi) == 1) { // one gid $filter3 = Net_LDAP2_Filter::create($this->options['groupgroupattr'], 'equals', $ugi[0]); } else { // mor gids $filtertmp = array(); foreach ($ugi as $g) { $filtertmp[] = Net_LDAP2_Filter::create($this->options['groupgroupattr'], 'equals', $g); } $filter3 = Net_LDAP2_Filter::combine('or', $filtertmp); } $filter = Net_LDAP2_Filter::combine('and', array($filter1, $filter3)); } else { // User has no group $filter = NULL; } } else { // not possible to get groups - return empty array return array(); } } if (Net_LDAP2::isError($filter)) { $this->add_log('ldap', 'LDAP Filter creation error: ' . $filter->getMessage() . ' at line ' . __LINE__ . ' in ' . __FILE__); return false; } $this->add_log('ldap', 'Searching for group entries with filter: ' . $filter->asString() . ' base ' . $this->groupbase_dn() . ' at line ' . __LINE__ . ' in ' . __FILE__); $searchoptions = array('scope' => $this->options['scope']); $searchresult = $this->ldaplink->search($this->groupbase_dn(), $filter, $searchoptions); if (Net_LDAP2::isError($searchresult)) { $this->add_log('ldap', 'Search failed: ' . $searchresult->getMessage() . ' at line ' . __LINE__ . ' in ' . __FILE__); return false; } $this->add_log('ldap', 'Found ' . $searchresult->count() . ' entries. Extracting entries now.'); $this->groups = array(); while ($entry = $searchresult->shiftEntry()) { if (Net_LDAP2::isError($entry)) { $this->add_log('ldap', 'Error fetching group entries: ' . $entry->getMessage() . ' at line ' . __LINE__ . ' in ' . __FILE__); return false; } $this->groups[$entry->dn()] = $entry->getValues(); // no error checking necessary here } $this->add_log('ldap', count($this->groups) . ' groups found at line ' . __LINE__ . ' in ' . __FILE__); return $this->groups; }
/** * @param $username string * @param $configFilter string * @return void */ private function PopulateUser($username, $configFilter) { $uidAttribute = $this->options->GetUserIdAttribute(); Log::Debug('LDAP - uid attribute: %s', $uidAttribute); $RequiredGroup = $this->options->GetRequiredGroup(); $filter = Net_LDAP2_Filter::create($uidAttribute, 'equals', $username); if ($configFilter) { $configFilter = Net_LDAP2_Filter::parse($configFilter); if (Net_LDAP2::isError($configFilter)) { $message = 'Could not parse search filter %s: ' . $configFilter->getMessage(); Log::Error($message, $username); } $filter = Net_LDAP2_Filter::combine('and', array($filter, $configFilter)); } $attributes = $this->options->Attributes(); Log::Debug('LDAP - Loading user attributes: %s', implode(', ', $attributes)); $options = array('attributes' => $attributes); Log::Debug('Searching ldap for user %s', $username); $searchResult = $this->ldap->search(null, $filter, $options); if (Net_LDAP2::isError($searchResult)) { $message = 'Could not search ldap for user %s: ' . $searchResult->getMessage(); Log::Error($message, $username); } $currentResult = $searchResult->current(); if ($searchResult->count() == 1 && $currentResult !== false) { Log::Debug('Found user %s', $username); if (!empty($RequiredGroup)) { Log::Debug('LDAP - Required Group: %s', $RequiredGroup); $group_filter = Net_LDAP2_Filter::create('uniquemember', 'equals', $currentResult->dn()); $group_searchResult = $this->ldap->search($RequiredGroup, $group_filter, null); if (Net_LDAP2::isError($group_searchResult) && !empty($RequiredGroup)) { $message = 'Could not match Required Group %s: ' . $group_searchResult->getMessage(); Log::Error($message, $username); } if ($group_searchResult->count() == 1 && $group_searchResult !== false) { Log::Debug('Matched Required Group %s', $RequiredGroup); /** @var Net_LDAP2_Entry $entry */ $this->user = new LdapUser($currentResult, $this->options->AttributeMapping()); } } else { /** @var Net_LDAP2_Entry $entry */ $this->user = new LdapUser($currentResult, $this->options->AttributeMapping()); } } else { Log::Debug('Could not find user %s', $username); } }
/** * Check if $user and $password are related to a valid user and password * * @param string $check_password * @return boolean */ function isValidPasswordLdap($user, $password, $config) { // Connecting using the configuration: require_once "Net/LDAP2.php"; $ldap = Net_LDAP2::connect($config); // Testing for connection error if (PEAR::isError($ldap)) { return false; } $filter = Net_LDAP2_Filter::create($config['uid'], 'equals', $user); $search = $ldap->search(null, $filter, null); if (Net_LDAP2::isError($search)) { return false; } if ($search->count() != 1) { return false; } // User exists so we may rebind to authenticate the password $entries = $search->entries(); $bind_result = $ldap->bind($entries[0]->dn(), $password); if (PEAR::isError($bind_result)) { return false; } return true; }
/** * Retrieve information from LDAP * * @param string $uid login or email * @return array */ public function getRemoteUserInfo($uid) { if (strpos($uid, '@') === false) { $filter = Net_LDAP2_Filter::create('uid', 'equals', $uid); } else { $filter = Net_LDAP2_Filter::create('mail', 'equals', $uid); } if (!empty($this->user_filter_string)) { $user_filter = Net_LDAP2_Filter::parse($this->user_filter_string); $filter = Net_LDAP2_Filter::combine('and', array($filter, $user_filter)); } $search = $this->connect()->search($this->basedn, $filter, array('sizelimit' => 1)); $entry = $search->shiftEntry(); if (!$entry || Misc::isError($entry)) { return null; } $details = array('uid' => $entry->get_value('uid'), 'full_name' => Misc::trim($entry->get_value('cn')), 'emails' => Misc::trim(Misc::lowercase($entry->get_value('mail', 'all'))), 'customer_id' => Misc::trim($entry->get_value($this->customer_id_attribute)) ?: null, 'contact_id' => Misc::trim($entry->get_value($this->contact_id_attribute)) ?: null); return $details; }
/** * Constructor of a new part of a LDAP filter. * * The following matching rules exists: * - equals: One of the attributes values is exactly $value * Please note that case sensitiviness is depends on the * attributes syntax configured in the server. * - begins: One of the attributes values must begin with $value * - ends: One of the attributes values must end with $value * - contains: One of the attributes values must contain $value * - present | any: The attribute can contain any value but must be existent * - greater: The attributes value is greater than $value * - less: The attributes value is less than $value * - greaterOrEqual: The attributes value is greater or equal than $value * - lessOrEqual: The attributes value is less or equal than $value * - approx: One of the attributes values is similar to $value * * Negation ("not") can be done by prepending the above operators with the * "not" or "!" keyword, see example below. * * If $escape is set to true (default) then $value will be escaped * properly. If it is set to false then $value will be treaten as raw filter value string. * You should escape yourself using {@link Net_LDAP2_Util::escape_filter_value()}! * * Examples: * <code> * // This will find entries that contain an attribute "sn" that ends with "foobar": * $filter = Net_LDAP2_Filter::create('sn', 'ends', 'foobar'); * * // This will find entries that contain an attribute "sn" that has any value set: * $filter = Net_LDAP2_Filter::create('sn', 'any'); * * // This will build a negated equals filter: * $filter = Net_LDAP2_Filter::create('sn', 'not equals', 'foobar'); * </code> * * @param string $attr_name Name of the attribute the filter should apply to * @param string $match Matching rule (equals, begins, ends, contains, greater, less, greaterOrEqual, lessOrEqual, approx, any) * @param string $value (optional) if given, then this is used as a filter * @param boolean $escape Should $value be escaped? (default: yes, see {@link Net_LDAP2_Util::escape_filter_value()} for detailed information) * * @return Net_LDAP2_Filter|Net_LDAP2_Error */ public static function &create($attr_name, $match, $value = '', $escape = true) { $leaf_filter = new Net_LDAP2_Filter(); if ($escape) { $array = Net_LDAP2_Util::escape_filter_value(array($value)); $value = $array[0]; } $match = strtolower($match); // detect negation $neg_matches = array(); $negate_filter = false; if (preg_match('/^(?:not|!)[\\s_-](.+)/', $match, $neg_matches)) { $negate_filter = true; $match = $neg_matches[1]; } // build basic filter switch ($match) { case 'equals': case '=': case '==': $leaf_filter->_filter = '(' . $attr_name . '=' . $value . ')'; break; case 'begins': $leaf_filter->_filter = '(' . $attr_name . '=' . $value . '*)'; break; case 'ends': $leaf_filter->_filter = '(' . $attr_name . '=*' . $value . ')'; break; case 'contains': $leaf_filter->_filter = '(' . $attr_name . '=*' . $value . '*)'; break; case 'greater': case '>': $leaf_filter->_filter = '(' . $attr_name . '>' . $value . ')'; break; case 'less': case '<': $leaf_filter->_filter = '(' . $attr_name . '<' . $value . ')'; break; case 'greaterorequal': case '>=': $leaf_filter->_filter = '(' . $attr_name . '>=' . $value . ')'; break; case 'lessorequal': case '<=': $leaf_filter->_filter = '(' . $attr_name . '<=' . $value . ')'; break; case 'approx': case '~=': $leaf_filter->_filter = '(' . $attr_name . '~=' . $value . ')'; break; case 'any': case 'present': // alias that may improve user code readability $leaf_filter->_filter = '(' . $attr_name . '=*)'; break; default: return PEAR::raiseError('Net_LDAP2_Filter create error: matching rule "' . $match . '" not known!'); } // negate if requested if ($negate_filter) { $leaf_filter = Net_LDAP2_Filter::combine('!', $leaf_filter); } return $leaf_filter; }
/** * Haal de rollen van de huidige gebruiker op voor een opgegeven applicatie naam * In onze LDAP server vertegenwoordigd het veld description de volledige naam van de applicatie * * @param KVDutil_Auth_Gebruiker $gebruiker * @param string $applicatieNaam * structuur: 'ou='.$applicatieNaam.',ou=productie,ou=groups,dc=vioe,dc=be' * @return KVDutil_AuthRolCollectie $rollen */ public function getRollenVoorApplicatieNaam(KVDutil_Auth_Gebruiker $gebruiker, $applicatieNaam) { $filter = Net_LDAP2_Filter::create($this->parameters['gebruiker_bij_rol'], 'contains', $gebruiker->getId()); $options = array('scope' => 'sub', 'attributes' => array($this->parameters['rol_naam'], $this->parameters['rol_beschrijving'])); //Voer zoekactie uit op boven meegegeven searchbase met de opgegeven options en filters $search = $this->connectie->search($applicatieNaam, $filter, $options); if (Net_LDAP2::isError($search)) { throw new Exception($search->getMessage()); } $results = array(); //objecten worden 1 voor 1 volledig geladen en in een array geplaatst. foreach ($search as $dn => $entry) { $results[$dn] = new KVDutil_Auth_Rol($dn, $entry->getValue($this->parameters['rol_naam'], 'single'), $entry->getValue($this->parameters['rol_beschrijving'], 'single')); } //De array met objecten wordt in een KVDdom_DomainObjectCollection geplaatst. return new KVDutil_Auth_RolCollectie($results); }
if ($r === NULL) { fail("searchUser {$token}", "invalid response\n{$js}"); } $got = map_obj_attr($r, 'uid'); expectToBe(json_encode($got), $expected, "searchUser {$token}"); } searchUser('Fooo Bar', '["fbar"]'); searchUser('o Bar', '["fbar","zbar"]'); searchUser('Fooo B', '["fbar"]'); searchUser('Fooo ', '["fbar"]'); searchUser('Fooo', '["fbar"]'); searchUser('Foo', '[]'); // no sub search if short token searchUser('Bar Fooo', '["fbar"]'); searchUser('Bar Foo', '["fbar"]'); searchUser('Bar', '["fbar","zbar"]'); // exact search on sn searchUser('99007', '["fbar"]'); // exact search on sn Xexpect('getSuperGroups structures', '{"diploma-L2T101":{"key":"diploma-L2T101","description":"L2T101 - Licence 1\\u00e8re ann\\u00e9e Droit (FC)","rawKey":"L2T101","name":"L2T101 - Licence 1\\u00e8re ann\\u00e9e Droit (FC)","category":"diploma","superGroups":[]}}', 'getSuperGroups', ['key' => 'structures-DGH']); $allGroups = <<<'EOS' [{"key":"groups-employees.administration.DGH","name":"employees.administration.DGH"},{"key":"groups-employees.administration.DGHA","name":"DSIUN-SAS : Service des applications et services num\u00e9riques","description":"employees.administration.DGH"},{"key":"groups-matiB1010514","name":"UFR 02 - Mati\u00e8re (Semestre 1) : Comptabilit\u00e9 d'entreprise","description":"<br>\n<br>\n<br>\n"},{"key":"affiliation-faculty","name":"Tous les enseignants","description":"Tous les enseignants"},{"key":"affiliation-teacher","name":"Tous les enseignants et charg\u00e9s d'enseignement","description":"Tous les enseignants et charg\u00e9s d'enseignement"},{"key":"affiliation-student","name":"Tous les \u00e9tudiants","description":"Tous les \u00e9tudiants"},{"key":"affiliation-staff","name":"Tous les Biatss","description":"Tous les Biatss"},{"key":"affiliation-researcher","name":"Tous les chercheurs","description":"Tous les chercheurs"},{"key":"affiliation-emeritus","name":"Tous les professeurs \u00e9m\u00e9rites","description":"Tous les professeurs \u00e9m\u00e9rites"},{"key":"affiliation-affiliate","name":"Tous les invit\u00e9s","description":"Tous les invit\u00e9s"},{"key":"businessCategory-research","name":"Laboratoires de recherche","description":"Laboratoires de recherche"},{"key":"businessCategory-library","name":"Biblioth\u00e8ques","description":"Biblioth\u00e8ques"},{"key":"businessCategory-doctoralSchool","name":"\u00c9coles doctorales","description":"\u00c9coles doctorales"},{"key":"businessCategory-administration","name":"Services","description":"Services"},{"key":"businessCategory-pedagogy","name":"Composantes personnels","description":"Composantes personnels"}] EOS; Xexpect('allGroups', $allGroups, 'allGroups', []); if (0) { $dn = 'uid=foo,dc=fr'; $entry = Net_LDAP2_Entry::createFresh($dn); $entry->add(array('entryDN' => $entry->dn())); $filter = Net_LDAP2_Filter::parse("(entryDN={$dn})"); var_dump($filter->matches($entry)); }
/** * Test match() */ public function testMatch() { // make up some local test entry $entry1 = Net_LDAP2_Entry::createFresh('cn=Simpson Homer,l=springfield,c=usa', array('cn' => 'Simpson Homer', 'sn' => 'Simpson', 'givenName' => 'Homer', 'fingers' => 5, 'hairColor' => 'black', 'donutsConsumed' => 4521875663232, 'height' => '175', 'mail' => '*****@*****.**', 'objectClass' => array('top', 'person', 'inetOrgPerson', 'myFancyTestClass'))); $entry2 = Net_LDAP2_Entry::createFresh('cn=Simpson Bart,l=springfield,c=usa', array('cn' => 'Simpson Bart', 'sn' => 'Simpson', 'givenName' => 'Bart', 'fingers' => 5, 'hairColor' => 'yellow', 'height' => '120', 'mail' => '*****@*****.**', 'objectClass' => array('top', 'person', 'inetOrgPerson', 'myFancyTestClass'))); $entry3 = Net_LDAP2_Entry::createFresh('cn=Brockman Kent,l=springfield,c=usa', array('cn' => 'Brockman Kent', 'sn' => 'Brockman', 'givenName' => 'Kent', 'fingers' => 5, 'hairColor' => 'white', 'height' => '185', 'mail' => '*****@*****.**', 'objectClass' => array('top', 'person', 'inetOrgPerson', 'myFancyTestClass'))); $allEntries = array($entry1, $entry2, $entry3); // Simple matching on single entry $filter = Net_LDAP2_Filter::create('cn', 'equals', 'Simpson Homer'); $this->assertEquals(1, $filter->matches($entry1)); $filter = Net_LDAP2_Filter::create('cn', 'equals', 'son'); $this->assertEquals(0, $filter->matches($entry1)); $filter = Net_LDAP2_Filter::create('mail', 'begins', 'Hom'); $this->assertEquals(1, $filter->matches($entry1)); $filter = Net_LDAP2_Filter::create('objectClass', 'contains', 'org'); // note the lowercase of 'org', as DirSTR is usually syntax CaseIgnore $this->assertEquals(1, $filter->matches($entry1)); // Simple negative tests on single entry $filter = Net_LDAP2_Filter::create('givenName', 'equals', 'Lisa-is-nonexistent'); $this->assertEquals(0, $filter->matches($entry1)); // Simple tests with multiple entries $filter = Net_LDAP2_Filter::create('cn', 'begins', 'Nomatch'); $this->assertEquals(0, $filter->matches($allEntries)); $filter = Net_LDAP2_Filter::create('cn', 'begins', 'Simpson Ho'); $this->assertEquals(1, $filter->matches($allEntries)); $filter = Net_LDAP2_Filter::create('cn', 'begins', 'Simpson'); $this->assertEquals(2, $filter->matches($allEntries)); // test with retrieving the resulting entries $filter = Net_LDAP2_Filter::create('cn', 'begins', 'Simpson Ho'); $filterresult = array(); $this->assertEquals(1, $filter->matches($allEntries, $filterresult)); $this->assertEquals(count($filterresult), $filter->matches($allEntries, $filterresult), "returned result and result counter differ!"); $this->assertEquals($entry1->dn(), array_shift($filterresult)->dn(), "Filtered entry does not equal expected entry! filter='" . $filter->asString() . "'"); // make sure return values are consistent with input and that all entries are found $filter = Net_LDAP2_Filter::parse('(objectClass=*)'); $filterresult = array(); $this->assertEquals(count($allEntries), $filter->matches($allEntries, $filterresult), "returned result does not match input data count"); $this->assertEquals(count($filterresult), $filter->matches($allEntries, $filterresult), "returned result and result counter differ!"); // Test for compliant "any" filtering: // Only entries should be returned, that have the attribute // Negation: Only Entries that don't have the attribute set at all $filter = Net_LDAP2_Filter::create('donutsConsumed', 'any'); // only homer consume donuts $filterresult = array(); $this->assertEquals(1, $filter->matches($allEntries, $filterresult)); $this->assertEquals($entry1->dn(), array_shift($filterresult)->dn(), "Filtered entry does not equal expected entry! filter='" . $filter->asString() . "'"); $filter = Net_LDAP2_Filter::combine('not', $filter); // all but homer consume donuts $this->assertEquals(count($allEntries) - 1, $filter->matches($allEntries, $filterresult), "Filtered entry does not equal expected entry! filter='" . $filter->asString() . "'"); // NOT combination test $filter = Net_LDAP2_Filter::create('givenName', 'not equals', 'Homer'); $filterresult = array(); $this->assertEquals(2, $filter->matches($allEntries, $filterresult)); $this->assertEquals($entry2->dn(), array_shift($filterresult)->dn(), "Filtered entry does not equal expected entry! filter='" . $filter->asString() . "'"); $this->assertEquals($entry3->dn(), array_shift($filterresult)->dn(), "Filtered entry does not equal expected entry! filter='" . $filter->asString() . "'"); // OR combination test $filter1 = Net_LDAP2_Filter::create('sn', 'equals', 'Simpson'); $filter2 = Net_LDAP2_Filter::create('givenName', 'equals', 'Kent'); $filter_or = Net_LDAP2_Filter::combine('or', array($filter1, $filter2)); $filterresult = array(); $this->assertEquals(3, $filter_or->matches($allEntries, $filterresult)); // AND combination test $filter1 = Net_LDAP2_Filter::create('sn', 'equals', 'Simpson'); $filter2 = Net_LDAP2_Filter::create('givenName', 'equals', 'Bart'); $filter_and = Net_LDAP2_Filter::combine('and', array($filter1, $filter2)); $filterresult = array(); $filter_and->matches($allEntries, $filterresult); $this->assertEquals(1, $filter_and->matches($allEntries, $filterresult), "AND Filter failed '" . $filter_and->asString() . "'"); // AND, NOT and OR combined test $filter1 = Net_LDAP2_Filter::combine('or', array(Net_LDAP2_Filter::create('hairColor', 'equals', 'white'), Net_LDAP2_Filter::create('hairColor', 'equals', 'black'))); $filter2 = Net_LDAP2_Filter::create('givenName', 'not equals', 'Homer'); // all except homer $filter_final = Net_LDAP2_Filter::combine('and', array($filter1, $filter2)); $this->assertEquals(2, $filter1->matches($allEntries)); // kent and homer $this->assertEquals(2, $filter2->matches($allEntries)); // kent and bart $filterresult = array(); $this->assertEquals(1, $filter_final->matches($allEntries, $filterresult)); // should leave only kent $this->assertEquals($entry3->dn(), array_shift($filterresult)->dn(), "Filtered entry does not equal expected entry! filter='" . $filter_final->asString() . "'"); // [TODO]: Further tests for >, <, >=, <= and ~=, when they are implemented. // ...until then: negative testing for those cases foreach (array('>', '<', '>=', '<=', '~=') as $to) { $filter = Net_LDAP2_Filter::parse("(fingers{$to}5)"); $this->assertInstanceOf('PEAR_Error', $filter->matches($allEntries), "Valid operator succeeded: WRITE THE TESTCASE FOR IT!"); } }
/** * testSearch(). */ public function testSearch() { if (!$this->ldapcfg) { $this->markTestSkipped('No ldapconfig.ini found. Skipping test!'); } else { $ldap = $this->connect(); // some testdata, so we can test sizelimit $base = $this->ldapcfg['global']['server_base_dn']; $ou1 = Net_LDAP2_Entry::createFresh('ou=Net_LDAP2_Test_search1,' . $base, array('objectClass' => array('top', 'organizationalUnit'), 'ou' => 'Net_LDAP2_Test_search1')); $ou1_1 = Net_LDAP2_Entry::createFresh('ou=Net_LDAP2_Test_search1_1,' . $ou1->dn(), array('objectClass' => array('top', 'organizationalUnit'), 'ou' => 'Net_LDAP2_Test_search2')); $ou2 = Net_LDAP2_Entry::createFresh('ou=Net_LDAP2_Test_search2,' . $base, array('objectClass' => array('top', 'organizationalUnit'), 'ou' => 'Net_LDAP2_Test_search2')); $this->assertTrue($ldap->add($ou1)); $this->assertTrue($ldap->dnExists($ou1->dn())); $this->assertTrue($ldap->add($ou1_1)); $this->assertTrue($ldap->dnExists($ou1_1->dn())); $this->assertTrue($ldap->add($ou2)); $this->assertTrue($ldap->dnExists($ou2->dn())); // Search for testfilter, should at least return our two test entries $res = $ldap->search(null, '(ou=Net_LDAP2*)', array('attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Search', $res); $this->assertThat($res->count(), $this->greaterThanOrEqual(2)); // Same, but with Net_LDAP2_Filter object $filtero = Net_LDAP2_Filter::create('ou', 'begins', 'Net_LDAP2'); $this->assertInstanceOf('Net_LDAP2_Filter', $filtero); $res = $ldap->search(null, $filtero, array('attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Search', $res); $this->assertThat($res->count(), $this->greaterThanOrEqual(2)); // Search using default filter for base-onelevel scope // should at least return our two test entries $res = $ldap->search(null, null, array('scope' => 'one', 'attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Search', $res); $this->assertThat($res->count(), $this->greaterThanOrEqual(2)); // Base-search using custom base (string) // should only return the test entry $ou1 and not the entry below it. $res = $ldap->search($ou1->dn(), null, array('scope' => 'base', 'attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Search', $res); $this->assertEquals(1, $res->count()); // Search using custom base, this time using an entry object // This tests if passing an entry object as base works // should only return the test entry $ou1 $res = $ldap->search($ou1, '(ou=*)', array('scope' => 'base', 'attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Search', $res); $this->assertEquals(1, $res->count()); // Search using default filter for base-onelevel scope with sizelimit // should of course return more than one entry, // but not more than sizelimit $res = $ldap->search(null, null, array('scope' => 'one', 'sizelimit' => 1, 'attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Search', $res); $this->assertEquals(1, $res->count()); $this->assertTrue($res->sizeLimitExceeded()); // sizelimit should be exceeded now // Bad filter $res = $ldap->search(null, 'somebadfilter', array('attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Error', $res); // Bad base $res = $ldap->search('badbase', null, array('attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Error', $res); // Passing Error object as base and as filter object $error = new Net_LDAP2_Error('Testerror'); $res = $ldap->search($error, null, array('attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Error', $res); $res = $ldap->search(null, $error, array('attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Error', $res); // Nullresult $res = $ldap->search(null, '(cn=nevermatching_filter)', array('scope' => 'base', 'attributes' => '1.1')); $this->assertInstanceOf('Net_LDAP2_Search', $res); $this->assertEquals(0, $res->count()); // cleanup $this->assertTrue($ldap->delete($ou1_1), 'Cleanup failed, please delete manually'); $this->assertTrue($ldap->delete($ou1), 'Cleanup failed, please delete manually'); $this->assertTrue($ldap->delete($ou2), 'Cleanup failed, please delete manually'); } }
// In this example, we want all users with first names // starting with "bened" and the last names ending with "ger". // Additionally, we want to exclude all users with names // containing "smith", which will be done throug a "negation". // Basic filter building $filter_sn = Net_LDAP2_Filter::create('gn', 'begins', 'bened'); $filter_gn = Net_LDAP2_Filter::create('sn', 'ends', 'ger'); // Building and negating the "no smith" filter component // this must be done in two steps, because // you are able to negate EVERY filter, not just leave filters. // the $filter_smith will not be used afterwards and is only // necessary for negation here. $filter_smith = Net_LDAP2_Filter::create('sn', 'contains', 'smith'); $filter_nosmith = Net_LDAP2_Filter::combine('not', $filter_smith); // Now combine all filter components to build our search filter $filter = Net_LDAP2_Filter::combine('and', array($filter_sn, $filter_gn, $filter_nosmith)); // The filter is ready now, so we can // use this filter now to search for entries. // The scope we use is "sub", meaning "all entries below the search base". // The base is "null", meaning the base defined in $ldap_config. This is similar // to call $ldap->search($ldap_config['base'], ... $requested_attributes = array('sn', 'gn', 'telephonenumber'); $search = $ldap->search(null, $filter, array('attributes' => $requested_attributes)); if (Net_LDAP2::isError($search)) { die('LDAP search failed: ' . $search->getMessage()); } // Lets see what entries we got and print the names and telephone numbers: if ($search->count() > 0) { echo "Found " . $search->count() . ' entries:<br>'; // Note, this is is only one of several ways to fetch entries! // You can also retrieve all entries in an array with
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; } $debugMode = defined('LDAP_AUTH_DEBUG') ? LDAP_AUTH_DEBUG : FALSE; $anonymousBeforeBind = defined('LDAP_AUTH_ANONYMOUSBEFOREBIND') ? LDAP_AUTH_ANONYMOUSBEFOREBIND : 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)); if (!$anonymousBeforeBind) { $ldapConnParams['binddn'] = LDAP_AUTH_BINDDN; $ldapConnParams['bindpw'] = LDAP_AUTH_BINDPW; } $ldapConnParams['starttls'] = defined('LDAP_AUTH_USETLS') ? LDAP_AUTH_USETLS : FALSE; if (is_int($parsedURI['port'])) { $ldapConnParams['port'] = $parsedURI['port']; } $ldapSchemaCacheEnable = defined('LDAP_AUTH_SCHEMA_CACHE_ENABLE') ? LDAP_AUTH_SCHEMA_CACHE_ENABLE : TRUE; $ldapSchemaCacheTimeout = defined('LDAP_AUTH_SCHEMA_CACHE_TIMEOUT') ? LDAP_AUTH_SCHEMA_CACHE_TIMEOUT : 86400; $logAttempts = defined('LDAP_AUTH_LOG_ATTEMPTS') ? LDAP_AUTH_LOG_ATTEMPTS : FALSE; // 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 if orignal connexion was anonymous if ($anonymousBeforeBind) { $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; } } //Cache LDAP Schema if ($ldapSchemaCacheEnable) { if (!sys_get_temp_dir()) { $tmpFile = tmp; $tmpDir = dirname($tmpFile); unlink($tmpFile); unset($tmpFile); } else { $tmpDir = sys_get_temp_dir(); } if (empty($parsedURI['port'])) { $ldapPort = $parsedURI['scheme'] == 'ldaps' ? 636 : 389; } else { $ldapPort = $parsedURI['port']; } $cacheFileLoc = $tmpDir . '/ttrss-ldapCache-' . $parsedURI['host'] . ':' . $ldapPort . '.cache'; if ($debugMode) { $this->_log('Schema Cache File: ' . $cacheFileLoc, E_USER_NOTICE); } $schemaCacheConf = array('path' => $cacheFileLoc, 'max_age' => $ldapSchemaCacheTimeout); $schemaCacheObj = new Net_LDAP2_SimpleFileSchemaCache($schemaCacheConf); $ldapConn->registerSchemaCache($schemaCacheObj); $schemaCacheObj->storeSchema($ldapConn->schema()); } //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) { if ($logAttempts) { $this->_logAttempt((string) $login, 'Unknown User'); } 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) { if ($logAttempts) { $this->_logAttempt((string) $login, 'successful'); } return $this->base->auto_create_user($login); } elseif ($loginAttempt->getCode() == 49) { if ($logAttempts) { $this->_logAttempt((string) $login, 'bad password'); } return FALSE; } else { $this->_log('Unknown Error: Code: ' . $loginAttempt->getCode() . ' Message: ' . $loginAttempt->getMessage() . ' user(' . (string) $login . ')'); return FALSE; } } return false; }
/** * 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; }