Skip to content

Commit 475a859

Browse files
authored
Merge pull request #31421 from nextcloud/fix/user_ldap-fix-ldap-connection-resets
user_ldap fix ldap connection resets
2 parents d9c0799 + df29acb commit 475a859

12 files changed

Lines changed: 189 additions & 247 deletions

File tree

apps/user_ldap/lib/Access.php

Lines changed: 69 additions & 133 deletions
Large diffs are not rendered by default.

apps/user_ldap/lib/Configuration.php

Lines changed: 29 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,23 @@ class Configuration {
4747
public const LDAP_SERVER_FEATURE_AVAILABLE = 'available';
4848
public const LDAP_SERVER_FEATURE_UNAVAILABLE = 'unavailable';
4949

50-
protected $configPrefix = null;
50+
/**
51+
* @var string
52+
*/
53+
protected $configPrefix;
54+
/**
55+
* @var bool
56+
*/
5157
protected $configRead = false;
5258
/**
5359
* @var string[] pre-filled with one reference key so that at least one entry is written on save request and
5460
* the config ID is registered
5561
*/
5662
protected $unsavedChanges = ['ldapConfigurationActive' => 'ldapConfigurationActive'];
5763

58-
//settings
64+
/**
65+
* @var array<string, mixed> settings
66+
*/
5967
protected $config = [
6068
'ldapHost' => null,
6169
'ldapPort' => null,
@@ -115,11 +123,7 @@ class Configuration {
115123
'ldapMatchingRuleInChainState' => self::LDAP_SERVER_FEATURE_UNKNOWN,
116124
];
117125

118-
/**
119-
* @param string $configPrefix
120-
* @param bool $autoRead
121-
*/
122-
public function __construct($configPrefix, $autoRead = true) {
126+
public function __construct(string $configPrefix, bool $autoRead = true) {
123127
$this->configPrefix = $configPrefix;
124128
if ($autoRead) {
125129
$this->readConfiguration();
@@ -145,10 +149,7 @@ public function __set($name, $value) {
145149
$this->setConfiguration([$name => $value]);
146150
}
147151

148-
/**
149-
* @return array
150-
*/
151-
public function getConfiguration() {
152+
public function getConfiguration(): array {
152153
return $this->config;
153154
}
154155

@@ -159,13 +160,8 @@ public function getConfiguration() {
159160
* @param array $config array that holds the config parameters in an associated
160161
* array
161162
* @param array &$applied optional; array where the set fields will be given to
162-
* @return false|null
163163
*/
164-
public function setConfiguration($config, &$applied = null) {
165-
if (!is_array($config)) {
166-
return false;
167-
}
168-
164+
public function setConfiguration(array $config, array &$applied = null): void {
169165
$cta = $this->getConfigTranslationArray();
170166
foreach ($config as $inputKey => $val) {
171167
if (strpos($inputKey, '_') !== false && array_key_exists($inputKey, $cta)) {
@@ -207,11 +203,10 @@ public function setConfiguration($config, &$applied = null) {
207203
}
208204
$this->unsavedChanges[$key] = $key;
209205
}
210-
return null;
211206
}
212207

213-
public function readConfiguration() {
214-
if (!$this->configRead && !is_null($this->configPrefix)) {
208+
public function readConfiguration(): void {
209+
if (!$this->configRead) {
215210
$cta = array_flip($this->getConfigTranslationArray());
216211
foreach ($this->config as $key => $val) {
217212
if (!isset($cta[$key])) {
@@ -260,7 +255,7 @@ public function readConfiguration() {
260255
/**
261256
* saves the current config changes in the database
262257
*/
263-
public function saveConfiguration() {
258+
public function saveConfiguration(): void {
264259
$cta = array_flip($this->getConfigTranslationArray());
265260
foreach ($this->unsavedChanges as $key) {
266261
$value = $this->config[$key];
@@ -293,7 +288,7 @@ public function saveConfiguration() {
293288
}
294289
$this->saveValue($cta[$key], $value);
295290
}
296-
$this->saveValue('_lastChange', time());
291+
$this->saveValue('_lastChange', (string)time());
297292
$this->unsavedChanges = [];
298293
}
299294

@@ -318,7 +313,7 @@ protected function getMultiLine($varName) {
318313
* @param string $varName name of config-key
319314
* @param array|string $value to set
320315
*/
321-
protected function setMultiLine($varName, $value) {
316+
protected function setMultiLine(string $varName, $value): void {
322317
if (empty($value)) {
323318
$value = '';
324319
} elseif (!is_array($value)) {
@@ -349,36 +344,20 @@ protected function setMultiLine($varName, $value) {
349344
$this->setRawValue($varName, $finalValue);
350345
}
351346

352-
/**
353-
* @param string $varName
354-
* @return string
355-
*/
356-
protected function getPwd($varName) {
347+
protected function getPwd(string $varName): string {
357348
return base64_decode($this->getValue($varName));
358349
}
359350

360-
/**
361-
* @param string $varName
362-
* @return string
363-
*/
364-
protected function getLcValue($varName) {
351+
protected function getLcValue(string $varName): string {
365352
return mb_strtolower($this->getValue($varName), 'UTF-8');
366353
}
367354

368-
/**
369-
* @param string $varName
370-
* @return string
371-
*/
372-
protected function getSystemValue($varName) {
355+
protected function getSystemValue(string $varName): string {
373356
//FIXME: if another system value is added, softcode the default value
374357
return \OC::$server->getConfig()->getSystemValue($varName, false);
375358
}
376359

377-
/**
378-
* @param string $varName
379-
* @return string
380-
*/
381-
protected function getValue($varName) {
360+
protected function getValue(string $varName): string {
382361
static $defaults;
383362
if (is_null($defaults)) {
384363
$defaults = $this->getDefaults();
@@ -394,7 +373,7 @@ protected function getValue($varName) {
394373
* @param string $varName name of config key
395374
* @param mixed $value to set
396375
*/
397-
protected function setValue($varName, $value) {
376+
protected function setValue(string $varName, $value): void {
398377
if (is_string($value)) {
399378
$value = trim($value);
400379
}
@@ -407,16 +386,11 @@ protected function setValue($varName, $value) {
407386
* @param string $varName name of config key
408387
* @param mixed $value to set
409388
*/
410-
protected function setRawValue($varName, $value) {
389+
protected function setRawValue(string $varName, $value): void {
411390
$this->config[$varName] = $value;
412391
}
413392

414-
/**
415-
* @param string $varName
416-
* @param string $value
417-
* @return bool
418-
*/
419-
protected function saveValue($varName, $value) {
393+
protected function saveValue(string $varName, string $value): bool {
420394
\OC::$server->getConfig()->setAppValue(
421395
'user_ldap',
422396
$this->configPrefix.$varName,
@@ -429,7 +403,7 @@ protected function saveValue($varName, $value) {
429403
* @return array an associative array with the default values. Keys are correspond
430404
* to config-value entries in the database table
431405
*/
432-
public function getDefaults() {
406+
public function getDefaults(): array {
433407
return [
434408
'ldap_host' => '',
435409
'ldap_port' => '',
@@ -492,7 +466,7 @@ public function getDefaults() {
492466
/**
493467
* @return array that maps internal variable names to database fields
494468
*/
495-
public function getConfigTranslationArray() {
469+
public function getConfigTranslationArray(): array {
496470
//TODO: merge them into one representation
497471
static $array = [
498472
'ldap_host' => 'ldapHost',
@@ -554,18 +528,16 @@ public function getConfigTranslationArray() {
554528
}
555529

556530
/**
557-
* @param string $rule
558-
* @return array
559531
* @throws \RuntimeException
560532
*/
561-
public function resolveRule($rule) {
533+
public function resolveRule(string $rule): array {
562534
if ($rule === 'avatar') {
563535
return $this->getAvatarAttributes();
564536
}
565537
throw new \RuntimeException('Invalid rule');
566538
}
567539

568-
public function getAvatarAttributes() {
540+
public function getAvatarAttributes(): array {
569541
$value = $this->ldapUserAvatarRule ?: self::AVATAR_PREFIX_DEFAULT;
570542
$defaultAttributes = ['jpegphoto', 'thumbnailphoto'];
571543

apps/user_ldap/lib/Connection.php

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,25 @@ class Connection extends LDAPUtility {
7878
* @var resource|\LDAP\Connection|null
7979
*/
8080
private $ldapConnectionRes = null;
81+
82+
/**
83+
* @var string
84+
*/
8185
private $configPrefix;
86+
87+
/**
88+
* @var ?string
89+
*/
8290
private $configID;
91+
92+
/**
93+
* @var bool
94+
*/
8395
private $configured = false;
84-
//whether connection should be kept on __destruct
96+
97+
/**
98+
* @var bool whether connection should be kept on __destruct
99+
*/
85100
private $dontDestruct = false;
86101

87102
/**
@@ -94,33 +109,42 @@ class Connection extends LDAPUtility {
94109
*/
95110
public $hasGidNumber = true;
96111

97-
//cache handler
98-
protected $cache;
112+
/**
113+
* @var \OCP\ICache|null
114+
*/
115+
protected $cache = null;
99116

100117
/** @var Configuration settings handler **/
101118
protected $configuration;
102119

120+
/**
121+
* @var bool
122+
*/
103123
protected $doNotValidate = false;
104124

125+
/**
126+
* @var bool
127+
*/
105128
protected $ignoreValidation = false;
106129

130+
/**
131+
* @var array{dn?: mixed, hash?: string, result?: bool}
132+
*/
107133
protected $bindResult = [];
108134

109135
/** @var LoggerInterface */
110136
protected $logger;
111137

112138
/**
113139
* Constructor
114-
* @param ILDAPWrapper $ldap
115140
* @param string $configPrefix a string with the prefix for the configkey column (appconfig table)
116141
* @param string|null $configID a string with the value for the appid column (appconfig table) or null for on-the-fly connections
117142
*/
118-
public function __construct(ILDAPWrapper $ldap, $configPrefix = '', $configID = 'user_ldap') {
143+
public function __construct(ILDAPWrapper $ldap, string $configPrefix = '', ?string $configID = 'user_ldap') {
119144
parent::__construct($ldap);
120145
$this->configPrefix = $configPrefix;
121146
$this->configID = $configID;
122-
$this->configuration = new Configuration($configPrefix,
123-
!is_null($configID));
147+
$this->configuration = new Configuration($configPrefix, !is_null($configID));
124148
$memcache = \OC::$server->getMemCacheFactory();
125149
if ($memcache->isAvailable()) {
126150
$this->cache = $memcache->createDistributed();
@@ -304,9 +328,9 @@ private function readConfiguration($force = false) {
304328
* set LDAP configuration with values delivered by an array, not read from configuration
305329
* @param array $config array that holds the config parameters in an associated array
306330
* @param array &$setParameters optional; array where the set fields will be given to
307-
* @return boolean true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
331+
* @return bool true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
308332
*/
309-
public function setConfiguration($config, &$setParameters = null) {
333+
public function setConfiguration($config, &$setParameters = null): bool {
310334
if (is_null($setParameters)) {
311335
$setParameters = [];
312336
}

apps/user_ldap/lib/Group_LDAP.php

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -863,20 +863,18 @@ private function getGroupsByMember(string $dn, array &$seen = null): array {
863863

864864
$groups = $this->access->fetchListOfGroups($filter,
865865
[strtolower($this->access->connection->ldapGroupMemberAssocAttr), $this->access->connection->ldapGroupDisplayName, 'dn']);
866-
if (is_array($groups)) {
867-
$fetcher = function ($dn) use (&$seen) {
868-
if (is_array($dn) && isset($dn['dn'][0])) {
869-
$dn = $dn['dn'][0];
870-
}
871-
return $this->getGroupsByMember($dn, $seen);
872-
};
873-
874-
if (empty($dn)) {
875-
$dn = "";
866+
$fetcher = function ($dn) use (&$seen) {
867+
if (is_array($dn) && isset($dn['dn'][0])) {
868+
$dn = $dn['dn'][0];
876869
}
870+
return $this->getGroupsByMember($dn, $seen);
871+
};
877872

878-
$allGroups = $this->walkNestedGroups($dn, $fetcher, $groups, $seen);
873+
if (empty($dn)) {
874+
$dn = "";
879875
}
876+
877+
$allGroups = $this->walkNestedGroups($dn, $fetcher, $groups, $seen);
880878
$visibleGroups = $this->filterValidGroups($allGroups);
881879
return array_intersect_key($allGroups, $visibleGroups);
882880
}
@@ -1349,7 +1347,7 @@ public function getDisplayName(string $gid): string {
13491347
$this->access->groupname2dn($gid),
13501348
$this->access->connection->ldapGroupDisplayName);
13511349

1352-
if ($displayName && (count($displayName) > 0)) {
1350+
if (($displayName !== false) && (count($displayName) > 0)) {
13531351
$displayName = $displayName[0];
13541352
$this->access->connection->writeToCache($cacheKey, $displayName);
13551353
return $displayName;

apps/user_ldap/lib/ILDAPWrapper.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function controlPagedResult($link, $pageSize, $isCritical);
6666
* Retrieve the LDAP pagination cookie
6767
* @param resource|\LDAP\Connection $link LDAP link resource
6868
* @param resource|\LDAP\Result $result LDAP result resource
69-
* @param string $cookie structure sent by LDAP server
69+
* @param string &$cookie structure sent by LDAP server
7070
* @return bool true on success, false otherwise
7171
*
7272
* Corresponds to ldap_control_paged_result_response
@@ -178,8 +178,8 @@ public function modReplace($link, $userDN, $password);
178178
/**
179179
* Sets the value of the specified option to be $value
180180
* @param resource|\LDAP\Connection $link LDAP link resource
181-
* @param string $option a defined LDAP Server option
182-
* @param int $value the new value for the option
181+
* @param int $option a defined LDAP Server option
182+
* @param mixed $value the new value for the option
183183
* @return bool true on success, false otherwise
184184
*/
185185
public function setOption($link, $option, $value);

apps/user_ldap/lib/Mapping/AbstractMapping.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,9 @@ public function getListOfIdsByDn(array $fdns): array {
280280
/**
281281
* Searches mapped names by the giving string in the name column
282282
*
283-
* @param string $search
284-
* @param string $prefixMatch
285-
* @param string $postfixMatch
286283
* @return string[]
287284
*/
288-
public function getNamesBySearch($search, $prefixMatch = "", $postfixMatch = "") {
285+
public function getNamesBySearch(string $search, string $prefixMatch = "", string $postfixMatch = ""): array {
289286
$statement = $this->dbc->prepare('
290287
SELECT `owncloud_name`
291288
FROM `' . $this->getTableName() . '`

apps/user_ldap/lib/User/User.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ public function getUsername() {
266266

267267
/**
268268
* returns the home directory of the user if specified by LDAP settings
269-
* @param string $valueFromLDAP
270-
* @return bool|string
269+
* @param ?string $valueFromLDAP
270+
* @return false|string
271271
* @throws \Exception
272272
*/
273273
public function getHomePath($valueFromLDAP = null) {
@@ -278,8 +278,7 @@ public function getHomePath($valueFromLDAP = null) {
278278
&& strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
279279
&& $this->access->connection->homeFolderNamingRule !== 'attr:') {
280280
$attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
281-
$homedir = $this->access->readAttribute(
282-
$this->access->username2dn($this->getUsername()), $attr);
281+
$homedir = $this->access->readAttribute($this->access->username2dn($this->getUsername()), $attr);
283282
if ($homedir && isset($homedir[0])) {
284283
$path = $homedir[0];
285284
}

0 commit comments

Comments
 (0)