diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php index 8ed1b7d668be..0e2087f63cee 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php @@ -79,7 +79,7 @@ public function addAttributeValues(Entry $entry, string $attribute, array $value $con = $this->getConnectionResource(); if (!@ldap_mod_add($con, $entry->getDn(), [$attribute => $values])) { - throw new LdapException(sprintf('Could not add values to entry "%s", attribute %s: ', $entry->getDn(), $attribute).ldap_error($con)); + throw new LdapException(sprintf('Could not add values to entry "%s", attribute "%s": ', $entry->getDn(), $attribute).ldap_error($con)); } } @@ -94,7 +94,7 @@ public function removeAttributeValues(Entry $entry, string $attribute, array $va $con = $this->getConnectionResource(); if (!@ldap_mod_del($con, $entry->getDn(), [$attribute => $values])) { - throw new LdapException(sprintf('Could not remove values from entry "%s", attribute %s: ', $entry->getDn(), $attribute).ldap_error($con)); + throw new LdapException(sprintf('Could not remove values from entry "%s", attribute "%s": ', $entry->getDn(), $attribute).ldap_error($con)); } } @@ -159,7 +159,7 @@ public function applyOperations(string $dn, iterable $operations): void private function parseRdnFromEntry(Entry $entry): string { - if (!preg_match('/^([^,]+),/', $entry->getDn(), $matches)) { + if (!preg_match('/(^[^,\\\\]*(?:\\\\.[^,\\\\]*)*),/', $entry->getDn(), $matches)) { throw new LdapException(sprintf('Entry "%s" malformed, could not parse RDN.', $entry->getDn())); } diff --git a/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/EntryManagerTest.php b/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/EntryManagerTest.php index a4aed634f5ea..d571c10ce0b1 100644 --- a/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/EntryManagerTest.php +++ b/src/Symfony/Component/Ldap/Tests/Adapter/ExtLdap/EntryManagerTest.php @@ -44,4 +44,34 @@ public function testGetResources() $entryManager = new EntryManager($connection); $entryManager->update($entry); } + + /** + * @see https://tools.ietf.org/html/rfc4514#section-3 + * + * @dataProvider moveWithRFC4514DistinguishedNameProvider + */ + public function testMoveWithRFC4514DistinguishedName(string $dn, string $expectedRdn) + { + $connection = $this->createMock(Connection::class); + + $entry = new Entry($dn); + $entryManager = new EntryManager($connection); + + $method = (new \ReflectionClass(EntryManager::class))->getMethod('parseRdnFromEntry'); + $method->setAccessible(true); + + $cn = $method->invokeArgs($entryManager, [$entry, 'a']); + + $this->assertSame($expectedRdn, $cn); + } + + public function moveWithRFC4514DistinguishedNameProvider(): array + { + return [ + ['CN=Simple,DC=example,DC=net', 'CN=Simple'], + ['CN=James \"Jim\" Smith\, III,DC=example,DC=net', 'CN=James \"Jim\" Smith\, III'], + ['UID=jsmith,DC=example,DC=net', 'UID=jsmith'], + ["CN=Before\0dAfter,DC=example,DC=net", "CN=Before\0dAfter"], + ]; + } }