Ejemplo n.º 1
0
 public function __construct(Ldap $link, $result = null)
 {
     $this->result = $result;
     if (is_resource($result)) {
         // Get the status code, matched DN and referrals from the response
         ldap_parse_result($link->resource(), $result, $this->code, $this->matchedDN, $this->message, $this->referrals);
         // Get the string representation of the status code
         $this->message = ldap_err2str($this->code);
         // Extract the data from the resource
         $this->data = ldap_get_entries($link->resource(), $result);
         $this->data = $this->cleanup_result($this->data);
         // Remove the referrals array if there's nothing inside
         count($this->referrals) == 0 && ($this->referrals = null);
         // Try to extract pagination cookie and estimated number of objects to be returned
         // Since there's no way to tell if pagination has been enabled or not, I am suppressing php errors
         @ldap_control_paged_result_response($link->resource(), $result, $this->cookie, $this->estimated);
     } else {
         $this->code = ldap_errno($link->resource());
         $this->message = ldap_error($link->resource());
     }
     // Active Directory conceals some additional error codes in the ErrorMessage of the response
     // that we cannot get to with ldap_errno() in authentication failures - let's try to
     // extract them!
     if ($this->code == 49) {
         $message = null;
         ldap_get_option($link->resource(), Option::ErrorString, $message);
         if (stripos($message, 'AcceptSecurityContext') !== false) {
             $message = explode(', ', $message);
             end($message);
             $message = prev($message);
             $this->code = explode(' ', $message)[1];
             // For compatibility reasons with standard ldap, if the error code
             // is 52e let's replace it with 49 ( their meanings are equal, it's just
             // Microsoft doing it its own way again )
             if ($this->code == '52e') {
                 $this->code = ResponseCode::InvalidCredentials;
             }
         }
     }
 }
Ejemplo n.º 2
0
<?php

require "connect.inc";
$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
insert_dummy_data($link);
ldap_add($link, "cn=userref,dc=my-domain,dc=com", array("objectClass" => array("extensibleObject", "referral"), "cn" => "userref", "ref" => "cn=userA,dc=my-domain,dc=com"));
$result = ldap_search($link, "cn=userref,dc=my-domain,dc=com", "(cn=user*)");
$errcode = $dn = $errmsg = $refs = null;
var_dump(ldap_parse_result($link, $result, $errcode, $dn, $errmsg, $refs), $errcode, $dn, $errmsg, $refs);
?>
===DONE===
<?php 
include "connect.inc";
$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
// Referral can only be removed with Manage DSA IT Control
ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array(array("oid" => "2.16.840.1.113730.3.4.2")));
ldap_delete($link, "cn=userref,dc=my-domain,dc=com");
remove_dummy_data($link);
 /**
  * Execute the LDAP search based on the stored credentials
  */
 private function _exec_search($count = false)
 {
     if ($this->ready) {
         $filter = $this->filter ? $this->filter : '(objectclass=*)';
         $function = $this->_scope2func($this->prop['scope'], $ns_function);
         $this->_debug("C: Search [{$filter}][dn: {$this->base_dn}]");
         // when using VLV, we get the total count by...
         if (!$count && $function != 'ldap_read' && $this->prop['vlv'] && !$this->group_id) {
             // ...either reading numSubOrdinates attribute
             if ($this->prop['numsub_filter'] && ($result_count = @$ns_function($this->conn, $this->base_dn, $this->prop['numsub_filter'], array('numSubOrdinates'), 0, 0, 0))) {
                 $counts = ldap_get_entries($this->conn, $result_count);
                 for ($this->vlv_count = $j = 0; $j < $counts['count']; $j++) {
                     $this->vlv_count += $counts[$j]['numsubordinates'][0];
                 }
                 $this->_debug("D: total numsubordinates = " . $this->vlv_count);
             } else {
                 if (!function_exists('ldap_parse_virtuallist_control')) {
                     // ...or by fetching all records dn and count them
                     $this->vlv_count = $this->_exec_search(true);
                 }
             }
             $this->vlv_active = $this->_vlv_set_controls($this->prop, $this->list_page, $this->page_size);
         }
         // only fetch dn for count (should keep the payload low)
         $attrs = $count ? array('dn') : array_values($this->fieldmap);
         if ($this->ldap_result = @$function($this->conn, $this->base_dn, $filter, $attrs, 0, (int) $this->prop['sizelimit'], (int) $this->prop['timelimit'])) {
             // when running on a patched PHP we can use the extended functions to retrieve the total count from the LDAP search result
             if ($this->vlv_active && function_exists('ldap_parse_virtuallist_control')) {
                 if (ldap_parse_result($this->conn, $this->ldap_result, $errcode, $matcheddn, $errmsg, $referrals, $serverctrls)) {
                     ldap_parse_virtuallist_control($this->conn, $serverctrls, $last_offset, $this->vlv_count, $vresult);
                     $this->_debug("S: VLV result: last_offset={$last_offset}; content_count={$this->vlv_count}");
                 } else {
                     $this->_debug("S: " . ($errmsg ? $errmsg : ldap_error($this->conn)));
                 }
             }
             $entries_count = ldap_count_entries($this->conn, $this->ldap_result);
             $this->_debug("S: {$entries_count} record(s)");
             return $count ? $entries_count : true;
         } else {
             $this->_debug("S: " . ldap_error($this->conn));
         }
     }
     return false;
 }
