From: Arthur Schiwon Date: Tue, 20 Aug 2013 12:23:49 +0000 (+0200) Subject: LDAP: establish wrapper interface to allow proper mocking X-Git-Tag: v6.0.0alpha2~103^2~12 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6e850e0bee24f1fcea6c59e074d576bee1ec3e5b;p=nextcloud-server.git LDAP: establish wrapper interface to allow proper mocking --- diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 6cdeff36677..4b7920b7162 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -73,13 +73,13 @@ abstract class Access extends BackendBase { \OCP\Util::writeLog('user_ldap', 'readAttribute: '.$dn.' found', \OCP\Util::DEBUG); return array(); } - $er = $this->ldap->first_entry($cr, $rr); + $er = $this->ldap->firstEntry($cr, $rr); if(!$this->ldap->isResource($er)) { //did not match the filter, return false return false; } //LDAP attributes are not case sensitive - $result = \OCP\Util::mb_array_change_key_case($this->ldap->get_attributes($cr, $er), MB_CASE_LOWER, 'UTF-8'); + $result = \OCP\Util::mb_array_change_key_case($this->ldap->getAttributes($cr, $er), MB_CASE_LOWER, 'UTF-8'); $attr = mb_strtolower($attr, 'UTF-8'); if(isset($result[$attr]) && $result[$attr]['count'] > 0) { @@ -683,13 +683,13 @@ abstract class Access extends BackendBase { $findings = array(); foreach($sr as $key => $res) { - $findings = array_merge($findings, $this->ldap->get_entries($link_resource, $res )); + $findings = array_merge($findings, $this->ldap->getEntries($link_resource, $res )); } if($pagedSearchOK) { \OCP\Util::writeLog('user_ldap', 'Paged search successful', \OCP\Util::INFO); foreach($sr as $key => $res) { $cookie = null; - if($this->ldap->control_paged_result_response($link_resource, $res, $cookie)) { + if($this->ldap->controlPagedResultResponse($link_resource, $res, $cookie)) { \OCP\Util::writeLog('user_ldap', 'Set paged search cookie', \OCP\Util::INFO); $this->setPagedResultCookie($base[$key], $filter, $limit, $offset, $cookie); } @@ -1103,8 +1103,9 @@ abstract class Access extends BackendBase { if($offset > 0) { \OCP\Util::writeLog('user_ldap', 'Cookie '.$cookie, \OCP\Util::INFO); } - $pagedSearchOK = $this->ldap->control_paged_result($this->connection->getConnectionResource(), - $limit, false, $cookie); + $pagedSearchOK = $this->ldap->controlPagedResult( + $this->connection->getConnectionResource(), $limit, + false, $cookie); if(!$pagedSearchOK) { return false; } diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 6a0d00405c0..6850169f2df 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -656,10 +656,10 @@ class Connection extends BackendBase { $host .= ':' . $port; } $this->ldapConnectionRes = $this->ldap->connect($host, $port); - if($this->ldap->set_option($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) { - if($this->ldap->set_option($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) { + if($this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) { + if($this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) { if($this->config['ldapTLS']) { - $this->ldap->start_tls($this->ldapConnectionRes); + $this->ldap->startTls($this->ldapConnectionRes); } } } diff --git a/apps/user_ldap/lib/ildapwrapper.php b/apps/user_ldap/lib/ildapwrapper.php new file mode 100644 index 00000000000..56f5cfb4a2d --- /dev/null +++ b/apps/user_ldap/lib/ildapwrapper.php @@ -0,0 +1,179 @@ +. + * + */ + +namespace OCA\user_ldap\lib; + +interface ILDAPWrapper { + + //LDAP functions in use + + /** + * @brief Bind to LDAP directory + * @param $link LDAP link resource + * @param $dn an RDN to log in with + * @param $password the password + * @return true on success, false otherwise + * + * with $dn and $password as null a anonymous bind is attempted. + */ + public function bind($link, $dn, $password); + + /** + * @brief connect to an LDAP server + * @param $host The host to connect to + * @param $port The port to connect to + * @return a link resource on success, otherwise false + */ + public function connect($host, $port); + + /** + * @brief Send LDAP pagination control + * @param $link LDAP link resource + * @param $pagesize number of results per page + * @param $isCritical Indicates whether the pagination is critical of not. + * @param $cookie structure sent by LDAP server + * @return true on success, false otherwise + */ + public function controlPagedResult($link, $pagesize, $isCritical, $cookie); + + /** + * @brief Retrieve the LDAP pagination cookie + * @param $link LDAP link resource + * @param $result LDAP result resource + * @param $cookie structure sent by LDAP server + * + * Corresponds to ldap_control_paged_result_response + */ + public function controlPagedResultResponse($link, $result, &$cookie); + + /** + * @brief Return the LDAP error number of the last LDAP command + * @param $link LDAP link resource + * @return error message as string + */ + public function errno($link); + + /** + * @brief Return the LDAP error message of the last LDAP command + * @param $link LDAP link resource + * @return error code as integer + */ + public function error($link); + + /** + * @brief Return first result id + * @param $link LDAP link resource + * @param $result LDAP result resource + * @return an LDAP search result resource + * */ + public function firstEntry($link, $result); + + /** + * @brief Get attributes from a search result entry + * @param $link LDAP link resource + * @param $result LDAP result resource + * @return array containing the results, false on error + * */ + public function getAttributes($link, $result); + + /** + * @brief Get all result entries + * @param $link LDAP link resource + * @param $result LDAP result resource + * @return array containing the results, false on error + */ + public function getEntries($link, $result); + + /** + * @brief Read an entry + * @param $link LDAP link resource + * @param $baseDN The DN of the entry to read from + * @param $filter An LDAP filter + * @param $attr array of the attributes to read + * @return an LDAP search result resource + */ + public function read($link, $baseDN, $filter, $attr); + + /** + * @brief Search LDAP tree + * @param $link LDAP link resource + * @param $baseDN The DN of the entry to read from + * @param $filter An LDAP filter + * @param $attr array of the attributes to read + * @return an LDAP search result resource, false on error + */ + public function search($link, $baseDN, $filter, $attr); + + /** + * @brief Sets the value of the specified option to be $value + * @param $link LDAP link resource + * @param $option a defined LDAP Server option + * @param $value the new value for the option + * @return true on success, false otherwise + */ + public function setOption($link, $option, $value); + + /** + * @brief establish Start TLS + * @param $link LDAP link resource + * @return true on success, false otherwise + */ + public function startTls($link); + + /** + * @brief Sort the result of a LDAP search + * @param $link LDAP link resource + * @param $result LDAP result resource + * @param $sortfilter attribute to use a key in sort + */ + public function sort($link, $result, $sortfilter); + + /** + * @brief Unbind from LDAP directory + * @param $link LDAP link resource + * @return true on success, false otherwise + */ + public function unbind($link); + + //additional required methods in owncloud + + /** + * @brief Checks whether the server supports LDAP + * @return true if it the case, false otherwise + * */ + public function areLDAPFunctionsAvailable(); + + /** + * @brief Checks whether PHP supports LDAP Paged Results + * @return true if it the case, false otherwise + * */ + public function hasPagedResultSupport(); + + /** + * @brief Checks whether the submitted parameter is a resource + * @param $resource the resource variable to check + * @return true if it is a resource, false otherwise + */ + public function isResource($resource); + +} \ No newline at end of file diff --git a/apps/user_ldap/lib/ldap.php b/apps/user_ldap/lib/ldap.php index 1de901aec12..0f082147b14 100644 --- a/apps/user_ldap/lib/ldap.php +++ b/apps/user_ldap/lib/ldap.php @@ -23,35 +23,89 @@ namespace OCA\user_ldap\lib; -class LDAP { +class LDAP implements ILDAPWrapper { protected $curFunc = ''; protected $curArgs = array(); - //Simple wrapper for the ldap functions - public function __call($name, $arguments) { - $func = 'ldap_' . $name; - if(function_exists($func)) { - $this->preFunctionCall($func, $arguments); - $result = call_user_func_array($func, $arguments); - $this->postFunctionCall(); - return $result; - } + public function bind($link, $dn, $password) { + return $this->invokeLDAPMethod('bind', $link, $dn, $password); } - public function control_paged_result_response($linkResource, $resultResource, &$cookie) { + public function connect($host, $port) { + return $this->invokeLDAPMethod('connect', $host, $port); + } + + public function controlPagedResultResponse($link, $result, &$cookie) { $this->preFunctionCall('ldap_control_paged_result_response', - array($linkResource, $resultResource, $cookie)); - $result = ldap_control_paged_result_response( - $linkResource, $resultResource, $cookie); + array($link, $result, $cookie)); + $result = ldap_control_paged_result_response($link, $result, $cookie); $this->postFunctionCall(); return $result; } + public function controlPagedResult($link, $pagesize, $isCritical, $cookie) { + return $this->invokeLDAPMethod('control_paged_result', $link, $pagesize, + $isCritical, $cookie); + } + + public function errno($link) { + return $this->invokeLDAPMethod('errno', $link); + } + + public function error($link) { + return $this->invokeLDAPMethod('error', $link); + } + + public function firstEntry($link, $result) { + return $this->invokeLDAPMethod('first_entry', $link, $result); + } + + public function getAttributes($link, $result) { + return $this->invokeLDAPMethod('get_attributes', $link, $result); + } + + public function getEntries($link, $result) { + return $this->invokeLDAPMethod('get_entries', $link, $result); + } + + public function read($link, $baseDN, $filter, $attr) { + return $this->invokeLDAPMethod('read', $link, $baseDN, $filter, $attr); + } + + public function search($link, $baseDN, $filter, $attr) { + return $this->invokeLDAPMethod('search', $link, $baseDN, + $filter, $attr); + } + + public function setOption($link, $option, $value) { + $this->invokeLDAPMethod('set_option', $link, $option, $value); + } + + public function sort($link, $result, $sortfilter) { + return $this->invokeLDAPMethod('sort', $link, $result, $sortfilter); + } + + public function startTls($link) { + return $this->invokeLDAPMethod('start_tls', $link); + } + + public function unbind($link) { + return $this->invokeLDAPMethod('unbind', $link); + } + + /** + * @brief Checks whether the server supports LDAP + * @return true if it the case, false otherwise + * */ public function areLDAPFunctionsAvailable() { return function_exists('ldap_connect'); } + /** + * @brief Checks whether PHP supports LDAP Paged Results + * @return true if it the case, false otherwise + * */ public function hasPagedResultSupport() { $hasSupport = function_exists('ldap_control_paged_result') && function_exists('ldap_control_paged_result_response'); @@ -59,8 +113,7 @@ class LDAP { } /** - * Checks whether the submitted parameter is a resource - * + * @brief Checks whether the submitted parameter is a resource * @param $resource the resource variable to check * @return true if it is a resource, false otherwise */ @@ -68,24 +121,38 @@ class LDAP { return is_resource($resource); } + private function invokeLDAPMethod() { + $arguments = func_get_args(); + $func = 'ldap_' . array_shift($arguments); + if(function_exists($func)) { + $this->preFunctionCall($func, $arguments); + $result = call_user_func_array($func, $arguments); + $this->postFunctionCall(); + return $result; + } + } + private function preFunctionCall($functionName, $args) { $this->curFunc = $functionName; $this->curArgs = $args; } private function postFunctionCall() { - if(is_resource($this->curArgs[0])) { + if($this->isResource($this->curArgs[0])) { $errorCode = ldap_errno($this->curArgs[0]); $errorMsg = ldap_error($this->curArgs[0]); if($errorCode !== 0) { if($this->curFunc === 'ldap_sort' && $errorCode === -4) { //You can safely ignore that decoding error. //… says https://bugs.php.net/bug.php?id=18023 - } else if($this->curFunc === 'ldap_get_entries' && $errorCode === -4) { + } else if($this->curFunc === 'ldap_get_entries' + && $errorCode === -4) { } else if ($errorCode === 32) { //for now } else { - throw new \Exception('LDAP error '.$errorMsg.' (' .$errorCode.') after calling '.$this->curFunc.' with arguments '.print_r($this->curArgs, true)); + throw new \Exception('LDAP error '.$errorMsg.' (' . + $errorCode.') after calling '.$this->curFunc. + ' with arguments '.print_r($this->curArgs, true)); } } }