Blame view

sources/apps/user_ldap/lib/connection.php 16.8 KB
03e52840d   Kload   Init
1
2
3
  <?php
  
  /**
31b7f2792   Kload   Upgrade to ownclo...
4
   * ownCloud – LDAP Connection
03e52840d   Kload   Init
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   *
   * @author Arthur Schiwon
   * @copyright 2012, 2013 Arthur Schiwon blizzz@owncloud.com
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
   * License as published by the Free Software Foundation; either
   * version 3 of the License, or any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
   *
   * You should have received a copy of the GNU Affero General Public
   * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
   *
   */
  
  namespace OCA\user_ldap\lib;
6d9380f96   Cédric Dupont   Update sources OC...
25
26
27
28
29
30
31
  //magic properties (incomplete)
  /**
   * responsible for LDAP connections in context with the provided configuration
   * @property string ldapUserFilter
   * @property string ldapUserDisplayName
   * @property boolean hasPagedResultSupport
  */
31b7f2792   Kload   Upgrade to ownclo...
32
  class Connection extends LDAPUtility {
03e52840d   Kload   Init
33
34
35
36
37
38
39
  	private $ldapConnectionRes = null;
  	private $configPrefix;
  	private $configID;
  	private $configured = false;
  
  	//whether connection should be kept on __destruct
  	private $dontDestruct = false;
31b7f2792   Kload   Upgrade to ownclo...
40
  	private $hasPagedResultSupport = true;
03e52840d   Kload   Init
41
42
43
  
  	//cache handler
  	protected $cache;
31b7f2792   Kload   Upgrade to ownclo...
44
45
46
47
  	//settings handler
  	protected $configuration;
  
  	protected $doNotValidate = false;
03e52840d   Kload   Init
48

6d9380f96   Cédric Dupont   Update sources OC...
49
  	protected $ignoreValidation = false;
03e52840d   Kload   Init
50
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
51
52
53
54
  	 * Constructor
  	 * @param ILDAPWrapper $ldap
  	 * @param string $configPrefix a string with the prefix for the configkey column (appconfig table)
  	 * @param string|null $configID a string with the value for the appid column (appconfig table) or null for on-the-fly connections
03e52840d   Kload   Init
55
  	 */
31b7f2792   Kload   Upgrade to ownclo...
56
57
  	public function __construct(ILDAPWrapper $ldap, $configPrefix = '', $configID = 'user_ldap') {
  		parent::__construct($ldap);
03e52840d   Kload   Init
58
59
  		$this->configPrefix = $configPrefix;
  		$this->configID = $configID;
a293d369c   Kload   Update sources to...
60
61
  		$this->configuration = new Configuration($configPrefix,
  												 !is_null($configID));
6d9380f96   Cédric Dupont   Update sources OC...
62
  		$memcache = \OC::$server->getMemCacheFactory();
31b7f2792   Kload   Upgrade to ownclo...
63
64
65
  		if($memcache->isAvailable()) {
  			$this->cache = $memcache->create();
  		} else {
6d9380f96   Cédric Dupont   Update sources OC...
66
  			$this->cache = \OC\Cache::getGlobalCache();
31b7f2792   Kload   Upgrade to ownclo...
67
68
69
70
71
  		}
  		$this->hasPagedResultSupport =
  			$this->ldap->hasPagedResultSupport();
  		$this->doNotValidate = !in_array($this->configPrefix,
  			Helper::getServerConfigurationPrefixes());
03e52840d   Kload   Init
72
73
74
  	}
  
  	public function __destruct() {
31b7f2792   Kload   Upgrade to ownclo...
75
76
77
  		if(!$this->dontDestruct &&
  			$this->ldap->isResource($this->ldapConnectionRes)) {
  			@$this->ldap->unbind($this->ldapConnectionRes);
03e52840d   Kload   Init
78
79
80
81
  		};
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
82
  	 * defines behaviour when the instance is cloned
03e52840d   Kload   Init
83
84
85
86
87
  	 */
  	public function __clone() {
  		//a cloned instance inherits the connection resource. It may use it,
  		//but it may not disconnect it
  		$this->dontDestruct = true;
837968727   Kload   [enh] Upgrade to ...
88
89
  		$this->configuration = new Configuration($this->configPrefix,
  												 !is_null($this->configID));
03e52840d   Kload   Init
90
  	}
6d9380f96   Cédric Dupont   Update sources OC...
91
92
93
94
  	/**
  	 * @param string $name
  	 * @return bool|mixed|void
  	 */
03e52840d   Kload   Init
95
96
97
98
  	public function __get($name) {
  		if(!$this->configured) {
  			$this->readConfiguration();
  		}
31b7f2792   Kload   Upgrade to ownclo...
99
100
  		if($name === 'hasPagedResultSupport') {
  			return $this->hasPagedResultSupport;
03e52840d   Kload   Init
101
  		}
31b7f2792   Kload   Upgrade to ownclo...
102
103
  
  		return $this->configuration->$name;
03e52840d   Kload   Init
104
  	}
6d9380f96   Cédric Dupont   Update sources OC...
105
106
107
108
  	/**
  	 * @param string $name
  	 * @param mixed $value
  	 */
03e52840d   Kload   Init
109
  	public function __set($name, $value) {
31b7f2792   Kload   Upgrade to ownclo...
110
111
112
113
114
  		$this->doNotValidate = false;
  		$before = $this->configuration->$name;
  		$this->configuration->$name = $value;
  		$after = $this->configuration->$name;
  		if($before !== $after) {
03e52840d   Kload   Init
115
  			if(!empty($this->configID)) {
31b7f2792   Kload   Upgrade to ownclo...
116
  				$this->configuration->saveConfiguration();
03e52840d   Kload   Init
117
  			}
03e52840d   Kload   Init
118
119
120
121
122
  			$this->validateConfiguration();
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
123
124
125
126
127
128
129
130
131
132
  	 * sets whether the result of the configuration validation shall
  	 * be ignored when establishing the connection. Used by the Wizard
  	 * in early configuration state.
  	 * @param bool $state
  	 */
  	public function setIgnoreValidation($state) {
  		$this->ignoreValidation = (bool)$state;
  	}
  
  	/**
03e52840d   Kload   Init
133
  	 * initializes the LDAP backend
6d9380f96   Cédric Dupont   Update sources OC...
134
  	 * @param bool $force read the config settings no matter what
03e52840d   Kload   Init
135
136
137
138
139
140
141
142
143
144
145
146
  	 */
  	public function init($force = false) {
  		$this->readConfiguration($force);
  		$this->establishConnection();
  	}
  
  	/**
  	 * Returns the LDAP handler
  	 */
  	public function getConnectionResource() {
  		if(!$this->ldapConnectionRes) {
  			$this->init();
31b7f2792   Kload   Upgrade to ownclo...
147
  		} else if(!$this->ldap->isResource($this->ldapConnectionRes)) {
03e52840d   Kload   Init
148
149
150
151
152
153
154
155
  			$this->ldapConnectionRes = null;
  			$this->establishConnection();
  		}
  		if(is_null($this->ldapConnectionRes)) {
  			\OCP\Util::writeLog('user_ldap', 'Connection could not be established', \OCP\Util::ERROR);
  		}
  		return $this->ldapConnectionRes;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
156
157
158
159
  	/**
  	 * @param string|null $key
  	 * @return string
  	 */
03e52840d   Kload   Init
160
161
162
163
164
165
166
  	private function getCacheKey($key) {
  		$prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-';
  		if(is_null($key)) {
  			return $prefix;
  		}
  		return $prefix.md5($key);
  	}
6d9380f96   Cédric Dupont   Update sources OC...
167
168
169
170
  	/**
  	 * @param string $key
  	 * @return mixed|null
  	 */
03e52840d   Kload   Init
171
172
173
174
  	public function getFromCache($key) {
  		if(!$this->configured) {
  			$this->readConfiguration();
  		}
31b7f2792   Kload   Upgrade to ownclo...
175
  		if(!$this->configuration->ldapCacheTTL) {
03e52840d   Kload   Init
176
177
178
179
180
181
182
183
184
185
  			return null;
  		}
  		if(!$this->isCached($key)) {
  			return null;
  
  		}
  		$key = $this->getCacheKey($key);
  
  		return unserialize(base64_decode($this->cache->get($key)));
  	}
6d9380f96   Cédric Dupont   Update sources OC...
186
187
188
189
  	/**
  	 * @param string $key
  	 * @return bool
  	 */
03e52840d   Kload   Init
190
191
192
193
  	public function isCached($key) {
  		if(!$this->configured) {
  			$this->readConfiguration();
  		}
31b7f2792   Kload   Upgrade to ownclo...
194
  		if(!$this->configuration->ldapCacheTTL) {
03e52840d   Kload   Init
195
196
197
198
199
  			return false;
  		}
  		$key = $this->getCacheKey($key);
  		return $this->cache->hasKey($key);
  	}
6d9380f96   Cédric Dupont   Update sources OC...
200
201
202
203
  	/**
  	 * @param string $key
  	 * @param mixed $value
  	 */
03e52840d   Kload   Init
204
205
206
207
  	public function writeToCache($key, $value) {
  		if(!$this->configured) {
  			$this->readConfiguration();
  		}
31b7f2792   Kload   Upgrade to ownclo...
208
209
  		if(!$this->configuration->ldapCacheTTL
  			|| !$this->configuration->ldapConfigurationActive) {
03e52840d   Kload   Init
210
211
212
213
  			return null;
  		}
  		$key   = $this->getCacheKey($key);
  		$value = base64_encode(serialize($value));
31b7f2792   Kload   Upgrade to ownclo...
214
  		$this->cache->set($key, $value, $this->configuration->ldapCacheTTL);
03e52840d   Kload   Init
215
216
217
218
219
  	}
  
  	public function clearCache() {
  		$this->cache->clear($this->getCacheKey(null));
  	}
03e52840d   Kload   Init
220
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
221
222
  	 * Caches the general LDAP configuration.
  	 * @param bool $force optional. true, if the re-read should be forced. defaults
31b7f2792   Kload   Upgrade to ownclo...
223
224
  	 * to false.
  	 * @return null
03e52840d   Kload   Init
225
226
227
  	 */
  	private function readConfiguration($force = false) {
  		if((!$this->configured || $force) && !is_null($this->configID)) {
31b7f2792   Kload   Upgrade to ownclo...
228
  			$this->configuration->readConfiguration();
03e52840d   Kload   Init
229
230
231
232
233
  			$this->configured = $this->validateConfiguration();
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
234
235
236
237
  	 * set LDAP configuration with values delivered by an array, not read from configuration
  	 * @param array $config array that holds the config parameters in an associated array
  	 * @param array &$setParameters optional; array where the set fields will be given to
  	 * @return boolean true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
03e52840d   Kload   Init
238
239
  	 */
  	public function setConfiguration($config, &$setParameters = null) {
31b7f2792   Kload   Upgrade to ownclo...
240
241
  		if(is_null($setParameters)) {
  			$setParameters = array();
03e52840d   Kload   Init
242
  		}
31b7f2792   Kload   Upgrade to ownclo...
243
244
245
246
  		$this->doNotValidate = false;
  		$this->configuration->setConfiguration($config, $setParameters);
  		if(count($setParameters) > 0) {
  			$this->configured = $this->validateConfiguration();
03e52840d   Kload   Init
247
  		}
03e52840d   Kload   Init
248
249
250
251
252
  
  		return $this->configured;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
253
  	 * saves the current Configuration in the database and empties the
31b7f2792   Kload   Upgrade to ownclo...
254
255
  	 * cache
  	 * @return null
03e52840d   Kload   Init
256
257
  	 */
  	public function saveConfiguration() {
31b7f2792   Kload   Upgrade to ownclo...
258
  		$this->configuration->saveConfiguration();
03e52840d   Kload   Init
259
260
261
262
  		$this->clearCache();
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
263
  	 * get the current LDAP configuration
03e52840d   Kload   Init
264
265
266
267
  	 * @return array
  	 */
  	public function getConfiguration() {
  		$this->readConfiguration();
31b7f2792   Kload   Upgrade to ownclo...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  		$config = $this->configuration->getConfiguration();
  		$cta = $this->configuration->getConfigTranslationArray();
  		$result = array();
  		foreach($cta as $dbkey => $configkey) {
  			switch($configkey) {
  				case 'homeFolderNamingRule':
  					if(strpos($config[$configkey], 'attr:') === 0) {
  						$result[$dbkey] = substr($config[$configkey], 5);
  					} else {
  						$result[$dbkey] = '';
  					}
  					break;
  				case 'ldapBase':
  				case 'ldapBaseUsers':
  				case 'ldapBaseGroups':
  				case 'ldapAttributesForUserSearch':
  				case 'ldapAttributesForGroupSearch':
  					if(is_array($config[$configkey])) {
  						$result[$dbkey] = implode("
  ", $config[$configkey]);
  						break;
  					} //else follows default
  				default:
  					$result[$dbkey] = $config[$configkey];
03e52840d   Kload   Init
292
  			}
03e52840d   Kload   Init
293
  		}
31b7f2792   Kload   Upgrade to ownclo...
294
  		return $result;
03e52840d   Kload   Init
295
  	}
31b7f2792   Kload   Upgrade to ownclo...
296
297
298
  	private function doSoftValidation() {
  		//if User or Group Base are not set, take over Base DN setting
  		foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) {
6d9380f96   Cédric Dupont   Update sources OC...
299
  			$val = $this->configuration->$keyBase;
31b7f2792   Kload   Upgrade to ownclo...
300
301
302
303
304
305
306
  			if(empty($val)) {
  				$obj = strpos('Users', $keyBase) !== false ? 'Users' : 'Groups';
  				\OCP\Util::writeLog('user_ldap',
  									'Base tree for '.$obj.
  									' is empty, using Base DN',
  									\OCP\Util::INFO);
  				$this->configuration->$keyBase = $this->configuration->ldapBase;
03e52840d   Kload   Init
307
308
  			}
  		}
31b7f2792   Kload   Upgrade to ownclo...
309
310
311
  
  		$groupFilter = $this->configuration->ldapGroupFilter;
  		if(empty($groupFilter)) {
03e52840d   Kload   Init
312
  			\OCP\Util::writeLog('user_ldap',
31b7f2792   Kload   Upgrade to ownclo...
313
314
315
  								'No group filter is specified, LDAP group '.
  								'feature will not be used.',
  								\OCP\Util::INFO);
03e52840d   Kload   Init
316
  		}
31b7f2792   Kload   Upgrade to ownclo...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  		foreach(array('ldapExpertUUIDUserAttr'  => 'ldapUuidUserAttribute',
  					  'ldapExpertUUIDGroupAttr' => 'ldapUuidGroupAttribute')
  				as $expertSetting => $effectiveSetting) {
  			$uuidOverride = $this->configuration->$expertSetting;
  			if(!empty($uuidOverride)) {
  				$this->configuration->$effectiveSetting = $uuidOverride;
  			} else {
  				$uuidAttributes = array('auto', 'entryuuid', 'nsuniqueid',
  										'objectguid', 'guid');
  				if(!in_array($this->configuration->$effectiveSetting,
  							$uuidAttributes)
  					&& (!is_null($this->configID))) {
  					$this->configuration->$effectiveSetting = 'auto';
  					$this->configuration->saveConfiguration();
  					\OCP\Util::writeLog('user_ldap',
  										'Illegal value for the '.
  										$effectiveSetting.', '.'reset to '.
  										'autodetect.', \OCP\Util::INFO);
  				}
03e52840d   Kload   Init
336

31b7f2792   Kload   Upgrade to ownclo...
337
338
  			}
  		}
03e52840d   Kload   Init
339

31b7f2792   Kload   Upgrade to ownclo...
340
341
342
  		$backupPort = $this->configuration->ldapBackupPort;
  		if(empty($backupPort)) {
  			$this->configuration->backupPort = $this->configuration->ldapPort;
03e52840d   Kload   Init
343
  		}
31b7f2792   Kload   Upgrade to ownclo...
344
345
  
  		//make sure empty search attributes are saved as simple, empty array
6d9380f96   Cédric Dupont   Update sources OC...
346
  		$saKeys = array('ldapAttributesForUserSearch',
31b7f2792   Kload   Upgrade to ownclo...
347
  						'ldapAttributesForGroupSearch');
6d9380f96   Cédric Dupont   Update sources OC...
348
  		foreach($saKeys as $key) {
31b7f2792   Kload   Upgrade to ownclo...
349
350
351
352
  			$val = $this->configuration->$key;
  			if(is_array($val) && count($val) === 1 && empty($val[0])) {
  				$this->configuration->$key = array();
  			}
03e52840d   Kload   Init
353
  		}
31b7f2792   Kload   Upgrade to ownclo...
354
355
356
357
  
  		if((stripos($this->configuration->ldapHost, 'ldaps://') === 0)
  			&& $this->configuration->ldapTLS) {
  			$this->configuration->ldapTLS = false;
03e52840d   Kload   Init
358
  			\OCP\Util::writeLog('user_ldap',
31b7f2792   Kload   Upgrade to ownclo...
359
360
361
  								'LDAPS (already using secure connection) and '.
  								'TLS do not work together. Switched off TLS.',
  								\OCP\Util::INFO);
03e52840d   Kload   Init
362
  		}
31b7f2792   Kload   Upgrade to ownclo...
363
  	}
6d9380f96   Cédric Dupont   Update sources OC...
364
365
366
  	/**
  	 * @return bool
  	 */
31b7f2792   Kload   Upgrade to ownclo...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
  	private function doCriticalValidation() {
  		$configurationOK = true;
  		$errorStr = 'Configuration Error (prefix '.
  					strval($this->configPrefix).'): ';
  
  		//options that shall not be empty
  		$options = array('ldapHost', 'ldapPort', 'ldapUserDisplayName',
  						 'ldapGroupDisplayName', 'ldapLoginFilter');
  		foreach($options as $key) {
  			$val = $this->configuration->$key;
  			if(empty($val)) {
  				switch($key) {
  					case 'ldapHost':
  						$subj = 'LDAP Host';
  						break;
  					case 'ldapPort':
  						$subj = 'LDAP Port';
  						break;
  					case 'ldapUserDisplayName':
  						$subj = 'LDAP User Display Name';
  						break;
  					case 'ldapGroupDisplayName':
  						$subj = 'LDAP Group Display Name';
  						break;
  					case 'ldapLoginFilter':
  						$subj = 'LDAP Login Filter';
  						break;
  					default:
  						$subj = $key;
  						break;
  				}
  				$configurationOK = false;
  				\OCP\Util::writeLog('user_ldap',
  									$errorStr.'No '.$subj.' given!',
  									\OCP\Util::WARN);
  			}
03e52840d   Kload   Init
403
  		}
31b7f2792   Kload   Upgrade to ownclo...
404
405
406
407
408
  
  		//combinations
  		$agent = $this->configuration->ldapAgentName;
  		$pwd = $this->configuration->ldapAgentPassword;
  		if((empty($agent) && !empty($pwd)) || (!empty($agent) && empty($pwd))) {
03e52840d   Kload   Init
409
  			\OCP\Util::writeLog('user_ldap',
31b7f2792   Kload   Upgrade to ownclo...
410
411
412
  								$errorStr.'either no password is given for the'.
  								'user agent or a password is given, but not an'.
  								'LDAP agent.',
03e52840d   Kload   Init
413
414
415
  				\OCP\Util::WARN);
  			$configurationOK = false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
416
417
418
419
420
421
  
  		$base = $this->configuration->ldapBase;
  		$baseUsers = $this->configuration->ldapBaseUsers;
  		$baseGroups = $this->configuration->ldapBaseGroups;
  
  		if(empty($base) && empty($baseUsers) && empty($baseGroups)) {
03e52840d   Kload   Init
422
  			\OCP\Util::writeLog('user_ldap',
31b7f2792   Kload   Upgrade to ownclo...
423
424
  								$errorStr.'Not a single Base DN given.',
  								\OCP\Util::WARN);
03e52840d   Kload   Init
425
426
  			$configurationOK = false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
427
428
429
  
  		if(mb_strpos($this->configuration->ldapLoginFilter, '%uid', 0, 'UTF-8')
  		   === false) {
03e52840d   Kload   Init
430
  			\OCP\Util::writeLog('user_ldap',
31b7f2792   Kload   Upgrade to ownclo...
431
432
433
  								$errorStr.'login filter does not contain %uid '.
  								'place holder.',
  								\OCP\Util::WARN);
03e52840d   Kload   Init
434
435
  			$configurationOK = false;
  		}
03e52840d   Kload   Init
436
437
438
439
  		return $configurationOK;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
440
441
  	 * Validates the user specified configuration
  	 * @return bool true if configuration seems OK, false otherwise
03e52840d   Kload   Init
442
  	 */
31b7f2792   Kload   Upgrade to ownclo...
443
444
445
446
447
448
449
450
451
452
453
454
  	private function validateConfiguration() {
  
  		if($this->doNotValidate) {
  			//don't do a validation if it is a new configuration with pure
  			//default values. Will be allowed on changes via __set or
  			//setConfiguration
  			return false;
  		}
  
  		// first step: "soft" checks: settings that are not really
  		// necessary, but advisable. If left empty, give an info message
  		$this->doSoftValidation();
6d9380f96   Cédric Dupont   Update sources OC...
455
456
  		//second step: critical checks. If left empty or filled wrong, mark as
  		//not configured and give a warning.
31b7f2792   Kload   Upgrade to ownclo...
457
  		return $this->doCriticalValidation();
03e52840d   Kload   Init
458
  	}
31b7f2792   Kload   Upgrade to ownclo...
459

03e52840d   Kload   Init
460
461
462
463
  	/**
  	 * Connects and Binds to LDAP
  	 */
  	private function establishConnection() {
31b7f2792   Kload   Upgrade to ownclo...
464
  		if(!$this->configuration->ldapConfigurationActive) {
03e52840d   Kload   Init
465
466
467
468
469
470
  			return null;
  		}
  		static $phpLDAPinstalled = true;
  		if(!$phpLDAPinstalled) {
  			return false;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
471
  		if(!$this->ignoreValidation && !$this->configured) {
31b7f2792   Kload   Upgrade to ownclo...
472
473
474
  			\OCP\Util::writeLog('user_ldap',
  								'Configuration is invalid, cannot connect',
  								\OCP\Util::WARN);
03e52840d   Kload   Init
475
476
477
  			return false;
  		}
  		if(!$this->ldapConnectionRes) {
31b7f2792   Kload   Upgrade to ownclo...
478
  			if(!$this->ldap->areLDAPFunctionsAvailable()) {
03e52840d   Kload   Init
479
480
  				$phpLDAPinstalled = false;
  				\OCP\Util::writeLog('user_ldap',
31b7f2792   Kload   Upgrade to ownclo...
481
482
483
  									'function ldap_connect is not available. Make '.
  									'sure that the PHP ldap module is installed.',
  									\OCP\Util::ERROR);
03e52840d   Kload   Init
484
485
486
  
  				return false;
  			}
31b7f2792   Kload   Upgrade to ownclo...
487
  			if($this->configuration->turnOffCertCheck) {
03e52840d   Kload   Init
488
489
490
491
492
  				if(putenv('LDAPTLS_REQCERT=never')) {
  					\OCP\Util::writeLog('user_ldap',
  						'Turned off SSL certificate validation successfully.',
  						\OCP\Util::WARN);
  				} else {
31b7f2792   Kload   Upgrade to ownclo...
493
494
495
  					\OCP\Util::writeLog('user_ldap',
  										'Could not turn off SSL certificate validation.',
  										\OCP\Util::WARN);
03e52840d   Kload   Init
496
497
  				}
  			}
31b7f2792   Kload   Upgrade to ownclo...
498
499
500
501
  			if(!$this->configuration->ldapOverrideMainServer
  			   && !$this->getFromCache('overrideMainServer')) {
  				$this->doConnect($this->configuration->ldapHost,
  								 $this->configuration->ldapPort);
03e52840d   Kload   Init
502
  				$bindStatus = $this->bind();
31b7f2792   Kload   Upgrade to ownclo...
503
504
  				$error = $this->ldap->isResource($this->ldapConnectionRes) ?
  							$this->ldap->errno($this->ldapConnectionRes) : -1;
03e52840d   Kload   Init
505
506
507
508
509
510
511
  			} else {
  				$bindStatus = false;
  				$error = null;
  			}
  
  			//if LDAP server is not reachable, try the Backup (Replica!) Server
  			if((!$bindStatus && ($error !== 0))
31b7f2792   Kload   Upgrade to ownclo...
512
  				|| $this->configuration->ldapOverrideMainServer
03e52840d   Kload   Init
513
  				|| $this->getFromCache('overrideMainServer')) {
31b7f2792   Kload   Upgrade to ownclo...
514
515
  					$this->doConnect($this->configuration->ldapBackupHost,
  									 $this->configuration->ldapBackupPort);
03e52840d   Kload   Init
516
517
518
519
520
521
522
523
524
525
  					$bindStatus = $this->bind();
  					if(!$bindStatus && $error === -1) {
  						//when bind to backup server succeeded and failed to main server,
  						//skip contacting him until next cache refresh
  						$this->writeToCache('overrideMainServer', true);
  					}
  			}
  			return $bindStatus;
  		}
  	}
6d9380f96   Cédric Dupont   Update sources OC...
526
527
528
529
530
  	/**
  	 * @param string $host
  	 * @param string $port
  	 * @return false|void
  	 */
03e52840d   Kload   Init
531
532
533
534
535
  	private function doConnect($host, $port) {
  		if(empty($host)) {
  			return false;
  		}
  		if(strpos($host, '://') !== false) {
6d9380f96   Cédric Dupont   Update sources OC...
536
  			//ldap_connect ignores port parameter when URLs are passed
03e52840d   Kload   Init
537
538
  			$host .= ':' . $port;
  		}
31b7f2792   Kload   Upgrade to ownclo...
539
540
541
542
543
  		$this->ldapConnectionRes = $this->ldap->connect($host, $port);
  		if($this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
  			if($this->ldap->setOption($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
  				if($this->configuration->ldapTLS) {
  					$this->ldap->startTls($this->ldapConnectionRes);
03e52840d   Kload   Init
544
545
546
547
548
549
550
551
552
553
  				}
  			}
  		}
  	}
  
  	/**
  	 * Binds to LDAP
  	 */
  	public function bind() {
  		static $getConnectionResourceAttempt = false;
31b7f2792   Kload   Upgrade to ownclo...
554
  		if(!$this->configuration->ldapConfigurationActive) {
03e52840d   Kload   Init
555
556
557
558
559
560
561
562
563
  			return false;
  		}
  		if($getConnectionResourceAttempt) {
  			$getConnectionResourceAttempt = false;
  			return false;
  		}
  		$getConnectionResourceAttempt = true;
  		$cr = $this->getConnectionResource();
  		$getConnectionResourceAttempt = false;
31b7f2792   Kload   Upgrade to ownclo...
564
  		if(!$this->ldap->isResource($cr)) {
03e52840d   Kload   Init
565
566
  			return false;
  		}
31b7f2792   Kload   Upgrade to ownclo...
567
568
569
  		$ldapLogin = @$this->ldap->bind($cr,
  										$this->configuration->ldapAgentName,
  										$this->configuration->ldapAgentPassword);
03e52840d   Kload   Init
570
571
  		if(!$ldapLogin) {
  			\OCP\Util::writeLog('user_ldap',
31b7f2792   Kload   Upgrade to ownclo...
572
  				'Bind failed: ' . $this->ldap->errno($cr) . ': ' . $this->ldap->error($cr),
03e52840d   Kload   Init
573
574
575
576
577
578
579
580
  				\OCP\Util::ERROR);
  			$this->ldapConnectionRes = null;
  			return false;
  		}
  		return true;
  	}
  
  }