Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Support LDAP dns longer than 255 characters
Adds an ldap_full_dn column to store the dn, and only store a sha256
 hash in the ldap_dn which is shorter and can be indexed without
 trouble.
Migration still needs to be implemented.

Signed-off-by: Côme Chilliet <[email protected]>
  • Loading branch information
come-nc committed Dec 14, 2021
commit 3d8d4f8c1bbdf8ad01aa7e7b999c5dd46d029b88
56 changes: 31 additions & 25 deletions apps/user_ldap/lib/Mapping/AbstractMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public function __construct(\OCP\IDBConnection $dbc) {
*/
public function isColNameValid($col) {
switch ($col) {
case 'ldap_full_dn':
case 'ldap_dn':
case 'owncloud_name':
case 'directory_uuid':
Expand Down Expand Up @@ -125,7 +126,7 @@ protected function modify($query, $parameters) {
*/
public function getDNByName($name) {
$dn = array_search($name, $this->cache);
if ($dn === false && ($dn = $this->getXbyY('ldap_dn', 'owncloud_name', $name)) !== false) {
if ($dn === false && ($dn = $this->getXbyY('ldap_full_dn', 'owncloud_name', $name)) !== false) {
$this->cache[$dn] = $name;
}
return $dn;
Expand All @@ -142,11 +143,11 @@ public function setDNbyUUID($fdn, $uuid) {
$oldDn = $this->getDnByUUID($uuid);
$query = $this->dbc->prepare('
UPDATE `' . $this->getTableName() . '`
SET `ldap_dn` = ?
SET `ldap_dn` = ?, `ldap_full_dn` = ?
WHERE `directory_uuid` = ?
');

$r = $this->modify($query, [$fdn, $uuid]);
$r = $this->modify($query, [$this->getDNHash($fdn), $fdn, $uuid]);

if ($r && is_string($oldDn) && isset($this->cache[$oldDn])) {
$this->cache[$fdn] = $this->cache[$oldDn];
Expand Down Expand Up @@ -174,7 +175,14 @@ public function setUUIDbyDN($uuid, $fdn) {

unset($this->cache[$fdn]);

return $this->modify($query, [$uuid, $fdn]);
return $this->modify($query, [$uuid, $this->getDNHash($fdn)]);
}

/**
* Get the hash to store in database column ldap_dn for a given dn
*/
protected function getDNHash(string $fdn): string {
return (string)hash('sha256', $fdn, false);
}

/**
Expand All @@ -185,35 +193,43 @@ public function setUUIDbyDN($uuid, $fdn) {
*/
public function getNameByDN($fdn) {
if (!isset($this->cache[$fdn])) {
$this->cache[$fdn] = $this->getXbyY('owncloud_name', 'ldap_dn', $fdn);
$this->cache[$fdn] = $this->getXbyY('owncloud_name', 'ldap_dn', $this->getDNHash($fdn));
}
return $this->cache[$fdn];
}

protected function prepareListOfIdsQuery(array $dnList): IQueryBuilder {
/**
* @param array<string> $hashList
*/
protected function prepareListOfIdsQuery(array $hashList): IQueryBuilder {
$qb = $this->dbc->getQueryBuilder();
$qb->select('owncloud_name', 'ldap_dn')
$qb->select('owncloud_name', 'ldap_dn', 'ldap_full_dn')
->from($this->getTableName(false))
->where($qb->expr()->in('ldap_dn', $qb->createNamedParameter($dnList, QueryBuilder::PARAM_STR_ARRAY)));
->where($qb->expr()->in('ldap_dn', $qb->createNamedParameter($hashList, QueryBuilder::PARAM_STR_ARRAY)));
return $qb;
}

protected function collectResultsFromListOfIdsQuery(IQueryBuilder $qb, array &$results): void {
$stmt = $qb->execute();
while ($entry = $stmt->fetch(\Doctrine\DBAL\FetchMode::ASSOCIATIVE)) {
$results[$entry['ldap_dn']] = $entry['owncloud_name'];
$this->cache[$entry['ldap_dn']] = $entry['owncloud_name'];
$results[$entry['ldap_full_dn']] = $entry['owncloud_name'];
$this->cache[$entry['ldap_full_dn']] = $entry['owncloud_name'];
}
$stmt->closeCursor();
}

/**
* @param array<string> $fdns
* @return array<string,string>
*/
public function getListOfIdsByDn(array $fdns): array {
$totalDBParamLimit = 65000;
$sliceSize = 1000;
$maxSlices = $totalDBParamLimit / $sliceSize;
$results = [];

$slice = 1;
$fdns = array_map([$this, 'getDNHash'], $fdns);
$fdnsSlice = count($fdns) > $sliceSize ? array_slice($fdns, 0, $sliceSize) : $fdns;
$qb = $this->prepareListOfIdsQuery($fdnsSlice);

Expand Down Expand Up @@ -283,7 +299,7 @@ public function getNameByUUID($uuid) {
}

public function getDnByUUID($uuid) {
return $this->getXbyY('ldap_dn', 'directory_uuid', $uuid);
return $this->getXbyY('ldap_full_dn', 'directory_uuid', $uuid);
}

/**
Expand All @@ -294,7 +310,7 @@ public function getDnByUUID($uuid) {
* @throws \Exception
*/
public function getUUIDByDN($dn) {
return $this->getXbyY('directory_uuid', 'ldap_dn', $dn);
return $this->getXbyY('directory_uuid', 'ldap_dn', $this->getDNHash($dn));
}

/**
Expand All @@ -307,7 +323,7 @@ public function getUUIDByDN($dn) {
public function getList($offset = null, $limit = null) {
$query = $this->dbc->prepare('
SELECT
`ldap_dn` AS `dn`,
`ldap_full_dn` AS `dn`,
`owncloud_name` AS `name`,
`directory_uuid` AS `uuid`
FROM `' . $this->getTableName() . '`',
Expand All @@ -328,19 +344,9 @@ public function getList($offset = null, $limit = null) {
* @return bool
*/
public function map($fdn, $name, $uuid) {
if (mb_strlen($fdn) > 255) {
\OC::$server->getLogger()->error(
'Cannot map, because the DN exceeds 255 characters: {dn}',
[
'app' => 'user_ldap',
'dn' => $fdn,
]
);
return false;
}

$row = [
'ldap_dn' => $fdn,
'ldap_dn' => $this->getDNHash($fdn),
'ldap_full_dn' => $fdn,
'owncloud_name' => $name,
'directory_uuid' => $uuid
];
Expand Down
14 changes: 12 additions & 2 deletions apps/user_ldap/lib/Migration/Version1010Date20200630192842.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
$table = $schema->createTable('ldap_user_mapping');
$table->addColumn('ldap_dn', Types::STRING, [
'notnull' => true,
'length' => 255,
'length' => 64,
'default' => '',
]);
$table->addColumn('ldap_full_dn', Types::STRING, [
'notnull' => true,
'length' => 4096,
'default' => '',
]);
$table->addColumn('owncloud_name', Types::STRING, [
Expand All @@ -68,7 +73,12 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
$table = $schema->createTable('ldap_group_mapping');
$table->addColumn('ldap_dn', Types::STRING, [
'notnull' => true,
'length' => 255,
'length' => 64,
'default' => '',
]);
$table->addColumn('ldap_full_dn', Types::STRING, [
'notnull' => true,
'length' => 4096,
'default' => '',
]);
$table->addColumn('owncloud_name', Types::STRING, [
Expand Down