Ejemplo n.º 4
0
 /**
  * Execute LDAP search
  *
  * @param string $base_dn    Base DN to use for searching
  * @param string $filter     Filter string to query
  * @param string $scope      The LDAP scope (list|sub|base)
  * @param array  $attrs      List of entry attributes to read
  * @param array  $prop       Hash array with query configuration properties:
  *   - sort:   array of sort attributes (has to be in sync with the VLV index)
  *   - search: search string used for VLV controls
  * @param bool   $count_only Set to true if only entry count is requested
  *
  * @return mixed Net_LDAP3_Result object or number of entries (if $count_only=true) or False on failure
  */
 public function search($base_dn, $filter = '(objectclass=*)', $scope = 'sub', $attrs = array('dn'), $props = array(), $count_only = false)
 {
     if (!$this->conn) {
         $this->_debug("No active connection for " . __CLASS__ . "::" . __FUNCTION__);
         return false;
     }
     // make sure attributes list is not empty
     if (empty($attrs)) {
         $attrs = array('dn');
     }
     // make sure filter is not empty
     if (empty($filter)) {
         $filter = '(objectclass=*)';
     }
     $this->_debug("C: Search base dn: [{$base_dn}] scope [{$scope}] with filter [{$filter}]");
     $function = self::scope_to_function($scope, $ns_function);
     if (!$count_only && ($sort = $this->find_vlv($base_dn, $filter, $scope, $props['sort']))) {
         // when using VLV, we get the total count by...
         // ...either reading numSubOrdinates attribute
         if (($sub_filter = $this->config_get('numsub_filter')) && ($result_count = @$ns_function($this->conn, $base_dn, $sub_filter, array('numSubOrdinates'), 0, 0, 0))) {
             $counts = ldap_get_entries($this->conn, $result_count);
             for ($vlv_count = $j = 0; $j < $counts['count']; $j++) {
                 $vlv_count += $counts[$j]['numsubordinates'][0];
             }
             $this->_debug("D: total numsubordinates = " . $vlv_count);
         } else {
             if (!function_exists('ldap_parse_virtuallist_control')) {
                 // @FIXME: this search will ignore $props['search']
                 $vlv_count = $this->search($base_dn, $filter, $scope, array('dn'), $props, true);
             }
         }
         $this->vlv_active = $this->_vlv_set_controls($sort, $this->list_page, $this->page_size, $this->_vlv_search($sort, $props['search']));
     } else {
         $this->vlv_active = false;
     }
     $sizelimit = (int) $this->config['sizelimit'];
     $timelimit = (int) $this->config['timelimit'];
     $phplimit = (int) @ini_get('max_execution_time');
     // set LDAP time limit to be (one second) less than PHP time limit
     // otherwise we have no chance to log the error below
     if ($phplimit && $timelimit >= $phplimit) {
         $timelimit = $phplimit - 1;
     }
     $this->_debug("Using function {$function} on scope {$scope} (\$ns_function is {$ns_function})");
     if ($this->vlv_active) {
         if (!empty($this->additional_filter)) {
             $filter = "(&" . $filter . $this->additional_filter . ")";
             $this->_debug("C: (With VLV) Setting a filter (with additional filter) of " . $filter);
         } else {
             $this->_debug("C: (With VLV) Setting a filter (without additional filter) of " . $filter);
         }
     } else {
         if (!empty($this->additional_filter)) {
             $filter = "(&" . $filter . $this->additional_filter . ")";
         }
         $this->_debug("C: (Without VLV) Setting a filter of " . $filter);
     }
     $this->_debug("Executing search with return attributes: " . var_export($attrs, true));
     $ldap_result = @$function($this->conn, $base_dn, $filter, $attrs, 0, $sizelimit, $timelimit);
     if (!$ldap_result) {
         $this->_warning("LDAP: {$function} failed for dn={$base_dn}. " . ldap_error($this->conn));
         return false;
     }
     // when running on a patched PHP we can use the extended functions
     // to retrieve the total count from the LDAP search result
     if ($this->vlv_active && function_exists('ldap_parse_virtuallist_control')) {
         if (ldap_parse_result($this->conn, $ldap_result, $errcode, $matcheddn, $errmsg, $referrals, $serverctrls)) {
             ldap_parse_virtuallist_control($this->conn, $serverctrls, $last_offset, $vlv_count, $vresult);
             $this->_debug("S: VLV result: last_offset={$last_offset}; content_count={$vlv_count}");
         } else {
             $this->_debug("S: " . ($errmsg ? $errmsg : ldap_error($this->conn)));
         }
     } else {
         $this->_debug("S: " . ldap_count_entries($this->conn, $ldap_result) . " record(s) found");
     }
     $result = new Net_LDAP3_Result($this->conn, $base_dn, $filter, $scope, $ldap_result);
     if (isset($last_offset)) {
         $result->set('offset', $last_offset);
     }
     if (isset($vlv_count)) {
         $result->set('count', $vlv_count);
     }
     $result->set('vlv', $this->vlv_active);
     return $count_only ? $result->count() : $result;
 }
