1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @link https://github.com/chrmorandi/yii2-ldap for the canonical source repository |
4
|
|
|
* @package yii2-ldap |
5
|
|
|
* @author Christopher Mota <[email protected]> |
6
|
|
|
* @license MIT License - view the LICENSE file that was distributed with this source code. |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace chrmorandi\ldap; |
10
|
|
|
|
11
|
|
|
use yii\base\Component; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* @property string $errNo Error number of the last command |
15
|
|
|
* |
16
|
|
|
* @author Christopher Mota <[email protected]> |
17
|
|
|
* @since 1.0 |
18
|
|
|
*/ |
19
|
|
|
class Connection extends Component |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* LDAP protocol string. |
23
|
|
|
* @var string |
24
|
|
|
*/ |
25
|
|
|
const PROTOCOL = 'ldap://'; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* LDAP port number. |
29
|
|
|
* @var string |
30
|
|
|
*/ |
31
|
|
|
const PORT = '389'; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @event Event an event that is triggered after a DB connection is established |
35
|
|
|
*/ |
36
|
|
|
const EVENT_AFTER_OPEN = 'afterOpen'; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @var string the LDAP base dn. |
40
|
|
|
*/ |
41
|
|
|
public $baseDn; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* https://msdn.microsoft.com/en-us/library/ms677913(v=vs.85).aspx |
45
|
|
|
* @var bool the integer to instruct the LDAP connection whether or not to follow referrals. |
46
|
|
|
*/ |
47
|
|
|
public $followReferrals = false; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @var string The LDAP port to use when connecting to the domain controllers. |
51
|
|
|
*/ |
52
|
|
|
public $port = self::PORT; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @var bool Determines whether or not to use TLS with the current LDAP connection. |
56
|
|
|
*/ |
57
|
|
|
public $useTLS = false; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @var array the domain controllers to connect to. |
61
|
|
|
*/ |
62
|
|
|
public $dc = []; |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* @var string the LDAP account suffix. |
66
|
|
|
*/ |
67
|
|
|
protected $accountSuffix; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @var string the LDAP account prefix. |
71
|
|
|
*/ |
72
|
|
|
protected $accountPrefix; |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* @var string the username for establishing LDAP connection. Defaults to `null` meaning no username to use. |
76
|
|
|
*/ |
77
|
|
|
public $username; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* @var string the password for establishing DB connection. Defaults to `null` meaning no password to use. |
81
|
|
|
*/ |
82
|
|
|
public $password; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @var bool stores the bool whether or not the current connection is bound. |
86
|
|
|
*/ |
87
|
|
|
protected $bound = false; |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* @var resource |
91
|
|
|
*/ |
92
|
|
|
protected $resource; |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Get the current resource of connection. |
96
|
|
|
* @return mixed |
97
|
|
|
*/ |
98
|
|
|
public function getResource() |
99
|
|
|
{ |
100
|
|
|
return $this->resource; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Connects and Binds to the Domain Controller with a administrator credentials. |
105
|
|
|
* @throws LdapException |
106
|
|
|
*/ |
107
|
|
|
public function open($anonymous = false) |
108
|
|
|
{ |
109
|
|
|
// Connect to the LDAP server. |
110
|
|
|
if ($this->connect($this->dc, $this->port)) { |
111
|
|
|
if ($anonymous) { |
|
|
|
|
112
|
|
|
//TODO |
113
|
|
|
} else { |
114
|
|
|
$this->bound = ldap_bind($this->resource, $this->username, $this->password); |
115
|
|
|
} |
116
|
|
|
} else { |
117
|
|
|
throw new LdapException(sprintf('Unable to connect to server: %s', $this->lastError), $this->errNo); |
|
|
|
|
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Returns true/false if the current connection is bound. |
123
|
|
|
* @return bool |
124
|
|
|
*/ |
125
|
|
|
public function isBound() |
126
|
|
|
{ |
127
|
|
|
return $this->bound; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Connection. |
132
|
|
|
* @param string $hostname |
133
|
|
|
* @param type $port |
134
|
|
|
* @return boolean |
135
|
|
|
* @throws LdapException |
136
|
|
|
*/ |
137
|
|
|
public function connect($hostname = [], $port = '389') |
138
|
|
|
{ |
139
|
|
|
$protocol = $this::PROTOCOL; |
140
|
|
|
|
141
|
|
|
if (is_array($hostname)) { |
142
|
|
|
$hostname = $protocol . implode(' ' . $protocol, $hostname); |
143
|
|
|
} |
144
|
|
|
$this->resource = ldap_connect($hostname, $port); |
145
|
|
|
|
146
|
|
|
if (!$this->resource) { |
147
|
|
|
return false; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
// Set the LDAP options. |
151
|
|
|
$this->setOption(LDAP_OPT_PROTOCOL_VERSION, 3); |
152
|
|
|
$this->setOption(LDAP_OPT_REFERRALS, $followReferrals); |
|
|
|
|
153
|
|
|
|
154
|
|
|
if ($this->useTLS && !$this->startTLS()) { |
155
|
|
|
throw new LdapException($this->lastError, $this->getErrNo()); |
|
|
|
|
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
$this->trigger(self::EVENT_AFTER_OPEN); |
159
|
|
|
|
160
|
|
|
return is_resource($this->resource); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Closes the current connection. |
165
|
|
|
* |
166
|
|
|
* @return boolean |
167
|
|
|
*/ |
168
|
|
|
public function close() |
169
|
|
|
{ |
170
|
|
|
if (is_resource($this->resource)) { |
171
|
|
|
ldap_close($this->resource); |
172
|
|
|
} |
173
|
|
|
return true; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Execute ldap functions like. |
178
|
|
|
* |
179
|
|
|
* http://php.net/manual/en/ref.ldap.php |
180
|
|
|
* |
181
|
|
|
* @param string $function php LDAP function |
182
|
|
|
* @param array $params params for execute ldap function |
183
|
|
|
* @return bool|DataReader |
184
|
|
|
* @throws LdapException |
185
|
|
|
*/ |
186
|
|
|
public function execute($function, $params) |
187
|
|
|
{ |
188
|
|
|
$this->open(); |
189
|
|
|
|
190
|
|
|
$result = call_user_func($function, $this->resource, ...$params); |
191
|
|
|
if (!$result) { |
192
|
|
|
throw new LdapException($this->getLastError(), $this->getErrNo()); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
if (is_resource($result)) { |
196
|
|
|
return new DataReader($this, $result); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
return $result; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Close the connection before serializing. |
204
|
|
|
* @return array |
205
|
|
|
*/ |
206
|
|
|
public function __sleep() |
207
|
|
|
{ |
208
|
|
|
$this->close(); |
209
|
|
|
return array_keys((array) $this); |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Sorts an AD search result by the specified attribute. |
214
|
|
|
* @param resource $result |
215
|
|
|
* @param string $attribute |
216
|
|
|
* @return bool |
217
|
|
|
*/ |
218
|
|
|
public function sort($result, $attribute) |
219
|
|
|
{ |
220
|
|
|
return ldap_sort($this->resource, $result, $attribute); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Adds an entry to the current connection. |
225
|
|
|
* @param string $dn |
226
|
|
|
* @param array $entry |
227
|
|
|
* @return bool |
228
|
|
|
*/ |
229
|
|
|
public function add($dn, array $entry) |
230
|
|
|
{ |
231
|
|
|
return ldap_add($this->resource, $dn, $entry); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* Deletes an entry on the current connection. |
236
|
|
|
* @param string $dn |
237
|
|
|
* @return bool |
238
|
|
|
*/ |
239
|
|
|
public function delete($dn) |
240
|
|
|
{ |
241
|
|
|
return ldap_delete($this->resource, $dn); |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Modify the name of an entry on the current connection. |
246
|
|
|
* |
247
|
|
|
* @param string $dn |
248
|
|
|
* @param string $newRdn |
249
|
|
|
* @param string $newParent |
250
|
|
|
* @param bool $deleteOldRdn |
251
|
|
|
* @return bool |
252
|
|
|
*/ |
253
|
|
|
public function rename($dn, $newRdn, $newParent, $deleteOldRdn = false) |
254
|
|
|
{ |
255
|
|
|
return ldap_rename($this->resource, $dn, $newRdn, $newParent, $deleteOldRdn); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Modifies an existing entry on the |
260
|
|
|
* current connection. |
261
|
|
|
* @param string $dn |
262
|
|
|
* @param array $entry |
263
|
|
|
* @return bool |
264
|
|
|
*/ |
265
|
|
|
public function modify($dn, array $entry) |
266
|
|
|
{ |
267
|
|
|
return ldap_modify($this->resource, $dn, $entry); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Batch modifies an existing entry on the current connection. |
272
|
|
|
* @param string $dn |
273
|
|
|
* @param array $values |
274
|
|
|
* @return mixed |
275
|
|
|
*/ |
276
|
|
|
public function modifyBatch($dn, array $values) |
277
|
|
|
{ |
278
|
|
|
return ldap_modify_batch($this->resource, $dn, $values); |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* Add attribute values to current attributes. |
283
|
|
|
* @param string $dn |
284
|
|
|
* @param array $entry |
285
|
|
|
* @return mixed |
286
|
|
|
*/ |
287
|
|
|
public function modAdd($dn, array $entry) |
288
|
|
|
{ |
289
|
|
|
return ldap_mod_add($this->resource, $dn, $entry); |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* Replaces attribute values with new ones. |
294
|
|
|
* @param string $dn |
295
|
|
|
* @param array $entry |
296
|
|
|
* @return mixed |
297
|
|
|
*/ |
298
|
|
|
public function modReplace($dn, array $entry) |
299
|
|
|
{ |
300
|
|
|
return ldap_mod_replace($this->resource, $dn, $entry); |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* Delete attribute values from current attributes. |
305
|
|
|
* @param string $dn |
306
|
|
|
* @param array $entry |
307
|
|
|
* @return mixed |
308
|
|
|
*/ |
309
|
|
|
public function modDelete($dn, array $entry) |
310
|
|
|
{ |
311
|
|
|
return ldap_mod_del($this->resource, $dn, $entry); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Retrieve the entries from a search result. |
316
|
|
|
* @param $searchResult |
317
|
|
|
* @return mixed |
318
|
|
|
*/ |
319
|
|
|
public function getEntries($searchResult) |
320
|
|
|
{ |
321
|
|
|
return ldap_get_entries($this->resource, $searchResult); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Returns the number of entries from a search result. |
326
|
|
|
* @param $searchResult |
327
|
|
|
* @return int |
328
|
|
|
*/ |
329
|
|
|
public function countEntries($searchResult) |
330
|
|
|
{ |
331
|
|
|
return ldap_count_entries($this->resource, $searchResult); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Retrieves the first entry from a search result. |
336
|
|
|
* @param $searchResult |
337
|
|
|
* @return mixed |
338
|
|
|
*/ |
339
|
|
|
public function getFirstEntry($searchResult) |
340
|
|
|
{ |
341
|
|
|
return ldap_first_entry($this->resource, $searchResult); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Retrieves the next entry from a search result. |
346
|
|
|
* @param $entry |
347
|
|
|
* @return mixed |
348
|
|
|
*/ |
349
|
|
|
public function getNextEntry($entry) |
350
|
|
|
{ |
351
|
|
|
return ldap_next_entry($this->resource, $entry); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Retrieves the ldap entry's attributes. |
356
|
|
|
* @param $entry |
357
|
|
|
* @return mixed |
358
|
|
|
*/ |
359
|
|
|
public function getAttributes($entry) |
360
|
|
|
{ |
361
|
|
|
return ldap_get_attributes($this->resource, $entry); |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* Sets an option on the current connection. |
366
|
|
|
* @param int $option |
367
|
|
|
* @param mixed $value |
368
|
|
|
* @return mixed |
369
|
|
|
*/ |
370
|
|
|
public function setOption($option, $value) |
371
|
|
|
{ |
372
|
|
|
return ldap_set_option($this->resource, $option, $value); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
/** |
376
|
|
|
* Starts a connection using TLS. |
377
|
|
|
* @return bool |
378
|
|
|
*/ |
379
|
|
|
public function startTLS() |
380
|
|
|
{ |
381
|
|
|
return ldap_start_tls($this->resource); |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* Retrieve the last error on the current connection. |
386
|
|
|
* @return string |
387
|
|
|
*/ |
388
|
|
|
public function getLastError() |
389
|
|
|
{ |
390
|
|
|
return ldap_error($this->resource); |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
/** |
394
|
|
|
* Returns the number of the last error on the current connection. |
395
|
|
|
* @return mixed |
396
|
|
|
*/ |
397
|
|
|
public function getErrNo() |
398
|
|
|
{ |
399
|
|
|
return ldap_errno($this->resource); |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
/** |
403
|
|
|
* Returns the error string of the specified error number. |
404
|
|
|
* @param int $number |
405
|
|
|
* @return string |
406
|
|
|
*/ |
407
|
|
|
public function err2Str($number) |
408
|
|
|
{ |
409
|
|
|
return ldap_err2str($number); |
410
|
|
|
} |
411
|
|
|
} |
412
|
|
|
|
This check looks for the bodies of
if
statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.These
if
bodies can be removed. If you have an empty if but statements in theelse
branch, consider inverting the condition.could be turned into
This is much more concise to read.