Projects
Kolab:3.4
php-pear-Net-LDAP3
0004-Fix-handling-of-special-characters-in-RDN-...
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0004-Fix-handling-of-special-characters-in-RDN-attributes.patch of Package php-pear-Net-LDAP3 (Revision 16)
Currently displaying revision
16
,
Show latest
From 5b282ccd4f97b1359abd058e7e6afefb167cf916 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <machniak@kolabsys.com> Date: Fri, 14 Nov 2014 07:01:02 -0500 Subject: [PATCH 4/4] Fix handling of special characters in RDN attributes (#3905) Fix update of objects which base DN contains special characters (#3824) --- lib/Net/LDAP3.php | 120 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 36 deletions(-) diff --git a/lib/Net/LDAP3.php b/lib/Net/LDAP3.php index 3930a07..311b3d2 100644 --- a/lib/Net/LDAP3.php +++ b/lib/Net/LDAP3.php @@ -1298,7 +1298,7 @@ class Net_LDAP3 $this->_debug("old attrs. is array, new attrs. is not array. new attr. exists in old attrs."); - $rdn_attr_value = array_shift($old_attrs[$attr]); + $rdn_attr_value = array_shift($old_attrs[$attr]); $_attr_to_remove = array(); foreach ($old_attrs[$attr] as $value) { @@ -1313,14 +1313,14 @@ class Net_LDAP3 if (strtolower($new_attrs[$attr]) !== strtolower($rdn_attr_value)) { $this->_debug("new attrs is not the same as the old rdn value, issuing a rename"); - $mod_array['rename']['dn'] = $subject_dn; - $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr][0]; + $mod_array['rename']['dn'] = $subject_dn; + $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . self::quote_string($new_attrs[$attr], true); } } else { $this->_debug("new attrs is not the same as any of the old rdn value, issuing a full rename"); - $mod_array['rename']['dn'] = $subject_dn; - $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr]; + $mod_array['rename']['dn'] = $subject_dn; + $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . self::quote_string($new_attrs[$attr], true); } } else { @@ -1331,17 +1331,17 @@ class Net_LDAP3 } else { // TODO: This fails. - $mod_array['rename']['dn'] = $subject_dn; - $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr][0]; - $mod_array['del'][$attr] = $old_attrs[$attr][0]; + $mod_array['rename']['dn'] = $subject_dn; + $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . self::quote_string($new_attrs[$attr][0], true); + $mod_array['del'][$attr] = $old_attrs[$attr][0]; } } } else { if (!is_array($new_attrs[$attr])) { $this->_debug("Renaming " . $old_attrs[$attr] . " to " . $new_attrs[$attr]); - $mod_array['rename']['dn'] = $subject_dn; - $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr]; + $mod_array['rename']['dn'] = $subject_dn; + $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . self::quote_string($new_attrs[$attr], true); } else { $this->_debug("Adding to replace"); @@ -1350,7 +1350,6 @@ class Net_LDAP3 continue; } } - } else { if (!isset($new_attrs[$attr]) || $new_attrs[$attr] === '' || (is_array($new_attrs[$attr]) && empty($new_attrs[$attr]))) { @@ -1446,9 +1445,12 @@ class Net_LDAP3 $old_ou = implode(',', $subject_dn_components); } + $subject_dn = self::unified_dn($subject_dn); + $prefix = self::unified_dn('ou=' . $old_ou) . ','; + // object is an organizational unit - if (strpos($subject_dn, 'ou=' . $old_ou) === 0) { - $root = substr($subject_dn, strlen($old_ou) + 4); // remove ou=*, + if (strpos($subject_dn, $prefix) === 0) { + $root = substr($subject_dn, strlen($prefix)); // remove ou=*, if ((!empty($new_attrs['base_dn']) && strtolower($new_attrs['base_dn']) !== strtolower($root)) || (strtolower($old_ou) !== strtolower($new_ou)) @@ -1459,15 +1461,22 @@ class Net_LDAP3 $mod_array['rename']['new_parent'] = $root; $mod_array['rename']['dn'] = $subject_dn; - $mod_array['rename']['new_rdn'] = 'ou=' . $new_ou; + $mod_array['rename']['new_rdn'] = 'ou=' . self::quote_string($new_ou, true); } } // not OU object, but changed ou attribute - else if ((!empty($old_ou) && !empty($new_ou)) && strtolower($old_ou) !== strtolower($new_ou)) { - $mod_array['rename']['new_parent'] = $new_ou; - if (empty($mod_array['rename']['dn']) || empty($mod_array['rename']['new_rdn'])) { - $mod_array['rename']['dn'] = $subject_dn; - $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$rdn_attr]; + else if (!empty($old_ou) && !empty($new_ou)) { + // unify DN strings for comparison + $old_ou = self::unified_dn($old_ou); + $new_ou = self::unified_dn($new_ou); + + if (strtolower($old_ou) !== strtolower($new_ou)) { + $mod_array['rename']['new_parent'] = $new_ou; + if (empty($mod_array['rename']['dn']) || empty($mod_array['rename']['new_rdn'])) { + $rdn_attr_value = self::quote_string($new_attrs[$rdn_attr], true); + $mod_array['rename']['dn'] = $subject_dn; + $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $rdn_attr_value; + } } } @@ -2202,23 +2211,23 @@ class Net_LDAP3 private function modify_entry_attributes($subject_dn, $attributes) { - // Opportunities to set false include failed ldap commands. - $result = true; - if (is_array($attributes['rename']) && !empty($attributes['rename'])) { - $olddn = $attributes['rename']['dn']; - $newrdn = $attributes['rename']['new_rdn']; - - if (!empty($attributes['rename']['new_parent'])) { - $new_parent = $attributes['rename']['new_parent']; - } - else { - $new_parent = null; - } + $olddn = $attributes['rename']['dn']; + $newrdn = $attributes['rename']['new_rdn']; + $new_parent = $attributes['rename']['new_parent']; $this->_debug("LDAP: C: Rename $olddn to $newrdn,$new_parent"); - $result = ldap_rename($this->conn, $olddn, $newrdn, $new_parent, true); + // Note: for some reason the operation fails if RDN contains special characters + // and last argument of ldap_rename() is set to TRUE. That's why we use FALSE. + // However, we need to modify RDN attribute value later, otherwise it + // will contain an array of previous and current values + for ($i = 1; $i >= 0; $i--) { + $result = ldap_rename($this->conn, $olddn, $newrdn, $new_parent, $i == 1); + if ($result) { + break; + } + } if ($result) { $this->_debug("LDAP: S: OK"); @@ -2233,6 +2242,12 @@ class Net_LDAP3 $old_parent_dn = implode(",", $old_parent_dn_components); $subject_dn = $newrdn . ',' . $old_parent_dn; } + + // modify RDN attribute value, see note above + if (!$i && empty($attributes['replace'][$attr])) { + list($attr, $val) = explode('=', $newrdn, 2); + $attributes['replace'][$attr] = self::quote_string($val, true, true); + } } else { $this->_debug("LDAP: S: " . ldap_error($this->conn)); @@ -2514,14 +2529,15 @@ class Net_LDAP3 /** * Quotes attribute value string * - * @param string $str Attribute value - * @param bool $dn True if the attribute is a DN + * @param string $str Attribute value + * @param bool $dn True if the attribute is a DN + * @param bool $reverse Do reverse replacement * * @return string Quoted string */ - public static function quote_string($str, $is_dn = false) + public static function quote_string($str, $is_dn = false, $reverse = false) { - // take firt entry if array given + // take first entry if array given if (is_array($str)) { $str = reset($str); } @@ -2549,10 +2565,42 @@ class Net_LDAP3 ); } + if ($reverse) { + return str_replace(array_values($replace), array_keys($replace), $str); + } + return strtr($str, $replace); } /** + * Unify DN string for comparison + * + * @para string $str DN string + * + * @return string Unified DN string + */ + public static function unified_dn($str) + { + $result = array(); + + foreach (explode(',', $str) as $token) { + list($attr, $value) = explode('=', $token, 2); + + $pos = 0; + while (preg_match('/\\\\[0-9a-fA-F]{2}/', $value, $matches, PREG_OFFSET_CAPTURE, $pos)) { + $char = chr(hexdec(substr($matches[0][0], 1))); + $pos = $matches[0][1]; + $value = substr_replace($value, $char, $pos, 3); + $pos += 1; + } + + $result[] = $attr . '=' . self::quote_string($value, true); + } + + return implode(',', $result); + } + + /** * create ber encoding for sort control * * @param array List of cols to sort by -- 1.9.3
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.