diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php index 8ed1b7d668..0e2087f63c 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php @@ -79,7 +79,7 @@ class EntryManager implements EntryManagerInterface $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 @@ class EntryManager implements EntryManagerInterface $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 @@ class EntryManager implements EntryManagerInterface 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 a4aed634f5..d571c10ce0 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 @@ class EntryManagerTest extends TestCase $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"], + ]; + } }