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