/** * Fetches a RootDSE object from an LDAP connection * * @param Net_LDAP2 $ldap Directory from which the RootDSE should be fetched * @param array $attrs Array of attributes to search for * * @access static * @return Net_LDAP2_RootDSE|Net_LDAP2_Error */ public static function fetch($ldap, $attrs = null) { if (!$ldap instanceof Net_LDAP2) { return PEAR::raiseError("Unable to fetch Schema: Parameter \$ldap must be a Net_LDAP2 object!"); } if (is_array($attrs) && count($attrs) > 0 ) { $attributes = $attrs; } else { $attributes = array('vendorName', 'vendorVersion', 'namingContexts', 'altServer', 'supportedExtension', 'supportedControl', 'supportedSASLMechanisms', 'supportedLDAPVersion', 'subschemaSubentry' ); } $result = $ldap->search('', '(objectClass=*)', array('attributes' => $attributes, 'scope' => 'base')); if (self::isError($result)) { return $result; } $entry = $result->shiftEntry(); if (false === $entry) { return PEAR::raiseError('Could not fetch RootDSE entry'); } $ret = new Net_LDAP2_RootDSE($entry); return $ret; }
/** * LDAP Password Driver * * Driver for passwords stored in LDAP * This driver use the PEAR Net_LDAP2 class (http://pear.php.net/package/Net_LDAP2). * * @version 1.0 (2009-06-24) * @author Edouard MOREAU <*****@*****.**> * * function hashPassword based on code from the phpLDAPadmin development team (http://phpldapadmin.sourceforge.net/). * function randomSalt based on code from the phpLDAPadmin development team (http://phpldapadmin.sourceforge.net/). * */ function password_save($curpass, $passwd) { $rcmail = rcmail::get_instance(); require_once 'Net/LDAP2.php'; // Building user DN $userDN = str_replace('%login', $_SESSION['username'], $rcmail->config->get('password_ldap_userDN_mask')); $parts = explode('@', $_SESSION['username']); if (count($parts) == 2) { $userDN = str_replace('%name', $parts[0], $userDN); $userDN = str_replace('%domain', $parts[1], $userDN); } if (empty($userDN)) { return PASSWORD_CONNECT_ERROR; } // Connection Method switch ($rcmail->config->get('password_ldap_method')) { case 'user': $binddn = $userDN; $bindpw = $curpass; break; case 'admin': $binddn = $rcmail->config->get('password_ldap_adminDN'); $bindpw = $rcmail->config->get('password_ldap_adminPW'); break; default: $binddn = $userDN; $bindpw = $curpass; break; // default is user mode } // Configuration array $ldapConfig = array('binddn' => $binddn, 'bindpw' => $bindpw, 'basedn' => $rcmail->config->get('password_ldap_basedn'), 'host' => $rcmail->config->get('password_ldap_host'), 'port' => $rcmail->config->get('password_ldap_port'), 'starttls' => $rcmail->config->get('password_ldap_starttls'), 'version' => $rcmail->config->get('password_ldap_version')); // Connecting using the configuration array $ldap = Net_LDAP2::connect($ldapConfig); // Checking for connection error if (PEAR::isError($ldap)) { return PASSWORD_CONNECT_ERROR; } // Crypting new password $newCryptedPassword = hashPassword($passwd, $rcmail->config->get('password_ldap_encodage')); if (!$newCryptedPassword) { return PASSWORD_CRYPT_ERROR; } // Writing new crypted password to LDAP $userEntry = $ldap->getEntry($userDN); if (Net_LDAP2::isError($userEntry)) { return PASSWORD_CONNECT_ERROR; } if (!$userEntry->replace(array($rcmail->config->get('password_ldap_pwattr') => $newCryptedPassword), $rcmail->config->get('password_ldap_force_replace'))) { return PASSWORD_CONNECT_ERROR; } if (Net_LDAP2::isError($userEntry->update())) { return PASSWORD_CONNECT_ERROR; } // All done, no error return PASSWORD_SUCCESS; }
/** * * @internal * * @throws Capall_Ldaper_LdapException * * @param string $login * * @return Capall_Ldaper_LdapUser */ public function getLdapUser($login) { // Search in tree for user... $users = $this->ldapConnection->search($this->baseDn, '(' . $this->loginAttribute . '=' . $login . ')'); if (PEAR::isError($users)) { throw new Capall_Ldaper_LdapException($users); } if ($users->count()) { return new Capall_Ldaper_LdapUser($users->shiftEntry(), $this->loginAttribute, $this->mailAttribute, $this->mailAttributeIndex); } }
/** * Establishes a working connection * * @return Net_LDAP2 */ public function &connect() { // Check extension if (true !== Net_LDAP2::checkLDAPExtension()) { $this->markTestSkipped('PHP LDAP extension not found or not loadable. Skipped Test.'); } // Simple working connect and privilegued bind $lcfg = array('host' => $this->ldapcfg['global']['server_address'], 'port' => $this->ldapcfg['global']['server_port'], 'basedn' => $this->ldapcfg['global']['server_base_dn'], 'binddn' => $this->ldapcfg['global']['server_binddn'], 'bindpw' => $this->ldapcfg['global']['server_bindpw'], 'filter' => '(ou=*)'); $ldap = Net_LDAP2::connect($lcfg); $this->assertInstanceOf('Net_LDAP2', $ldap, 'Connect failed but was supposed to work. Check credentials and host address. If those are correct, file a bug!'); return $ldap; }
/** * 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; }
/** * Create LDAP connection. * * @return Net_LDAP2 */ protected function connect() { static $conn; if (!$conn) { $setup = Setup::get()->ldap; $options = array('host' => $setup['host'], 'port' => $setup['port'], 'binddn' => $setup['binddn'], 'bindpw' => $setup['bindpw'], 'basedn' => $this->basedn); $conn = Net_LDAP2::connect($options); if (Misc::isError($conn)) { throw new AuthException($conn->getMessage(), $conn->getCode()); } } return $conn; }
/** * @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); } }
/** * Bind with searchDN and searchPW and search for the user's DN. * Use search_base and search_filter defined in config file. * Return the found DN. */ function search_userdn($rcmail) { $ldapConfig = array('binddn' => $rcmail->config->get('password_ldap_searchDN'), 'bindpw' => $rcmail->config->get('password_ldap_searchPW'), 'basedn' => $rcmail->config->get('password_ldap_basedn'), 'host' => $rcmail->config->get('password_ldap_host'), 'port' => $rcmail->config->get('password_ldap_port'), 'starttls' => $rcmail->config->get('password_ldap_starttls'), 'version' => $rcmail->config->get('password_ldap_version')); $ldap = Net_LDAP2::connect($ldapConfig); if (PEAR::isError($ldap)) { return ''; } $base = $rcmail->config->get('password_ldap_search_base'); $filter = substitute_vars($rcmail->config->get('password_ldap_search_filter')); $options = array('scope' => 'sub', 'attributes' => array()); $result = $ldap->search($base, $filter, $options); $ldap->done(); if (PEAR::isError($result) || $result->count() != 1) { return ''; } return $result->current()->dn(); }
/** * Retrieve information from LDAP * * @param string $uid login or email * @return array */ private 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->conn->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' => $entry->get_value('cn'), 'emails' => $entry->get_value('mail', 'all'), 'customer_id' => $entry->get_value($this->customer_id_attribute), 'contact_id' => $entry->get_value($this->contact_id_attribute)); return $details; }
function connect($user, $passwd) { require_once '/usr/share/pear/Net/LDAP2.php'; $config = array('binddn' => "uid={$user},ou=people,dc=domain,dc=com", 'bindpw' => "{$passwd}", 'basedn' => 'dc=domain,dc=com', 'host' => 'ldaprr.domain.com'); $ldap = Net_LDAP2::connect($config); if (PEAR::isError($ldap)) { //echo 'Could not connect to LDAP-server: '.$ldap->getMessage(); return FALSE; } $filter = 'uid=' . $user; $searchbase = 'dc=domain,dc=com'; $options = array('scope' => 'sub', 'attributes' => array('uid', 'cn')); $result = $ldap->search($searchbase, $filter, $options); $entries = $result->entries(); if (count($entries) != 1) { echo "."; } else { foreach ($entries as $entry) { setcookie('UName', $entry->getValue('cn'), time() + 900); } } return TRUE; }
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; }
function getConnection() { require_once 'include/Net/LDAP2.php'; // Set reasonable timeout limits $defaults = array('options' => array('LDAP_OPT_TIMELIMIT' => 5, 'LDAP_OPT_NETWORK_TIMEOUT' => 5)); if ($this->getConfig()->get('tls')) { $defaults['starttls'] = true; } if ($this->getConfig()->get('schema') == 'msad') { // Special options for Active Directory (2000+) servers //$defaults['starttls'] = true; $defaults['options'] += array('LDAP_OPT_PROTOCOL_VERSION' => 3, 'LDAP_OPT_REFERRALS' => 0); // Active Directory servers almost always use self-signed certs putenv('LDAPTLS_REQCERT=never'); } foreach ($this->getServers() as $s) { $params = $defaults + $s; $c = new Net_LDAP2($params); $r = $c->bind(); if (!PEAR::isError($r)) { return $c; } var_dump($r); } }
/** * Net_LDAP2_Error constructor. * * @param string $message String with error message. * @param integer $code Net_LDAP2 error code * @param integer $mode what "error mode" to operate in * @param mixed $level what error level to use for $mode & PEAR_ERROR_TRIGGER * @param mixed $debuginfo additional debug info, such as the last query * * @access public * @see PEAR_Error */ public function __construct($message = 'Net_LDAP2_Error', $code = NET_LDAP2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null) { if (is_int($code)) { $this->PEAR_Error($message . ': ' . Net_LDAP2::errorMessage($code), $code, $mode, $level, $debuginfo); } else { $this->PEAR_Error("{$message}: {$code}", NET_LDAP2_ERROR, $mode, $level, $debuginfo); } }
/** * Update the entry on the directory server * * This will evaluate all changes made so far and send them * to the directory server. * Please note, that if you make changes to objectclasses wich * have mandatory attributes set, update() will currently fail. * Remove the entry from the server and readd it as new in such cases. * This also will deal with problems with setting structural object classes. * * @param Net_LDAP2 $ldap If passed, a call to setLDAP() is issued prior update, thus switching the LDAP-server. This is for perl-ldap interface compliance * * @access public * @return true|Net_LDAP2_Error * @todo Entry rename with a DN containing special characters needs testing! */ public function update($ldap = null) { if ($ldap) { $msg = $this->setLDAP($ldap); if (Net_LDAP2::isError($msg)) { return PEAR::raiseError('You passed an invalid $ldap variable to update()'); } } // ensure we have a valid LDAP object $ldap = $this->getLDAP(); if (!$ldap instanceof Net_LDAP2) { return PEAR::raiseError("The entries LDAP object is not valid"); } // Get and check link $link = $ldap->getLink(); if (!is_resource($link)) { return PEAR::raiseError("Could not update entry: internal LDAP link is invalid"); } /* * Delete the entry */ if (true === $this->_delete) { return $ldap->delete($this); } /* * New entry */ if (true === $this->_new) { $msg = $ldap->add($this); if (Net_LDAP2::isError($msg)) { return $msg; } $this->_new = false; $this->_changes['add'] = array(); $this->_changes['delete'] = array(); $this->_changes['replace'] = array(); $this->_original = $this->_attributes; // In case the "new" entry was moved after creation, we must // adjust the internal DNs as the entry was already created // with the most current DN. if (false == is_null($this->_newdn)) { $this->_dn = $this->_newdn; $this->_newdn = null; } $return = true; return $return; } /* * Rename/move entry */ if (false == is_null($this->_newdn)) { if ($ldap->getLDAPVersion() !== 3) { return PEAR::raiseError("Renaming/Moving an entry is only supported in LDAPv3"); } // make dn relative to parent (needed for ldap rename) $parent = Net_LDAP2_Util::ldap_explode_dn($this->_newdn, array('casefolding' => 'none', 'reverse' => false, 'onlyvalues' => false)); if (Net_LDAP2::isError($parent)) { return $parent; } $child = array_shift($parent); // maybe the dn consist of a multivalued RDN, we must build the dn in this case // because the $child-RDN is an array! if (is_array($child)) { $child = Net_LDAP2_Util::canonical_dn($child); } $parent = Net_LDAP2_Util::canonical_dn($parent); // rename/move if (false == @ldap_rename($link, $this->_dn, $child, $parent, false)) { return PEAR::raiseError("Entry not renamed: " . @ldap_error($link), @ldap_errno($link)); } // reflect changes to local copy $this->_dn = $this->_newdn; $this->_newdn = null; } /* * Retrieve a entry that has all attributes we need so that the list of changes to build is created accurately */ $fullEntry = $ldap->getEntry($this->dn()); if (Net_LDAP2::isError($fullEntry)) { return PEAR::raiseError("Could not retrieve a full set of attributes to reconcile changes with"); } $modifications = array(); // ADD foreach ($this->_changes["add"] as $attr => $value) { // if attribute exists, we need to combine old and new values if ($fullEntry->exists($attr)) { $currentValue = $fullEntry->getValue($attr, "all"); $value = array_merge($currentValue, $value); } $modifications[$attr] = $value; } // DELETE foreach ($this->_changes["delete"] as $attr => $value) { // In LDAPv3 you need to specify the old values for deleting if (is_null($value) && $ldap->getLDAPVersion() === 3) { $value = $fullEntry->getValue($attr); } if (!is_array($value)) { $value = array($value); } // Find out what is missing from $value and exclude it $currentValue = isset($modifications[$attr]) ? $modifications[$attr] : $fullEntry->getValue($attr, "all"); $modifications[$attr] = array_values(array_diff($currentValue, $value)); } // REPLACE foreach ($this->_changes["replace"] as $attr => $value) { $modifications[$attr] = $value; } // COMMIT if (false === @ldap_modify($link, $this->dn(), $modifications)) { return PEAR::raiseError("Could not modify the entry: " . @ldap_error($link), @ldap_errno($link)); } // all went well, so _original (server) becomes _attributes (local copy), reset _changes too... $this->_changes['add'] = array(); $this->_changes['delete'] = array(); $this->_changes['replace'] = array(); $this->_original = $this->_attributes; $return = true; return $return; }
define('LDAP_LAYER', getenv('PHP_PEAR_XML_QUERY2XML_TEST_LDAPLAYER')); } else { if (@(include_once 'Net/LDAP2.php')) { define('LDAP_LAYER', 'LDAP2'); } else { define('LDAP_LAYER', 'LDAP'); } } } if (LDAP_LAYER == 'LDAP2') { if (!@(include_once 'Net/LDAP2.php')) { print 'skip could not find Net/LDAP2.php'; exit; } else { include_once dirname(dirname(__FILE__)) . '/settings.php'; $ldap = Net_LDAP2::connect($ldapConfig); if (PEAR::isError($ldap)) { print 'skip could not connect to LDAP directory'; exit; } } } else { if (!@(include_once 'Net/LDAP.php')) { print 'skip could not find Net/LDAP.php'; exit; } else { include_once dirname(dirname(__FILE__)) . '/settings.php'; $ldap = Net_LDAP::connect($ldapConfig); if (PEAR::isError($ldap)) { print 'skip could not connect to LDAP directory'; exit;
if (Net_LDAP2::isError($result)) { die('Unable to add attribute: ' . $result->getMessage()); } // Now we modify the first value // Note, that we must give all old values, otherwise the attribute // will be deleted. We specify the new absolute attribute state $result = $entry->replace(array('mail' => array('*****@*****.**', '*****@*****.**'))); if (Net_LDAP2::isError($result)) { die('Unable to modify attribute: ' . $result->getMessage()); } // And now we delete the second attribute value // We must provide the old value, so the ldap server knows, // which value we want to be deleted $result = $entry->delete(array('mail' => '*****@*****.**')); if (Net_LDAP2::isError($result)) { die('Unable to delete attribute value: ' . $result->getMessage()); } // Finally, we delete the whole attribute 'telephoneNumber': $result = $entry->delete('telephoneNumber'); if (Net_LDAP2::isError($result)) { die('Unable to delete attribute: ' . $result->getMessage()); } // Now it is time to transfer the changes to the ldap // directory. However, for security reasons, this line is // commented out. /* $result = $entry->update(); if (Net_LDAP2::isError($result)) { die('Unable to update entry: '.$result->getMessage()); } */
/** * Bind with searchDN and searchPW and search for the user's DN. * Use search_base and search_filter defined in config file. * Return the found DN. */ function search_userdn($rcmail) { $binddn = $rcmail->config->get('password_ldap_searchDN'); $bindpw = $rcmail->config->get('password_ldap_searchPW'); $ldapConfig = array('basedn' => $rcmail->config->get('password_ldap_basedn'), 'host' => $rcmail->config->get('password_ldap_host'), 'port' => $rcmail->config->get('password_ldap_port'), 'starttls' => $rcmail->config->get('password_ldap_starttls'), 'version' => $rcmail->config->get('password_ldap_version')); // allow anonymous searches if (!empty($binddn)) { $ldapConfig['binddn'] = $binddn; $ldapConfig['bindpw'] = $bindpw; } $ldap = Net_LDAP2::connect($ldapConfig); if (is_a($ldap, 'PEAR_Error')) { return ''; } $base = self::substitute_vars($rcmail->config->get('password_ldap_search_base')); $filter = self::substitute_vars($rcmail->config->get('password_ldap_search_filter')); $options = array('scope' => 'sub', 'attributes' => array()); $result = $ldap->search($base, $filter, $options); $ldap->done(); if (is_a($result, 'PEAR_Error') || $result->count() != 1) { return ''; } return $result->current()->dn(); }
function validate_user_ldap($user, $pass) { if (!$pass) { // An LDAP password cannot be empty. Treat specially so that Tiki does *NOT* unintentionally request an unauthenticated bind. return PASSWORD_INCORRECT; } global $prefs; global $logslib; // First connection on the ldap server in anonymous, now we can search the real name of the $user // It's required to pass in param the username & password because the username is used to determine the realname (dn) $this->init_ldap($user, $pass); $err = $this->ldap->bind(); if (is_int($err)) { $err=Net_LDAP2::errorMessage($err); } // Change the default bind_type to use the full, call get_user_attributes function to use the realname (dn) in the credentials test $this->ldap->setOption('bind_type', 'full'); $this->ldap->get_user_attributes(); // Credentials test! To test it we force the reconnection. $err = $this->ldap->bind(true); if (is_int($err)) { $err = Net_LDAP2::errorMessage($err); } switch($err) { case 'LDAP_INVALID_CREDENTIALS': return PASSWORD_INCORRECT; case 'LDAP_INVALID_SYNTAX': case 'LDAP_NO_SUCH_OBJECT': case 'LDAP_INVALID_DN_SYNTAX': if ($prefs['auth_ldap_debug'] == 'y') $logslib->add_log('ldap', 'Error'.$err); return USER_NOT_FOUND; case 'LDAP_SUCCESS': if ($prefs['auth_ldap_debug'] == 'y') $logslib->add_log('ldap', 'Bind successful.'); return USER_VALID; default: if ($prefs['auth_ldap_debug'] == 'y') $logslib->add_log('ldap', 'Error'.$err); return SERVER_ERROR; } // this should never happen die('Assertion failed ' . __FILE__ . ':' . __LINE__); }
function vacation_write(array &$data) { require_once 'Net/LDAP2.php'; $rcmail = rcmail::get_instance(); $search = array('%username', '%email_local', '%email_domain', '%email'); $replace = array($data['username'], $data['email_local'], $data['email_domain'], $data['email']); $ldap_basedn = str_replace($search, $replace, $rcmail->config->get('vacation_ldap_basedn')); $ldap_binddn = str_replace($search, $replace, $rcmail->config->get('vacation_ldap_binddn')); $search = array('%username', '%password', '%email_local', '%email_domain', '%email'); $replace = array($data['username'], $rcmail->decrypt($_SESSION['password']), $data['email_local'], $data['email_domain'], $data['email']); $ldap_bindpw = str_replace($search, $replace, $rcmail->config->get('vacation_ldap_bindpw')); $ldapConfig = array('host' => $rcmail->config->get('vacation_ldap_host'), 'port' => $rcmail->config->get('vacation_ldap_port'), 'starttls' => $rcmail->config->get('vacation_ldap_starttls'), 'version' => $rcmail->config->get('vacation_ldap_version'), 'basedn' => $ldap_basedn, 'binddn' => $ldap_binddn, 'bindpw' => $ldap_bindpw); $ldap = Net_LDAP2::connect($ldapConfig); if (PEAR::isError($ldap)) { return PLUGIN_ERROR_CONNECT; } $dns = $rcmail->config->get('vacation_ldap_modify_dns'); $ops = $rcmail->config->get('vacation_ldap_modify_ops'); for ($i = 0; $i < count($dns) && $i < count($ops); $i++) { $search = array('%username', '%email_local', '%email_domain', '%email', '%vacation_enable', '%vacation_start', '%vacation_end', '%vacation_subject', '%vacation_message', '%vacation_keepcopyininbox', '%vacation_forwarder'); $replace = array($data['username'], $data['email_local'], $data['email_domain'], $data['email'], $data['vacation_enable'] ? "TRUE" : "FALSE", $data['vacation_start'], $data['vacation_end'], $data['vacation_subject'], $data['vacation_message'], $data['vacation_keepcopyininbox'], $data['vacation_forwarder']); $dns[$i] = str_replace($search, $replace, $dns[$i]); foreach ($ops[$i] as $op => $args) { foreach ($args as $key => $value) { $search = array('%username', '%email_local', '%email_domain', '%email', '%vacation_enable', '%vacation_start', '%vacation_end', '%vacation_subject', '%vacation_message', '%vacation_keepcopyininbox', '%vacation_forwarder'); $replace = array($data['username'], $data['email_local'], $data['email_domain'], $data['email'], $data['vacation_enable'] ? $rcmail->config->get('vacation_ldap_attr_vacationenable_value_enabled') : $rcmail->config->get('vacation_ldap_attr_vacationenable_value_disabled'), $data['vacation_start'], $data['vacation_end'], $data['vacation_subject'], $data['vacation_message'], $data['vacation_keepcopyininbox'], $data['vacation_forwarder']); $ops[$i][$op][$key] = str_replace($search, $replace, $value); } } $ret = $ldap->modify($dns[$i], $ops[$i]); if (PEAR::isError($ldap)) { $ldap->done(); return PLUGIN_ERROR_PROCESS; } } $ldap->done(); return PLUGIN_SUCCESS; }
function changePassword($username, $oldpassword, $newpassword) { if (!isset($this->attributes['password']) || !isset($this->password_encoding)) { //throw new Exception(_('Sorry, changing LDAP passwords is not supported at this time')); return false; } $entry = $this->get_user($username, array('dn' => 'dn')); if (!$entry) { return false; } else { $config = $this->get_ldap_config(); $config['binddn'] = $entry->dn(); $config['bindpw'] = $oldpassword; try { $ldap = $this->get_ldap_connection($config); $entry = $this->get_user($username, array(), $ldap); $newCryptedPassword = $this->hashPassword($newpassword, $this->password_encoding); if ($newCryptedPassword === false) { return false; } if ($this->password_encoding == 'ad') { //TODO I believe this code will work once this bug is fixed: http://pear.php.net/bugs/bug.php?id=16796 $oldCryptedPassword = $this->hashPassword($oldpassword, $this->password_encoding); $entry->delete(array($this->attributes['password'] => $oldCryptedPassword)); } $entry->replace(array($this->attributes['password'] => $newCryptedPassword), true); if (Net_LDAP2::isError($entry->upate())) { return false; } return true; } catch (LdapInvalidCredentialsException $e) { return false; } } return false; }
/** * @todo Implement testCreateFresh(). */ public function testCreateFresh() { // test failing creation $t = Net_LDAP2_Entry::createFresh("cn=test", "I should be an array"); $this->assertTrue(Net_LDAP2::isError($t), 'Creating fresh entry succeeded but was supposed to fail!'); // test failing creation $t = Net_LDAP2_Entry::createFresh("cn=test", array('attr1' => 'single', 'attr2' => array('mv1', 'mv2'))); $this->assertInstanceOf('Net_LDAP2_Entry', $t, 'Creating fresh entry failed but was supposed to succeed!'); }
function pre_save(&$config, &$errors) { require_once 'include/Net/LDAP2.php'; global $ost; if ($ost && !extension_loaded('ldap')) { $ost->setWarning('LDAP extension is not available'); return; } if ($config['domain'] && !$config['servers']) { if (!($servers = LDAPAuthentication::autodiscover($config['domain'], preg_split('/,?\\s+/', $config['dns'])))) { $this->getForm()->getField('servers')->addError("Unable to find LDAP servers for this domain. Try giving\n an address of one of the DNS servers or manually specify\n the LDAP servers for this domain below."); } } else { if (!$config['servers']) { $this->getForm()->getField('servers')->addError("No servers specified. Either specify a Active Directory\n domain or a list of servers"); } else { $servers = array(); foreach (preg_split('/\\s+/', $config['servers']) as $host) { $servers[] = array('host' => $host); } } } $connection_error = false; foreach ($servers as $info) { // Assume MSAD $info['options']['LDAP_OPT_REFERRALS'] = 0; if ($config['tls']) { $info['starttls'] = true; // Don't require a certificate here putenv('LDAPTLS_REQCERT=never'); } if ($config['bind_dn']) { $info['binddn'] = $config['bind_dn']; $info['bindpw'] = $config['bind_pw'] ? $config['bind_pw'] : Crypto::decrypt($this->get('bind_pw'), SECRET_SALT, $this->getNamespace()); } // Set reasonable timeouts so we dont exceed max_execution_time $info['options'] = array('LDAP_OPT_TIMELIMIT' => 5, 'LDAP_OPT_NETWORK_TIMEOUT' => 5); $c = new Net_LDAP2($info); $r = $c->bind(); if (PEAR::isError($r)) { $connection_error = $r->getMessage() . ': Unable to bind to ' . $info['host']; } else { $connection_error = false; break; } } if ($connection_error) { $this->getForm()->getField('servers')->addError($connection_error); $errors['err'] = 'Unable to connect any listed LDAP servers'; } if (!$errors && $config['bind_pw']) { $config['bind_pw'] = Crypto::encrypt($config['bind_pw'], SECRET_SALT, $this->getNamespace()); } else { $config['bind_pw'] = $this->get('bind_pw'); } global $msg; if (!$errors) { $msg = 'LDAP configuration updated successfully'; } return !$errors; }
/** * 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); }
/** * Execute the shutdown procedure. * * @throws <b>AgaviDatabaseException</b> If an error occurs while shutting * down this database. * * @author Bram Goessens <*****@*****.**> */ public function shutdown() { if ($this->connection != null) { @($result = $this->connection->done()); $this->connection = null; if (Net_LDAP2::isError($result)) { $error = 'Could not close KVDag_LdapDatabase connection'; throw new AgaviDatabaseException($error); } } }
/** * Applies a regular expression onto a single- or multivalued attribute (like preg_match()) * * This method behaves like PHPs preg_match() but with some exceptions. * If you want to retrieve match information, then you MUST pass the * $matches parameter via reference! otherwise you will get no matches. * Since it is possible to have multi valued attributes the $matches * array will have a additionally numerical dimension (one for each value): * <code> * $matches = array( * 0 => array (usual preg_match() returnarray), * 1 => array (usual preg_match() returnarray) * ) * </code> * Please note, that $matches will be initialized to an empty array inside. * * Usage example: * <code> * $result = $entry->preg_match('/089(\d+)/', 'telephoneNumber', &$matches); * if ( $result === true ){ * echo "First match: ".$matches[0][1]; // Match of value 1, content of first bracket * } else { * if ( Net_LDAP2::isError($result) ) { * echo "Error: ".$result->getMessage(); * } else { * echo "No match found."; * } * } * </code> * * Please note that it is important to test for an Net_LDAP2_Error, because objects are * evaluating to true by default, thus if an error occured, and you only check using "==" then * you get misleading results. Use the "identical" (===) operator to test for matches to * avoid this as shown above. * * @param string $regex The regular expression * @param string $attr_name The attribute to search in * @param array $matches (optional, PASS BY REFERENCE!) Array to store matches in * * @return boolean|Net_LDAP2_Error TRUE, if we had a match in one of the values, otherwise false. Net_LDAP2_Error in case something went wrong */ public function pregMatch($regex, $attr_name, $matches = array()) { $matches = array(); // fetch attribute values $attr = $this->getValue($attr_name, 'all'); if (Net_LDAP2::isError($attr)) { return $attr; } else { unset($attr['count']); } // perform preg_match() on all values $match = false; foreach ($attr as $thisvalue) { $matches_int = array(); if (preg_match($regex, $thisvalue, $matches_int)) { $match = true; array_push($matches, $matches_int); // store matches in reference } } return $match; }
} } /** * Store the schema object in session * * @return true|Net_LDAP2_Error */ public function storeSchema($schema) { // Just dump the given object into the session // unless in loadSchema(), it is important to only return // Net_LDAP2_Error objects if something crucial went wrong. // If you feel that you want to return an error object, be sure // that you have read the comments in Net_LDAP2_SchemaCache.interface.php // or you will seriously hurt the performance of your application!!!! $_SESSION[__CLASS__] = $schema; return true; } } // Ok, now we have our finished cache object. Now initialize and register it // the usual way: $mySchemaCache = new MySessionSchemaCache(); $ldap = Net_LDAP2::connect($ldap_config); if (Net_LDAP2::isError($ldap)) { die('BIND FAILED: ' . $ldap->getMessage()); } $res = $ldap->registerSchemaCache($mySchemaCache); if (Net_LDAP2::isError($res)) { die('REGISTER CACHE FAILED: ' . $res->getMessage()); } // Now, the Schema is cached in the PHP session :)
/** * Returns last error message if error was found. * * Example: * <code> * $ldif->someAction(); * if ($ldif->error()) { * echo "Error: ".$ldif->error()." at input line: ".$ldif->error_lines(); * } * </code> * * @param boolean $as_string If set to true, only the message is returned * * @return false|Net_LDAP2_Error */ public function error($as_string = false) { if (Net_LDAP2::isError($this->_error['error'])) { return $as_string ? $this->_error['error']->getMessage() : $this->_error['error']; } else { return false; } }
private function init_schema() { // use PEAR include if autoloading failed if (!class_exists('Net_LDAP2')) { require_once 'Net/LDAP2.php'; } $port = $this->config_get('port', 389); $tls = $this->config_get('use_tls', false); foreach ((array) $this->config_get('hosts') as $host) { $this->_debug("C: Connect [{$host}:{$port}]"); $_ldap_cfg = array('host' => $host, 'port' => $port, 'tls' => $tls, 'version' => 3, 'binddn' => $this->config_get('service_bind_dn'), 'bindpw' => $this->config_get('service_bind_pw')); $_ldap_schema_cache_cfg = array('path' => "/tmp/" . $host . ":" . ($port ? $port : '389') . "-Net_LDAP2_Schema.cache", 'max_age' => 86400); $_ldap = Net_LDAP2::connect($_ldap_cfg); if (!is_a($_ldap, 'Net_LDAP2_Error')) { $this->_debug("S: OK"); break; } $this->_debug("S: NOT OK"); $this->_debug($_ldap->getMessage()); } if (is_a($_ldap, 'Net_LDAP2_Error')) { return null; } $_ldap_schema_cache = new Net_LDAP2_SimpleFileSchemaCache($_ldap_schema_cache_cfg); $_ldap->registerSchemaCache($_ldap_schema_cache); // TODO: We should learn what LDAP tech. we're running against. // Perhaps with a scope base objectclass recognize rootdse entry $schema_root_dn = $this->config_get('schema_root_dn'); if (!$schema_root_dn) { $_schema = $_ldap->schema(); } return $_schema; }
/** * Returns wether a attribute syntax is binary or not * * This method gets used by Net_LDAP2_Entry to decide which * PHP function needs to be used to fetch the value in the * proper format (e.g. binary or string) * * @param string $attribute The name of the attribute (eg.: 'sn') * * @access public * @return boolean */ public function isBinary($attribute) { $return = false; // default to false // This list contains all syntax that should be treaten as // containing binary values // The Syntax Definitons go into constants at the top of this page $syntax_binary = array(NET_LDAP2_SYNTAX_OCTET_STRING, NET_LDAP2_SYNTAX_JPEG); // Check Syntax $attr_s = $this->get('attribute', $attribute); if (Net_LDAP2::isError($attr_s)) { // Attribute not found in schema $return = false; // consider attr not binary } elseif (isset($attr_s['syntax']) && in_array($attr_s['syntax'], $syntax_binary)) { // Syntax is defined as binary in schema $return = true; } else { // Syntax not defined as binary, or not found // if attribute is a subtype, check superior attribute syntaxes if (isset($attr_s['sup'])) { foreach ($attr_s['sup'] as $superattr) { $return = $this->isBinary($superattr); if ($return) { break; // stop checking parents since we are binary } } } } return $return; }
/** * 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; }