Completed
Pull Request — master (#10031)
by Blizzz
18:14 queued 01:24
created
apps/user_ldap/lib/Connection.php 2 patches
Indentation   +614 added lines, -614 removed lines patch added patch discarded remove patch
@@ -59,619 +59,619 @@
 block discarded – undo
59 59
  * @property string ldapExpertUUIDGroupAttr
60 60
  */
61 61
 class Connection extends LDAPUtility {
62
-	private $ldapConnectionRes = null;
63
-	private $configPrefix;
64
-	private $configID;
65
-	private $configured = false;
66
-	private $hasPagedResultSupport = true;
67
-	//whether connection should be kept on __destruct
68
-	private $dontDestruct = false;
69
-
70
-	/**
71
-	 * @var bool runtime flag that indicates whether supported primary groups are available
72
-	 */
73
-	public $hasPrimaryGroups = true;
74
-
75
-	/**
76
-	 * @var bool runtime flag that indicates whether supported POSIX gidNumber are available
77
-	 */
78
-	public $hasGidNumber = true;
79
-
80
-	//cache handler
81
-	protected $cache;
82
-
83
-	/** @var Configuration settings handler **/
84
-	protected $configuration;
85
-
86
-	protected $doNotValidate = false;
87
-
88
-	protected $ignoreValidation = false;
89
-
90
-	protected $bindResult = [];
91
-
92
-	/**
93
-	 * Constructor
94
-	 * @param ILDAPWrapper $ldap
95
-	 * @param string $configPrefix a string with the prefix for the configkey column (appconfig table)
96
-	 * @param string|null $configID a string with the value for the appid column (appconfig table) or null for on-the-fly connections
97
-	 */
98
-	public function __construct(ILDAPWrapper $ldap, $configPrefix = '', $configID = 'user_ldap') {
99
-		parent::__construct($ldap);
100
-		$this->configPrefix = $configPrefix;
101
-		$this->configID = $configID;
102
-		$this->configuration = new Configuration($configPrefix,
103
-												 !is_null($configID));
104
-		$memcache = \OC::$server->getMemCacheFactory();
105
-		if($memcache->isAvailable()) {
106
-			$this->cache = $memcache->createDistributed();
107
-		}
108
-		$helper = new Helper(\OC::$server->getConfig());
109
-		$this->doNotValidate = !in_array($this->configPrefix,
110
-			$helper->getServerConfigurationPrefixes());
111
-		$this->hasPagedResultSupport =
112
-			(int)$this->configuration->ldapPagingSize !== 0
113
-			|| $this->ldap->hasPagedResultSupport();
114
-	}
115
-
116
-	public function __destruct() {
117
-		if(!$this->dontDestruct && $this->ldap->isResource($this->ldapConnectionRes)) {
118
-			@$this->ldap->unbind($this->ldapConnectionRes);
119
-			$this->bindResult = [];
120
-		}
121
-	}
122
-
123
-	/**
124
-	 * defines behaviour when the instance is cloned
125
-	 */
126
-	public function __clone() {
127
-		$this->configuration = new Configuration($this->configPrefix,
128
-												 !is_null($this->configID));
129
-		if(count($this->bindResult) !== 0 && $this->bindResult['result'] === true) {
130
-			$this->bindResult = [];
131
-		}
132
-		$this->ldapConnectionRes = null;
133
-		$this->dontDestruct = true;
134
-	}
135
-
136
-	/**
137
-	 * @param string $name
138
-	 * @return bool|mixed
139
-	 */
140
-	public function __get($name) {
141
-		if(!$this->configured) {
142
-			$this->readConfiguration();
143
-		}
144
-
145
-		if($name === 'hasPagedResultSupport') {
146
-			return $this->hasPagedResultSupport;
147
-		}
148
-
149
-		return $this->configuration->$name;
150
-	}
151
-
152
-	/**
153
-	 * @param string $name
154
-	 * @param mixed $value
155
-	 */
156
-	public function __set($name, $value) {
157
-		$this->doNotValidate = false;
158
-		$before = $this->configuration->$name;
159
-		$this->configuration->$name = $value;
160
-		$after = $this->configuration->$name;
161
-		if($before !== $after) {
162
-			if ($this->configID !== '' && $this->configID !== null) {
163
-				$this->configuration->saveConfiguration();
164
-			}
165
-			$this->validateConfiguration();
166
-		}
167
-	}
168
-
169
-	/**
170
-	 * sets whether the result of the configuration validation shall
171
-	 * be ignored when establishing the connection. Used by the Wizard
172
-	 * in early configuration state.
173
-	 * @param bool $state
174
-	 */
175
-	public function setIgnoreValidation($state) {
176
-		$this->ignoreValidation = (bool)$state;
177
-	}
178
-
179
-	/**
180
-	 * initializes the LDAP backend
181
-	 * @param bool $force read the config settings no matter what
182
-	 */
183
-	public function init($force = false) {
184
-		$this->readConfiguration($force);
185
-		$this->establishConnection();
186
-	}
187
-
188
-	/**
189
-	 * Returns the LDAP handler
190
-	 */
191
-	public function getConnectionResource() {
192
-		if(!$this->ldapConnectionRes) {
193
-			$this->init();
194
-		} else if(!$this->ldap->isResource($this->ldapConnectionRes)) {
195
-			$this->ldapConnectionRes = null;
196
-			$this->establishConnection();
197
-		}
198
-		if(is_null($this->ldapConnectionRes)) {
199
-			\OCP\Util::writeLog('user_ldap', 'No LDAP Connection to server ' . $this->configuration->ldapHost, ILogger::ERROR);
200
-			throw new ServerNotAvailableException('Connection to LDAP server could not be established');
201
-		}
202
-		return $this->ldapConnectionRes;
203
-	}
204
-
205
-	/**
206
-	 * resets the connection resource
207
-	 */
208
-	public function resetConnectionResource() {
209
-		if(!is_null($this->ldapConnectionRes)) {
210
-			@$this->ldap->unbind($this->ldapConnectionRes);
211
-			$this->ldapConnectionRes = null;
212
-			$this->bindResult = [];
213
-		}
214
-	}
215
-
216
-	/**
217
-	 * @param string|null $key
218
-	 * @return string
219
-	 */
220
-	private function getCacheKey($key) {
221
-		$prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-';
222
-		if(is_null($key)) {
223
-			return $prefix;
224
-		}
225
-		return $prefix.hash('sha256', $key);
226
-	}
227
-
228
-	/**
229
-	 * @param string $key
230
-	 * @return mixed|null
231
-	 */
232
-	public function getFromCache($key) {
233
-		if(!$this->configured) {
234
-			$this->readConfiguration();
235
-		}
236
-		if(is_null($this->cache) || !$this->configuration->ldapCacheTTL) {
237
-			return null;
238
-		}
239
-		$key = $this->getCacheKey($key);
240
-
241
-		return json_decode(base64_decode($this->cache->get($key)), true);
242
-	}
243
-
244
-	/**
245
-	 * @param string $key
246
-	 * @param mixed $value
247
-	 *
248
-	 * @return string
249
-	 */
250
-	public function writeToCache($key, $value) {
251
-		if(!$this->configured) {
252
-			$this->readConfiguration();
253
-		}
254
-		if(is_null($this->cache)
255
-			|| !$this->configuration->ldapCacheTTL
256
-			|| !$this->configuration->ldapConfigurationActive) {
257
-			return null;
258
-		}
259
-		$key   = $this->getCacheKey($key);
260
-		$value = base64_encode(json_encode($value));
261
-		$this->cache->set($key, $value, $this->configuration->ldapCacheTTL);
262
-	}
263
-
264
-	public function clearCache() {
265
-		if(!is_null($this->cache)) {
266
-			$this->cache->clear($this->getCacheKey(null));
267
-		}
268
-	}
269
-
270
-	/**
271
-	 * Caches the general LDAP configuration.
272
-	 * @param bool $force optional. true, if the re-read should be forced. defaults
273
-	 * to false.
274
-	 * @return null
275
-	 */
276
-	private function readConfiguration($force = false) {
277
-		if((!$this->configured || $force) && !is_null($this->configID)) {
278
-			$this->configuration->readConfiguration();
279
-			$this->configured = $this->validateConfiguration();
280
-		}
281
-	}
282
-
283
-	/**
284
-	 * set LDAP configuration with values delivered by an array, not read from configuration
285
-	 * @param array $config array that holds the config parameters in an associated array
286
-	 * @param array &$setParameters optional; array where the set fields will be given to
287
-	 * @return boolean true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
288
-	 */
289
-	public function setConfiguration($config, &$setParameters = null) {
290
-		if(is_null($setParameters)) {
291
-			$setParameters = array();
292
-		}
293
-		$this->doNotValidate = false;
294
-		$this->configuration->setConfiguration($config, $setParameters);
295
-		if(count($setParameters) > 0) {
296
-			$this->configured = $this->validateConfiguration();
297
-		}
298
-
299
-
300
-		return $this->configured;
301
-	}
302
-
303
-	/**
304
-	 * saves the current Configuration in the database and empties the
305
-	 * cache
306
-	 * @return null
307
-	 */
308
-	public function saveConfiguration() {
309
-		$this->configuration->saveConfiguration();
310
-		$this->clearCache();
311
-	}
312
-
313
-	/**
314
-	 * get the current LDAP configuration
315
-	 * @return array
316
-	 */
317
-	public function getConfiguration() {
318
-		$this->readConfiguration();
319
-		$config = $this->configuration->getConfiguration();
320
-		$cta = $this->configuration->getConfigTranslationArray();
321
-		$result = array();
322
-		foreach($cta as $dbkey => $configkey) {
323
-			switch($configkey) {
324
-				case 'homeFolderNamingRule':
325
-					if(strpos($config[$configkey], 'attr:') === 0) {
326
-						$result[$dbkey] = substr($config[$configkey], 5);
327
-					} else {
328
-						$result[$dbkey] = '';
329
-					}
330
-					break;
331
-				case 'ldapBase':
332
-				case 'ldapBaseUsers':
333
-				case 'ldapBaseGroups':
334
-				case 'ldapAttributesForUserSearch':
335
-				case 'ldapAttributesForGroupSearch':
336
-					if(is_array($config[$configkey])) {
337
-						$result[$dbkey] = implode("\n", $config[$configkey]);
338
-						break;
339
-					} //else follows default
340
-				default:
341
-					$result[$dbkey] = $config[$configkey];
342
-			}
343
-		}
344
-		return $result;
345
-	}
346
-
347
-	private function doSoftValidation() {
348
-		//if User or Group Base are not set, take over Base DN setting
349
-		foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) {
350
-			$val = $this->configuration->$keyBase;
351
-			if(empty($val)) {
352
-				$this->configuration->$keyBase = $this->configuration->ldapBase;
353
-			}
354
-		}
355
-
356
-		foreach(array('ldapExpertUUIDUserAttr'  => 'ldapUuidUserAttribute',
357
-					  'ldapExpertUUIDGroupAttr' => 'ldapUuidGroupAttribute')
358
-				as $expertSetting => $effectiveSetting) {
359
-			$uuidOverride = $this->configuration->$expertSetting;
360
-			if(!empty($uuidOverride)) {
361
-				$this->configuration->$effectiveSetting = $uuidOverride;
362
-			} else {
363
-				$uuidAttributes = Access::UUID_ATTRIBUTES;
364
-				array_unshift($uuidAttributes, 'auto');
365
-				if(!in_array($this->configuration->$effectiveSetting,
366
-							$uuidAttributes)
367
-					&& (!is_null($this->configID))) {
368
-					$this->configuration->$effectiveSetting = 'auto';
369
-					$this->configuration->saveConfiguration();
370
-					\OCP\Util::writeLog('user_ldap',
371
-										'Illegal value for the '.
372
-										$effectiveSetting.', '.'reset to '.
373
-										'autodetect.', ILogger::INFO);
374
-				}
375
-
376
-			}
377
-		}
378
-
379
-		$backupPort = (int)$this->configuration->ldapBackupPort;
380
-		if ($backupPort <= 0) {
381
-			$this->configuration->backupPort = $this->configuration->ldapPort;
382
-		}
383
-
384
-		//make sure empty search attributes are saved as simple, empty array
385
-		$saKeys = array('ldapAttributesForUserSearch',
386
-						'ldapAttributesForGroupSearch');
387
-		foreach($saKeys as $key) {
388
-			$val = $this->configuration->$key;
389
-			if(is_array($val) && count($val) === 1 && empty($val[0])) {
390
-				$this->configuration->$key = array();
391
-			}
392
-		}
393
-
394
-		if((stripos($this->configuration->ldapHost, 'ldaps://') === 0)
395
-			&& $this->configuration->ldapTLS) {
396
-			$this->configuration->ldapTLS = false;
397
-			\OCP\Util::writeLog(
398
-				'user_ldap',
399
-				'LDAPS (already using secure connection) and TLS do not work together. Switched off TLS.',
400
-				ILogger::INFO
401
-			);
402
-		}
403
-	}
404
-
405
-	/**
406
-	 * @return bool
407
-	 */
408
-	private function doCriticalValidation() {
409
-		$configurationOK = true;
410
-		$errorStr = 'Configuration Error (prefix '.
411
-			(string)$this->configPrefix .'): ';
412
-
413
-		//options that shall not be empty
414
-		$options = array('ldapHost', 'ldapPort', 'ldapUserDisplayName',
415
-						 'ldapGroupDisplayName', 'ldapLoginFilter');
416
-		foreach($options as $key) {
417
-			$val = $this->configuration->$key;
418
-			if(empty($val)) {
419
-				switch($key) {
420
-					case 'ldapHost':
421
-						$subj = 'LDAP Host';
422
-						break;
423
-					case 'ldapPort':
424
-						$subj = 'LDAP Port';
425
-						break;
426
-					case 'ldapUserDisplayName':
427
-						$subj = 'LDAP User Display Name';
428
-						break;
429
-					case 'ldapGroupDisplayName':
430
-						$subj = 'LDAP Group Display Name';
431
-						break;
432
-					case 'ldapLoginFilter':
433
-						$subj = 'LDAP Login Filter';
434
-						break;
435
-					default:
436
-						$subj = $key;
437
-						break;
438
-				}
439
-				$configurationOK = false;
440
-				\OCP\Util::writeLog(
441
-					'user_ldap',
442
-					$errorStr.'No '.$subj.' given!',
443
-					ILogger::WARN
444
-				);
445
-			}
446
-		}
447
-
448
-		//combinations
449
-		$agent = $this->configuration->ldapAgentName;
450
-		$pwd = $this->configuration->ldapAgentPassword;
451
-		if (
452
-			($agent === ''  && $pwd !== '')
453
-			|| ($agent !== '' && $pwd === '')
454
-		) {
455
-			\OCP\Util::writeLog(
456
-				'user_ldap',
457
-				$errorStr.'either no password is given for the user ' .
458
-					'agent or a password is given, but not an LDAP agent.',
459
-				ILogger::WARN);
460
-			$configurationOK = false;
461
-		}
462
-
463
-		$base = $this->configuration->ldapBase;
464
-		$baseUsers = $this->configuration->ldapBaseUsers;
465
-		$baseGroups = $this->configuration->ldapBaseGroups;
466
-
467
-		if(empty($base) && empty($baseUsers) && empty($baseGroups)) {
468
-			\OCP\Util::writeLog(
469
-				'user_ldap',
470
-				$errorStr.'Not a single Base DN given.',
471
-				ILogger::WARN
472
-			);
473
-			$configurationOK = false;
474
-		}
475
-
476
-		if(mb_strpos($this->configuration->ldapLoginFilter, '%uid', 0, 'UTF-8')
477
-		   === false) {
478
-			\OCP\Util::writeLog(
479
-				'user_ldap',
480
-				$errorStr.'login filter does not contain %uid place holder.',
481
-				ILogger::WARN
482
-			);
483
-			$configurationOK = false;
484
-		}
485
-
486
-		return $configurationOK;
487
-	}
488
-
489
-	/**
490
-	 * Validates the user specified configuration
491
-	 * @return bool true if configuration seems OK, false otherwise
492
-	 */
493
-	private function validateConfiguration() {
494
-
495
-		if($this->doNotValidate) {
496
-			//don't do a validation if it is a new configuration with pure
497
-			//default values. Will be allowed on changes via __set or
498
-			//setConfiguration
499
-			return false;
500
-		}
501
-
502
-		// first step: "soft" checks: settings that are not really
503
-		// necessary, but advisable. If left empty, give an info message
504
-		$this->doSoftValidation();
505
-
506
-		//second step: critical checks. If left empty or filled wrong, mark as
507
-		//not configured and give a warning.
508
-		return $this->doCriticalValidation();
509
-	}
510
-
511
-
512
-	/**
513
-	 * Connects and Binds to LDAP
514
-	 *
515
-	 * @throws ServerNotAvailableException
516
-	 */
517
-	private function establishConnection() {
518
-		if(!$this->configuration->ldapConfigurationActive) {
519
-			return null;
520
-		}
521
-		static $phpLDAPinstalled = true;
522
-		if(!$phpLDAPinstalled) {
523
-			return false;
524
-		}
525
-		if(!$this->ignoreValidation && !$this->configured) {
526
-			\OCP\Util::writeLog(
527
-				'user_ldap',
528
-				'Configuration is invalid, cannot connect',
529
-				ILogger::WARN
530
-			);
531
-			return false;
532
-		}
533
-		if(!$this->ldapConnectionRes) {
534
-			if(!$this->ldap->areLDAPFunctionsAvailable()) {
535
-				$phpLDAPinstalled = false;
536
-				\OCP\Util::writeLog(
537
-					'user_ldap',
538
-					'function ldap_connect is not available. Make sure that the PHP ldap module is installed.',
539
-					ILogger::ERROR
540
-				);
541
-
542
-				return false;
543
-			}
544
-			if($this->configuration->turnOffCertCheck) {
545
-				if(putenv('LDAPTLS_REQCERT=never')) {
546
-					\OCP\Util::writeLog('user_ldap',
547
-						'Turned off SSL certificate validation successfully.',
548
-						ILogger::DEBUG);
549
-				} else {
550
-					\OCP\Util::writeLog(
551
-						'user_ldap',
552
-						'Could not turn off SSL certificate validation.',
553
-						ILogger::WARN
554
-					);
555
-				}
556
-			}
557
-
558
-			$isOverrideMainServer = ($this->configuration->ldapOverrideMainServer
559
-				|| $this->getFromCache('overrideMainServer'));
560
-			$isBackupHost = (trim($this->configuration->ldapBackupHost) !== "");
561
-			$bindStatus = false;
562
-			try {
563
-				if (!$isOverrideMainServer) {
564
-					$this->doConnect($this->configuration->ldapHost,
565
-						$this->configuration->ldapPort);
566
-				}
567
-				return $this->bind();
568
-			} catch (ServerNotAvailableException $e) {
569
-				if(!$isBackupHost) {
570
-					throw $e;
571
-				}
572
-			}
573
-
574
-			//if LDAP server is not reachable, try the Backup (Replica!) Server
575
-			if($isBackupHost || $isOverrideMainServer) {
576
-				$this->doConnect($this->configuration->ldapBackupHost,
577
-								 $this->configuration->ldapBackupPort);
578
-				$this->bindResult = [];
579
-				$bindStatus = $this->bind();
580
-				$error = $this->ldap->isResource($this->ldapConnectionRes) ?
581
-					$this->ldap->errno($this->ldapConnectionRes) : -1;
582
-				if($bindStatus && $error === 0 && !$this->getFromCache('overrideMainServer')) {
583
-					//when bind to backup server succeeded and failed to main server,
584
-					//skip contacting him until next cache refresh
585
-					$this->writeToCache('overrideMainServer', true);
586
-				}
587
-			}
588
-
589
-			return $bindStatus;
590
-		}
591
-		return null;
592
-	}
593
-
594
-	/**
595
-	 * @param string $host
596
-	 * @param string $port
597
-	 * @return bool
598
-	 * @throws \OC\ServerNotAvailableException
599
-	 */
600
-	private function doConnect($host, $port) {
601
-		if ($host === '') {
602
-			return false;
603
-		}
604
-
605
-		$this->ldapConnectionRes = $this->ldap->connect($host, $port);
606
-
607
-		if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
608
-			throw new ServerNotAvailableException('Could not set required LDAP Protocol version.');
609
-		}
610
-
611
-		if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
612
-			throw new ServerNotAvailableException('Could not disable LDAP referrals.');
613
-		}
614
-
615
-		if($this->configuration->ldapTLS) {
616
-			if(!$this->ldap->startTls($this->ldapConnectionRes)) {
617
-				throw new ServerNotAvailableException('Start TLS failed, when connecting to LDAP host ' . $host . '.');
618
-			}
619
-		}
620
-
621
-		return true;
622
-	}
623
-
624
-	/**
625
-	 * Binds to LDAP
626
-	 */
627
-	public function bind() {
628
-		if(!$this->configuration->ldapConfigurationActive) {
629
-			return false;
630
-		}
631
-		$cr = $this->ldapConnectionRes;
632
-		if(!$this->ldap->isResource($cr)) {
633
-			$cr = $this->getConnectionResource();
634
-		}
635
-
636
-		if(
637
-			count($this->bindResult) !== 0
638
-			&& $this->bindResult['dn'] === $this->configuration->ldapAgentName
639
-			&& \OC::$server->getHasher()->verify(
640
-				$this->configPrefix . $this->configuration->ldapAgentPassword,
641
-				$this->bindResult['hash']
642
-			)
643
-		) {
644
-			// don't attempt to bind again with the same data as before
645
-			// bind might have been invoked via getConnectionResource(),
646
-			// but we need results specifically for e.g. user login
647
-			return $this->bindResult['result'];
648
-		}
649
-
650
-		$ldapLogin = @$this->ldap->bind($cr,
651
-										$this->configuration->ldapAgentName,
652
-										$this->configuration->ldapAgentPassword);
653
-
654
-		$this->bindResult = [
655
-			'dn' => $this->configuration->ldapAgentName,
656
-			'hash' => \OC::$server->getHasher()->hash($this->configPrefix . $this->configuration->ldapAgentPassword),
657
-			'result' => $ldapLogin,
658
-		];
659
-
660
-		if(!$ldapLogin) {
661
-			$errno = $this->ldap->errno($cr);
662
-
663
-			\OCP\Util::writeLog('user_ldap',
664
-				'Bind failed: ' . $errno . ': ' . $this->ldap->error($cr),
665
-				ILogger::WARN);
666
-
667
-			// Set to failure mode, if LDAP error code is not LDAP_SUCCESS or LDAP_INVALID_CREDENTIALS
668
-			if($errno !== 0x00 && $errno !== 0x31) {
669
-				$this->ldapConnectionRes = null;
670
-			}
671
-
672
-			return false;
673
-		}
674
-		return true;
675
-	}
62
+    private $ldapConnectionRes = null;
63
+    private $configPrefix;
64
+    private $configID;
65
+    private $configured = false;
66
+    private $hasPagedResultSupport = true;
67
+    //whether connection should be kept on __destruct
68
+    private $dontDestruct = false;
69
+
70
+    /**
71
+     * @var bool runtime flag that indicates whether supported primary groups are available
72
+     */
73
+    public $hasPrimaryGroups = true;
74
+
75
+    /**
76
+     * @var bool runtime flag that indicates whether supported POSIX gidNumber are available
77
+     */
78
+    public $hasGidNumber = true;
79
+
80
+    //cache handler
81
+    protected $cache;
82
+
83
+    /** @var Configuration settings handler **/
84
+    protected $configuration;
85
+
86
+    protected $doNotValidate = false;
87
+
88
+    protected $ignoreValidation = false;
89
+
90
+    protected $bindResult = [];
91
+
92
+    /**
93
+     * Constructor
94
+     * @param ILDAPWrapper $ldap
95
+     * @param string $configPrefix a string with the prefix for the configkey column (appconfig table)
96
+     * @param string|null $configID a string with the value for the appid column (appconfig table) or null for on-the-fly connections
97
+     */
98
+    public function __construct(ILDAPWrapper $ldap, $configPrefix = '', $configID = 'user_ldap') {
99
+        parent::__construct($ldap);
100
+        $this->configPrefix = $configPrefix;
101
+        $this->configID = $configID;
102
+        $this->configuration = new Configuration($configPrefix,
103
+                                                    !is_null($configID));
104
+        $memcache = \OC::$server->getMemCacheFactory();
105
+        if($memcache->isAvailable()) {
106
+            $this->cache = $memcache->createDistributed();
107
+        }
108
+        $helper = new Helper(\OC::$server->getConfig());
109
+        $this->doNotValidate = !in_array($this->configPrefix,
110
+            $helper->getServerConfigurationPrefixes());
111
+        $this->hasPagedResultSupport =
112
+            (int)$this->configuration->ldapPagingSize !== 0
113
+            || $this->ldap->hasPagedResultSupport();
114
+    }
115
+
116
+    public function __destruct() {
117
+        if(!$this->dontDestruct && $this->ldap->isResource($this->ldapConnectionRes)) {
118
+            @$this->ldap->unbind($this->ldapConnectionRes);
119
+            $this->bindResult = [];
120
+        }
121
+    }
122
+
123
+    /**
124
+     * defines behaviour when the instance is cloned
125
+     */
126
+    public function __clone() {
127
+        $this->configuration = new Configuration($this->configPrefix,
128
+                                                    !is_null($this->configID));
129
+        if(count($this->bindResult) !== 0 && $this->bindResult['result'] === true) {
130
+            $this->bindResult = [];
131
+        }
132
+        $this->ldapConnectionRes = null;
133
+        $this->dontDestruct = true;
134
+    }
135
+
136
+    /**
137
+     * @param string $name
138
+     * @return bool|mixed
139
+     */
140
+    public function __get($name) {
141
+        if(!$this->configured) {
142
+            $this->readConfiguration();
143
+        }
144
+
145
+        if($name === 'hasPagedResultSupport') {
146
+            return $this->hasPagedResultSupport;
147
+        }
148
+
149
+        return $this->configuration->$name;
150
+    }
151
+
152
+    /**
153
+     * @param string $name
154
+     * @param mixed $value
155
+     */
156
+    public function __set($name, $value) {
157
+        $this->doNotValidate = false;
158
+        $before = $this->configuration->$name;
159
+        $this->configuration->$name = $value;
160
+        $after = $this->configuration->$name;
161
+        if($before !== $after) {
162
+            if ($this->configID !== '' && $this->configID !== null) {
163
+                $this->configuration->saveConfiguration();
164
+            }
165
+            $this->validateConfiguration();
166
+        }
167
+    }
168
+
169
+    /**
170
+     * sets whether the result of the configuration validation shall
171
+     * be ignored when establishing the connection. Used by the Wizard
172
+     * in early configuration state.
173
+     * @param bool $state
174
+     */
175
+    public function setIgnoreValidation($state) {
176
+        $this->ignoreValidation = (bool)$state;
177
+    }
178
+
179
+    /**
180
+     * initializes the LDAP backend
181
+     * @param bool $force read the config settings no matter what
182
+     */
183
+    public function init($force = false) {
184
+        $this->readConfiguration($force);
185
+        $this->establishConnection();
186
+    }
187
+
188
+    /**
189
+     * Returns the LDAP handler
190
+     */
191
+    public function getConnectionResource() {
192
+        if(!$this->ldapConnectionRes) {
193
+            $this->init();
194
+        } else if(!$this->ldap->isResource($this->ldapConnectionRes)) {
195
+            $this->ldapConnectionRes = null;
196
+            $this->establishConnection();
197
+        }
198
+        if(is_null($this->ldapConnectionRes)) {
199
+            \OCP\Util::writeLog('user_ldap', 'No LDAP Connection to server ' . $this->configuration->ldapHost, ILogger::ERROR);
200
+            throw new ServerNotAvailableException('Connection to LDAP server could not be established');
201
+        }
202
+        return $this->ldapConnectionRes;
203
+    }
204
+
205
+    /**
206
+     * resets the connection resource
207
+     */
208
+    public function resetConnectionResource() {
209
+        if(!is_null($this->ldapConnectionRes)) {
210
+            @$this->ldap->unbind($this->ldapConnectionRes);
211
+            $this->ldapConnectionRes = null;
212
+            $this->bindResult = [];
213
+        }
214
+    }
215
+
216
+    /**
217
+     * @param string|null $key
218
+     * @return string
219
+     */
220
+    private function getCacheKey($key) {
221
+        $prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-';
222
+        if(is_null($key)) {
223
+            return $prefix;
224
+        }
225
+        return $prefix.hash('sha256', $key);
226
+    }
227
+
228
+    /**
229
+     * @param string $key
230
+     * @return mixed|null
231
+     */
232
+    public function getFromCache($key) {
233
+        if(!$this->configured) {
234
+            $this->readConfiguration();
235
+        }
236
+        if(is_null($this->cache) || !$this->configuration->ldapCacheTTL) {
237
+            return null;
238
+        }
239
+        $key = $this->getCacheKey($key);
240
+
241
+        return json_decode(base64_decode($this->cache->get($key)), true);
242
+    }
243
+
244
+    /**
245
+     * @param string $key
246
+     * @param mixed $value
247
+     *
248
+     * @return string
249
+     */
250
+    public function writeToCache($key, $value) {
251
+        if(!$this->configured) {
252
+            $this->readConfiguration();
253
+        }
254
+        if(is_null($this->cache)
255
+            || !$this->configuration->ldapCacheTTL
256
+            || !$this->configuration->ldapConfigurationActive) {
257
+            return null;
258
+        }
259
+        $key   = $this->getCacheKey($key);
260
+        $value = base64_encode(json_encode($value));
261
+        $this->cache->set($key, $value, $this->configuration->ldapCacheTTL);
262
+    }
263
+
264
+    public function clearCache() {
265
+        if(!is_null($this->cache)) {
266
+            $this->cache->clear($this->getCacheKey(null));
267
+        }
268
+    }
269
+
270
+    /**
271
+     * Caches the general LDAP configuration.
272
+     * @param bool $force optional. true, if the re-read should be forced. defaults
273
+     * to false.
274
+     * @return null
275
+     */
276
+    private function readConfiguration($force = false) {
277
+        if((!$this->configured || $force) && !is_null($this->configID)) {
278
+            $this->configuration->readConfiguration();
279
+            $this->configured = $this->validateConfiguration();
280
+        }
281
+    }
282
+
283
+    /**
284
+     * set LDAP configuration with values delivered by an array, not read from configuration
285
+     * @param array $config array that holds the config parameters in an associated array
286
+     * @param array &$setParameters optional; array where the set fields will be given to
287
+     * @return boolean true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
288
+     */
289
+    public function setConfiguration($config, &$setParameters = null) {
290
+        if(is_null($setParameters)) {
291
+            $setParameters = array();
292
+        }
293
+        $this->doNotValidate = false;
294
+        $this->configuration->setConfiguration($config, $setParameters);
295
+        if(count($setParameters) > 0) {
296
+            $this->configured = $this->validateConfiguration();
297
+        }
298
+
299
+
300
+        return $this->configured;
301
+    }
302
+
303
+    /**
304
+     * saves the current Configuration in the database and empties the
305
+     * cache
306
+     * @return null
307
+     */
308
+    public function saveConfiguration() {
309
+        $this->configuration->saveConfiguration();
310
+        $this->clearCache();
311
+    }
312
+
313
+    /**
314
+     * get the current LDAP configuration
315
+     * @return array
316
+     */
317
+    public function getConfiguration() {
318
+        $this->readConfiguration();
319
+        $config = $this->configuration->getConfiguration();
320
+        $cta = $this->configuration->getConfigTranslationArray();
321
+        $result = array();
322
+        foreach($cta as $dbkey => $configkey) {
323
+            switch($configkey) {
324
+                case 'homeFolderNamingRule':
325
+                    if(strpos($config[$configkey], 'attr:') === 0) {
326
+                        $result[$dbkey] = substr($config[$configkey], 5);
327
+                    } else {
328
+                        $result[$dbkey] = '';
329
+                    }
330
+                    break;
331
+                case 'ldapBase':
332
+                case 'ldapBaseUsers':
333
+                case 'ldapBaseGroups':
334
+                case 'ldapAttributesForUserSearch':
335
+                case 'ldapAttributesForGroupSearch':
336
+                    if(is_array($config[$configkey])) {
337
+                        $result[$dbkey] = implode("\n", $config[$configkey]);
338
+                        break;
339
+                    } //else follows default
340
+                default:
341
+                    $result[$dbkey] = $config[$configkey];
342
+            }
343
+        }
344
+        return $result;
345
+    }
346
+
347
+    private function doSoftValidation() {
348
+        //if User or Group Base are not set, take over Base DN setting
349
+        foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) {
350
+            $val = $this->configuration->$keyBase;
351
+            if(empty($val)) {
352
+                $this->configuration->$keyBase = $this->configuration->ldapBase;
353
+            }
354
+        }
355
+
356
+        foreach(array('ldapExpertUUIDUserAttr'  => 'ldapUuidUserAttribute',
357
+                        'ldapExpertUUIDGroupAttr' => 'ldapUuidGroupAttribute')
358
+                as $expertSetting => $effectiveSetting) {
359
+            $uuidOverride = $this->configuration->$expertSetting;
360
+            if(!empty($uuidOverride)) {
361
+                $this->configuration->$effectiveSetting = $uuidOverride;
362
+            } else {
363
+                $uuidAttributes = Access::UUID_ATTRIBUTES;
364
+                array_unshift($uuidAttributes, 'auto');
365
+                if(!in_array($this->configuration->$effectiveSetting,
366
+                            $uuidAttributes)
367
+                    && (!is_null($this->configID))) {
368
+                    $this->configuration->$effectiveSetting = 'auto';
369
+                    $this->configuration->saveConfiguration();
370
+                    \OCP\Util::writeLog('user_ldap',
371
+                                        'Illegal value for the '.
372
+                                        $effectiveSetting.', '.'reset to '.
373
+                                        'autodetect.', ILogger::INFO);
374
+                }
375
+
376
+            }
377
+        }
378
+
379
+        $backupPort = (int)$this->configuration->ldapBackupPort;
380
+        if ($backupPort <= 0) {
381
+            $this->configuration->backupPort = $this->configuration->ldapPort;
382
+        }
383
+
384
+        //make sure empty search attributes are saved as simple, empty array
385
+        $saKeys = array('ldapAttributesForUserSearch',
386
+                        'ldapAttributesForGroupSearch');
387
+        foreach($saKeys as $key) {
388
+            $val = $this->configuration->$key;
389
+            if(is_array($val) && count($val) === 1 && empty($val[0])) {
390
+                $this->configuration->$key = array();
391
+            }
392
+        }
393
+
394
+        if((stripos($this->configuration->ldapHost, 'ldaps://') === 0)
395
+            && $this->configuration->ldapTLS) {
396
+            $this->configuration->ldapTLS = false;
397
+            \OCP\Util::writeLog(
398
+                'user_ldap',
399
+                'LDAPS (already using secure connection) and TLS do not work together. Switched off TLS.',
400
+                ILogger::INFO
401
+            );
402
+        }
403
+    }
404
+
405
+    /**
406
+     * @return bool
407
+     */
408
+    private function doCriticalValidation() {
409
+        $configurationOK = true;
410
+        $errorStr = 'Configuration Error (prefix '.
411
+            (string)$this->configPrefix .'): ';
412
+
413
+        //options that shall not be empty
414
+        $options = array('ldapHost', 'ldapPort', 'ldapUserDisplayName',
415
+                            'ldapGroupDisplayName', 'ldapLoginFilter');
416
+        foreach($options as $key) {
417
+            $val = $this->configuration->$key;
418
+            if(empty($val)) {
419
+                switch($key) {
420
+                    case 'ldapHost':
421
+                        $subj = 'LDAP Host';
422
+                        break;
423
+                    case 'ldapPort':
424
+                        $subj = 'LDAP Port';
425
+                        break;
426
+                    case 'ldapUserDisplayName':
427
+                        $subj = 'LDAP User Display Name';
428
+                        break;
429
+                    case 'ldapGroupDisplayName':
430
+                        $subj = 'LDAP Group Display Name';
431
+                        break;
432
+                    case 'ldapLoginFilter':
433
+                        $subj = 'LDAP Login Filter';
434
+                        break;
435
+                    default:
436
+                        $subj = $key;
437
+                        break;
438
+                }
439
+                $configurationOK = false;
440
+                \OCP\Util::writeLog(
441
+                    'user_ldap',
442
+                    $errorStr.'No '.$subj.' given!',
443
+                    ILogger::WARN
444
+                );
445
+            }
446
+        }
447
+
448
+        //combinations
449
+        $agent = $this->configuration->ldapAgentName;
450
+        $pwd = $this->configuration->ldapAgentPassword;
451
+        if (
452
+            ($agent === ''  && $pwd !== '')
453
+            || ($agent !== '' && $pwd === '')
454
+        ) {
455
+            \OCP\Util::writeLog(
456
+                'user_ldap',
457
+                $errorStr.'either no password is given for the user ' .
458
+                    'agent or a password is given, but not an LDAP agent.',
459
+                ILogger::WARN);
460
+            $configurationOK = false;
461
+        }
462
+
463
+        $base = $this->configuration->ldapBase;
464
+        $baseUsers = $this->configuration->ldapBaseUsers;
465
+        $baseGroups = $this->configuration->ldapBaseGroups;
466
+
467
+        if(empty($base) && empty($baseUsers) && empty($baseGroups)) {
468
+            \OCP\Util::writeLog(
469
+                'user_ldap',
470
+                $errorStr.'Not a single Base DN given.',
471
+                ILogger::WARN
472
+            );
473
+            $configurationOK = false;
474
+        }
475
+
476
+        if(mb_strpos($this->configuration->ldapLoginFilter, '%uid', 0, 'UTF-8')
477
+            === false) {
478
+            \OCP\Util::writeLog(
479
+                'user_ldap',
480
+                $errorStr.'login filter does not contain %uid place holder.',
481
+                ILogger::WARN
482
+            );
483
+            $configurationOK = false;
484
+        }
485
+
486
+        return $configurationOK;
487
+    }
488
+
489
+    /**
490
+     * Validates the user specified configuration
491
+     * @return bool true if configuration seems OK, false otherwise
492
+     */
493
+    private function validateConfiguration() {
494
+
495
+        if($this->doNotValidate) {
496
+            //don't do a validation if it is a new configuration with pure
497
+            //default values. Will be allowed on changes via __set or
498
+            //setConfiguration
499
+            return false;
500
+        }
501
+
502
+        // first step: "soft" checks: settings that are not really
503
+        // necessary, but advisable. If left empty, give an info message
504
+        $this->doSoftValidation();
505
+
506
+        //second step: critical checks. If left empty or filled wrong, mark as
507
+        //not configured and give a warning.
508
+        return $this->doCriticalValidation();
509
+    }
510
+
511
+
512
+    /**
513
+     * Connects and Binds to LDAP
514
+     *
515
+     * @throws ServerNotAvailableException
516
+     */
517
+    private function establishConnection() {
518
+        if(!$this->configuration->ldapConfigurationActive) {
519
+            return null;
520
+        }
521
+        static $phpLDAPinstalled = true;
522
+        if(!$phpLDAPinstalled) {
523
+            return false;
524
+        }
525
+        if(!$this->ignoreValidation && !$this->configured) {
526
+            \OCP\Util::writeLog(
527
+                'user_ldap',
528
+                'Configuration is invalid, cannot connect',
529
+                ILogger::WARN
530
+            );
531
+            return false;
532
+        }
533
+        if(!$this->ldapConnectionRes) {
534
+            if(!$this->ldap->areLDAPFunctionsAvailable()) {
535
+                $phpLDAPinstalled = false;
536
+                \OCP\Util::writeLog(
537
+                    'user_ldap',
538
+                    'function ldap_connect is not available. Make sure that the PHP ldap module is installed.',
539
+                    ILogger::ERROR
540
+                );
541
+
542
+                return false;
543
+            }
544
+            if($this->configuration->turnOffCertCheck) {
545
+                if(putenv('LDAPTLS_REQCERT=never')) {
546
+                    \OCP\Util::writeLog('user_ldap',
547
+                        'Turned off SSL certificate validation successfully.',
548
+                        ILogger::DEBUG);
549
+                } else {
550
+                    \OCP\Util::writeLog(
551
+                        'user_ldap',
552
+                        'Could not turn off SSL certificate validation.',
553
+                        ILogger::WARN
554
+                    );
555
+                }
556
+            }
557
+
558
+            $isOverrideMainServer = ($this->configuration->ldapOverrideMainServer
559
+                || $this->getFromCache('overrideMainServer'));
560
+            $isBackupHost = (trim($this->configuration->ldapBackupHost) !== "");
561
+            $bindStatus = false;
562
+            try {
563
+                if (!$isOverrideMainServer) {
564
+                    $this->doConnect($this->configuration->ldapHost,
565
+                        $this->configuration->ldapPort);
566
+                }
567
+                return $this->bind();
568
+            } catch (ServerNotAvailableException $e) {
569
+                if(!$isBackupHost) {
570
+                    throw $e;
571
+                }
572
+            }
573
+
574
+            //if LDAP server is not reachable, try the Backup (Replica!) Server
575
+            if($isBackupHost || $isOverrideMainServer) {
576
+                $this->doConnect($this->configuration->ldapBackupHost,
577
+                                    $this->configuration->ldapBackupPort);
578
+                $this->bindResult = [];
579
+                $bindStatus = $this->bind();
580
+                $error = $this->ldap->isResource($this->ldapConnectionRes) ?
581
+                    $this->ldap->errno($this->ldapConnectionRes) : -1;
582
+                if($bindStatus && $error === 0 && !$this->getFromCache('overrideMainServer')) {
583
+                    //when bind to backup server succeeded and failed to main server,
584
+                    //skip contacting him until next cache refresh
585
+                    $this->writeToCache('overrideMainServer', true);
586
+                }
587
+            }
588
+
589
+            return $bindStatus;
590
+        }
591
+        return null;
592
+    }
593
+
594
+    /**
595
+     * @param string $host
596
+     * @param string $port
597
+     * @return bool
598
+     * @throws \OC\ServerNotAvailableException
599
+     */
600
+    private function doConnect($host, $port) {
601
+        if ($host === '') {
602
+            return false;
603
+        }
604
+
605
+        $this->ldapConnectionRes = $this->ldap->connect($host, $port);
606
+
607
+        if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
608
+            throw new ServerNotAvailableException('Could not set required LDAP Protocol version.');
609
+        }
610
+
611
+        if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
612
+            throw new ServerNotAvailableException('Could not disable LDAP referrals.');
613
+        }
614
+
615
+        if($this->configuration->ldapTLS) {
616
+            if(!$this->ldap->startTls($this->ldapConnectionRes)) {
617
+                throw new ServerNotAvailableException('Start TLS failed, when connecting to LDAP host ' . $host . '.');
618
+            }
619
+        }
620
+
621
+        return true;
622
+    }
623
+
624
+    /**
625
+     * Binds to LDAP
626
+     */
627
+    public function bind() {
628
+        if(!$this->configuration->ldapConfigurationActive) {
629
+            return false;
630
+        }
631
+        $cr = $this->ldapConnectionRes;
632
+        if(!$this->ldap->isResource($cr)) {
633
+            $cr = $this->getConnectionResource();
634
+        }
635
+
636
+        if(
637
+            count($this->bindResult) !== 0
638
+            && $this->bindResult['dn'] === $this->configuration->ldapAgentName
639
+            && \OC::$server->getHasher()->verify(
640
+                $this->configPrefix . $this->configuration->ldapAgentPassword,
641
+                $this->bindResult['hash']
642
+            )
643
+        ) {
644
+            // don't attempt to bind again with the same data as before
645
+            // bind might have been invoked via getConnectionResource(),
646
+            // but we need results specifically for e.g. user login
647
+            return $this->bindResult['result'];
648
+        }
649
+
650
+        $ldapLogin = @$this->ldap->bind($cr,
651
+                                        $this->configuration->ldapAgentName,
652
+                                        $this->configuration->ldapAgentPassword);
653
+
654
+        $this->bindResult = [
655
+            'dn' => $this->configuration->ldapAgentName,
656
+            'hash' => \OC::$server->getHasher()->hash($this->configPrefix . $this->configuration->ldapAgentPassword),
657
+            'result' => $ldapLogin,
658
+        ];
659
+
660
+        if(!$ldapLogin) {
661
+            $errno = $this->ldap->errno($cr);
662
+
663
+            \OCP\Util::writeLog('user_ldap',
664
+                'Bind failed: ' . $errno . ': ' . $this->ldap->error($cr),
665
+                ILogger::WARN);
666
+
667
+            // Set to failure mode, if LDAP error code is not LDAP_SUCCESS or LDAP_INVALID_CREDENTIALS
668
+            if($errno !== 0x00 && $errno !== 0x31) {
669
+                $this->ldapConnectionRes = null;
670
+            }
671
+
672
+            return false;
673
+        }
674
+        return true;
675
+    }
676 676
 