Ejemplo n.º 5
0
 protected function _parse_referrals($result_id)
 {
     if (!ldap_parse_result($this->adxLink->get_link(), $result_id, $code, $matchedDN, $errMsg, $referrals)) {
         return;
     }
     if (count($referrals) == 0) {
         return;
     }
     // Referral looks like this:
     // ldap://example.com/DC=example,DC=com
     //
     // Extract the protocol and url from the referral string
     if (preg_match("/^ldaps?:\\/\\/[a-zA-Z0-9_\\-.]*/", $referrals[0], $matches) !== 1) {
         throw new Exception("Unable to parse referral - {$referrals[0]}");
     }
     // Match found? Return it!
     if (isset($matches[0])) {
         return $matches[0];
     }
 }
Ejemplo n.º 6
0
 /**
  * Execute the LDAP search based on the stored credentials
  *
  * @param string $base_dn  The base DN to query
  * @param string $filter   The LDAP filter for search
  * @param string $scope    The LDAP scope (list|sub|base)
  * @param array  $attrs    List of entry attributes to read
  * @param array  $prop     Hash array with query configuration properties:
  *   - sort: array of sort attributes (has to be in sync with the VLV index)
  *   - search: search string used for VLV controls
  * @param boolean $count_only Set to true if only entry count is requested
  *
  * @return mixed  rcube_ldap_result object or number of entries (if count_only=true) or false on error
  */
 public function search($base_dn, $filter = '', $scope = 'sub', $attrs = array('dn'), $prop = array(), $count_only = false)
 {
     if (!$this->conn) {
         return false;
     }
     if (empty($filter)) {
         $filter = '(objectclass=*)';
     }
     $this->_debug("C: Search {$base_dn} for {$filter}");
     $function = self::scope2func($scope, $ns_function);
     // find available VLV index for this query
     if (!$count_only && ($vlv_sort = $this->_find_vlv($base_dn, $filter, $scope, $prop['sort']))) {
         // when using VLV, we get the total count by...
         // ...either reading numSubOrdinates attribute
         if (($sub_filter = $this->config['numsub_filter']) && ($result_count = @$ns_function($this->conn, $base_dn, $sub_filter, array('numSubOrdinates'), 0, 0, 0))) {
             $counts = ldap_get_entries($this->conn, $result_count);
             for ($vlv_count = $j = 0; $j < $counts['count']; $j++) {
                 $vlv_count += $counts[$j]['numsubordinates'][0];
             }
             $this->_debug("D: total numsubordinates = " . $vlv_count);
         } else {
             if (!function_exists('ldap_parse_virtuallist_control')) {
                 $vlv_count = $this->search($base_dn, $filter, $scope, array('dn'), $prop, true);
             }
         }
         $this->vlv_active = $this->_vlv_set_controls($vlv_sort, $this->list_page, $this->page_size, $prop['search']);
     } else {
         $this->vlv_active = false;
     }
     // only fetch dn for count (should keep the payload low)
     if ($ldap_result = @$function($this->conn, $base_dn, $filter, $attrs, 0, (int) $this->config['sizelimit'], (int) $this->config['timelimit'])) {
         // when running on a patched PHP we can use the extended functions
         // to retrieve the total count from the LDAP search result
         if ($this->vlv_active && function_exists('ldap_parse_virtuallist_control')) {
             if (ldap_parse_result($this->conn, $ldap_result, $errcode, $matcheddn, $errmsg, $referrals, $serverctrls)) {
                 ldap_parse_virtuallist_control($this->conn, $serverctrls, $last_offset, $vlv_count, $vresult);
                 $this->_debug("S: VLV result: last_offset={$last_offset}; content_count={$vlv_count}");
             } else {
                 $this->_debug("S: " . ($errmsg ? $errmsg : ldap_error($this->conn)));
             }
         } else {
             if ($this->debug) {
                 $this->_debug("S: " . ldap_count_entries($this->conn, $ldap_result) . " record(s) found");
             }
         }
         $this->result = new rcube_ldap_result($this->conn, $ldap_result, $base_dn, $filter, $vlv_count);
         return $count_only ? $this->result->count() : $this->result;
     } else {
         $this->_debug("S: " . ldap_error($this->conn));
     }
     return false;
 }
Ejemplo n.º 7
0
 /**
  * @link http://php.net/manual/en/function.ldap-parse-result.php
  * @param $link
  * @param $result
  * @param $errcode
  * @param null $matcheddn
  * @param null $errmsg
  * @param array|null $referrals
  * @return bool
  */
 public function parseResult($link, $result, &$errcode, &$matcheddn = null, &$errmsg = null, array &$referrals = null)
 {
     return ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals);
 }
Ejemplo n.º 8
0
<?php

require "connect.inc";
var_dump(ldap_parse_result(null, null));
?>
===DONE===
Ejemplo n.º 9
0
 /**
  * @return array
  * @throws InformationRetrievalFailureException
  */
 public function parse()
 {
     if (!ldap_parse_result($this->link, $this->result, $errCode, $matchedDN, $errMsg, $referrals)) {
         throw new InformationRetrievalFailureException(ldap_error($this->link), ldap_errno($this->link));
     }
     return ['errcode' => $errCode, 'errmsg' => $errMsg, 'matcheddn' => $matchedDN, 'referrals' => $referrals];
 }