summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@users.noreply.github.com>2021-12-09 17:18:43 +0100
committerGitHub <noreply@github.com>2021-12-09 17:18:43 +0100
commit2e869fd215f87ec634aa0e25b84a97c197aa9f96 (patch)
tree2d1669673ca91106b22b545642244b8206224a06 /apps
parent64cd011f47d09adf7724fb384af9039bd3525ba6 (diff)
parenta35904749f78b5acf248886d27edc001f1bc5c63 (diff)
downloadnextcloud-server-2e869fd215f87ec634aa0e25b84a97c197aa9f96.tar.gz
nextcloud-server-2e869fd215f87ec634aa0e25b84a97c197aa9f96.zip
Merge pull request #29523 from nextcloud/fix/support-ldap-long-dns
Diffstat (limited to 'apps')
-rw-r--r--apps/user_ldap/composer/composer/autoload_classmap.php1
-rw-r--r--apps/user_ldap/composer/composer/autoload_static.php1
-rw-r--r--apps/user_ldap/lib/Mapping/AbstractMapping.php48
-rw-r--r--apps/user_ldap/lib/Migration/Version1010Date20200630192842.php16
-rw-r--r--apps/user_ldap/lib/Migration/Version1120Date20210917155206.php34
-rw-r--r--apps/user_ldap/lib/Migration/Version1130Date20211102154716.php146
6 files changed, 213 insertions, 33 deletions
diff --git a/apps/user_ldap/composer/composer/autoload_classmap.php b/apps/user_ldap/composer/composer/autoload_classmap.php
index 10d61327c2d..186f28db828 100644
--- a/apps/user_ldap/composer/composer/autoload_classmap.php
+++ b/apps/user_ldap/composer/composer/autoload_classmap.php
@@ -61,6 +61,7 @@ return array(
'OCA\\User_LDAP\\Migration\\UnsetDefaultProvider' => $baseDir . '/../lib/Migration/UnsetDefaultProvider.php',
'OCA\\User_LDAP\\Migration\\Version1010Date20200630192842' => $baseDir . '/../lib/Migration/Version1010Date20200630192842.php',
'OCA\\User_LDAP\\Migration\\Version1120Date20210917155206' => $baseDir . '/../lib/Migration/Version1120Date20210917155206.php',
+ 'OCA\\User_LDAP\\Migration\\Version1130Date20211102154716' => $baseDir . '/../lib/Migration/Version1130Date20211102154716.php',
'OCA\\User_LDAP\\Notification\\Notifier' => $baseDir . '/../lib/Notification/Notifier.php',
'OCA\\User_LDAP\\PagedResults\\IAdapter' => $baseDir . '/../lib/PagedResults/IAdapter.php',
'OCA\\User_LDAP\\PagedResults\\Php73' => $baseDir . '/../lib/PagedResults/Php73.php',
diff --git a/apps/user_ldap/composer/composer/autoload_static.php b/apps/user_ldap/composer/composer/autoload_static.php
index e1133fd8700..121439f0239 100644
--- a/apps/user_ldap/composer/composer/autoload_static.php
+++ b/apps/user_ldap/composer/composer/autoload_static.php
@@ -76,6 +76,7 @@ class ComposerStaticInitUser_LDAP
'OCA\\User_LDAP\\Migration\\UnsetDefaultProvider' => __DIR__ . '/..' . '/../lib/Migration/UnsetDefaultProvider.php',
'OCA\\User_LDAP\\Migration\\Version1010Date20200630192842' => __DIR__ . '/..' . '/../lib/Migration/Version1010Date20200630192842.php',
'OCA\\User_LDAP\\Migration\\Version1120Date20210917155206' => __DIR__ . '/..' . '/../lib/Migration/Version1120Date20210917155206.php',
+ 'OCA\\User_LDAP\\Migration\\Version1130Date20211102154716' => __DIR__ . '/..' . '/../lib/Migration/Version1130Date20211102154716.php',
'OCA\\User_LDAP\\Notification\\Notifier' => __DIR__ . '/..' . '/../lib/Notification/Notifier.php',
'OCA\\User_LDAP\\PagedResults\\IAdapter' => __DIR__ . '/..' . '/../lib/PagedResults/IAdapter.php',
'OCA\\User_LDAP\\PagedResults\\Php73' => __DIR__ . '/..' . '/../lib/PagedResults/Php73.php',
diff --git a/apps/user_ldap/lib/Mapping/AbstractMapping.php b/apps/user_ldap/lib/Mapping/AbstractMapping.php
index 85fc91590fb..1d3e1a221f7 100644
--- a/apps/user_ldap/lib/Mapping/AbstractMapping.php
+++ b/apps/user_ldap/lib/Mapping/AbstractMapping.php
@@ -68,6 +68,7 @@ abstract class AbstractMapping {
public function isColNameValid($col) {
switch ($col) {
case 'ldap_dn':
+ case 'ldap_dn_hash':
case 'owncloud_name':
case 'directory_uuid':
return true;
@@ -151,11 +152,11 @@ abstract class AbstractMapping {
$oldDn = $this->getDnByUUID($uuid);
$statement = $this->dbc->prepare('
UPDATE `' . $this->getTableName() . '`
- SET `ldap_dn` = ?
+ SET `ldap_dn_hash` = ?, `ldap_dn` = ?
WHERE `directory_uuid` = ?
');
- $r = $this->modify($statement, [$fdn, $uuid]);
+ $r = $this->modify($statement, [$this->getDNHash($fdn), $fdn, $uuid]);
if ($r && is_string($oldDn) && isset($this->cache[$oldDn])) {
$this->cache[$fdn] = $this->cache[$oldDn];
@@ -178,12 +179,24 @@ abstract class AbstractMapping {
$statement = $this->dbc->prepare('
UPDATE `' . $this->getTableName() . '`
SET `directory_uuid` = ?
- WHERE `ldap_dn` = ?
+ WHERE `ldap_dn_hash` = ?
');
unset($this->cache[$fdn]);
- return $this->modify($statement, [$uuid, $fdn]);
+ return $this->modify($statement, [$uuid, $this->getDNHash($fdn)]);
+ }
+
+ /**
+ * Get the hash to store in database column ldap_dn_hash for a given dn
+ */
+ protected function getDNHash(string $fdn): string {
+ $hash = hash('sha256', $fdn, false);
+ if (is_string($hash)) {
+ return $hash;
+ } else {
+ throw new \RuntimeException('hash function did not return a string');
+ }
}
/**
@@ -194,16 +207,19 @@ abstract class AbstractMapping {
*/
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_hash', $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_hash', 'ldap_dn')
->from($this->getTableName(false))
- ->where($qb->expr()->in('ldap_dn', $qb->createNamedParameter($dnList, QueryBuilder::PARAM_STR_ARRAY)));
+ ->where($qb->expr()->in('ldap_dn_hash', $qb->createNamedParameter($hashList, QueryBuilder::PARAM_STR_ARRAY)));
return $qb;
}
@@ -216,6 +232,10 @@ abstract class AbstractMapping {
$stmt->closeCursor();
}
+ /**
+ * @param array<string> $fdns
+ * @return array<string,string>
+ */
public function getListOfIdsByDn(array $fdns): array {
$totalDBParamLimit = 65000;
$sliceSize = 1000;
@@ -223,6 +243,7 @@ abstract class AbstractMapping {
$results = [];
$slice = 1;
+ $fdns = array_map([$this, 'getDNHash'], $fdns);
$fdnsSlice = count($fdns) > $sliceSize ? array_slice($fdns, 0, $sliceSize) : $fdns;
$qb = $this->prepareListOfIdsQuery($fdnsSlice);
@@ -240,7 +261,7 @@ abstract class AbstractMapping {
}
if (!empty($fdnsSlice)) {
- $qb->orWhere($qb->expr()->in('ldap_dn', $qb->createNamedParameter($fdnsSlice, QueryBuilder::PARAM_STR_ARRAY)));
+ $qb->orWhere($qb->expr()->in('ldap_dn_hash', $qb->createNamedParameter($fdnsSlice, QueryBuilder::PARAM_STR_ARRAY)));
}
if ($slice % $maxSlices === 0) {
@@ -305,7 +326,7 @@ abstract class AbstractMapping {
* @throws \Exception
*/
public function getUUIDByDN($dn) {
- return $this->getXbyY('directory_uuid', 'ldap_dn', $dn);
+ return $this->getXbyY('directory_uuid', 'ldap_dn_hash', $this->getDNHash($dn));
}
/**
@@ -339,9 +360,9 @@ abstract class AbstractMapping {
* @return bool
*/
public function map($fdn, $name, $uuid) {
- if (mb_strlen($fdn) > 255) {
+ if (mb_strlen($fdn) > 4096) {
\OC::$server->getLogger()->error(
- 'Cannot map, because the DN exceeds 255 characters: {dn}',
+ 'Cannot map, because the DN exceeds 4096 characters: {dn}',
[
'app' => 'user_ldap',
'dn' => $fdn,
@@ -351,6 +372,7 @@ abstract class AbstractMapping {
}
$row = [
+ 'ldap_dn_hash' => $this->getDNHash($fdn),
'ldap_dn' => $fdn,
'owncloud_name' => $name,
'directory_uuid' => $uuid
@@ -438,7 +460,7 @@ abstract class AbstractMapping {
*/
public function count() {
$qb = $this->dbc->getQueryBuilder();
- $query = $qb->select($qb->func()->count('ldap_dn'))
+ $query = $qb->select($qb->func()->count('ldap_dn_hash'))
->from($this->getTableName());
$res = $query->execute();
$count = $res->fetchOne();
diff --git a/apps/user_ldap/lib/Migration/Version1010Date20200630192842.php b/apps/user_ldap/lib/Migration/Version1010Date20200630192842.php
index e2c78ed59f8..939db69a6ab 100644
--- a/apps/user_ldap/lib/Migration/Version1010Date20200630192842.php
+++ b/apps/user_ldap/lib/Migration/Version1010Date20200630192842.php
@@ -60,8 +60,13 @@ class Version1010Date20200630192842 extends SimpleMigrationStep {
'length' => 255,
'default' => '',
]);
+ $table->addColumn('ldap_dn_hash', Types::STRING, [
+ 'notnull' => false,
+ 'length' => 64,
+ ]);
$table->setPrimaryKey(['owncloud_name']);
- $table->addUniqueIndex(['ldap_dn'], 'ldap_dn_users');
+ $table->addUniqueIndex(['ldap_dn_hash'], 'ldap_user_dn_hashes');
+ $table->addUniqueIndex(['directory_uuid'], 'ldap_user_directory_uuid');
}
if (!$schema->hasTable('ldap_group_mapping')) {
@@ -81,8 +86,13 @@ class Version1010Date20200630192842 extends SimpleMigrationStep {
'length' => 255,
'default' => '',
]);
- $table->setPrimaryKey(['ldap_dn']);
- $table->addUniqueIndex(['owncloud_name'], 'owncloud_name_groups');
+ $table->addColumn('ldap_dn_hash', Types::STRING, [
+ 'notnull' => false,
+ 'length' => 64,
+ ]);
+ $table->setPrimaryKey(['owncloud_name']);
+ $table->addUniqueIndex(['ldap_dn_hash'], 'ldap_group_dn_hashes');
+ $table->addUniqueIndex(['directory_uuid'], 'ldap_group_directory_uuid');
}
if (!$schema->hasTable('ldap_group_members')) {
diff --git a/apps/user_ldap/lib/Migration/Version1120Date20210917155206.php b/apps/user_ldap/lib/Migration/Version1120Date20210917155206.php
index d46107733dc..3ab069679ef 100644
--- a/apps/user_ldap/lib/Migration/Version1120Date20210917155206.php
+++ b/apps/user_ldap/lib/Migration/Version1120Date20210917155206.php
@@ -70,19 +70,19 @@ class Version1120Date20210917155206 extends SimpleMigrationStep {
}
protected function handleIDs(string $table, bool $emitHooks) {
- $q = $this->getSelectQuery($table);
- $u = $this->getUpdateQuery($table);
+ $select = $this->getSelectQuery($table);
+ $update = $this->getUpdateQuery($table);
- $r = $q->executeQuery();
- while ($row = $r->fetch()) {
+ $result = $select->executeQuery();
+ while ($row = $result->fetch()) {
$newId = hash('sha256', $row['owncloud_name'], false);
if ($emitHooks) {
$this->emitUnassign($row['owncloud_name'], true);
}
- $u->setParameter('uuid', $row['directory_uuid']);
- $u->setParameter('newId', $newId);
+ $update->setParameter('uuid', $row['directory_uuid']);
+ $update->setParameter('newId', $newId);
try {
- $u->executeStatement();
+ $update->executeStatement();
if ($emitHooks) {
$this->emitUnassign($row['owncloud_name'], false);
$this->emitAssign($newId);
@@ -100,23 +100,23 @@ class Version1120Date20210917155206 extends SimpleMigrationStep {
);
}
}
- $r->closeCursor();
+ $result->closeCursor();
}
protected function getSelectQuery(string $table): IQueryBuilder {
- $q = $this->dbc->getQueryBuilder();
- $q->select('owncloud_name', 'directory_uuid')
+ $qb = $this->dbc->getQueryBuilder();
+ $qb->select('owncloud_name', 'directory_uuid')
->from($table)
- ->where($q->expr()->like('owncloud_name', $q->createNamedParameter(str_repeat('_', 65) . '%'), Types::STRING));
- return $q;
+ ->where($qb->expr()->like('owncloud_name', $qb->createNamedParameter(str_repeat('_', 65) . '%'), Types::STRING));
+ return $qb;
}
protected function getUpdateQuery(string $table): IQueryBuilder {
- $q = $this->dbc->getQueryBuilder();
- $q->update($table)
- ->set('owncloud_name', $q->createParameter('newId'))
- ->where($q->expr()->eq('directory_uuid', $q->createParameter('uuid')));
- return $q;
+ $qb = $this->dbc->getQueryBuilder();
+ $qb->update($table)
+ ->set('owncloud_name', $qb->createParameter('newId'))
+ ->where($qb->expr()->eq('directory_uuid', $qb->createParameter('uuid')));
+ return $qb;
}
protected function emitUnassign(string $oldId, bool $pre): void {
diff --git a/apps/user_ldap/lib/Migration/Version1130Date20211102154716.php b/apps/user_ldap/lib/Migration/Version1130Date20211102154716.php
new file mode 100644
index 00000000000..b79dbabd5a0
--- /dev/null
+++ b/apps/user_ldap/lib/Migration/Version1130Date20211102154716.php
@@ -0,0 +1,146 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OCA\User_LDAP\Migration;
+
+use Closure;
+use OCP\DB\Exception;
+use OCP\DB\ISchemaWrapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\DB\Types;
+use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+use Psr\Log\LoggerInterface;
+
+class Version1130Date20211102154716 extends SimpleMigrationStep {
+
+ /** @var IDBConnection */
+ private $dbc;
+ /** @var LoggerInterface */
+ private $logger;
+
+ public function __construct(IDBConnection $dbc, LoggerInterface $logger) {
+ $this->dbc = $dbc;
+ $this->logger = $logger;
+ }
+
+ public function getName() {
+ return 'Adjust LDAP user and group ldap_dn column lengths and add ldap_dn_hash columns';
+ }
+
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ $changeSchema = false;
+ foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
+ $table = $schema->getTable($tableName);
+ if (!$table->hasColumn('ldap_dn_hash')) {
+ $table->addColumn('ldap_dn_hash', Types::STRING, [
+ 'notnull' => false,
+ 'length' => 64,
+ ]);
+ $changeSchema = true;
+ }
+ $column = $table->getColumn('ldap_dn');
+ if ($column->getLength() < 4096) {
+ $column->setLength(4096);
+ $changeSchema = true;
+ }
+ if ($tableName === 'ldap_user_mapping') {
+ if ($table->hasIndex('ldap_dn_users')) {
+ $table->dropIndex('ldap_dn_users');
+ $changeSchema = true;
+ }
+ if (!$table->hasIndex('ldap_user_dn_hashes')) {
+ $table->addUniqueIndex(['ldap_dn_hash'], 'ldap_user_dn_hashes');
+ $changeSchema = true;
+ }
+ if (!$table->hasIndex('ldap_user_directory_uuid')) {
+ $table->addUniqueIndex(['directory_uuid'], 'ldap_user_directory_uuid');
+ $changeSchema = true;
+ }
+ } else {
+ if ($table->hasIndex('owncloud_name_groups')) {
+ $table->dropIndex('owncloud_name_groups');
+ $changeSchema = true;
+ }
+ if (!$table->hasIndex('ldap_group_dn_hashes')) {
+ $table->addUniqueIndex(['ldap_dn_hash'], 'ldap_group_dn_hashes');
+ $changeSchema = true;
+ }
+ if (!$table->hasIndex('ldap_group_directory_uuid')) {
+ $table->addUniqueIndex(['directory_uuid'], 'ldap_group_directory_uuid');
+ $changeSchema = true;
+ }
+ if (!$table->hasPrimaryKey() || ($table->getPrimaryKeyColumns() !== ['owncloud_name'])) {
+ $table->dropPrimaryKey();
+ $table->setPrimaryKey(['owncloud_name']);
+ $changeSchema = true;
+ }
+ }
+ }
+
+ return $changeSchema ? $schema : null;
+ }
+
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ */
+ public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
+ $this->handleDNHashes('ldap_group_mapping');
+ $this->handleDNHashes('ldap_user_mapping');
+ }
+
+ protected function handleDNHashes(string $table): void {
+ $select = $this->getSelectQuery($table);
+ $update = $this->getUpdateQuery($table);
+
+ $result = $select->executeQuery();
+ while ($row = $result->fetch()) {
+ $dnHash = hash('sha256', $row['ldap_dn'], false);
+ $update->setParameter('name', $row['owncloud_name']);
+ $update->setParameter('dn_hash', $dnHash);
+ try {
+ $update->executeStatement();
+ } catch (Exception $e) {
+ $this->logger->error('Failed to add hash "{dnHash}" ("{name}" of {table})',
+ [
+ 'app' => 'user_ldap',
+ 'name' => $row['owncloud_name'],
+ 'dnHash' => $dnHash,
+ 'table' => $table,
+ 'exception' => $e,
+ ]
+ );
+ }
+ }
+ $result->closeCursor();
+ }
+
+ protected function getSelectQuery(string $table): IQueryBuilder {
+ $qb = $this->dbc->getQueryBuilder();
+ $qb->select('owncloud_name', 'ldap_dn', 'ldap_dn_hash')
+ ->from($table)
+ ->where($qb->expr()->isNull('ldap_dn_hash'));
+ return $qb;
+ }
+
+ protected function getUpdateQuery(string $table): IQueryBuilder {
+ $qb = $this->dbc->getQueryBuilder();
+ $qb->update($table)
+ ->set('ldap_dn_hash', $qb->createParameter('dn_hash'))
+ ->where($qb->expr()->eq('owncloud_name', $qb->createParameter('name')));
+ return $qb;
+ }
+}