677 677
 }
Please login to merge, or discard this patch.
Spacing   +67 added lines, -67 removed lines patch added patch discarded remove patch
@@ -102,19 +102,19 @@  discard block
 block discarded – undo
102 102
 		$this->configuration = new Configuration($configPrefix,
103 103
 												 !is_null($configID));
104 104
 		$memcache = \OC::$server->getMemCacheFactory();
105
-		if($memcache->isAvailable()) {
105
+		if ($memcache->isAvailable()) {
106 106
 			$this->cache = $memcache->createDistributed();
107 107
 		}
108 108
 		$helper = new Helper(\OC::$server->getConfig());
109 109
 		$this->doNotValidate = !in_array($this->configPrefix,
110 110
 			$helper->getServerConfigurationPrefixes());
111 111
 		$this->hasPagedResultSupport =
112
-			(int)$this->configuration->ldapPagingSize !== 0
112
+			(int) $this->configuration->ldapPagingSize !== 0
113 113
 			|| $this->ldap->hasPagedResultSupport();
114 114
 	}
115 115
 
116 116
 	public function __destruct() {
117
-		if(!$this->dontDestruct && $this->ldap->isResource($this->ldapConnectionRes)) {
117
+		if (!$this->dontDestruct && $this->ldap->isResource($this->ldapConnectionRes)) {
118 118
 			@$this->ldap->unbind($this->ldapConnectionRes);
119 119
 			$this->bindResult = [];
120 120
 		}
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
 	public function __clone() {
127 127
 		$this->configuration = new Configuration($this->configPrefix,
128 128
 												 !is_null($this->configID));
129
-		if(count($this->bindResult) !== 0 && $this->bindResult['result'] === true) {
129
+		if (count($this->bindResult) !== 0 && $this->bindResult['result'] === true) {
130 130
 			$this->bindResult = [];
131 131
 		}
132 132
 		$this->ldapConnectionRes = null;
@@ -138,11 +138,11 @@  discard block
 block discarded – undo
138 138
 	 * @return bool|mixed
139 139
 	 */
140 140
 	public function __get($name) {
141
-		if(!$this->configured) {
141
+		if (!$this->configured) {
142 142
 			$this->readConfiguration();
143 143
 		}
144 144
 
145
-		if($name === 'hasPagedResultSupport') {
145
+		if ($name === 'hasPagedResultSupport') {
146 146
 			return $this->hasPagedResultSupport;
147 147
 		}
148 148
 
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
 		$before = $this->configuration->$name;
159 159
 		$this->configuration->$name = $value;
160 160
 		$after = $this->configuration->$name;
161
-		if($before !== $after) {
161
+		if ($before !== $after) {
162 162
 			if ($this->configID !== '' && $this->configID !== null) {
163 163
 				$this->configuration->saveConfiguration();
164 164
 			}
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
 	 * @param bool $state
174 174
 	 */
175 175
 	public function setIgnoreValidation($state) {
176
-		$this->ignoreValidation = (bool)$state;
176
+		$this->ignoreValidation = (bool) $state;
177 177
 	}
178 178
 
179 179
 	/**
@@ -189,14 +189,14 @@  discard block
 block discarded – undo
189 189
 	 * Returns the LDAP handler
190 190
 	 */
191 191
 	public function getConnectionResource() {
192
-		if(!$this->ldapConnectionRes) {
192
+		if (!$this->ldapConnectionRes) {
193 193
 			$this->init();
194
-		} else if(!$this->ldap->isResource($this->ldapConnectionRes)) {
194
+		} else if (!$this->ldap->isResource($this->ldapConnectionRes)) {
195 195
 			$this->ldapConnectionRes = null;
196 196
 			$this->establishConnection();
197 197
 		}
198
-		if(is_null($this->ldapConnectionRes)) {
199
-			\OCP\Util::writeLog('user_ldap', 'No LDAP Connection to server ' . $this->configuration->ldapHost, ILogger::ERROR);
198
+		if (is_null($this->ldapConnectionRes)) {
199
+			\OCP\Util::writeLog('user_ldap', 'No LDAP Connection to server '.$this->configuration->ldapHost, ILogger::ERROR);
200 200
 			throw new ServerNotAvailableException('Connection to LDAP server could not be established');
201 201
 		}
202 202
 		return $this->ldapConnectionRes;
@@ -206,7 +206,7 @@  discard block
 block discarded – undo
206 206
 	 * resets the connection resource
207 207
 	 */
208 208
 	public function resetConnectionResource() {
209
-		if(!is_null($this->ldapConnectionRes)) {
209
+		if (!is_null($this->ldapConnectionRes)) {
210 210
 			@$this->ldap->unbind($this->ldapConnectionRes);
211 211
 			$this->ldapConnectionRes = null;
212 212
 			$this->bindResult = [];
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
 	 */
220 220
 	private function getCacheKey($key) {
221 221
 		$prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-';
222
-		if(is_null($key)) {
222
+		if (is_null($key)) {
223 223
 			return $prefix;
224 224
 		}
225 225
 		return $prefix.hash('sha256', $key);
@@ -230,10 +230,10 @@  discard block
 block discarded – undo
230 230
 	 * @return mixed|null
231 231
 	 */
232 232
 	public function getFromCache($key) {
233
-		if(!$this->configured) {
233
+		if (!$this->configured) {
234 234
 			$this->readConfiguration();
235 235
 		}
236
-		if(is_null($this->cache) || !$this->configuration->ldapCacheTTL) {
236
+		if (is_null($this->cache) || !$this->configuration->ldapCacheTTL) {
237 237
 			return null;
238 238
 		}
239 239
 		$key = $this->getCacheKey($key);
@@ -248,10 +248,10 @@  discard block
 block discarded – undo
248 248
 	 * @return string
249 249
 	 */
250 250
 	public function writeToCache($key, $value) {
251
-		if(!$this->configured) {
251
+		if (!$this->configured) {
252 252
 			$this->readConfiguration();
253 253
 		}
254
-		if(is_null($this->cache)
254
+		if (is_null($this->cache)
255 255
 			|| !$this->configuration->ldapCacheTTL
256 256
 			|| !$this->configuration->ldapConfigurationActive) {
257 257
 			return null;
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
 	}
263 263
 
264 264
 	public function clearCache() {
265
-		if(!is_null($this->cache)) {
265
+		if (!is_null($this->cache)) {
266 266
 			$this->cache->clear($this->getCacheKey(null));
267 267
 		}
268 268
 	}
@@ -274,7 +274,7 @@  discard block
 block discarded – undo
274 274
 	 * @return null
275 275
 	 */
276 276
 	private function readConfiguration($force = false) {
277
-		if((!$this->configured || $force) && !is_null($this->configID)) {
277
+		if ((!$this->configured || $force) && !is_null($this->configID)) {
278 278
 			$this->configuration->readConfiguration();
279 279
 			$this->configured = $this->validateConfiguration();
280 280
 		}
@@ -287,12 +287,12 @@  discard block
 block discarded – undo
287 287
 	 * @return boolean true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
288 288
 	 */
289 289
 	public function setConfiguration($config, &$setParameters = null) {
290
-		if(is_null($setParameters)) {
290
+		if (is_null($setParameters)) {
291 291
 			$setParameters = array();
292 292
 		}
293 293
 		$this->doNotValidate = false;
294 294
 		$this->configuration->setConfiguration($config, $setParameters);
295
-		if(count($setParameters) > 0) {
295
+		if (count($setParameters) > 0) {
296 296
 			$this->configured = $this->validateConfiguration();
297 297
 		}
298 298
 
@@ -319,10 +319,10 @@  discard block
 block discarded – undo
319 319
 		$config = $this->configuration->getConfiguration();
320 320
 		$cta = $this->configuration->getConfigTranslationArray();
321 321
 		$result = array();
322
-		foreach($cta as $dbkey => $configkey) {
323
-			switch($configkey) {
322
+		foreach ($cta as $dbkey => $configkey) {
323
+			switch ($configkey) {
324 324
 				case 'homeFolderNamingRule':
325
-					if(strpos($config[$configkey], 'attr:') === 0) {
325
+					if (strpos($config[$configkey], 'attr:') === 0) {
326 326
 						$result[$dbkey] = substr($config[$configkey], 5);
327 327
 					} else {
328 328
 						$result[$dbkey] = '';
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
 				case 'ldapBaseGroups':
334 334
 				case 'ldapAttributesForUserSearch':
335 335
 				case 'ldapAttributesForGroupSearch':
336
-					if(is_array($config[$configkey])) {
336
+					if (is_array($config[$configkey])) {
337 337
 						$result[$dbkey] = implode("\n", $config[$configkey]);
338 338
 						break;
339 339
 					} //else follows default
@@ -346,23 +346,23 @@  discard block
 block discarded – undo
346 346
 
347 347
 	private function doSoftValidation() {
348 348
 		//if User or Group Base are not set, take over Base DN setting
349
-		foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) {
349
+		foreach (array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) {
350 350
 			$val = $this->configuration->$keyBase;
351
-			if(empty($val)) {
351
+			if (empty($val)) {
352 352
 				$this->configuration->$keyBase = $this->configuration->ldapBase;
353 353
 			}
354 354
 		}
355 355
 
356
-		foreach(array('ldapExpertUUIDUserAttr'  => 'ldapUuidUserAttribute',
356
+		foreach (array('ldapExpertUUIDUserAttr'  => 'ldapUuidUserAttribute',
357 357
 					  'ldapExpertUUIDGroupAttr' => 'ldapUuidGroupAttribute')
358 358
 				as $expertSetting => $effectiveSetting) {
359 359
 			$uuidOverride = $this->configuration->$expertSetting;
360
-			if(!empty($uuidOverride)) {
360
+			if (!empty($uuidOverride)) {
361 361
 				$this->configuration->$effectiveSetting = $uuidOverride;
362 362
 			} else {
363 363
 				$uuidAttributes = Access::UUID_ATTRIBUTES;
364 364
 				array_unshift($uuidAttributes, 'auto');
365
-				if(!in_array($this->configuration->$effectiveSetting,
365
+				if (!in_array($this->configuration->$effectiveSetting,
366 366
 							$uuidAttributes)
367 367
 					&& (!is_null($this->configID))) {
368 368
 					$this->configuration->$effectiveSetting = 'auto';
@@ -376,7 +376,7 @@  discard block
 block discarded – undo
376 376
 			}
377 377
 		}
378 378
 
379
-		$backupPort = (int)$this->configuration->ldapBackupPort;
379
+		$backupPort = (int) $this->configuration->ldapBackupPort;
380 380
 		if ($backupPort <= 0) {
381 381
 			$this->configuration->backupPort = $this->configuration->ldapPort;
382 382
 		}
@@ -384,14 +384,14 @@  discard block
 block discarded – undo
384 384
 		//make sure empty search attributes are saved as simple, empty array
385 385
 		$saKeys = array('ldapAttributesForUserSearch',
386 386
 						'ldapAttributesForGroupSearch');
387
-		foreach($saKeys as $key) {
387
+		foreach ($saKeys as $key) {
388 388
 			$val = $this->configuration->$key;
389
-			if(is_array($val) && count($val) === 1 && empty($val[0])) {
389
+			if (is_array($val) && count($val) === 1 && empty($val[0])) {
390 390
 				$this->configuration->$key = array();
391 391
 			}
392 392
 		}
393 393
 
394
-		if((stripos($this->configuration->ldapHost, 'ldaps://') === 0)
394
+		if ((stripos($this->configuration->ldapHost, 'ldaps://') === 0)
395 395
 			&& $this->configuration->ldapTLS) {
396 396
 			$this->configuration->ldapTLS = false;
397 397
 			\OCP\Util::writeLog(
@@ -408,15 +408,15 @@  discard block
 block discarded – undo
408 408
 	private function doCriticalValidation() {
409 409
 		$configurationOK = true;
410 410
 		$errorStr = 'Configuration Error (prefix '.
411
-			(string)$this->configPrefix .'): ';
411
+			(string) $this->configPrefix.'): ';
412 412
 
413 413
 		//options that shall not be empty
414 414
 		$options = array('ldapHost', 'ldapPort', 'ldapUserDisplayName',
415 415
 						 'ldapGroupDisplayName', 'ldapLoginFilter');
416
-		foreach($options as $key) {
416
+		foreach ($options as $key) {
417 417
 			$val = $this->configuration->$key;
418
-			if(empty($val)) {
419
-				switch($key) {
418
+			if (empty($val)) {
419
+				switch ($key) {
420 420
 					case 'ldapHost':
421 421
 						$subj = 'LDAP Host';
422 422
 						break;
@@ -449,12 +449,12 @@  discard block
 block discarded – undo
449 449
 		$agent = $this->configuration->ldapAgentName;
450 450
 		$pwd = $this->configuration->ldapAgentPassword;
451 451
 		if (
452
-			($agent === ''  && $pwd !== '')
452
+			($agent === '' && $pwd !== '')
453 453
 			|| ($agent !== '' && $pwd === '')
454 454
 		) {
455 455
 			\OCP\Util::writeLog(
456 456
 				'user_ldap',
457
-				$errorStr.'either no password is given for the user ' .
457
+				$errorStr.'either no password is given for the user '.
458 458
 					'agent or a password is given, but not an LDAP agent.',
459 459
 				ILogger::WARN);
460 460
 			$configurationOK = false;
@@ -464,7 +464,7 @@  discard block
 block discarded – undo
464 464
 		$baseUsers = $this->configuration->ldapBaseUsers;
465 465
 		$baseGroups = $this->configuration->ldapBaseGroups;
466 466
 
467
-		if(empty($base) && empty($baseUsers) && empty($baseGroups)) {
467
+		if (empty($base) && empty($baseUsers) && empty($baseGroups)) {
468 468
 			\OCP\Util::writeLog(
469 469
 				'user_ldap',
470 470
 				$errorStr.'Not a single Base DN given.',
@@ -473,7 +473,7 @@  discard block
 block discarded – undo
473 473
 			$configurationOK = false;
474 474
 		}
475 475
 
476
-		if(mb_strpos($this->configuration->ldapLoginFilter, '%uid', 0, 'UTF-8')
476
+		if (mb_strpos($this->configuration->ldapLoginFilter, '%uid', 0, 'UTF-8')
477 477
 		   === false) {
478 478
 			\OCP\Util::writeLog(
479 479
 				'user_ldap',
@@ -492,7 +492,7 @@  discard block
 block discarded – undo
492 492
 	 */
493 493
 	private function validateConfiguration() {
494 494
 
495
-		if($this->doNotValidate) {
495
+		if ($this->doNotValidate) {
496 496
 			//don't do a validation if it is a new configuration with pure
497 497
 			//default values. Will be allowed on changes via __set or
498 498
 			//setConfiguration
@@ -515,14 +515,14 @@  discard block
 block discarded – undo
515 515
 	 * @throws ServerNotAvailableException
516 516
 	 */
517 517
 	private function establishConnection() {
518
-		if(!$this->configuration->ldapConfigurationActive) {
518
+		if (!$this->configuration->ldapConfigurationActive) {
519 519
 			return null;
520 520
 		}
521 521
 		static $phpLDAPinstalled = true;
522
-		if(!$phpLDAPinstalled) {
522
+		if (!$phpLDAPinstalled) {
523 523
 			return false;
524 524
 		}
525
-		if(!$this->ignoreValidation && !$this->configured) {
525
+		if (!$this->ignoreValidation && !$this->configured) {
526 526
 			\OCP\Util::writeLog(
527 527
 				'user_ldap',
528 528
 				'Configuration is invalid, cannot connect',
@@ -530,8 +530,8 @@  discard block
 block discarded – undo
530 530
 			);
531 531
 			return false;
532 532
 		}
533
-		if(!$this->ldapConnectionRes) {
534
-			if(!$this->ldap->areLDAPFunctionsAvailable()) {
533
+		if (!$this->ldapConnectionRes) {
534
+			if (!$this->ldap->areLDAPFunctionsAvailable()) {
535 535
 				$phpLDAPinstalled = false;
536 536
 				\OCP\Util::writeLog(
537 537
 					'user_ldap',
@@ -541,8 +541,8 @@  discard block
 block discarded – undo
541 541
 
542 542
 				return false;
543 543
 			}
544
-			if($this->configuration->turnOffCertCheck) {
545
-				if(putenv('LDAPTLS_REQCERT=never')) {
544
+			if ($this->configuration->turnOffCertCheck) {
545
+				if (putenv('LDAPTLS_REQCERT=never')) {
546 546
 					\OCP\Util::writeLog('user_ldap',
547 547
 						'Turned off SSL certificate validation successfully.',
548 548
 						ILogger::DEBUG);
@@ -566,20 +566,20 @@  discard block
 block discarded – undo
566 566
 				}
567 567
 				return $this->bind();
568 568
 			} catch (ServerNotAvailableException $e) {
569
-				if(!$isBackupHost) {
569
+				if (!$isBackupHost) {
570 570
 					throw $e;
571 571
 				}
572 572
 			}
573 573
 
574 574
 			//if LDAP server is not reachable, try the Backup (Replica!) Server
575
-			if($isBackupHost || $isOverrideMainServer) {
575
+			if ($isBackupHost || $isOverrideMainServer) {
576 576
 				$this->doConnect($this->configuration->ldapBackupHost,
577 577
 								 $this->configuration->ldapBackupPort);
578 578
 				$this->bindResult = [];
579 579
 				$bindStatus = $this->bind();
580 580
 				$error = $this->ldap->isResource($this->ldapConnectionRes) ?
581 581
 					$this->ldap->errno($this->ldapConnectionRes) : -1;
582
-				if($bindStatus && $error === 0 && !$this->getFromCache('overrideMainServer')) {
582
+				if ($bindStatus && $error === 0 && !$this->getFromCache('overrideMainServer')) {
583 583
 					//when bind to backup server succeeded and failed to main server,
584 584
 					//skip contacting him until next cache refresh
585 585
 					$this->writeToCache('overrideMainServer', true);
@@ -604,17 +604,17 @@  discard block
 block discarded – undo
604 604
 
605 605
 		$this->ldapConnectionRes = $this->ldap->connect($host, $port);
606 606
 
607
-		if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
607
+		if (!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
608 608
 			throw new ServerNotAvailableException('Could not set required LDAP Protocol version.');
609 609
 		}
610 610
 
611
-		if(!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
611
+		if (!$this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
612 612
 			throw new ServerNotAvailableException('Could not disable LDAP referrals.');
613 613
 		}
614 614
 
615
-		if($this->configuration->ldapTLS) {
616
-			if(!$this->ldap->startTls($this->ldapConnectionRes)) {
617
-				throw new ServerNotAvailableException('Start TLS failed, when connecting to LDAP host ' . $host . '.');
615
+		if ($this->configuration->ldapTLS) {
616
+			if (!$this->ldap->startTls($this->ldapConnectionRes)) {
617
+				throw new ServerNotAvailableException('Start TLS failed, when connecting to LDAP host '.$host.'.');
618 618
 			}
619 619
 		}
620 620
 
@@ -625,19 +625,19 @@  discard block
 block discarded – undo
625 625
 	 * Binds to LDAP
626 626
 	 */
627 627
 	public function bind() {
628
-		if(!$this->configuration->ldapConfigurationActive) {
628
+		if (!$this->configuration->ldapConfigurationActive) {
629 629
 			return false;
630 630
 		}
631 631
 		$cr = $this->ldapConnectionRes;
632
-		if(!$this->ldap->isResource($cr)) {
632
+		if (!$this->ldap->isResource($cr)) {
633 633
 			$cr = $this->getConnectionResource();
634 634
 		}
635 635
 
636
-		if(
636
+		if (
637 637
 			count($this->bindResult) !== 0
638 638
 			&& $this->bindResult['dn'] === $this->configuration->ldapAgentName
639 639
 			&& \OC::$server->getHasher()->verify(
640
-				$this->configPrefix . $this->configuration->ldapAgentPassword,
640
+				$this->configPrefix.$this->configuration->ldapAgentPassword,
641 641
 				$this->bindResult['hash']
642 642
 			)
643 643
 		) {
@@ -653,19 +653,19 @@  discard block
 block discarded – undo
653 653
 
654 654
 		$this->bindResult = [
655 655
 			'dn' => $this->configuration->ldapAgentName,
656
-			'hash' => \OC::$server->getHasher()->hash($this->configPrefix . $this->configuration->ldapAgentPassword),
656
+			'hash' => \OC::$server->getHasher()->hash($this->configPrefix.$this->configuration->ldapAgentPassword),
657 657
 			'result' => $ldapLogin,
658 658
 		];
659 659
 
660
-		if(!$ldapLogin) {
660
+		if (!$ldapLogin) {
661 661
 			$errno = $this->ldap->errno($cr);
662 662
 
663 663
 			\OCP\Util::writeLog('user_ldap',
664
-				'Bind failed: ' . $errno . ': ' . $this->ldap->error($cr),
664
+				'Bind failed: '.$errno.': '.$this->ldap->error($cr),
665 665
 				ILogger::WARN);
666 666
 
667 667
 			// Set to failure mode, if LDAP error code is not LDAP_SUCCESS or LDAP_INVALID_CREDENTIALS
668
-			if($errno !== 0x00 && $errno !== 0x31) {
668
+			if ($errno !== 0x00 && $errno !== 0x31) {
669 669
 				$this->ldapConnectionRes = null;
670 670
 			}
671 671
 
Please login to merge, or discard this patch.