php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
ldap.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Amitay Isaacs <amitay@w-o-i.com> |
14 | Eric Warnke <ericw@albany.edu> |
15 | Rasmus Lerdorf <rasmus@php.net> |
16 | Gerrit Thomson <334647@swin.edu.au> |
17 | Jani Taskinen <sniper@iki.fi> |
18 | Stig Venaas <venaas@uninett.no> |
19 | Doug Goldstein <cardoe@cardoe.com> |
20 | Côme Chilliet <mcmic@php.net> |
21 | PHP 4.0 updates: Zeev Suraski <zeev@php.net> |
22 +----------------------------------------------------------------------+
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include "php.h"
30#include "php_ini.h"
32
33#include <stddef.h>
34
35#include "ext/standard/dl.h"
36#include "php_ldap.h"
37
38#ifdef PHP_WIN32
39#include <string.h>
40#include "config.w32.h"
41#undef strcasecmp
42#undef strncasecmp
43#define WINSOCK 1
44#define __STDC__ 1
45#endif
46
47#include "ext/standard/info.h"
48
49#ifdef HAVE_LDAP_SASL
50#include <sasl/sasl.h>
51#endif
52
53#define PHP_LDAP_ESCAPE_FILTER 0x01
54#define PHP_LDAP_ESCAPE_DN 0x02
55
56#include "ldap_arginfo.h"
57
58#if defined(LDAP_CONTROL_PAGEDRESULTS) && !defined(HAVE_LDAP_CONTROL_FIND)
59LDAPControl *ldap_control_find( const char *oid, LDAPControl **ctrls, LDAPControl ***nextctrlp)
60{
61 assert(nextctrlp == NULL);
62 return ldap_find_control(oid, ctrls);
63}
64#endif
65
66#if !defined(LDAP_API_FEATURE_X_OPENLDAP)
67void ldap_memvfree(void **v)
68{
69 ldap_value_free((char **)v);
70}
71#endif
72
73typedef struct {
75#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
76 zval rebindproc;
77#endif
80
81typedef struct {
82 LDAPMessage *result;
85
86typedef struct {
87 LDAPMessage *data;
88 BerElement *ber;
92
94static PHP_GINIT_FUNCTION(ldap);
95
96static zend_class_entry *ldap_link_ce, *ldap_result_ce, *ldap_result_entry_ce;
97static zend_object_handlers ldap_link_object_handlers, ldap_result_object_handlers, ldap_result_entry_object_handlers;
98
99#ifdef COMPILE_DL_LDAP
100#ifdef ZTS
102#endif
103ZEND_GET_MODULE(ldap)
104#endif
105
106static inline ldap_linkdata *ldap_link_from_obj(zend_object *obj) {
107 return (ldap_linkdata *)((char *)(obj) - XtOffsetOf(ldap_linkdata, std));
108}
109
110#define Z_LDAP_LINK_P(zv) ldap_link_from_obj(Z_OBJ_P(zv))
111
112static zend_object *ldap_link_create_object(zend_class_entry *class_type) {
113 ldap_linkdata *intern = zend_object_alloc(sizeof(ldap_linkdata), class_type);
114
115 zend_object_std_init(&intern->std, class_type);
116 object_properties_init(&intern->std, class_type);
117
118 return &intern->std;
119}
120
121static zend_function *ldap_link_get_constructor(zend_object *object) {
122 zend_throw_error(NULL, "Cannot directly construct LDAP\\Connection, use ldap_connect() instead");
123 return NULL;
124}
125
126static void ldap_link_free(ldap_linkdata *ld)
127{
128 /* We use ldap_destroy rather than ldap_unbind here, because ldap_unbind
129 * will skip the destructor entirely if a critical client control is set. */
130 ldap_destroy(ld->link);
131 ld->link = NULL;
132
133#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
134 zval_ptr_dtor(&ld->rebindproc);
135#endif
136
137 LDAPG(num_links)--;
138}
139
140static void ldap_link_free_obj(zend_object *obj)
141{
142 ldap_linkdata *ld = ldap_link_from_obj(obj);
143
144 if (ld->link) {
145 ldap_link_free(ld);
146 }
147
149}
150
151static inline ldap_resultdata *ldap_result_from_obj(zend_object *obj) {
152 return (ldap_resultdata *)((char *)(obj) - XtOffsetOf(ldap_resultdata, std));
153}
154
155#define Z_LDAP_RESULT_P(zv) ldap_result_from_obj(Z_OBJ_P(zv))
156
157static zend_object *ldap_result_create_object(zend_class_entry *class_type) {
158 ldap_resultdata *intern = zend_object_alloc(sizeof(ldap_resultdata), class_type);
159
160 zend_object_std_init(&intern->std, class_type);
161 object_properties_init(&intern->std, class_type);
162
163 return &intern->std;
164}
165
166static zend_function *ldap_result_get_constructor(zend_object *object) {
167 zend_throw_error(NULL, "Cannot directly construct LDAP\\Result, use the dedicated functions instead");
168 return NULL;
169}
170
171static void ldap_result_free(ldap_resultdata *result)
172{
173 ldap_msgfree(result->result);
174 result->result = NULL;
175}
176
177static void ldap_result_free_obj(zend_object *obj)
178{
179 ldap_resultdata *result = ldap_result_from_obj(obj);
180
181 if (result->result) {
182 ldap_result_free(result);
183 }
184
186}
187
188static inline ldap_result_entry *ldap_result_entry_from_obj(zend_object *obj) {
189 return (ldap_result_entry *)((char *)(obj) - XtOffsetOf(ldap_result_entry, std));
190}
191
192#define Z_LDAP_RESULT_ENTRY_P(zv) ldap_result_entry_from_obj(Z_OBJ_P(zv))
193
194static zend_object *ldap_result_entry_create_object(zend_class_entry *class_type) {
195 ldap_result_entry *intern = zend_object_alloc(sizeof(ldap_result_entry), class_type);
196
197 zend_object_std_init(&intern->std, class_type);
198 object_properties_init(&intern->std, class_type);
199
200 return &intern->std;
201}
202
203static zend_function *ldap_result_entry_get_constructor(zend_object *obj) {
204 zend_throw_error(NULL, "Cannot directly construct LDAP\\ResultEntry, use the dedicated functions instead");
205 return NULL;
206}
207
208static void ldap_result_entry_free_obj(zend_object *obj)
209{
210 ldap_result_entry *entry = ldap_result_entry_from_obj(obj);
211
212 if (entry->ber != NULL) {
213 ber_free(entry->ber, 0);
214 entry->ber = NULL;
215 }
216 zval_ptr_dtor(&entry->res);
217
218 zend_object_std_dtor(&entry->std);
219}
220
221#define VERIFY_LDAP_LINK_CONNECTED(ld) \
222{ \
223 if (!ld->link) { \
224 zend_throw_error(NULL, "LDAP connection has already been closed"); \
225 RETURN_THROWS(); \
226 } \
227}
228
229#define VERIFY_LDAP_RESULT_OPEN(lr) \
230{ \
231 if (!lr->result) { \
232 zend_throw_error(NULL, "LDAP result has already been closed"); \
233 RETURN_THROWS(); \
234 } \
235}
236
237static bool php_ldap_is_numerically_indexed_array(zend_array *arr)
238{
239 if (zend_hash_num_elements(arr) == 0 || HT_IS_PACKED(arr)) {
240 return true;
241 }
242
243 zend_string *str_key;
244 ZEND_HASH_MAP_FOREACH_STR_KEY(arr, str_key) {
245 if (str_key) {
246 return false;
247 }
249
250 return true;
251}
252
253/* {{{ Parse controls from and to arrays */
254static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, int request)
255{
256 array_init(array);
257
258 add_assoc_string(array, "oid", ctrl->ldctl_oid);
259 if (request) {
260 /* iscritical field only makes sense in request controls (which may be obtained by ldap_get_option) */
261 add_assoc_bool(array, "iscritical", (ctrl->ldctl_iscritical != 0));
262 }
263
264 /* If it is a known oid, parse to values */
265 if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
266 int expire = 0, grace = 0, rc;
267 LDAPPasswordPolicyError pperr;
268 zval value;
269
270 rc = ldap_parse_passwordpolicy_control(ld, ctrl, &expire, &grace, &pperr);
271 if ( rc == LDAP_SUCCESS ) {
273 add_assoc_long(&value, "expire", expire);
274 add_assoc_long(&value, "grace", grace);
275
276 if ( pperr != PP_noError ) {
277 add_assoc_long(&value, "error", pperr);
278 }
279 add_assoc_zval(array, "value", &value);
280 } else {
281 add_assoc_null(array, "value");
282 }
283 } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) {
284 int lestimated, rc;
285 struct berval lcookie = { 0L, NULL };
286 zval value;
287
288 if (ctrl->ldctl_value.bv_len) {
289 /* ldap_parse_pageresponse_control() allocates lcookie.bv_val */
290 rc = ldap_parse_pageresponse_control(ld, ctrl, &lestimated, &lcookie);
291 } else {
292 /* ldap_parse_pageresponse_control will crash if value is empty */
293 rc = -1;
294 }
295
296 if ( rc == LDAP_SUCCESS ) {
298 add_assoc_long(&value, "size", lestimated);
299 add_assoc_stringl(&value, "cookie", lcookie.bv_val, lcookie.bv_len);
300 add_assoc_zval(array, "value", &value);
301 } else {
302 add_assoc_null(array, "value");
303 }
304
305 if (lcookie.bv_val) {
306 ldap_memfree(lcookie.bv_val);
307 }
308 } else if ((strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_POST_READ) == 0)) {
309 BerElement *ber;
310 struct berval bv;
311
312 ber = ber_init(&ctrl->ldctl_value);
313 if (ber == NULL) {
314 add_assoc_null(array, "value");
315 } else if (ber_scanf(ber, "{m{" /*}}*/, &bv) == LBER_ERROR) {
316 add_assoc_null(array, "value");
317 } else {
318 zval value;
319
321 add_assoc_stringl(&value, "dn", bv.bv_val, bv.bv_len);
322
323 while (ber_scanf(ber, "{m" /*}*/, &bv) != LBER_ERROR) {
324 int i;
325 BerVarray vals = NULL;
326 zval tmp;
327
328 if (ber_scanf(ber, "[W]", &vals) == LBER_ERROR || vals == NULL)
329 {
330 break;
331 }
332
333 array_init(&tmp);
334 for (i = 0; vals[i].bv_val != NULL; i++) {
335 add_next_index_stringl(&tmp, vals[i].bv_val, vals[i].bv_len);
336 }
337 add_assoc_zval(&value, bv.bv_val, &tmp);
338
339 ber_bvarray_free(vals);
340 }
341 add_assoc_zval(array, "value", &value);
342 }
343
344 if (ber != NULL) {
345 ber_free(ber, 1);
346 }
347 } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_SORTRESPONSE) == 0) {
348 zval value;
349 int errcode, rc;
350 char* attribute;
351
352 if (ctrl->ldctl_value.bv_len) {
353 rc = ldap_parse_sortresponse_control(ld, ctrl, &errcode, &attribute);
354 } else {
355 rc = -1;
356 }
357 if ( rc == LDAP_SUCCESS ) {
359 add_assoc_long(&value, "errcode", errcode);
360 if (attribute) {
361 add_assoc_string(&value, "attribute", attribute);
362 ldap_memfree(attribute);
363 }
364 add_assoc_zval(array, "value", &value);
365 } else {
366 add_assoc_null(array, "value");
367 }
368 } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_VLVRESPONSE) == 0) {
369 int target, count, errcode, rc;
370 struct berval *context;
371 zval value;
372
373 if (ctrl->ldctl_value.bv_len) {
374 rc = ldap_parse_vlvresponse_control(ld, ctrl, &target, &count, &context, &errcode);
375 } else {
376 rc = -1;
377 }
378 if ( rc == LDAP_SUCCESS ) {
380 add_assoc_long(&value, "target", target);
381 add_assoc_long(&value, "count", count);
382 add_assoc_long(&value, "errcode", errcode);
383 if (context) {
384 add_assoc_stringl(&value, "context", context->bv_val, context->bv_len);
385 }
386 add_assoc_zval(array, "value", &value);
387 ber_bvfree(context);
388 } else {
389 add_assoc_null(array, "value");
390 }
391 } else {
392 if (ctrl->ldctl_value.bv_len) {
393 add_assoc_stringl(array, "value", ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len);
394 } else {
395 add_assoc_null(array, "value");
396 }
397 }
398}
399
400static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* array)
401{
402 zval* val;
403 zend_string *control_oid;
404 int control_iscritical = 0, rc = LDAP_SUCCESS;
405 char** ldap_attrs = NULL;
406 LDAPSortKey** sort_keys = NULL;
407 zend_string *tmpstring = NULL, **tmpstrings1 = NULL, **tmpstrings2 = NULL;
408 size_t num_tmpstrings1 = 0, num_tmpstrings2 = 0;
409
410 if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "oid", sizeof("oid") - 1)) == NULL) {
411 zend_value_error("%s(): Control must have an \"oid\" key", get_active_function_name());
412 return -1;
413 }
414
415 control_oid = zval_get_string(val);
416 if (EG(exception)) {
417 return -1;
418 }
419
420 if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "iscritical", sizeof("iscritical") - 1)) != NULL) {
421 control_iscritical = zend_is_true(val);
422 } else {
423 control_iscritical = 0;
424 }
425
426 BerElement *ber = NULL;
427 struct berval control_value = { 0L, NULL };
428 int control_value_alloc = 0;
429
430 if ((val = zend_hash_find(Z_ARRVAL_P(array), ZSTR_KNOWN(ZEND_STR_VALUE))) != NULL) {
431 if (Z_TYPE_P(val) != IS_ARRAY) {
432 tmpstring = zval_get_string(val);
433 if (EG(exception)) {
434 rc = -1;
435 goto failure;
436 }
437 control_value.bv_val = ZSTR_VAL(tmpstring);
438 control_value.bv_len = ZSTR_LEN(tmpstring);
439 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PAGEDRESULTS) == 0) {
440 zval* tmp;
441 int pagesize = 1;
442 struct berval cookie = { 0L, NULL };
443 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) {
444 pagesize = zval_get_long(tmp);
445 }
446 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "cookie", sizeof("cookie") - 1)) != NULL) {
447 tmpstring = zval_get_string(tmp);
448 if (EG(exception)) {
449 rc = -1;
450 goto failure;
451 }
452 cookie.bv_val = ZSTR_VAL(tmpstring);
453 cookie.bv_len = ZSTR_LEN(tmpstring);
454 }
455 /* ldap_create_page_control_value() allocates memory for control_value.bv_val */
456 control_value_alloc = 1;
457 rc = ldap_create_page_control_value(ld, pagesize, &cookie, &control_value);
458 if (rc != LDAP_SUCCESS) {
459 php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc);
460 }
461 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_ASSERT) == 0) {
462 zval* tmp;
464 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) {
465 rc = -1;
466 zend_value_error("%s(): Control must have a \"filter\" key", get_active_function_name());
467 } else {
468 assert = zval_get_string(tmp);
469 if (EG(exception)) {
470 rc = -1;
471 goto failure;
472 }
473 /* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
474 See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
475 int success = LDAP_SUCCESS;
476 ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
477 /* ldap_create_assertion_control_value() allocates memory for control_value.bv_val */
478 control_value_alloc = 1;
479 rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), &control_value);
480 if (rc != LDAP_SUCCESS) {
481 php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
482 }
483 zend_string_release(assert);
484 }
485 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VALUESRETURNFILTER) == 0) {
486 zval* tmp;
487 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) {
488 rc = -1;
489 zend_value_error("%s(): Control must have a \"filter\" key", get_active_function_name());
490 } else {
491 ber = ber_alloc_t(LBER_USE_DER);
492 if (ber == NULL) {
493 rc = -1;
494 php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
495 } else {
496 tmpstring = zval_get_string(tmp);
497 if (EG(exception)) {
498 rc = -1;
499 goto failure;
500 }
501 if (ldap_put_vrFilter(ber, ZSTR_VAL(tmpstring)) == -1) {
502 rc = -1;
503 php_error_docref(NULL, E_WARNING, "Failed to create control value: Bad ValuesReturnFilter: %s", ZSTR_VAL(tmpstring));
504 } else if (ber_flatten2(ber, &control_value, control_value_alloc) == -1) {
505 rc = -1;
506 }
507 }
508 }
509 } else if ((strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_POST_READ) == 0)) {
510 zval* tmp;
511 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrs", sizeof("attrs") - 1)) == NULL) {
512 rc = -1;
513 zend_value_error("%s(): Control must have an \"attrs\" key", get_active_function_name());
514 } else {
515 ber = ber_alloc_t(LBER_USE_DER);
516
517 if (ber == NULL) {
518 rc = -1;
519 php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
520 } else {
521 int num_attribs, i;
522 zval* attr;
523
524 num_attribs = zend_hash_num_elements(Z_ARRVAL_P(tmp));
525 ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
526 tmpstrings1 = safe_emalloc(num_attribs, sizeof(zend_string*), 0);
527 num_tmpstrings1 = 0;
528
529 for (i = 0; i<num_attribs; i++) {
530 if ((attr = zend_hash_index_find(Z_ARRVAL_P(tmp), i)) == NULL) {
531 rc = -1;
532 php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
533 goto failure;
534 }
535
536 tmpstrings1[num_tmpstrings1] = zval_get_string(attr);
537 if (EG(exception)) {
538 rc = -1;
539 goto failure;
540 }
541 ldap_attrs[i] = ZSTR_VAL(tmpstrings1[num_tmpstrings1]);
542 ++num_tmpstrings1;
543 }
544 ldap_attrs[num_attribs] = NULL;
545
546 ber_init2( ber, NULL, LBER_USE_DER );
547
548 if (ber_printf(ber, "{v}", ldap_attrs) == -1) {
549 rc = -1;
550 php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
551 } else {
552 int err;
553 err = ber_flatten2(ber, &control_value, control_value_alloc);
554 if (err < 0) {
555 rc = -1;
556 php_error_docref(NULL, E_WARNING, "Failed to encode control value (%d)", err);
557 }
558 }
559 }
560 }
561 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_SORTREQUEST) == 0) {
562 int num_keys, i;
563 zval *sortkey, *tmp;
564
565 num_keys = zend_hash_num_elements(Z_ARRVAL_P(val));
566 sort_keys = safe_emalloc((num_keys+1), sizeof(LDAPSortKey*), 0);
567 tmpstrings1 = safe_emalloc(num_keys, sizeof(zend_string*), 0);
568 tmpstrings2 = safe_emalloc(num_keys, sizeof(zend_string*), 0);
569 num_tmpstrings1 = 0;
570 num_tmpstrings2 = 0;
571
572 for (i = 0; i<num_keys; i++) {
573 if ((sortkey = zend_hash_index_find(Z_ARRVAL_P(val), i)) == NULL) {
574 rc = -1;
575 php_error_docref(NULL, E_WARNING, "Failed to encode sort keys list");
576 goto failure;
577 }
578
579 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "attr", sizeof("attr") - 1)) == NULL) {
580 rc = -1;
581 zend_value_error("%s(): Sort key list must have an \"attr\" key", get_active_function_name());
582 goto failure;
583 }
584 sort_keys[i] = emalloc(sizeof(LDAPSortKey));
585 tmpstrings1[num_tmpstrings1] = zval_get_string(tmp);
586 if (EG(exception)) {
587 rc = -1;
588 goto failure;
589 }
590 sort_keys[i]->attributeType = ZSTR_VAL(tmpstrings1[num_tmpstrings1]);
591 ++num_tmpstrings1;
592
593 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "oid", sizeof("oid") - 1)) != NULL) {
594 tmpstrings2[num_tmpstrings2] = zval_get_string(tmp);
595 if (EG(exception)) {
596 rc = -1;
597 goto failure;
598 }
599 sort_keys[i]->orderingRule = ZSTR_VAL(tmpstrings2[num_tmpstrings2]);
600 ++num_tmpstrings2;
601 } else {
602 sort_keys[i]->orderingRule = NULL;
603 }
604
605 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "reverse", sizeof("reverse") - 1)) != NULL) {
606 sort_keys[i]->reverseOrder = zend_is_true(tmp);
607 } else {
608 sort_keys[i]->reverseOrder = 0;
609 }
610 }
611 sort_keys[num_keys] = NULL;
612 /* ldap_create_sort_control_value() allocates memory for control_value.bv_val */
613 control_value_alloc = 1;
614 rc = ldap_create_sort_control_value(ld, sort_keys, &control_value);
615 if (rc != LDAP_SUCCESS) {
616 php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
617 }
618 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VLVREQUEST) == 0) {
619 zval* tmp;
620 LDAPVLVInfo vlvInfo;
621 struct berval attrValue;
622 struct berval context;
623
624 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "before", sizeof("before") - 1)) != NULL) {
625 vlvInfo.ldvlv_before_count = zval_get_long(tmp);
626 } else {
627 rc = -1;
628 zend_value_error("%s(): Array value for VLV control must have a \"before\" key", get_active_function_name());
629 goto failure;
630 }
631
632 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "after", sizeof("after") - 1)) != NULL) {
633 vlvInfo.ldvlv_after_count = zval_get_long(tmp);
634 } else {
635 rc = -1;
636 zend_value_error("%s(): Array value for VLV control must have an \"after\" key", get_active_function_name());
637 goto failure;
638 }
639
640 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrvalue", sizeof("attrvalue") - 1)) != NULL) {
641 tmpstring = zval_get_string(tmp);
642 if (EG(exception)) {
643 rc = -1;
644 goto failure;
645 }
646 attrValue.bv_val = ZSTR_VAL(tmpstring);
647 attrValue.bv_len = ZSTR_LEN(tmpstring);
648 vlvInfo.ldvlv_attrvalue = &attrValue;
649 } else if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "offset", sizeof("offset") - 1)) != NULL) {
650 vlvInfo.ldvlv_attrvalue = NULL;
651 vlvInfo.ldvlv_offset = zval_get_long(tmp);
652 /* Find "count" key */
653 if ((tmp = zend_hash_find(Z_ARRVAL_P(val), ZSTR_KNOWN(ZEND_STR_COUNT))) != NULL) {
654 vlvInfo.ldvlv_count = zval_get_long(tmp);
655 } else {
656 rc = -1;
657 zend_value_error("%s(): Array value for VLV control must have a \"count\" key", get_active_function_name());
658 goto failure;
659 }
660 } else {
661 rc = -1;
662 zend_value_error("%s(): Array value for VLV control must have either an \"attrvalue\" or an \"offset\" key", get_active_function_name());
663 goto failure;
664 }
665
666 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "context", sizeof("context") - 1)) != NULL) {
667 tmpstring = zval_get_string(tmp);
668 if (EG(exception)) {
669 rc = -1;
670 goto failure;
671 }
672 context.bv_val = ZSTR_VAL(tmpstring);
673 context.bv_len = ZSTR_LEN(tmpstring);
674 vlvInfo.ldvlv_context = &context;
675 } else {
676 vlvInfo.ldvlv_context = NULL;
677 }
678
679 /* ldap_create_vlv_control_value() allocates memory for control_value.bv_val */
680 control_value_alloc = 1;
681 rc = ldap_create_vlv_control_value(ld, &vlvInfo, &control_value);
682 if (rc != LDAP_SUCCESS) {
683 php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc);
684 }
685 } else {
686 zend_type_error("%s(): Control OID %s cannot be of type array", get_active_function_name(), ZSTR_VAL(control_oid));
687 rc = -1;
688 }
689 }
690
691 if (rc == LDAP_SUCCESS) {
692 rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, &control_value, 1, ctrl);
693 }
694
695failure:
696 zend_string_release(control_oid);
697 if (tmpstring != NULL) {
698 zend_string_release(tmpstring);
699 }
700 if (tmpstrings1 != NULL) {
701 int i;
702 for (i = 0; i < num_tmpstrings1; ++i) {
703 zend_string_release(tmpstrings1[i]);
704 }
705 efree(tmpstrings1);
706 }
707 if (tmpstrings2 != NULL) {
708 int i;
709 for (i = 0; i < num_tmpstrings2; ++i) {
710 zend_string_release(tmpstrings2[i]);
711 }
712 efree(tmpstrings2);
713 }
714 if (control_value.bv_val != NULL && control_value_alloc != 0) {
715 ber_memfree(control_value.bv_val);
716 }
717 if (ber != NULL) {
718 ber_free(ber, 1);
719 }
720 if (ldap_attrs != NULL) {
721 efree(ldap_attrs);
722 }
723 if (sort_keys != NULL) {
724 LDAPSortKey** sortp = sort_keys;
725 while (*sortp) {
726 efree(*sortp);
727 sortp++;
728 }
729 efree(sort_keys);
730 sort_keys = NULL;
731 }
732
733 if (rc == LDAP_SUCCESS) {
734 return LDAP_SUCCESS;
735 }
736
737 /* Failed */
738 *ctrl = NULL;
739 return -1;
740}
741
742static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* array, int request)
743{
744 zval tmp1;
745 LDAPControl **ctrlp;
746
747 array = zend_try_array_init(array);
748 if (!array) {
749 return;
750 }
751
752 if (ctrls == NULL) {
753 return;
754 }
755 ctrlp = ctrls;
756 while (*ctrlp != NULL) {
757 _php_ldap_control_to_array(ld, *ctrlp, &tmp1, request);
758 add_assoc_zval(array, (*ctrlp)->ldctl_oid, &tmp1);
759 ctrlp++;
760 }
761 ldap_controls_free(ctrls);
762}
763
764static LDAPControl** _php_ldap_controls_from_array(LDAP *ld, zval* array, uint32_t arg_num)
765{
766 int ncontrols;
767 LDAPControl** ctrlp, **ctrls = NULL;
768 zval* ctrlarray;
769 int error = 0;
770
771 ncontrols = zend_hash_num_elements(Z_ARRVAL_P(array));
772 ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0);
773 *ctrls = NULL;
774 ctrlp = ctrls;
775 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), ctrlarray) {
776 if (Z_TYPE_P(ctrlarray) != IS_ARRAY) {
777 zend_argument_type_error(arg_num, "must contain only arrays, where each array is a control");
778 error = 1;
779 break;
780 }
781
782 if (_php_ldap_control_from_array(ld, ctrlp, ctrlarray) == LDAP_SUCCESS) {
783 ++ctrlp;
784 } else {
785 error = 1;
786 break;
787 }
788
789 *ctrlp = NULL;
791
792 if (error) {
793 ctrlp = ctrls;
794 while (*ctrlp) {
795 ldap_control_free(*ctrlp);
796 ctrlp++;
797 }
798 efree(ctrls);
799 ctrls = NULL;
800 }
801
802 return ctrls;
803}
804
805static void _php_ldap_controls_free (LDAPControl*** ctrls)
806{
807 LDAPControl **ctrlp;
808
809 if (*ctrls) {
810 ctrlp = *ctrls;
811 while (*ctrlp) {
812 ldap_control_free(*ctrlp);
813 ctrlp++;
814 }
815 efree(*ctrls);
816 *ctrls = NULL;
817 }
818}
819/* }}} */
820
821/* {{{ PHP_INI_BEGIN */
823 STD_PHP_INI_ENTRY_EX("ldap.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_ldap_globals, ldap_globals, display_link_numbers)
825/* }}} */
826
827/* {{{ PHP_GINIT_FUNCTION */
828static PHP_GINIT_FUNCTION(ldap)
829{
830#if defined(COMPILE_DL_LDAP) && defined(ZTS)
832#endif
833 ldap_globals->num_links = 0;
834}
835/* }}} */
836
837/* {{{ PHP_RINIT_FUNCTION */
838static PHP_RINIT_FUNCTION(ldap)
839{
840#if defined(COMPILE_DL_LDAP) && defined(ZTS)
842#endif
843
844 /* needed before first connect and after TLS option changes */
845 LDAPG(tls_newctx) = true;
846
847 return SUCCESS;
848}
849/* }}} */
850
851
852/* {{{ PHP_MINIT_FUNCTION */
854{
856
857 ldap_link_ce = register_class_LDAP_Connection();
858 ldap_link_ce->create_object = ldap_link_create_object;
859 ldap_link_ce->default_object_handlers = &ldap_link_object_handlers;
860
861 memcpy(&ldap_link_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
862 ldap_link_object_handlers.offset = XtOffsetOf(ldap_linkdata, std);
863 ldap_link_object_handlers.free_obj = ldap_link_free_obj;
864 ldap_link_object_handlers.get_constructor = ldap_link_get_constructor;
865 ldap_link_object_handlers.clone_obj = NULL;
866 ldap_link_object_handlers.compare = zend_objects_not_comparable;
867
868 ldap_result_ce = register_class_LDAP_Result();
869 ldap_result_ce->create_object = ldap_result_create_object;
870 ldap_result_ce->default_object_handlers = &ldap_result_object_handlers;
871
872 memcpy(&ldap_result_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
873 ldap_result_object_handlers.offset = XtOffsetOf(ldap_resultdata, std);
874 ldap_result_object_handlers.free_obj = ldap_result_free_obj;
875 ldap_result_object_handlers.get_constructor = ldap_result_get_constructor;
876 ldap_result_object_handlers.clone_obj = NULL;
877 ldap_result_object_handlers.compare = zend_objects_not_comparable;
878
879 ldap_result_entry_ce = register_class_LDAP_ResultEntry();
880 ldap_result_entry_ce->create_object = ldap_result_entry_create_object;
881 ldap_result_entry_ce->default_object_handlers = &ldap_result_entry_object_handlers;
882
883 memcpy(&ldap_result_entry_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
884 ldap_result_entry_object_handlers.offset = XtOffsetOf(ldap_result_entry, std);
885 ldap_result_entry_object_handlers.free_obj = ldap_result_entry_free_obj;
886 ldap_result_entry_object_handlers.get_constructor = ldap_result_entry_get_constructor;
887 ldap_result_entry_object_handlers.clone_obj = NULL;
888 ldap_result_entry_object_handlers.compare = zend_objects_not_comparable;
889
890 register_ldap_symbols(module_number);
891
892 ldap_module_entry.type = type;
893
894 return SUCCESS;
895}
896/* }}} */
897
898/* {{{ PHP_MSHUTDOWN_FUNCTION */
900{
902 return SUCCESS;
903}
904/* }}} */
905
906/* {{{ PHP_MINFO_FUNCTION */
908{
909 char tmp[32];
910
912 php_info_print_table_row(2, "LDAP Support", "enabled");
913
914 if (LDAPG(max_links) == -1) {
915 snprintf(tmp, 31, ZEND_LONG_FMT "/unlimited", LDAPG(num_links));
916 } else {
918 }
919 php_info_print_table_row(2, "Total Links", tmp);
920
921#ifdef LDAP_API_VERSION
922 snprintf(tmp, 31, "%d", LDAP_API_VERSION);
923 php_info_print_table_row(2, "API Version", tmp);
924#endif
925
926#ifdef LDAP_VENDOR_NAME
927 php_info_print_table_row(2, "Vendor Name", LDAP_VENDOR_NAME);
928#endif
929
930#ifdef LDAP_VENDOR_VERSION
931 snprintf(tmp, 31, "%d", LDAP_VENDOR_VERSION);
932 php_info_print_table_row(2, "Vendor Version", tmp);
933#endif
934
935#ifdef HAVE_LDAP_SASL
936 php_info_print_table_row(2, "SASL Support", "Enabled");
937#endif
938
941}
942/* }}} */
943
944/* {{{ Connect to an LDAP server */
946{
947 char *host = NULL;
948 size_t hostlen = 0;
949 zend_long port = LDAP_PORT;
950#ifdef HAVE_ORALDAP
951 char *wallet = NULL, *walletpasswd = NULL;
952 size_t walletlen = 0, walletpasswdlen = 0;
953 zend_long authmode = GSLC_SSL_NO_AUTH;
954 int ssl=0;
955#endif
956 ldap_linkdata *ld;
957 LDAP *ldap = NULL;
958
959 if (ZEND_NUM_ARGS() > 2) {
960 zend_error(E_DEPRECATED, "Calling ldap_connect() with Oracle-specific arguments is deprecated, "
961 "use ldap_connect_wallet() instead");
962 } else if (ZEND_NUM_ARGS() == 2) {
963 zend_error(E_DEPRECATED, "Usage of ldap_connect with two arguments is deprecated");
964 }
965
966#ifdef HAVE_ORALDAP
967 if (ZEND_NUM_ARGS() == 3 || ZEND_NUM_ARGS() == 4) {
969 }
970
971 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!lssl", &host, &hostlen, &port, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) != SUCCESS) {
973 }
974
975 if (ZEND_NUM_ARGS() == 5) {
976 ssl = 1;
977 }
978#else
979 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!l", &host, &hostlen, &port) != SUCCESS) {
981 }
982#endif
983
984 if (LDAPG(max_links) != -1 && LDAPG(num_links) >= LDAPG(max_links)) {
985 php_error_docref(NULL, E_WARNING, "Too many open links (" ZEND_LONG_FMT ")", LDAPG(num_links));
987 }
988
989 object_init_ex(return_value, ldap_link_ce);
991
992 {
993 int rc = LDAP_SUCCESS;
994 char *url = host;
995 if (url && !ldap_is_ldap_url(url)) {
996 size_t urllen = hostlen + sizeof( "ldap://:65535" );
997
998 if (port <= 0 || port > 65535) {
999 zend_argument_value_error(2, "must be between 1 and 65535");
1000 RETURN_THROWS();
1001 }
1002
1003 url = emalloc(urllen);
1004 snprintf( url, urllen, "ldap://%s:" ZEND_LONG_FMT, host, port );
1005 }
1006
1007#ifdef LDAP_OPT_X_TLS_NEWCTX
1008 if (LDAPG(tls_newctx) && url && !strncmp(url, "ldaps:", 6)) {
1009 int val = 0;
1010
1011 /* ensure all pending TLS options are applied in a new context */
1012 if (ldap_set_option(NULL, LDAP_OPT_X_TLS_NEWCTX, &val) != LDAP_OPT_SUCCESS) {
1014 php_error_docref(NULL, E_WARNING, "Could not create new security context");
1016 }
1017 LDAPG(tls_newctx) = false;
1018 }
1019#endif
1020
1021#ifdef LDAP_API_FEATURE_X_OPENLDAP
1022 /* ldap_init() is deprecated, use ldap_initialize() instead.
1023 */
1024 rc = ldap_initialize(&ldap, url);
1025#else /* ! LDAP_API_FEATURE_X_OPENLDAP */
1026 /* ldap_init does not support URLs.
1027 * We must try the original host and port information.
1028 */
1029 ldap = ldap_init(host, port);
1030 if (ldap == NULL) {
1032 php_error_docref(NULL, E_WARNING, "Could not create session handle");
1034 }
1035#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
1036 if (url != host) {
1037 efree(url);
1038 }
1039 if (rc != LDAP_SUCCESS) {
1041 php_error_docref(NULL, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
1043 }
1044 }
1045
1046 if (ldap == NULL) {
1049 } else {
1050#ifdef HAVE_ORALDAP
1051 if (ssl) {
1052 if (ldap_init_SSL(&ldap->ld_sb, wallet, walletpasswd, authmode)) {
1054 php_error_docref(NULL, E_WARNING, "SSL init failed");
1056 }
1057 }
1058#endif
1059 LDAPG(num_links)++;
1060 ld->link = ldap;
1061 }
1062
1063}
1064/* }}} */
1065
1066#if defined(HAVE_ORALDAP) && defined(LDAP_API_FEATURE_X_OPENLDAP)
1068 char *host = NULL;
1069 size_t hostlen = 0;
1070 char *wallet = NULL, *walletpasswd = NULL;
1071 size_t walletlen = 0, walletpasswdlen = 0;
1072 zend_long authmode = GSLC_SSL_NO_AUTH;
1073 bool ssl = false;
1074
1075 ldap_linkdata *ld;
1076 LDAP *ldap = NULL;
1077
1078 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!ss|l",
1079 &host, &hostlen, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) != SUCCESS
1080 ) {
1081 RETURN_THROWS();
1082 }
1083
1084 if (authmode != 0) {
1085 ssl = true;
1086 }
1087
1088 if (LDAPG(max_links) != -1 && LDAPG(num_links) >= LDAPG(max_links)) {
1089 php_error_docref(NULL, E_WARNING, "Too many open links (" ZEND_LONG_FMT ")", LDAPG(num_links));
1091 }
1092
1093 object_init_ex(return_value, ldap_link_ce);
1095
1096 {
1097 int rc = LDAP_SUCCESS;
1098 char *url = host;
1099 if (url && !ldap_is_ldap_url(url)) {
1100 size_t urllen = hostlen + sizeof( "ldap://:65535" );
1101
1102 url = emalloc(urllen);
1103 snprintf( url, urllen, "ldap://%s", host );
1104 }
1105
1106 /* ldap_init() is deprecated, use ldap_initialize() instead. */
1107 rc = ldap_initialize(&ldap, url);
1108 if (url != host) {
1109 efree(url);
1110 }
1111 if (rc != LDAP_SUCCESS) {
1113 php_error_docref(NULL, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
1115 }
1116 }
1117
1118 if (ldap == NULL) {
1121 } else {
1122 if (ssl) {
1123 if (ldap_init_SSL(&ldap->ld_sb, wallet, walletpasswd, authmode)) {
1125 php_error_docref(NULL, E_WARNING, "SSL init failed");
1127 }
1128 }
1129 LDAPG(num_links)++;
1130 ld->link = ldap;
1131 }
1132}
1133#endif
1134
1135/* {{{ _get_lderrno */
1136static int _get_lderrno(LDAP *ldap)
1137{
1138#if LDAP_API_VERSION > 2000 || defined(HAVE_ORALDAP)
1139 int lderr;
1140
1141 /* New versions of OpenLDAP do it this way */
1143 return lderr;
1144#else
1145 return ldap->ld_errno;
1146#endif
1147}
1148/* }}} */
1149
1150/* {{{ _set_lderrno */
1151static void _set_lderrno(LDAP *ldap, int lderr)
1152{
1153#if LDAP_API_VERSION > 2000 || defined(HAVE_ORALDAP)
1154 /* New versions of OpenLDAP do it this way */
1156#else
1157 ldap->ld_errno = lderr;
1158#endif
1159}
1160/* }}} */
1161
1162/* {{{ Bind to LDAP directory */
1164{
1165 zval *link;
1166 char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
1167 size_t ldap_bind_dnlen, ldap_bind_pwlen;
1168 ldap_linkdata *ld;
1169 int rc;
1170
1171 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!", &link, ldap_link_ce, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen) != SUCCESS) {
1172 RETURN_THROWS();
1173 }
1174
1175 ld = Z_LDAP_LINK_P(link);
1177
1178 if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
1179 _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
1180 zend_argument_type_error(2, "must not contain null bytes");
1181 RETURN_THROWS();
1182 }
1183
1184 if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
1185 _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
1186 zend_argument_type_error(3, "must not contain null bytes");
1187 RETURN_THROWS();
1188 }
1189
1190 {
1191#ifdef LDAP_API_FEATURE_X_OPENLDAP
1192 /* ldap_simple_bind_s() is deprecated, use ldap_sasl_bind_s() instead.
1193 */
1194 struct berval cred;
1195
1196 cred.bv_val = ldap_bind_pw;
1197 cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
1198 rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
1199 NULL, NULL, /* no controls right now */
1200 NULL); /* we don't care about the server's credentials */
1201#else /* ! LDAP_API_FEATURE_X_OPENLDAP */
1202 rc = ldap_simple_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw);
1203#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
1204 }
1205 if ( rc != LDAP_SUCCESS) {
1206 php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
1208 } else {
1210 }
1211}
1212/* }}} */
1213
1214/* {{{ Bind to LDAP directory */
1216{
1217 zval *serverctrls = NULL;
1218 zval *link;
1219 char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
1220 size_t ldap_bind_dnlen, ldap_bind_pwlen;
1221 ldap_linkdata *ld;
1222 LDAPControl **lserverctrls = NULL;
1224 LDAPMessage *ldap_res;
1225 int rc;
1226
1227 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!a!", &link, ldap_link_ce, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen, &serverctrls) != SUCCESS) {
1228 RETURN_THROWS();
1229 }
1230
1231 ld = Z_LDAP_LINK_P(link);
1233
1234 if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
1235 _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
1236 zend_argument_type_error(2, "must not contain null bytes");
1237 RETURN_THROWS();
1238 }
1239
1240 if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
1241 _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
1242 zend_argument_type_error(3, "must not contain null bytes");
1243 RETURN_THROWS();
1244 }
1245
1246 if (serverctrls) {
1247 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 4);
1248 if (lserverctrls == NULL) {
1250 goto cleanup;
1251 }
1252 }
1253
1254 {
1255 /* ldap_simple_bind() is deprecated, use ldap_sasl_bind() instead */
1256 struct berval cred;
1257 int msgid;
1258
1259 cred.bv_val = ldap_bind_pw;
1260 cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
1261 /* asynchronous call */
1262 rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
1263 lserverctrls, NULL, &msgid);
1264 if (rc != LDAP_SUCCESS ) {
1265 php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s (%d)", ldap_err2string(rc), rc);
1267 goto cleanup;
1268 }
1269
1270 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
1271 if (rc == -1) {
1272 php_error_docref(NULL, E_WARNING, "Bind operation failed");
1274 goto cleanup;
1275 }
1276
1277 /* return a PHP control object */
1278 object_init_ex(return_value, ldap_result_ce);
1280 result->result = ldap_res;
1281 }
1282
1283cleanup:
1284 if (lserverctrls) {
1285 _php_ldap_controls_free(&lserverctrls);
1286 }
1287
1288 return;
1289}
1290/* }}} */
1291
1292#ifdef HAVE_LDAP_SASL
1293typedef struct {
1294 char *mech;
1295 char *realm;
1296 char *authcid;
1297 char *passwd;
1298 char *authzid;
1299} php_ldap_bictx;
1300
1301/* {{{ _php_sasl_setdefs */
1302static php_ldap_bictx *_php_sasl_setdefs(LDAP *ld, char *sasl_mech, char *sasl_realm, char *sasl_authc_id, char *passwd, char *sasl_authz_id)
1303{
1304 php_ldap_bictx *ctx;
1305
1306 ctx = ber_memalloc(sizeof(php_ldap_bictx));
1307 ctx->mech = (sasl_mech) ? ber_strdup(sasl_mech) : NULL;
1308 ctx->realm = (sasl_realm) ? ber_strdup(sasl_realm) : NULL;
1309 ctx->authcid = (sasl_authc_id) ? ber_strdup(sasl_authc_id) : NULL;
1310 ctx->passwd = (passwd) ? ber_strdup(passwd) : NULL;
1311 ctx->authzid = (sasl_authz_id) ? ber_strdup(sasl_authz_id) : NULL;
1312
1313 if (ctx->mech == NULL) {
1314 ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &ctx->mech);
1315 }
1316 if (ctx->realm == NULL) {
1317 ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &ctx->realm);
1318 }
1319 if (ctx->authcid == NULL) {
1320 ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &ctx->authcid);
1321 }
1322 if (ctx->authzid == NULL) {
1323 ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &ctx->authzid);
1324 }
1325
1326 return ctx;
1327}
1328/* }}} */
1329
1330/* {{{ _php_sasl_freedefs */
1331static void _php_sasl_freedefs(php_ldap_bictx *ctx)
1332{
1333 if (ctx->mech) ber_memfree(ctx->mech);
1334 if (ctx->realm) ber_memfree(ctx->realm);
1335 if (ctx->authcid) ber_memfree(ctx->authcid);
1336 if (ctx->passwd) ber_memfree(ctx->passwd);
1337 if (ctx->authzid) ber_memfree(ctx->authzid);
1338 ber_memfree(ctx);
1339}
1340/* }}} */
1341
1342/* {{{ _php_sasl_interact
1343 Internal interact function for SASL */
1344static int _php_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
1345{
1346 sasl_interact_t *interact = in;
1347 const char *p;
1348 php_ldap_bictx *ctx = defaults;
1349
1350 for (;interact->id != SASL_CB_LIST_END;interact++) {
1351 p = NULL;
1352 switch(interact->id) {
1353 case SASL_CB_GETREALM:
1354 p = ctx->realm;
1355 break;
1356 case SASL_CB_AUTHNAME:
1357 p = ctx->authcid;
1358 break;
1359 case SASL_CB_USER:
1360 p = ctx->authzid;
1361 break;
1362 case SASL_CB_PASS:
1363 p = ctx->passwd;
1364 break;
1365 }
1366 if (p) {
1367 interact->result = p;
1368 interact->len = strlen(interact->result);
1369 }
1370 }
1371 return LDAP_SUCCESS;
1372}
1373/* }}} */
1374
1375/* {{{ Bind to LDAP directory using SASL */
1377{
1378 zval *link;
1379 ldap_linkdata *ld;
1380 char *binddn = NULL;
1381 char *passwd = NULL;
1382 char *sasl_mech = NULL;
1383 char *sasl_realm = NULL;
1384 char *sasl_authz_id = NULL;
1385 char *sasl_authc_id = NULL;
1386 char *props = NULL;
1387 size_t rc, dn_len, passwd_len, mech_len, realm_len, authc_id_len, authz_id_len, props_len;
1388 php_ldap_bictx *ctx;
1389
1390 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s!s!s!s!s!s!s!", &link, ldap_link_ce, &binddn, &dn_len, &passwd, &passwd_len, &sasl_mech, &mech_len, &sasl_realm, &realm_len, &sasl_authc_id, &authc_id_len, &sasl_authz_id, &authz_id_len, &props, &props_len) != SUCCESS) {
1391 RETURN_THROWS();
1392 }
1393
1394 ld = Z_LDAP_LINK_P(link);
1396
1397 ctx = _php_sasl_setdefs(ld->link, sasl_mech, sasl_realm, sasl_authc_id, passwd, sasl_authz_id);
1398
1399 if (props) {
1400 ldap_set_option(ld->link, LDAP_OPT_X_SASL_SECPROPS, props);
1401 }
1402
1403 rc = ldap_sasl_interactive_bind_s(ld->link, binddn, ctx->mech, NULL, NULL, LDAP_SASL_QUIET, _php_sasl_interact, ctx);
1404 if (rc != LDAP_SUCCESS) {
1405 php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
1407 } else {
1409 }
1410 _php_sasl_freedefs(ctx);
1411}
1412/* }}} */
1413#endif /* HAVE_LDAP_SASL */
1414
1415/* {{{ Unbind from LDAP directory */
1417{
1418 zval *link;
1419 ldap_linkdata *ld;
1420
1421 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) {
1422 RETURN_THROWS();
1423 }
1424
1425 ld = Z_LDAP_LINK_P(link);
1427
1428 ldap_link_free(ld);
1429
1431}
1432/* }}} */
1433
1434/* {{{ php_set_opts */
1435static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, int *old_sizelimit, int *old_timelimit, int *old_deref)
1436{
1437 /* sizelimit */
1438 if (sizelimit > -1) {
1439#if (LDAP_API_VERSION >= 2004) || defined(HAVE_ORALDAP)
1440 ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_sizelimit);
1441 ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit);
1442#else
1443 *old_sizelimit = ldap->ld_sizelimit;
1444 ldap->ld_sizelimit = sizelimit;
1445#endif
1446 }
1447
1448 /* timelimit */
1449 if (timelimit > -1) {
1450#if (LDAP_API_VERSION >= 2004) || defined(HAVE_ORALDAP)
1451 ldap_get_option(ldap, LDAP_OPT_TIMELIMIT, old_timelimit);
1452 ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit);
1453#else
1454 *old_timelimit = ldap->ld_timelimit;
1455 ldap->ld_timelimit = timelimit;
1456#endif
1457 }
1458
1459 /* deref */
1460 if (deref > -1) {
1461#if (LDAP_API_VERSION >= 2004) || defined(HAVE_ORALDAP)
1462 ldap_get_option(ldap, LDAP_OPT_DEREF, old_deref);
1463 ldap_set_option(ldap, LDAP_OPT_DEREF, &deref);
1464#else
1465 *old_deref = ldap->ld_deref;
1466 ldap->ld_deref = deref;
1467#endif
1468 }
1469}
1470/* }}} */
1471
1472/* {{{ php_ldap_do_search */
1473static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
1474{
1475 zval *link, *attrs = NULL, *attr, *serverctrls = NULL;
1476 zend_string *base_dn_str, *filter_str;
1477 HashTable *base_dn_ht, *filter_ht;
1478 zend_long attrsonly, sizelimit, timelimit, deref;
1479 zend_string *ldap_filter = NULL, *ldap_base_dn = NULL;
1480 char **ldap_attrs = NULL;
1481 ldap_linkdata *ld = NULL;
1483 LDAPMessage *ldap_res = NULL;
1484 LDAPControl **lserverctrls = NULL;
1485 int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1;
1486 int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
1487 int num_attribs = 0, ret = 1, i, ldap_errno, argcount = ZEND_NUM_ARGS();
1488
1491 Z_PARAM_ARRAY_HT_OR_STR(base_dn_ht, base_dn_str)
1492 Z_PARAM_ARRAY_HT_OR_STR(filter_ht, filter_str)
1494 Z_PARAM_ARRAY_EX(attrs, 0, 1)
1495 Z_PARAM_LONG(attrsonly)
1496 Z_PARAM_LONG(sizelimit)
1497 Z_PARAM_LONG(timelimit)
1498 Z_PARAM_LONG(deref)
1499 Z_PARAM_ARRAY_EX(serverctrls, 1, 1)
1501
1502 /* Reverse -> fall through */
1503 switch (argcount) {
1504 case 9:
1505 case 8:
1506 ldap_deref = deref;
1508 case 7:
1509 ldap_timelimit = timelimit;
1511 case 6:
1512 ldap_sizelimit = sizelimit;
1514 case 5:
1515 ldap_attrsonly = attrsonly;
1517 case 4:
1518 num_attribs = zend_hash_num_elements(Z_ARRVAL_P(attrs));
1519 ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
1520
1521 if (!php_ldap_is_numerically_indexed_array(Z_ARRVAL_P(attrs))) {
1522 php_error_docref(NULL, E_WARNING, "Argument #4 ($attributes) must be an array with numeric keys");
1523 ret = 0;
1524 goto cleanup;
1525 }
1526
1527 i = 0;
1530 if (EG(exception)) {
1531 ret = 0;
1532 goto cleanup;
1533 }
1534 ldap_attrs[i++] = Z_STRVAL_P(attr);
1536
1537 ldap_attrs[num_attribs] = NULL;
1539 default:
1540 break;
1541 }
1542
1543 /* parallel search? */
1544 if (Z_TYPE_P(link) == IS_ARRAY) {
1545 int i, nlinks, nbases, nfilters, *rcs;
1546 ldap_linkdata **lds;
1547 zval *entry, object;
1548
1549 nlinks = zend_hash_num_elements(Z_ARRVAL_P(link));
1550 if (nlinks == 0) {
1552 ret = 0;
1553 goto cleanup;
1554 }
1555 if (!zend_array_is_list(Z_ARRVAL_P(link))) {
1556 zend_argument_value_error(1, "must be a list");
1557 ret = 0;
1558 goto cleanup;
1559 }
1560
1561 if (base_dn_ht) {
1562 nbases = zend_hash_num_elements(base_dn_ht);
1563 if (nbases != nlinks) {
1564 zend_argument_value_error(2, "must have the same number of elements as the links array");
1565 ret = 0;
1566 goto cleanup;
1567 }
1568 zend_hash_internal_pointer_reset(base_dn_ht);
1569 } else {
1570 nbases = 0; /* this means string, not array */
1571 ldap_base_dn = zend_string_copy(base_dn_str);
1572 if (EG(exception)) {
1573 ret = 0;
1574 goto cleanup;
1575 }
1576 }
1577
1578 if (filter_ht) {
1579 nfilters = zend_hash_num_elements(filter_ht);
1580 if (nfilters != nlinks) {
1581 zend_argument_value_error(3, "must have the same number of elements as the links array");
1582 ret = 0;
1583 goto cleanup;
1584 }
1585 zend_hash_internal_pointer_reset(filter_ht);
1586 } else {
1587 nfilters = 0; /* this means string, not array */
1588 ldap_filter = zend_string_copy(filter_str);
1589 }
1590
1591 lds = safe_emalloc(nlinks, sizeof(ldap_linkdata), 0);
1592 rcs = safe_emalloc(nlinks, sizeof(*rcs), 0);
1593
1594 zend_hash_internal_pointer_reset(Z_ARRVAL_P(link));
1595 for (i=0; i<nlinks; i++) {
1596 entry = zend_hash_get_current_data(Z_ARRVAL_P(link));
1597
1598 if (Z_TYPE_P(entry) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(entry), ldap_link_ce)) {
1599 zend_argument_value_error(1, "must only contain objects of type LDAP");
1600 ret = 0;
1601 goto cleanup_parallel;
1602 }
1603
1604 ld = Z_LDAP_LINK_P(entry);
1605 if (!ld->link) {
1606 zend_throw_error(NULL, "LDAP connection has already been closed");
1607 ret = 0;
1608 goto cleanup_parallel;
1609 }
1610
1611 if (nbases != 0) { /* base_dn an array? */
1612 entry = zend_hash_get_current_data(base_dn_ht);
1613 zend_hash_move_forward(base_dn_ht);
1614 ldap_base_dn = zval_get_string(entry);
1615 if (EG(exception)) {
1616 ret = 0;
1617 goto cleanup_parallel;
1618 }
1619 }
1620 if (nfilters != 0) { /* filter an array? */
1621 entry = zend_hash_get_current_data(filter_ht);
1622 zend_hash_move_forward(filter_ht);
1623 ldap_filter = zval_get_string(entry);
1624 if (EG(exception)) {
1625 ret = 0;
1626 goto cleanup_parallel;
1627 }
1628 }
1629
1630 if (serverctrls) {
1631 /* We have to parse controls again for each link as they use it */
1632 _php_ldap_controls_free(&lserverctrls);
1633 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 9);
1634 if (lserverctrls == NULL) {
1635 rcs[i] = -1;
1636 continue;
1637 }
1638 }
1639
1640 php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
1641
1642 /* Run the actual search */
1643 ldap_search_ext(ld->link, ZSTR_VAL(ldap_base_dn), scope, ZSTR_VAL(ldap_filter), ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &rcs[i]);
1644 lds[i] = ld;
1645 zend_hash_move_forward(Z_ARRVAL_P(link));
1646 }
1647
1649
1650 /* Collect results from the searches */
1651 for (i=0; i<nlinks; i++) {
1652 if (rcs[i] != -1) {
1653 rcs[i] = ldap_result(lds[i]->link, LDAP_RES_ANY, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
1654 }
1655 if (rcs[i] != -1) {
1656 object_init_ex(&object, ldap_result_ce);
1657 result = Z_LDAP_RESULT_P(&object);
1658 result->result = ldap_res;
1659 add_next_index_zval(return_value, &object);
1660 } else {
1662 }
1663 }
1664
1665cleanup_parallel:
1666 efree(lds);
1667 efree(rcs);
1668 } else if (Z_TYPE_P(link) == IS_OBJECT && instanceof_function(Z_OBJCE_P(link), ldap_link_ce)) {
1669 ld = Z_LDAP_LINK_P(link);
1670 if (!ld->link) {
1671 zend_throw_error(NULL, "LDAP connection has already been closed");
1672 ret = 0;
1673 goto cleanup;
1674 }
1675
1676 if (!base_dn_str) {
1677 zend_argument_type_error(2, "must be of type string when argument #1 ($ldap) is an LDAP instance");
1678 ret = 0;
1679 goto cleanup;
1680 }
1681 ldap_base_dn = zend_string_copy(base_dn_str);
1682
1683 if (!filter_str) {
1684 zend_argument_type_error(3, "must be of type string when argument #1 ($ldap) is an LDAP instance");
1685 ret = 0;
1686 goto cleanup;
1687 }
1688 ldap_filter = zend_string_copy(filter_str);
1689
1690 if (serverctrls) {
1691 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 9);
1692 if (lserverctrls == NULL) {
1693 ret = 0;
1694 goto cleanup;
1695 }
1696 }
1697
1698 php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
1699
1700 /* Run the actual search */
1701 ldap_errno = ldap_search_ext_s(ld->link, ZSTR_VAL(ldap_base_dn), scope, ZSTR_VAL(ldap_filter), ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &ldap_res);
1702
1703 if (ldap_errno != LDAP_SUCCESS
1704 && ldap_errno != LDAP_SIZELIMIT_EXCEEDED
1705#ifdef LDAP_ADMINLIMIT_EXCEEDED
1706 && ldap_errno != LDAP_ADMINLIMIT_EXCEEDED
1707#endif
1708#ifdef LDAP_REFERRAL
1709 && ldap_errno != LDAP_REFERRAL
1710#endif
1711 ) {
1712 /* ldap_res should be freed regardless of return value of ldap_search_ext_s()
1713 * see: https://linux.die.net/man/3/ldap_search_ext_s */
1714 if (ldap_res != NULL) {
1715 ldap_msgfree(ldap_res);
1716 }
1717 php_error_docref(NULL, E_WARNING, "Search: %s", ldap_err2string(ldap_errno));
1718 ret = 0;
1719 } else {
1720 if (ldap_errno == LDAP_SIZELIMIT_EXCEEDED) {
1721 php_error_docref(NULL, E_WARNING, "Partial search results returned: Sizelimit exceeded");
1722 }
1723#ifdef LDAP_ADMINLIMIT_EXCEEDED
1724 else if (ldap_errno == LDAP_ADMINLIMIT_EXCEEDED) {
1725 php_error_docref(NULL, E_WARNING, "Partial search results returned: Adminlimit exceeded");
1726 }
1727#endif
1728 object_init_ex(return_value, ldap_result_ce);
1730 result->result = ldap_res;
1731 }
1732 } else {
1733 zend_argument_type_error(1, "must be of type LDAP|array, %s given", zend_zval_value_name(link));
1734 }
1735
1736cleanup:
1737 if (ld) {
1738 /* Restoring previous options */
1739 php_set_opts(ld->link, old_ldap_sizelimit, old_ldap_timelimit, old_ldap_deref, &ldap_sizelimit, &ldap_timelimit, &ldap_deref);
1740 }
1741 if (ldap_filter) {
1742 zend_string_release(ldap_filter);
1743 }
1744 if (ldap_base_dn) {
1745 zend_string_release(ldap_base_dn);
1746 }
1747 if (ldap_attrs != NULL) {
1748 efree(ldap_attrs);
1749 }
1750 if (!ret) {
1752 }
1753 if (lserverctrls) {
1754 _php_ldap_controls_free(&lserverctrls);
1755 }
1756}
1757/* }}} */
1758
1759/* {{{ Read an entry */
1761{
1762 php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_BASE);
1763}
1764/* }}} */
1765
1766/* {{{ Single-level search */
1768{
1769 php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_ONELEVEL);
1770}
1771/* }}} */
1772
1773/* {{{ Search LDAP tree under base_dn */
1775{
1776 php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_SUBTREE);
1777}
1778/* }}} */
1779
1780/* {{{ Free result memory */
1782{
1783 zval *result;
1784 ldap_resultdata *ldap_result;
1785
1786 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &result, ldap_result_ce) != SUCCESS) {
1787 RETURN_THROWS();
1788 }
1789
1790 ldap_result = Z_LDAP_RESULT_P(result);
1791 VERIFY_LDAP_RESULT_OPEN(ldap_result);
1792
1793 ldap_result_free(ldap_result);
1794
1796}
1797/* }}} */
1798
1799/* {{{ Count the number of entries in a search result */
1801{
1802 zval *link, *result;
1803 ldap_linkdata *ld;
1804 ldap_resultdata *ldap_result;
1805
1806 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
1807 RETURN_THROWS();
1808 }
1809
1810 ld = Z_LDAP_LINK_P(link);
1812
1813 ldap_result = Z_LDAP_RESULT_P(result);
1814 VERIFY_LDAP_RESULT_OPEN(ldap_result);
1815
1816 RETURN_LONG(ldap_count_entries(ld->link, ldap_result->result));
1817}
1818/* }}} */
1819
1820/* {{{ Return first result id */
1822{
1823 zval *link, *result;
1824 ldap_linkdata *ld;
1825 ldap_result_entry *resultentry;
1826 ldap_resultdata *ldap_result;
1827 LDAPMessage *entry;
1828
1829 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
1830 RETURN_THROWS();
1831 }
1832
1833 ld = Z_LDAP_LINK_P(link);
1835
1836 ldap_result = Z_LDAP_RESULT_P(result);
1837 VERIFY_LDAP_RESULT_OPEN(ldap_result);
1838
1839 if ((entry = ldap_first_entry(ld->link, ldap_result->result)) == NULL) {
1841 } else {
1842 object_init_ex(return_value, ldap_result_entry_ce);
1843 resultentry = Z_LDAP_RESULT_ENTRY_P(return_value);
1844 ZVAL_COPY(&resultentry->res, result);
1845 resultentry->data = entry;
1846 resultentry->ber = NULL;
1847 }
1848}
1849/* }}} */
1850
1851/* {{{ Get next result entry */
1853{
1854 zval *link, *result_entry;
1855 ldap_linkdata *ld;
1856 ldap_result_entry *resultentry, *resultentry_next;
1857 LDAPMessage *entry_next;
1858
1859 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
1860 RETURN_THROWS();
1861 }
1862
1863 ld = Z_LDAP_LINK_P(link);
1865
1866 resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
1867
1868 if ((entry_next = ldap_next_entry(ld->link, resultentry->data)) == NULL) {
1870 } else {
1871 object_init_ex(return_value, ldap_result_entry_ce);
1872 resultentry_next = Z_LDAP_RESULT_ENTRY_P(return_value);
1873 ZVAL_COPY(&resultentry_next->res, &resultentry->res);
1874 resultentry_next->data = entry_next;
1875 resultentry_next->ber = NULL;
1876 }
1877}
1878/* }}} */
1879
1880/* {{{ Get all result entries */
1882{
1883 zval *link, *result;
1884 ldap_resultdata *ldap_result;
1885 LDAPMessage *ldap_result_entry;
1886 zval tmp1, tmp2;
1887 ldap_linkdata *ld;
1888 LDAP *ldap;
1889 int num_entries, num_attrib, num_values, i;
1890 BerElement *ber;
1891 char *attribute;
1892 size_t attr_len;
1893 struct berval **ldap_value;
1894 char *dn;
1895
1896 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
1897 RETURN_THROWS();
1898 }
1899
1900 ld = Z_LDAP_LINK_P(link);
1902
1903 ldap_result = Z_LDAP_RESULT_P(result);
1904 VERIFY_LDAP_RESULT_OPEN(ldap_result);
1905
1906 ldap = ld->link;
1907 num_entries = ldap_count_entries(ldap, ldap_result->result);
1908
1910 add_assoc_long(return_value, "count", num_entries);
1911
1912 if (num_entries == 0) {
1913 return;
1914 }
1915
1916 ldap_result_entry = ldap_first_entry(ldap, ldap_result->result);
1917 if (ldap_result_entry == NULL) {
1920 }
1921
1922 num_entries = 0;
1923 while (ldap_result_entry != NULL) {
1924 array_init(&tmp1);
1925
1926 num_attrib = 0;
1927 attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber);
1928
1929 while (attribute != NULL) {
1930 ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute);
1931 num_values = ldap_count_values_len(ldap_value);
1932
1933 array_init(&tmp2);
1934 add_assoc_long(&tmp2, "count", num_values);
1935 for (i = 0; i < num_values; i++) {
1936 add_index_stringl(&tmp2, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len);
1937 }
1938 ldap_value_free_len(ldap_value);
1939
1940 attr_len = strlen(attribute);
1941 zend_str_tolower(attribute, attr_len);
1942 zend_hash_str_update(Z_ARRVAL(tmp1), attribute, attr_len, &tmp2);
1943 add_index_string(&tmp1, num_attrib, attribute);
1944
1945 num_attrib++;
1946#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
1947 ldap_memfree(attribute);
1948#endif
1949 attribute = ldap_next_attribute(ldap, ldap_result_entry, ber);
1950 }
1951#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
1952 if (ber != NULL) {
1953 ber_free(ber, 0);
1954 }
1955#endif
1956
1957 add_assoc_long(&tmp1, "count", num_attrib);
1958 dn = ldap_get_dn(ldap, ldap_result_entry);
1959 if (dn) {
1960 add_assoc_string(&tmp1, "dn", dn);
1961 } else {
1962 add_assoc_null(&tmp1, "dn");
1963 }
1964#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
1965 ldap_memfree(dn);
1966#else
1967 free(dn);
1968#endif
1969
1971
1972 num_entries++;
1974 }
1975
1976 add_assoc_long(return_value, "count", num_entries);
1977
1978}
1979/* }}} */
1980
1981/* {{{ Return first attribute */
1983{
1984 zval *link, *result_entry;
1985 ldap_linkdata *ld;
1986 ldap_result_entry *resultentry;
1987 char *attribute;
1988
1989 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
1990 RETURN_THROWS();
1991 }
1992
1993 ld = Z_LDAP_LINK_P(link);
1995
1996 resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
1997
1998 if ((attribute = ldap_first_attribute(ld->link, resultentry->data, &resultentry->ber)) == NULL) {
2000 } else {
2001 RETVAL_STRING(attribute);
2002#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
2003 ldap_memfree(attribute);
2004#endif
2005 }
2006}
2007/* }}} */
2008
2009/* {{{ Get the next attribute in result */
2011{
2012 zval *link, *result_entry;
2013 ldap_linkdata *ld;
2014 ldap_result_entry *resultentry;
2015 char *attribute;
2016
2017 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
2018 RETURN_THROWS();
2019 }
2020
2021 ld = Z_LDAP_LINK_P(link);
2023
2024 resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
2025
2026 if (resultentry->ber == NULL) {
2027 php_error_docref(NULL, E_WARNING, "Called before calling ldap_first_attribute() or no attributes found in result entry");
2029 }
2030
2031 if ((attribute = ldap_next_attribute(ld->link, resultentry->data, resultentry->ber)) == NULL) {
2032#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
2033 if (resultentry->ber != NULL) {
2034 ber_free(resultentry->ber, 0);
2035 resultentry->ber = NULL;
2036 }
2037#endif
2039 } else {
2040 RETVAL_STRING(attribute);
2041#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
2042 ldap_memfree(attribute);
2043#endif
2044 }
2045}
2046/* }}} */
2047
2048/* {{{ Get attributes from a search result entry */
2050{
2051 zval *link, *result_entry;
2052 zval tmp;
2053 ldap_linkdata *ld;
2054 ldap_result_entry *resultentry;
2055 char *attribute;
2056 struct berval **ldap_value;
2057 int i, num_values, num_attrib;
2058 BerElement *ber;
2059
2060 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
2061 RETURN_THROWS();
2062 }
2063
2064 ld = Z_LDAP_LINK_P(link);
2066
2067 resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
2068
2070 num_attrib = 0;
2071
2072 attribute = ldap_first_attribute(ld->link, resultentry->data, &ber);
2073 while (attribute != NULL) {
2074 ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute);
2075 num_values = ldap_count_values_len(ldap_value);
2076
2077 array_init(&tmp);
2078 add_assoc_long(&tmp, "count", num_values);
2079 for (i = 0; i < num_values; i++) {
2080 add_index_stringl(&tmp, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len);
2081 }
2082 ldap_value_free_len(ldap_value);
2083
2084 zend_hash_str_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute), &tmp);
2085 add_index_string(return_value, num_attrib, attribute);
2086
2087 num_attrib++;
2088#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
2089 ldap_memfree(attribute);
2090#endif
2091 attribute = ldap_next_attribute(ld->link, resultentry->data, ber);
2092 }
2093#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
2094 if (ber != NULL) {
2095 ber_free(ber, 0);
2096 }
2097#endif
2098
2099 add_assoc_long(return_value, "count", num_attrib);
2100}
2101/* }}} */
2102
2103/* {{{ Get all values with lengths from a result entry */
2105{
2106 zval *link, *result_entry;
2107 ldap_linkdata *ld;
2108 ldap_result_entry *resultentry;
2109 char *attr;
2110 struct berval **ldap_value_len;
2111 int i, num_values;
2112 size_t attr_len;
2113
2114 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOs", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce, &attr, &attr_len) != SUCCESS) {
2115 RETURN_THROWS();
2116 }
2117
2118 ld = Z_LDAP_LINK_P(link);
2120
2121 resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
2122
2123 if ((ldap_value_len = ldap_get_values_len(ld->link, resultentry->data, attr)) == NULL) {
2124 php_error_docref(NULL, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link)));
2126 }
2127
2128 num_values = ldap_count_values_len(ldap_value_len);
2130
2131 for (i=0; i<num_values; i++) {
2132 add_next_index_stringl(return_value, ldap_value_len[i]->bv_val, ldap_value_len[i]->bv_len);
2133 }
2134
2135 add_assoc_long(return_value, "count", num_values);
2136 ldap_value_free_len(ldap_value_len);
2137
2138}
2139/* }}} */
2140
2141/* {{{ Get the DN of a result entry */
2143{
2144 zval *link, *result_entry;
2145 ldap_linkdata *ld;
2146 ldap_result_entry *resultentry;
2147 char *text;
2148
2149 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
2150 RETURN_THROWS();
2151 }
2152
2153 ld = Z_LDAP_LINK_P(link);
2155
2156 resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
2157
2158 text = ldap_get_dn(ld->link, resultentry->data);
2159 if (text != NULL) {
2161#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
2162 ldap_memfree(text);
2163#else
2164 free(text);
2165#endif
2166 } else {
2168 }
2169}
2170/* }}} */
2171
2172/* {{{ Splits DN into its component parts */
2174{
2175 zend_long with_attrib;
2176 char *dn, **ldap_value;
2177 int i, count;
2178 size_t dn_len;
2179
2180 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &dn, &dn_len, &with_attrib) != SUCCESS) {
2181 RETURN_THROWS();
2182 }
2183
2184 if (!(ldap_value = ldap_explode_dn(dn, with_attrib))) {
2185 /* Invalid parameters were passed to ldap_explode_dn */
2187 }
2188
2189 i=0;
2190 while (ldap_value[i] != NULL) i++;
2191 count = i;
2192
2194
2195 add_assoc_long(return_value, "count", count);
2196 for (i = 0; i<count; i++) {
2197 add_index_string(return_value, i, ldap_value[i]);
2198 }
2199
2200 ldap_memvfree((void **)ldap_value);
2201}
2202/* }}} */
2203
2204/* {{{ Convert DN to User Friendly Naming format */
2206{
2207 char *dn, *ufn;
2208 size_t dn_len;
2209
2210 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &dn, &dn_len) != SUCCESS) {
2211 RETURN_THROWS();
2212 }
2213
2214 ufn = ldap_dn2ufn(dn);
2215
2216 if (ufn != NULL) {
2217 RETVAL_STRING(ufn);
2218#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
2219 ldap_memfree(ufn);
2220#endif
2221 } else {
2223 }
2224}
2225/* }}} */
2226
2227
2228/* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */
2229#define PHP_LD_FULL_ADD 0xff
2230/* {{{ php_ldap_do_modify */
2231static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext)
2232{
2233 zval *serverctrls = NULL;
2234 zval *link, *entry, *value, *ivalue;
2235 ldap_linkdata *ld;
2236 char *dn;
2237 LDAPMod **ldap_mods;
2238 LDAPControl **lserverctrls = NULL;
2240 LDAPMessage *ldap_res;
2241 int i, j, num_attribs, num_values, msgid;
2242 size_t dn_len;
2243 int *num_berval;
2244 zend_string *attribute;
2245 zend_ulong index;
2246 int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */
2247
2248 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osa/|a!", &link, ldap_link_ce, &dn, &dn_len, &entry, &serverctrls) != SUCCESS) {
2249 RETURN_THROWS();
2250 }
2251
2252 ld = Z_LDAP_LINK_P(link);
2254
2255 num_attribs = zend_hash_num_elements(Z_ARRVAL_P(entry));
2256 ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0);
2257 num_berval = safe_emalloc(num_attribs, sizeof(int), 0);
2258 zend_hash_internal_pointer_reset(Z_ARRVAL_P(entry));
2259
2260 /* added by gerrit thomson to fix ldap_add using ldap_mod_add */
2261 if (oper == PHP_LD_FULL_ADD) {
2262 oper = LDAP_MOD_ADD;
2263 is_full_add = 1;
2264 }
2265 /* end additional , gerrit thomson */
2266
2267 for (i = 0; i < num_attribs; i++) {
2268 ldap_mods[i] = emalloc(sizeof(LDAPMod));
2269 ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
2270 ldap_mods[i]->mod_type = NULL;
2271
2272 if (zend_hash_get_current_key(Z_ARRVAL_P(entry), &attribute, &index) == HASH_KEY_IS_STRING) {
2273 ldap_mods[i]->mod_type = estrndup(ZSTR_VAL(attribute), ZSTR_LEN(attribute));
2274 } else {
2275 php_error_docref(NULL, E_WARNING, "Unknown attribute in the data");
2277 num_berval[i] = 0;
2278 num_attribs = i + 1;
2279 ldap_mods[i]->mod_bvalues = NULL;
2280 goto cleanup;
2281 }
2282
2283 value = zend_hash_get_current_data(Z_ARRVAL_P(entry));
2284
2286 if (Z_TYPE_P(value) != IS_ARRAY) {
2287 num_values = 1;
2288 } else {
2290 num_values = zend_hash_num_elements(Z_ARRVAL_P(value));
2291 }
2292
2293 num_berval[i] = num_values;
2294 ldap_mods[i]->mod_bvalues = safe_emalloc((num_values + 1), sizeof(struct berval *), 0);
2295
2296/* allow for arrays with one element, no allowance for arrays with none but probably not required, gerrit thomson. */
2297 if ((num_values == 1) && (Z_TYPE_P(value) != IS_ARRAY)) {
2299 if (EG(exception)) {
2301 num_berval[i] = 0;
2302 num_attribs = i + 1;
2303 goto cleanup;
2304 }
2305 ldap_mods[i]->mod_bvalues[0] = (struct berval *) emalloc (sizeof(struct berval));
2306 ldap_mods[i]->mod_bvalues[0]->bv_val = Z_STRVAL_P(value);
2307 ldap_mods[i]->mod_bvalues[0]->bv_len = Z_STRLEN_P(value);
2308 } else {
2309 if (!php_ldap_is_numerically_indexed_array(Z_ARRVAL_P(value))) {
2310 zend_argument_value_error(3, "attribute \"%s\" must be an array with numeric keys", ZSTR_VAL(attribute));
2312 num_berval[i] = 0;
2313 num_attribs = i + 1;
2314 goto cleanup;
2315 }
2316
2317 j = 0;
2319 convert_to_string(ivalue);
2320 if (EG(exception)) {
2321 num_berval[i] = j;
2322 num_attribs = i + 1;
2324 goto cleanup;
2325 }
2326 ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval));
2327 ldap_mods[i]->mod_bvalues[j]->bv_val = Z_STRVAL_P(ivalue);
2328 ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_P(ivalue);
2329 j++;
2331 }
2332 ldap_mods[i]->mod_bvalues[num_values] = NULL;
2333 zend_hash_move_forward(Z_ARRVAL_P(entry));
2334 }
2335 ldap_mods[num_attribs] = NULL;
2336
2337 if (serverctrls) {
2338 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 4);
2339 if (lserverctrls == NULL) {
2341 goto cleanup;
2342 }
2343 }
2344
2345/* check flag to see if do_mod was called to perform full add , gerrit thomson */
2346 if (is_full_add == 1) {
2347 if (ext) {
2348 i = ldap_add_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid);
2349 } else {
2350 i = ldap_add_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL);
2351 }
2352 if (i != LDAP_SUCCESS) {
2353 php_error_docref(NULL, E_WARNING, "Add: %s", ldap_err2string(i));
2355 } else if (ext) {
2356 i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
2357 if (i == -1) {
2358 php_error_docref(NULL, E_WARNING, "Add operation failed");
2360 goto cleanup;
2361 }
2362
2363 /* return a PHP control object */
2364 object_init_ex(return_value, ldap_result_ce);
2366 result->result = ldap_res;
2367 } else RETVAL_TRUE;
2368 } else {
2369 if (ext) {
2370 i = ldap_modify_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid);
2371 } else {
2372 i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL);
2373 }
2374 if (i != LDAP_SUCCESS) {
2375 php_error_docref(NULL, E_WARNING, "Modify: %s", ldap_err2string(i));
2377 } else if (ext) {
2378 i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
2379 if (i == -1) {
2380 php_error_docref(NULL, E_WARNING, "Modify operation failed");
2382 goto cleanup;
2383 }
2384
2385 /* return a PHP control object */
2386 object_init_ex(return_value, ldap_result_ce);
2388 result->result = ldap_res;
2389 } else RETVAL_TRUE;
2390 }
2391
2392cleanup:
2393 for (i = 0; i < num_attribs; i++) {
2394 efree(ldap_mods[i]->mod_type);
2395 for (j = 0; j < num_berval[i]; j++) {
2396 efree(ldap_mods[i]->mod_bvalues[j]);
2397 }
2398 efree(ldap_mods[i]->mod_bvalues);
2399 efree(ldap_mods[i]);
2400 }
2401 efree(num_berval);
2402 efree(ldap_mods);
2403
2404 if (lserverctrls) {
2405 _php_ldap_controls_free(&lserverctrls);
2406 }
2407
2408 return;
2409}
2410/* }}} */
2411
2412/* {{{ Add entries to LDAP directory */
2414{
2415 /* use a newly define parameter into the do_modify so ldap_mod_add can be used the way it is supposed to be used , Gerrit THomson */
2416 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0);
2417}
2418/* }}} */
2419
2420/* {{{ Add entries to LDAP directory */
2425/* }}} */
2426
2427/* three functions for attribute base modifications, gerrit Thomson */
2428
2429/* {{{ Replace attribute values with new ones */
2431{
2432 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 0);
2433}
2434/* }}} */
2435
2436/* {{{ Replace attribute values with new ones */
2438{
2439 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 1);
2440}
2441/* }}} */
2442
2443/* {{{ Add attribute values to current */
2445{
2446 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 0);
2447}
2448/* }}} */
2449
2450/* {{{ Add attribute values to current */
2452{
2453 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1);
2454}
2455/* }}} */
2456
2457/* {{{ Delete attribute values */
2459{
2460 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 0);
2461}
2462/* }}} */
2463
2464/* {{{ Delete attribute values */
2466{
2467 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1);
2468}
2469/* }}} */
2470
2471/* {{{ php_ldap_do_delete */
2472static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext)
2473{
2474 zval *serverctrls = NULL;
2475 zval *link;
2476 ldap_linkdata *ld;
2477 LDAPControl **lserverctrls = NULL;
2479 LDAPMessage *ldap_res;
2480 char *dn;
2481 int rc, msgid;
2482 size_t dn_len;
2483
2484 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|a!", &link, ldap_link_ce, &dn, &dn_len, &serverctrls) != SUCCESS) {
2485 RETURN_THROWS();
2486 }
2487
2488 ld = Z_LDAP_LINK_P(link);
2490
2491 if (serverctrls) {
2492 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 3);
2493 if (lserverctrls == NULL) {
2495 goto cleanup;
2496 }
2497 }
2498
2499 if (ext) {
2500 rc = ldap_delete_ext(ld->link, dn, lserverctrls, NULL, &msgid);
2501 } else {
2502 rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, NULL);
2503 }
2504 if (rc != LDAP_SUCCESS) {
2505 php_error_docref(NULL, E_WARNING, "Delete: %s", ldap_err2string(rc));
2507 goto cleanup;
2508 } else if (ext) {
2509 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
2510 if (rc == -1) {
2511 php_error_docref(NULL, E_WARNING, "Delete operation failed");
2513 goto cleanup;
2514 }
2515
2516 /* return a PHP control object */
2517 object_init_ex(return_value, ldap_result_ce);
2519 result->result = ldap_res;
2520 } else {
2522 }
2523
2524cleanup:
2525 if (lserverctrls) {
2526 _php_ldap_controls_free(&lserverctrls);
2527 }
2528
2529 return;
2530}
2531/* }}} */
2532
2533/* {{{ Delete an entry from a directory */
2535{
2536 php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2537}
2538/* }}} */
2539
2540/* {{{ Delete an entry from a directory */
2542{
2543 php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2544}
2545/* }}} */
2546
2547/* {{{ _ldap_str_equal_to_const */
2548static size_t _ldap_str_equal_to_const(const char *str, size_t str_len, const char *cstr)
2549{
2550 size_t i;
2551
2552 if (strlen(cstr) != str_len)
2553 return 0;
2554
2555 for (i = 0; i < str_len; ++i) {
2556 if (str[i] != cstr[i]) {
2557 return 0;
2558 }
2559 }
2560
2561 return 1;
2562}
2563/* }}} */
2564
2565/* {{{ _ldap_strlen_max */
2566static size_t _ldap_strlen_max(const char *str, size_t max_len)
2567{
2568 size_t i;
2569
2570 for (i = 0; i < max_len; ++i) {
2571 if (str[i] == '\0') {
2572 return i;
2573 }
2574 }
2575
2576 return max_len;
2577}
2578/* }}} */
2579
2580/* {{{ _ldap_hash_fetch */
2581static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out)
2582{
2584}
2585/* }}} */
2586
2587/* {{{ Perform multiple modifications as part of one operation */
2589{
2590 zval *serverctrls = NULL;
2591 ldap_linkdata *ld;
2592 zval *link, *mods, *mod, *modinfo;
2593 zend_string *modval;
2594 zval *attrib, *modtype, *vals;
2595 zval *fetched;
2596 char *dn;
2597 size_t dn_len;
2598 int i, j;
2599 int num_mods, num_modprops, num_modvals;
2600 LDAPMod **ldap_mods;
2601 LDAPControl **lserverctrls = NULL;
2602 uint32_t oper;
2603
2604 /*
2605 $mods = array(
2606 array(
2607 "attrib" => "unicodePwd",
2608 "modtype" => LDAP_MODIFY_BATCH_REMOVE,
2609 "values" => array($oldpw)
2610 ),
2611 array(
2612 "attrib" => "unicodePwd",
2613 "modtype" => LDAP_MODIFY_BATCH_ADD,
2614 "values" => array($newpw)
2615 ),
2616 array(
2617 "attrib" => "userPrincipalName",
2618 "modtype" => LDAP_MODIFY_BATCH_REPLACE,
2619 "values" => array("janitor@corp.contoso.com")
2620 ),
2621 array(
2622 "attrib" => "userCert",
2623 "modtype" => LDAP_MODIFY_BATCH_REMOVE_ALL
2624 )
2625 );
2626 */
2627
2628 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osa/|a!", &link, ldap_link_ce, &dn, &dn_len, &mods, &serverctrls) != SUCCESS) {
2629 RETURN_THROWS();
2630 }
2631
2632 ld = Z_LDAP_LINK_P(link);
2634
2635 /* perform validation */
2636 {
2637 zend_string *modkey;
2638 zend_long modtype;
2639
2640 /* to store the wrongly-typed keys */
2641 zend_ulong tmpUlong;
2642
2643 /* make sure the DN contains no NUL bytes */
2644 if (_ldap_strlen_max(dn, dn_len) != dn_len) {
2645 zend_argument_type_error(2, "must not contain null bytes");
2646 RETURN_THROWS();
2647 }
2648
2649 /* make sure the top level is a normal array */
2650 zend_hash_internal_pointer_reset(Z_ARRVAL_P(mods));
2651 if (zend_hash_get_current_key_type(Z_ARRVAL_P(mods)) != HASH_KEY_IS_LONG) {
2652 zend_argument_type_error(3, "must be integer-indexed");
2653 RETURN_THROWS();
2654 }
2655
2656 num_mods = zend_hash_num_elements(Z_ARRVAL_P(mods));
2657
2658 if (!php_ldap_is_numerically_indexed_array(Z_ARRVAL_P(mods))) {
2659 zend_argument_value_error(3, "must be an array with numeric keys");
2660 RETURN_THROWS();
2661 }
2662
2663 i = 0;
2664 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(mods), fetched) {
2665 ZVAL_DEREF(fetched);
2666 mod = fetched;
2667
2668 /* is it an array? */
2669 if (Z_TYPE_P(mod) != IS_ARRAY) {
2670 zend_argument_value_error(3, "must only contain arrays");
2671 RETURN_THROWS();
2672 }
2673
2674 SEPARATE_ARRAY(mod);
2675 /* for the modification hashtable... */
2676 zend_hash_internal_pointer_reset(Z_ARRVAL_P(mod));
2677 num_modprops = zend_hash_num_elements(Z_ARRVAL_P(mod));
2678 bool has_attrib_key = false;
2679 bool has_modtype_key = false;
2680
2681 for (j = 0; j < num_modprops; j++) {
2682
2683 /* are the keys strings? */
2684 if (zend_hash_get_current_key(Z_ARRVAL_P(mod), &modkey, &tmpUlong) != HASH_KEY_IS_STRING) {
2685 zend_argument_type_error(3, "must only contain string-indexed arrays");
2686 RETURN_THROWS();
2687 }
2688
2689 /* is this a valid entry? */
2690 if (
2691 !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_ATTRIB) &&
2692 !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_MODTYPE) &&
2693 !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_VALUES)
2694 ) {
2695 zend_argument_value_error(3, "must contain arrays only containing the \"" LDAP_MODIFY_BATCH_ATTRIB "\", \"" LDAP_MODIFY_BATCH_MODTYPE "\" and \"" LDAP_MODIFY_BATCH_VALUES "\" keys");
2696 RETURN_THROWS();
2697 }
2698
2699 fetched = zend_hash_get_current_data(Z_ARRVAL_P(mod));
2700 modinfo = fetched;
2701
2702 /* does the value type match the key? */
2703 if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_ATTRIB)) {
2704 has_attrib_key = true;
2705 if (Z_TYPE_P(modinfo) != IS_STRING) {
2706 zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_ATTRIB "\" must be of type string, %s given", get_active_function_name(), zend_zval_value_name(modinfo));
2707 RETURN_THROWS();
2708 }
2709
2710 if (Z_STRLEN_P(modinfo) != _ldap_strlen_max(Z_STRVAL_P(modinfo), Z_STRLEN_P(modinfo))) {
2711 zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_ATTRIB "\" cannot contain null-bytes", get_active_function_name());
2712 RETURN_THROWS();
2713 }
2714 }
2715 else if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_MODTYPE)) {
2716 has_modtype_key = true;
2717 if (Z_TYPE_P(modinfo) != IS_LONG) {
2718 zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_MODTYPE "\" must be of type int, %s given", get_active_function_name(), zend_zval_value_name(modinfo));
2719 RETURN_THROWS();
2720 }
2721
2722 /* is the value in range? */
2723 modtype = Z_LVAL_P(modinfo);
2724 if (
2725 modtype != LDAP_MODIFY_BATCH_ADD &&
2726 modtype != LDAP_MODIFY_BATCH_REMOVE &&
2727 modtype != LDAP_MODIFY_BATCH_REPLACE &&
2729 ) {
2730 zend_value_error("%s(): Option \"" LDAP_MODIFY_BATCH_MODTYPE "\" must be one of the LDAP_MODIFY_BATCH_* constants", get_active_function_name());
2731 RETURN_THROWS();
2732 }
2733
2734 /* if it's REMOVE_ALL, there must not be a values array; otherwise, there must */
2735 if (modtype == LDAP_MODIFY_BATCH_REMOVE_ALL) {
2736 if (zend_hash_str_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES))) {
2737 zend_value_error("%s(): If option \"" LDAP_MODIFY_BATCH_MODTYPE "\" is LDAP_MODIFY_BATCH_REMOVE_ALL, option \"" LDAP_MODIFY_BATCH_VALUES "\" cannot be provided", get_active_function_name());
2738 RETURN_THROWS();
2739 }
2740 }
2741 else {
2742 if (!zend_hash_str_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES))) {
2743 zend_value_error("%s(): If option \"" LDAP_MODIFY_BATCH_MODTYPE "\" is not LDAP_MODIFY_BATCH_REMOVE_ALL, option \"" LDAP_MODIFY_BATCH_VALUES "\" must be provided", get_active_function_name());
2744 RETURN_THROWS();
2745 }
2746 }
2747 }
2748 else if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_VALUES)) {
2749 if (Z_TYPE_P(modinfo) != IS_ARRAY) {
2750 zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_VALUES "\" must be of type array, %s given", get_active_function_name(), zend_zval_value_name(modinfo));
2751 RETURN_THROWS();
2752 }
2753
2754 SEPARATE_ARRAY(modinfo);
2755 /* is the array not empty? */
2756 zend_hash_internal_pointer_reset(Z_ARRVAL_P(modinfo));
2757 num_modvals = zend_hash_num_elements(Z_ARRVAL_P(modinfo));
2758 if (num_modvals == 0) {
2759 zend_value_error("%s(): Option \"" LDAP_MODIFY_BATCH_VALUES "\" must not be empty", get_active_function_name());
2760 RETURN_THROWS();
2761 }
2762
2763 if (!php_ldap_is_numerically_indexed_array(Z_ARRVAL_P(modinfo))) {
2764 zend_value_error("%s(): Option \"" LDAP_MODIFY_BATCH_VALUES "\" must be an array with numeric keys", get_active_function_name());
2765 RETURN_THROWS();
2766 }
2767 }
2768
2769 zend_hash_move_forward(Z_ARRVAL_P(mod));
2770 }
2771
2772 if (!has_attrib_key) {
2773 zend_value_error("%s(): Required option \"" LDAP_MODIFY_BATCH_ATTRIB "\" is missing", get_active_function_name());
2774 RETURN_THROWS();
2775 }
2776 if (!has_modtype_key) {
2777 zend_value_error("%s(): Required option \"" LDAP_MODIFY_BATCH_MODTYPE "\" is missing", get_active_function_name());
2778 RETURN_THROWS();
2779 }
2780
2781 i++;
2783 }
2784 /* validation was successful */
2785
2786 /* allocate array of modifications */
2787 ldap_mods = safe_emalloc((num_mods+1), sizeof(LDAPMod *), 0);
2788
2789 /* for each modification */
2790 i = 0;
2791 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(mods), fetched) {
2792 /* allocate the modification struct */
2793 ldap_mods[i] = safe_emalloc(1, sizeof(LDAPMod), 0);
2794
2795 /* fetch the relevant data */
2796 mod = fetched;
2797
2798 _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_ATTRIB, &attrib);
2799 _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_MODTYPE, &modtype);
2800 _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_VALUES, &vals);
2801
2802 /* map the modification type */
2803 switch (Z_LVAL_P(modtype)) {
2805 oper = LDAP_MOD_ADD;
2806 break;
2809 oper = LDAP_MOD_DELETE;
2810 break;
2812 oper = LDAP_MOD_REPLACE;
2813 break;
2814 default:
2815 zend_throw_error(NULL, "Unknown and uncaught modification type.");
2817 efree(ldap_mods[i]);
2818 num_mods = i;
2819 goto cleanup;
2820 }
2821
2822 /* fill in the basic info */
2823 ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
2824 ldap_mods[i]->mod_type = estrndup(Z_STRVAL_P(attrib), Z_STRLEN_P(attrib));
2825
2826 if (Z_LVAL_P(modtype) == LDAP_MODIFY_BATCH_REMOVE_ALL) {
2827 /* no values */
2828 ldap_mods[i]->mod_bvalues = NULL;
2829 }
2830 else {
2831 /* allocate space for the values as part of this modification */
2832 num_modvals = zend_hash_num_elements(Z_ARRVAL_P(vals));
2833 ldap_mods[i]->mod_bvalues = safe_emalloc((num_modvals+1), sizeof(struct berval *), 0);
2834
2835 /* for each value */
2836 j = 0;
2837 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(vals), fetched) {
2838 /* fetch it */
2839 modval = zval_get_string(fetched);
2840 if (EG(exception)) {
2842 ldap_mods[i]->mod_bvalues[j] = NULL;
2843 num_mods = i + 1;
2844 goto cleanup;
2845 }
2846
2847 /* allocate the data struct */
2848 ldap_mods[i]->mod_bvalues[j] = safe_emalloc(1, sizeof(struct berval), 0);
2849
2850 /* fill it */
2851 ldap_mods[i]->mod_bvalues[j]->bv_len = ZSTR_LEN(modval);
2852 ldap_mods[i]->mod_bvalues[j]->bv_val = estrndup(ZSTR_VAL(modval), ZSTR_LEN(modval));
2853 zend_string_release(modval);
2854 j++;
2856
2857 /* NULL-terminate values */
2858 ldap_mods[i]->mod_bvalues[num_modvals] = NULL;
2859 }
2860
2861 i++;
2863
2864 /* NULL-terminate modifications */
2865 ldap_mods[num_mods] = NULL;
2866
2867 if (serverctrls) {
2868 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 4);
2869 if (lserverctrls == NULL) {
2871 goto cleanup;
2872 }
2873 }
2874
2875 /* perform (finally) */
2876 if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) {
2877 php_error_docref(NULL, E_WARNING, "Batch Modify: %s", ldap_err2string(i));
2879 } else RETVAL_TRUE;
2880
2881 /* clean up */
2882 cleanup: {
2883 for (i = 0; i < num_mods; i++) {
2884 /* attribute */
2885 efree(ldap_mods[i]->mod_type);
2886
2887 if (ldap_mods[i]->mod_bvalues != NULL) {
2888 /* each BER value */
2889 for (j = 0; ldap_mods[i]->mod_bvalues[j] != NULL; j++) {
2890 /* free the data bytes */
2891 efree(ldap_mods[i]->mod_bvalues[j]->bv_val);
2892
2893 /* free the bvalue struct */
2894 efree(ldap_mods[i]->mod_bvalues[j]);
2895 }
2896
2897 /* the BER value array */
2898 efree(ldap_mods[i]->mod_bvalues);
2899 }
2900
2901 /* the modification */
2902 efree(ldap_mods[i]);
2903 }
2904
2905 /* the modifications array */
2906 efree(ldap_mods);
2907
2908 if (lserverctrls) {
2909 _php_ldap_controls_free(&lserverctrls);
2910 }
2911 }
2912}
2913/* }}} */
2914
2915/* {{{ Get the current ldap error number */
2917{
2918 zval *link;
2919 ldap_linkdata *ld;
2920
2921 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) {
2922 RETURN_THROWS();
2923 }
2924
2925 ld = Z_LDAP_LINK_P(link);
2927
2928 RETURN_LONG(_get_lderrno(ld->link));
2929}
2930/* }}} */
2931
2932/* {{{ Convert error number to error string */
2934{
2935 zend_long perrno;
2936
2937 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &perrno) != SUCCESS) {
2938 RETURN_THROWS();
2939 }
2940
2941 RETURN_STRING(ldap_err2string(perrno));
2942}
2943/* }}} */
2944
2945/* {{{ Get the current ldap error string */
2947{
2948 zval *link;
2949 ldap_linkdata *ld;
2950 int ld_errno;
2951
2952 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) {
2953 RETURN_THROWS();
2954 }
2955
2956 ld = Z_LDAP_LINK_P(link);
2958
2959 ld_errno = _get_lderrno(ld->link);
2960
2961 RETURN_STRING(ldap_err2string(ld_errno));
2962}
2963/* }}} */
2964
2965/* {{{ Determine if an entry has a specific value for one of its attributes */
2967{
2968 zval *serverctrls = NULL;
2969 zval *link;
2970 char *dn, *attr, *value;
2971 size_t dn_len, attr_len, value_len;
2972 ldap_linkdata *ld;
2973 LDAPControl **lserverctrls = NULL;
2974 int ldap_errno;
2975 struct berval lvalue;
2976
2977 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osss|a!", &link, ldap_link_ce, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &serverctrls) != SUCCESS) {
2978 RETURN_THROWS();
2979 }
2980
2981 ld = Z_LDAP_LINK_P(link);
2983
2984 if (serverctrls) {
2985 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 5);
2986 if (lserverctrls == NULL) {
2988 goto cleanup;
2989 }
2990 }
2991
2992 lvalue.bv_val = value;
2993 lvalue.bv_len = value_len;
2994
2995 ldap_errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, lserverctrls, NULL);
2996
2997 switch (ldap_errno) {
2998 case LDAP_COMPARE_TRUE:
3000 break;
3001
3002 case LDAP_COMPARE_FALSE:
3004 break;
3005
3006 default:
3007 php_error_docref(NULL, E_WARNING, "Compare: %s", ldap_err2string(ldap_errno));
3008 RETVAL_LONG(-1);
3009 }
3010
3011cleanup:
3012 if (lserverctrls) {
3013 _php_ldap_controls_free(&lserverctrls);
3014 }
3015
3016 return;
3017}
3018/* }}} */
3019
3020#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
3021/* {{{ Get the current value of various session-wide parameters */
3023{
3024 zval *link, *retval;
3025 ldap_linkdata *ld;
3026 zend_long option;
3027
3028 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olz", &link, ldap_link_ce, &option, &retval) != SUCCESS) {
3029 RETURN_THROWS();
3030 }
3031
3032 ld = Z_LDAP_LINK_P(link);
3034
3035 switch (option) {
3036 /* options with int value */
3037 case LDAP_OPT_DEREF:
3038 case LDAP_OPT_SIZELIMIT:
3039 case LDAP_OPT_TIMELIMIT:
3042 case LDAP_OPT_REFERRALS:
3043#ifdef LDAP_OPT_RESTART
3044 case LDAP_OPT_RESTART:
3045#endif
3046#ifdef LDAP_OPT_X_SASL_NOCANON
3048#endif
3049#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
3051#endif
3052#ifdef LDAP_OPT_X_TLS_CRLCHECK
3054#endif
3055#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
3057#endif
3058#ifdef LDAP_OPT_X_TLS_PROTOCOL_MAX
3060#endif
3061#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
3065#endif
3066 {
3067 int val;
3068
3069 if (ldap_get_option(ld->link, option, &val)) {
3071 }
3073 } break;
3074#ifdef LDAP_OPT_NETWORK_TIMEOUT
3076 {
3077 struct timeval *timeout = NULL;
3078
3079 if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
3080 if (timeout) {
3081 ldap_memfree(timeout);
3082 }
3084 }
3085 if (!timeout) {
3087 }
3088 ZEND_TRY_ASSIGN_REF_LONG(retval, timeout->tv_sec);
3089 ldap_memfree(timeout);
3090 } break;
3091#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
3092 case LDAP_X_OPT_CONNECT_TIMEOUT:
3093 {
3094 int timeout;
3095
3096 if (ldap_get_option(ld->link, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
3098 }
3099 ZEND_TRY_ASSIGN_REF_LONG(retval, (timeout / 1000));
3100 } break;
3101#endif
3102#ifdef LDAP_OPT_TIMEOUT
3103 case LDAP_OPT_TIMEOUT:
3104 {
3105 struct timeval *timeout = NULL;
3106
3107 if (ldap_get_option(ld->link, LDAP_OPT_TIMEOUT, (void *) &timeout)) {
3108 if (timeout) {
3109 ldap_memfree(timeout);
3110 }
3112 }
3113 if (!timeout) {
3115 }
3116 ZEND_TRY_ASSIGN_REF_LONG(retval, timeout->tv_sec);
3117 ldap_memfree(timeout);
3118 } break;
3119#endif
3120 /* options with string value */
3122#ifdef LDAP_OPT_HOST_NAME
3123 case LDAP_OPT_HOST_NAME:
3124#endif
3125#ifdef HAVE_LDAP_SASL
3130#endif
3131#ifdef LDAP_OPT_X_SASL_USERNAME
3133#endif
3134#if (LDAP_API_VERSION > 2000)
3141#endif
3142#ifdef LDAP_OPT_X_TLS_PACKAGE
3144#endif
3145#ifdef LDAP_OPT_X_TLS_CRLFILE
3147#endif
3148#ifdef LDAP_OPT_X_TLS_DHFILE
3150#endif
3151#ifdef LDAP_OPT_MATCHED_DN
3153#endif
3154 {
3155 char *val = NULL;
3156
3157 if (ldap_get_option(ld->link, option, &val) || val == NULL || *val == '\0') {
3158 if (val) {
3159 ldap_memfree(val);
3160 }
3162 }
3164 ldap_memfree(val);
3165 } break;
3168 {
3169 LDAPControl **ctrls = NULL;
3170
3171 if (ldap_get_option(ld->link, option, &ctrls) || ctrls == NULL) {
3172 if (ctrls) {
3173 ldap_memfree(ctrls);
3174 }
3176 }
3177 _php_ldap_controls_to_array(ld->link, ctrls, retval, 1);
3178 } break;
3179/* options not implemented
3180 case LDAP_OPT_API_INFO:
3181 case LDAP_OPT_API_FEATURE_INFO:
3182*/
3183 default:
3185 }
3187}
3188/* }}} */
3189
3190/* {{{ Set the value of various session-wide parameters */
3192{
3193 zval *link = NULL, *newval;
3194 ldap_linkdata *ld;
3195 LDAP *ldap;
3196 zend_long option;
3197
3198 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O!lz", &link, ldap_link_ce, &option, &newval) != SUCCESS) {
3199 RETURN_THROWS();
3200 }
3201
3202 if (!link) {
3203 ldap = NULL;
3204 } else {
3205 ld = Z_LDAP_LINK_P(link);
3207 ldap = ld->link;
3208 }
3209
3210 switch (option) {
3211 /* TLS options with int value */
3212#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
3214#endif
3215#ifdef LDAP_OPT_X_TLS_CRLCHECK
3217#endif
3218#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
3220#endif
3221#ifdef LDAP_OPT_X_TLS_PROTOCOL_MAX
3223#endif
3224 /* TLS option change requires resetting TLS context */
3225 LDAPG(tls_newctx) = true;
3227 /* other options with int value */
3228 case LDAP_OPT_DEREF:
3229 case LDAP_OPT_SIZELIMIT:
3230 case LDAP_OPT_TIMELIMIT:
3233#ifdef LDAP_OPT_DEBUG_LEVEL
3235#endif
3236#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
3240#endif
3241 {
3242 int val;
3243
3244 convert_to_long(newval);
3245 if (ZEND_LONG_EXCEEDS_INT(Z_LVAL_P(newval))) {
3246 zend_argument_value_error(3, "is too large");
3247 RETURN_THROWS();
3248 }
3249 val = (int)Z_LVAL_P(newval);
3250 if (ldap_set_option(ldap, option, &val)) {
3252 }
3253 } break;
3254#ifdef LDAP_OPT_NETWORK_TIMEOUT
3256 {
3257 struct timeval timeout;
3258
3259 convert_to_long(newval);
3260 timeout.tv_sec = Z_LVAL_P(newval);
3261 timeout.tv_usec = 0;
3262 if (ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
3264 }
3265 } break;
3266#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
3267 case LDAP_X_OPT_CONNECT_TIMEOUT:
3268 {
3269 int timeout;
3270
3271 convert_to_long(newval);
3272 timeout = 1000 * Z_LVAL_P(newval); /* Convert to milliseconds */
3273 if (ldap_set_option(ldap, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
3275 }
3276 } break;
3277#endif
3278#ifdef LDAP_OPT_TIMEOUT
3279 case LDAP_OPT_TIMEOUT:
3280 {
3281 struct timeval timeout;
3282
3283 convert_to_long(newval);
3284 timeout.tv_sec = Z_LVAL_P(newval);
3285 timeout.tv_usec = 0;
3286 if (ldap_set_option(ldap, LDAP_OPT_TIMEOUT, (void *) &timeout)) {
3288 }
3289 } break;
3290#endif
3291 /* TLS options with string value */
3292#if (LDAP_API_VERSION > 2000)
3299#endif
3300#ifdef LDAP_OPT_X_TLS_CRLFILE
3302#endif
3303#ifdef LDAP_OPT_X_TLS_DHFILE
3305#endif
3306 /* TLS option change requires resetting TLS context */
3307 LDAPG(tls_newctx) = true;
3309 /* other options with string value */
3311#ifdef LDAP_OPT_HOST_NAME
3312 case LDAP_OPT_HOST_NAME:
3313#endif
3314#ifdef HAVE_LDAP_SASL
3319#endif
3320#ifdef LDAP_OPT_MATCHED_DN
3322#endif
3323 {
3325 val = zval_get_string(newval);
3326 if (EG(exception)) {
3327 RETURN_THROWS();
3328 }
3329 if (ldap_set_option(ldap, option, ZSTR_VAL(val))) {
3330 zend_string_release(val);
3332 }
3333 zend_string_release(val);
3334 } break;
3335 /* options with boolean value */
3336 case LDAP_OPT_REFERRALS:
3337#ifdef LDAP_OPT_RESTART
3338 case LDAP_OPT_RESTART:
3339#endif
3340#ifdef LDAP_OPT_X_SASL_NOCANON
3342#endif
3343 {
3344 void *val;
3345 val = zend_is_true(newval) ? LDAP_OPT_ON : LDAP_OPT_OFF;
3346 if (ldap_set_option(ldap, option, val)) {
3348 }
3349 } break;
3350 /* options with control list value */
3353 {
3354 LDAPControl **ctrls;
3355 int rc;
3356
3357 if (Z_TYPE_P(newval) != IS_ARRAY) {
3358 zend_argument_type_error(3, "must be of type array for the LDAP_OPT_CLIENT_CONTROLS option, %s given", zend_zval_value_name(newval));
3359 RETURN_THROWS();
3360 }
3361
3362 ctrls = _php_ldap_controls_from_array(ldap, newval, 3);
3363
3364 if (ctrls == NULL) {
3366 } else {
3367 rc = ldap_set_option(ldap, option, ctrls);
3368 _php_ldap_controls_free(&ctrls);
3369 if (rc != LDAP_SUCCESS) {
3371 }
3372 }
3373 } break;
3374 default:
3376 }
3378}
3379/* }}} */
3380
3381#ifdef HAVE_LDAP_PARSE_RESULT
3382/* {{{ Extract information from result */
3384{
3385 zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals, *serverctrls;
3386 ldap_linkdata *ld;
3387 ldap_resultdata *ldap_result;
3388 LDAPControl **lserverctrls = NULL;
3389 char **lreferrals, **refp;
3390 char *lmatcheddn, *lerrmsg;
3391 int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
3392
3393 if (zend_parse_parameters(myargcount, "OOz|zzzz", &link, ldap_link_ce, &result, ldap_result_ce, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) {
3394 RETURN_THROWS();
3395 }
3396
3397 ld = Z_LDAP_LINK_P(link);
3399
3400 ldap_result = Z_LDAP_RESULT_P(result);
3401 VERIFY_LDAP_RESULT_OPEN(ldap_result);
3402
3403 rc = ldap_parse_result(ld->link, ldap_result->result, &lerrcode,
3404 myargcount > 3 ? &lmatcheddn : NULL,
3405 myargcount > 4 ? &lerrmsg : NULL,
3406 myargcount > 5 ? &lreferrals : NULL,
3407 myargcount > 6 ? &lserverctrls : NULL,
3408 0);
3409 if (rc != LDAP_SUCCESS) {
3410 php_error_docref(NULL, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
3412 }
3413
3414 ZEND_TRY_ASSIGN_REF_LONG(errcode, lerrcode);
3415
3416 /* Reverse -> fall through */
3417 switch (myargcount) {
3418 case 7:
3419 _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
3421 case 6:
3422 referrals = zend_try_array_init(referrals);
3423 if (!referrals) {
3424 RETURN_THROWS();
3425 }
3426 if (lreferrals != NULL) {
3427 refp = lreferrals;
3428 while (*refp) {
3429 add_next_index_string(referrals, *refp);
3430 refp++;
3431 }
3432 ldap_memvfree((void**)lreferrals);
3433 }
3435 case 5:
3436 if (lerrmsg == NULL) {
3438 } else {
3439 ZEND_TRY_ASSIGN_REF_STRING(errmsg, lerrmsg);
3440 ldap_memfree(lerrmsg);
3441 }
3443 case 4:
3444 if (lmatcheddn == NULL) {
3446 } else {
3447 ZEND_TRY_ASSIGN_REF_STRING(matcheddn, lmatcheddn);
3448 ldap_memfree(lmatcheddn);
3449 }
3450 }
3452}
3453/* }}} */
3454#endif
3455
3456/* {{{ Extended operation response parsing, Pierangelo Masarati */
3457#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
3458/* {{{ Extract information from extended operation result */
3460{
3461 zval *link, *result, *retdata, *retoid;
3462 ldap_linkdata *ld;
3463 ldap_resultdata *ldap_result;
3464 char *lretoid;
3465 struct berval *lretdata;
3466 int rc, myargcount = ZEND_NUM_ARGS();
3467
3468 if (zend_parse_parameters(myargcount, "OO|zz", &link, ldap_link_ce, &result, ldap_result_ce, &retdata, &retoid) != SUCCESS) {
3469 RETURN_THROWS();
3470 }
3471
3472 ld = Z_LDAP_LINK_P(link);
3474
3475 ldap_result = Z_LDAP_RESULT_P(result);
3476 VERIFY_LDAP_RESULT_OPEN(ldap_result);
3477
3478 rc = ldap_parse_extended_result(ld->link, ldap_result->result,
3479 myargcount > 3 ? &lretoid: NULL,
3480 myargcount > 2 ? &lretdata: NULL,
3481 0);
3482 if (rc != LDAP_SUCCESS) {
3483 php_error_docref(NULL, E_WARNING, "Unable to parse extended operation result: %s", ldap_err2string(rc));
3485 }
3486
3487 /* Reverse -> fall through */
3488 switch (myargcount) {
3489 case 4:
3490 if (lretoid == NULL) {
3492 } else {
3493 ZEND_TRY_ASSIGN_REF_STRING(retoid, lretoid);
3494 ldap_memfree(lretoid);
3495 }
3497 case 3:
3498 /* use arg #3 as the data returned by the server */
3499 if (lretdata == NULL) {
3501 } else {
3502 ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
3503 ldap_memfree(lretdata->bv_val);
3504 ldap_memfree(lretdata);
3505 }
3506 }
3508}
3509/* }}} */
3510#endif
3511/* }}} */
3512
3513/* {{{ Count the number of references in a search result */
3515{
3516 zval *link, *result;
3517 ldap_linkdata *ld;
3518 ldap_resultdata *ldap_result;
3519
3520 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
3521 RETURN_THROWS();
3522 }
3523
3524 ld = Z_LDAP_LINK_P(link);
3526
3527 ldap_result = Z_LDAP_RESULT_P(result);
3528 VERIFY_LDAP_RESULT_OPEN(ldap_result);
3529
3530 RETURN_LONG(ldap_count_references(ld->link, ldap_result->result));
3531}
3532/* }}} */
3533
3534/* {{{ Return first reference */
3536{
3537 zval *link, *result;
3538 ldap_linkdata *ld;
3539 ldap_result_entry *resultentry;
3540 ldap_resultdata *ldap_result;
3541 LDAPMessage *entry;
3542
3543 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) {
3544 RETURN_THROWS();
3545 }
3546
3547 ld = Z_LDAP_LINK_P(link);
3549
3550 ldap_result = Z_LDAP_RESULT_P(result);
3551 VERIFY_LDAP_RESULT_OPEN(ldap_result);
3552
3553 if ((entry = ldap_first_reference(ld->link, ldap_result->result)) == NULL) {
3555 } else {
3556 object_init_ex(return_value, ldap_result_entry_ce);
3557 resultentry = Z_LDAP_RESULT_ENTRY_P(return_value);
3558 ZVAL_COPY(&resultentry->res, result);
3559 resultentry->data = entry;
3560 resultentry->ber = NULL;
3561 }
3562}
3563/* }}} */
3564
3565/* {{{ Get next reference */
3567{
3568 zval *link, *result_entry;
3569 ldap_linkdata *ld;
3570 ldap_result_entry *resultentry, *resultentry_next;
3571 LDAPMessage *entry_next;
3572
3573 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) {
3574 RETURN_THROWS();
3575 }
3576
3577 ld = Z_LDAP_LINK_P(link);
3579
3580 resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
3581
3582 if ((entry_next = ldap_next_reference(ld->link, resultentry->data)) == NULL) {
3584 } else {
3585 object_init_ex(return_value, ldap_result_entry_ce);
3586 resultentry_next = Z_LDAP_RESULT_ENTRY_P(return_value);
3587 ZVAL_COPY(&resultentry_next->res, &resultentry->res);
3588 resultentry_next->data = entry_next;
3589 resultentry_next->ber = NULL;
3590 }
3591}
3592/* }}} */
3593
3594#ifdef HAVE_LDAP_PARSE_REFERENCE
3595/* {{{ Extract information from reference entry */
3597{
3598 zval *link, *result_entry, *referrals;
3599 ldap_linkdata *ld;
3600 ldap_result_entry *resultentry;
3601 char **lreferrals, **refp;
3602
3603 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOz", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce, &referrals) != SUCCESS) {
3604 RETURN_THROWS();
3605 }
3606
3607 ld = Z_LDAP_LINK_P(link);
3609
3610 resultentry = Z_LDAP_RESULT_ENTRY_P(result_entry);
3611
3612 if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
3614 }
3615
3616 referrals = zend_try_array_init(referrals);
3617 if (!referrals) {
3618 RETURN_THROWS();
3619 }
3620
3621 if (lreferrals != NULL) {
3622 refp = lreferrals;
3623 while (*refp) {
3624 add_next_index_string(referrals, *refp);
3625 refp++;
3626 }
3627 ldap_memvfree((void**)lreferrals);
3628 }
3630}
3631/* }}} */
3632#endif
3633
3634/* {{{ php_ldap_do_rename */
3635static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, int ext)
3636{
3637 zval *serverctrls = NULL;
3638 zval *link;
3639 ldap_linkdata *ld;
3640 LDAPControl **lserverctrls = NULL;
3642 LDAPMessage *ldap_res;
3643 int rc, msgid;
3644 char *dn, *newrdn, *newparent;
3645 size_t dn_len, newrdn_len, newparent_len;
3646 bool deleteoldrdn;
3647
3648 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osssb|a!", &link, ldap_link_ce, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn, &serverctrls) != SUCCESS) {
3649 RETURN_THROWS();
3650 }
3651
3652 ld = Z_LDAP_LINK_P(link);
3654
3655 if (newparent_len == 0) {
3656 newparent = NULL;
3657 }
3658
3659#if (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP)
3660 if (serverctrls) {
3661 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 6);
3662 if (lserverctrls == NULL) {
3664 goto cleanup;
3665 }
3666 }
3667
3668 if (ext) {
3669 rc = ldap_rename(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL, &msgid);
3670 } else {
3671 rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL);
3672 }
3673#else
3674 if (newparent_len != 0) {
3675 php_error_docref(NULL, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN");
3677 }
3678 if (serverctrls) {
3679 php_error_docref(NULL, E_WARNING, "You are using old LDAP API, controls are not supported");
3681 }
3682 if (ext) {
3683 php_error_docref(NULL, E_WARNING, "You are using old LDAP API, ldap_rename_ext is not supported");
3685 }
3686/* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */
3687 rc = ldap_modrdn2_s(ld->link, dn, newrdn, deleteoldrdn);
3688#endif
3689
3690 if (rc != LDAP_SUCCESS) {
3692 } else if (ext) {
3693 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
3694 if (rc == -1) {
3695 php_error_docref(NULL, E_WARNING, "Rename operation failed");
3697 goto cleanup;
3698 }
3699
3700 /* return a PHP control object */
3701 object_init_ex(return_value, ldap_result_ce);
3703 result->result = ldap_res;
3704 } else {
3706 }
3707
3708cleanup:
3709 if (lserverctrls) {
3710 _php_ldap_controls_free(&lserverctrls);
3711 }
3712
3713 return;
3714}
3715/* }}} */
3716
3717/* {{{ Modify the name of an entry */
3719{
3720 php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3721}
3722/* }}} */
3723
3724/* {{{ Modify the name of an entry */
3726{
3727 php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3728}
3729/* }}} */
3730
3731#ifdef HAVE_LDAP_START_TLS_S
3732/*
3733 Force new tls context creation with string options inherited from global
3734 Workaround to https://bugs.openldap.org/show_bug.cgi?id=10337
3735 */
3736static int _php_ldap_tls_newctx(LDAP *ld)
3737{
3738 int val = 0, i, opts[] = {
3739#if (LDAP_API_VERSION > 2000)
3746#endif
3747#ifdef LDAP_OPT_X_TLS_CRLFILE
3749#endif
3750#ifdef LDAP_OPT_X_TLS_DHFILE
3752#endif
3753#ifdef LDAP_OPT_X_TLS_ECNAME
3754 LDAP_OPT_X_TLS_ECNAME,
3755#endif
3756 0};
3757
3758 for (i=0 ; opts[i] ; i++) {
3759 char *path = NULL;
3760
3761 ldap_get_option(ld, opts[i], &path);
3762 if (path) { /* already set locally */
3763 ldap_memfree(path);
3764 } else {
3765 ldap_get_option(NULL, opts[i], &path);
3766 if (path) { /* set globally, inherit */
3767 ldap_set_option(ld, opts[i], path);
3768 ldap_memfree(path);
3769 }
3770 }
3771 }
3772
3773 return ldap_set_option(ld, LDAP_OPT_X_TLS_NEWCTX, &val);
3774}
3775
3776/* {{{ Start TLS */
3778{
3779 zval *link;
3780 ldap_linkdata *ld;
3781 int rc, protocol = LDAP_VERSION3;
3782
3783 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) != SUCCESS) {
3784 RETURN_THROWS();
3785 }
3786
3787 ld = Z_LDAP_LINK_P(link);
3789
3790 if (((rc = ldap_set_option(ld->link, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) ||
3791#ifdef LDAP_OPT_X_TLS_NEWCTX
3792 (LDAPG(tls_newctx) && (rc = _php_ldap_tls_newctx(ld->link)) != LDAP_OPT_SUCCESS) ||
3793#endif
3794 ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS)
3795 ) {
3796 php_error_docref(NULL, E_WARNING,"Unable to start TLS: %s", ldap_err2string(rc));
3798 }
3799 LDAPG(tls_newctx) = false;
3801}
3802/* }}} */
3803#endif
3804#endif /* (LDAP_API_VERSION > 2000) || defined(HAVE_ORALDAP) */
3805
3806#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
3807/* {{{ _ldap_rebind_proc() */
3808int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params)
3809{
3810 ldap_linkdata *ld = NULL;
3811 int retval;
3812 zval cb_args[2];
3813 zval cb_retval;
3814 zval *cb_link = (zval *) params;
3815
3816 ld = Z_LDAP_LINK_P(cb_link);
3817 if (!ld->link) {
3818 zend_throw_error(NULL, "LDAP connection has already been closed");
3819 return LDAP_OTHER;
3820 }
3821
3822 /* link exists and callback set? */
3823 if (Z_ISUNDEF(ld->rebindproc)) {
3824 php_error_docref(NULL, E_WARNING, "No callback set");
3825 return LDAP_OTHER;
3826 }
3827
3828 /* callback */
3829 ZVAL_COPY_VALUE(&cb_args[0], cb_link);
3830 ZVAL_STRING(&cb_args[1], url);
3831 if (call_user_function(EG(function_table), NULL, &ld->rebindproc, &cb_retval, 2, cb_args) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
3832 retval = zval_get_long(&cb_retval);
3833 zval_ptr_dtor(&cb_retval);
3834 } else {
3835 php_error_docref(NULL, E_WARNING, "rebind_proc PHP callback failed");
3836 retval = LDAP_OTHER;
3837 }
3838 zval_ptr_dtor(&cb_args[1]);
3839 return retval;
3840}
3841/* }}} */
3842
3843/* {{{ Set a callback function to do re-binds on referral chasing. */
3845{
3846 zval *link;
3847 zend_fcall_info fci;
3849 ldap_linkdata *ld;
3850
3851 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Of!", &link, ldap_link_ce, &fci, &fcc) == FAILURE) {
3852 RETURN_THROWS();
3853 }
3854
3855 ld = Z_LDAP_LINK_P(link);
3857
3858 if (!ZEND_FCI_INITIALIZED(fci)) {
3859 /* unregister rebind procedure */
3860 if (!Z_ISUNDEF(ld->rebindproc)) {
3861 zval_ptr_dtor(&ld->rebindproc);
3862 ZVAL_UNDEF(&ld->rebindproc);
3864 }
3866 }
3867
3868 /* register rebind procedure */
3869 if (Z_ISUNDEF(ld->rebindproc)) {
3870 ldap_set_rebind_proc(ld->link, _ldap_rebind_proc, (void *) link);
3871 } else {
3872 zval_ptr_dtor(&ld->rebindproc);
3873 }
3874
3875 ZVAL_COPY(&ld->rebindproc, &fci.function_name);
3877}
3878/* }}} */
3879#endif
3880
3881static zend_string* php_ldap_do_escape(const bool *map, const char *value, size_t valuelen, zend_long flags)
3882{
3883 char hex[] = "0123456789abcdef";
3884 size_t i, p = 0;
3885 size_t len = 0;
3887
3888 for (i = 0; i < valuelen; i++) {
3889 size_t addend = (map[(unsigned char) value[i]]) ? 3 : 1;
3890 if (len > ZSTR_MAX_LEN - addend) {
3891 return NULL;
3892 }
3893 len += addend;
3894 }
3895 /* Per RFC 4514, a leading and trailing space must be escaped */
3896 if ((flags & PHP_LDAP_ESCAPE_DN) && (value[0] == ' ')) {
3897 if (len > ZSTR_MAX_LEN - 2) {
3898 return NULL;
3899 }
3900 len += 2;
3901 }
3902 if ((flags & PHP_LDAP_ESCAPE_DN) && ((valuelen > 1) && (value[valuelen - 1] == ' '))) {
3903 if (len > ZSTR_MAX_LEN - 2) {
3904 return NULL;
3905 }
3906 len += 2;
3907 }
3908
3909 ret = zend_string_alloc(len, 0);
3910
3911 for (i = 0; i < valuelen; i++) {
3912 unsigned char v = (unsigned char) value[i];
3913
3914 if (map[v] || ((flags & PHP_LDAP_ESCAPE_DN) && ((i == 0) || (i + 1 == valuelen)) && (v == ' '))) {
3915 ZSTR_VAL(ret)[p++] = '\\';
3916 ZSTR_VAL(ret)[p++] = hex[v >> 4];
3917 ZSTR_VAL(ret)[p++] = hex[v & 0x0f];
3918 } else {
3919 ZSTR_VAL(ret)[p++] = v;
3920 }
3921 }
3922
3923 ZSTR_VAL(ret)[p] = '\0';
3924 ZSTR_LEN(ret) = p;
3925 return ret;
3926}
3927
3928static void php_ldap_escape_map_set_chars(bool *map, const char *chars, const size_t charslen, char escape)
3929{
3930 size_t i = 0;
3931 while (i < charslen) {
3932 map[(unsigned char) chars[i++]] = escape;
3933 }
3934}
3935
3937{
3938 char *value, *ignores;
3939 size_t valuelen = 0, ignoreslen = 0;
3940 int i;
3941 zend_long flags = 0;
3942 bool map[256] = {0}, havecharlist = 0;
3943
3944 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sl", &value, &valuelen, &ignores, &ignoreslen, &flags) != SUCCESS) {
3945 RETURN_THROWS();
3946 }
3947
3948 if (!valuelen) {
3950 }
3951
3953 havecharlist = 1;
3954 php_ldap_escape_map_set_chars(map, "\\*()\0", sizeof("\\*()\0") - 1, 1);
3955 }
3956
3957 if (flags & PHP_LDAP_ESCAPE_DN) {
3958 havecharlist = 1;
3959 php_ldap_escape_map_set_chars(map, "\\,=+<>;\"#\r", sizeof("\\,=+<>;\"#\r") - 1, 1);
3960 }
3961
3962 if (!havecharlist) {
3963 for (i = 0; i < 256; i++) {
3964 map[i] = 1;
3965 }
3966 }
3967
3968 if (ignoreslen) {
3969 php_ldap_escape_map_set_chars(map, ignores, ignoreslen, 0);
3970 }
3971
3972 zend_string *result = php_ldap_do_escape(map, value, valuelen, flags);
3973 if (UNEXPECTED(!result)) {
3974 zend_argument_value_error(1, "is too long");
3975 RETURN_THROWS();
3976 }
3977
3979}
3980
3981#ifdef STR_TRANSLATION
3982/* {{{ php_ldap_do_translate */
3983static void php_ldap_do_translate(INTERNAL_FUNCTION_PARAMETERS, int way)
3984{
3985 char *value;
3986 size_t value_len;
3987 int result;
3988
3989 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value, &value_len) != SUCCESS) {
3990 RETURN_THROWS();
3991 }
3992
3993 if (value_len == 0) {
3995 }
3996
3997 if (way == 1) {
3998 result = ldap_8859_to_t61(&value, &value_len, 0);
3999 } else {
4000 result = ldap_t61_to_8859(&value, &value_len, 0);
4001 }
4002
4003 if (result == LDAP_SUCCESS) {
4004 RETVAL_STRINGL(value, value_len);
4005 free(value);
4006 } else {
4007 php_error_docref(NULL, E_WARNING, "Conversion from ISO-8859-1 to t61 failed: %s", ldap_err2string(result));
4009 }
4010}
4011/* }}} */
4012
4013/* {{{ Translate t61 characters to 8859 characters */
4015{
4016 php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
4017}
4018/* }}} */
4019
4020/* {{{ Translate 8859 characters to t61 characters */
4022{
4023 php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
4024}
4025/* }}} */
4026#endif
4027
4028/* {{{ Extended operations, Pierangelo Masarati */
4029#ifdef HAVE_LDAP_EXTENDED_OPERATION_S
4030static void php_ldap_exop(INTERNAL_FUNCTION_PARAMETERS, bool force_sync) {
4031 zval *serverctrls = NULL;
4032 zval *link, *retdata = NULL, *retoid = NULL;
4033 char *lretoid = NULL;
4034 zend_string *reqoid, *reqdata = NULL;
4035 struct berval lreqdata, *lretdata = NULL;
4036 ldap_linkdata *ld;
4038 LDAPMessage *ldap_res;
4039 LDAPControl **lserverctrls = NULL;
4040 int rc, msgid;
4041
4042 if (force_sync == false && ZEND_NUM_ARGS() > 4) {
4043 zend_error(E_DEPRECATED, "Calling ldap_exop() with more than 4 arguments is deprecated, use ldap_exop_sync() instead");
4044 if (UNEXPECTED(EG(exception))) {
4045 RETURN_THROWS();
4046 }
4047 }
4048
4049 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|S!a!zz", &link, ldap_link_ce, &reqoid, &reqdata, &serverctrls, &retdata, &retoid) != SUCCESS) {
4050 RETURN_THROWS();
4051 }
4052
4053 ld = Z_LDAP_LINK_P(link);
4055
4056 if (reqdata) {
4057 lreqdata.bv_val = ZSTR_VAL(reqdata);
4058 lreqdata.bv_len = ZSTR_LEN(reqdata);
4059 } else {
4060 lreqdata.bv_len = 0;
4061 }
4062
4063 if (serverctrls) {
4064 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls, 4);
4065 if (lserverctrls == NULL) {
4067 goto cleanup;
4068 }
4069 }
4070
4071 if (force_sync || retdata) {
4072 /* synchronous call */
4073 rc = ldap_extended_operation_s(ld->link, ZSTR_VAL(reqoid),
4074 lreqdata.bv_len > 0 ? &lreqdata: NULL,
4075 lserverctrls,
4076 NULL,
4077 retoid ? &lretoid : NULL,
4078 &lretdata );
4079 if (rc != LDAP_SUCCESS ) {
4080 php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc);
4082 goto cleanup;
4083 }
4084
4085 if (retoid) {
4086 if (lretoid) {
4087 ZEND_TRY_ASSIGN_REF_STRING(retoid, lretoid);
4088 ldap_memfree(lretoid);
4089 } else {
4091 }
4092 }
4093
4094 if (lretdata) {
4095 ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
4096 ldap_memfree(lretdata->bv_val);
4097 ldap_memfree(lretdata);
4098 } else {
4100 }
4101
4103 goto cleanup;
4104 }
4105
4106 /* asynchronous call */
4107 rc = ldap_extended_operation(ld->link, ZSTR_VAL(reqoid),
4108 lreqdata.bv_len > 0 ? &lreqdata: NULL,
4109 lserverctrls,
4110 NULL,
4111 &msgid);
4112 if (rc != LDAP_SUCCESS ) {
4113 php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc);
4115 goto cleanup;
4116 }
4117
4118 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
4119 if (rc == -1) {
4120 php_error_docref(NULL, E_WARNING, "Extended operation %s failed", ZSTR_VAL(reqoid));
4122 goto cleanup;
4123 }
4124
4125 /* return a PHP control object */
4126 object_init_ex(return_value, ldap_result_ce);
4128 result->result = ldap_res;
4129
4130cleanup:
4131 if (lserverctrls) {
4132 _php_ldap_controls_free(&lserverctrls);
4133 }
4134}
4135
4136/* {{{ Extended operation */
4138{
4139 php_ldap_exop(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
4140}
4141/* }}} */
4142
4144{
4145 php_ldap_exop(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
4146}
4147#endif
4148
4149#ifdef HAVE_LDAP_PASSWD
4150/* {{{ Passwd modify extended operation */
4152{
4153 zval *link, *serverctrls;
4154 struct berval luser = { 0L, NULL };
4155 struct berval loldpw = { 0L, NULL };
4156 struct berval lnewpw = { 0L, NULL };
4157 struct berval lgenpasswd = { 0L, NULL };
4158 LDAPControl *ctrl, **lserverctrls = NULL, *requestctrls[2] = { NULL, NULL };
4159 LDAPMessage* ldap_res = NULL;
4160 ldap_linkdata *ld;
4161 int rc, myargcount = ZEND_NUM_ARGS(), msgid, err;
4162 char* errmsg = NULL;
4163
4164 if (zend_parse_parameters(myargcount, "O|sssz/", &link, ldap_link_ce, &luser.bv_val, &luser.bv_len, &loldpw.bv_val, &loldpw.bv_len, &lnewpw.bv_val, &lnewpw.bv_len, &serverctrls) == FAILURE) {
4165 RETURN_THROWS();
4166 }
4167
4168 ld = Z_LDAP_LINK_P(link);
4170
4171 switch (myargcount) {
4172 case 5:
4173 /* ldap_create_passwordpolicy_control() allocates ctrl */
4174 if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) {
4175 requestctrls[0] = ctrl;
4176 }
4177 }
4178
4179 /* asynchronous call to get result and controls */
4180 rc = ldap_passwd(ld->link, &luser,
4181 loldpw.bv_len > 0 ? &loldpw : NULL,
4182 lnewpw.bv_len > 0 ? &lnewpw : NULL,
4183 requestctrls,
4184 NULL, &msgid);
4185
4186 if (requestctrls[0] != NULL) {
4187 ldap_control_free(requestctrls[0]);
4188 }
4189
4190 if (rc != LDAP_SUCCESS ) {
4191 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4193 goto cleanup;
4194 }
4195
4196 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
4197 if ((rc < 0) || !ldap_res) {
4198 rc = _get_lderrno(ld->link);
4199 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4201 goto cleanup;
4202 }
4203
4204 rc = ldap_parse_passwd(ld->link, ldap_res, &lgenpasswd);
4205 if( rc != LDAP_SUCCESS ) {
4206 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4208 goto cleanup;
4209 }
4210
4211 rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 0);
4212 if( rc != LDAP_SUCCESS ) {
4213 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4215 goto cleanup;
4216 }
4217
4218 if (myargcount > 4) {
4219 _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
4220 }
4221
4222 /* return */
4223 if (lnewpw.bv_len == 0) {
4224 if (lgenpasswd.bv_len == 0) {
4226 } else {
4227 RETVAL_STRINGL(lgenpasswd.bv_val, lgenpasswd.bv_len);
4228 }
4229 } else if (err == LDAP_SUCCESS) {
4231 } else {
4232 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", (errmsg ? errmsg : ldap_err2string(err)), err);
4234 }
4235
4236cleanup:
4237 if (lgenpasswd.bv_val != NULL) {
4238 ldap_memfree(lgenpasswd.bv_val);
4239 }
4240 if (ldap_res != NULL) {
4241 ldap_msgfree(ldap_res);
4242 }
4243 if (errmsg != NULL) {
4244 ldap_memfree(errmsg);
4245 }
4246}
4247/* }}} */
4248#endif
4249
4250#ifdef HAVE_LDAP_WHOAMI_S
4251/* {{{ Whoami extended operation */
4253{
4254 zval *link;
4255 struct berval *lauthzid;
4256 ldap_linkdata *ld;
4257 int rc;
4258
4259 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &link, ldap_link_ce) == FAILURE) {
4260 RETURN_THROWS();
4261 }
4262
4263 ld = Z_LDAP_LINK_P(link);
4265
4266 /* synchronous call */
4267 rc = ldap_whoami_s(ld->link, &lauthzid, NULL, NULL);
4268 if (rc != LDAP_SUCCESS ) {
4269 php_error_docref(NULL, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4271 }
4272
4273 if (lauthzid == NULL) {
4275 } else {
4276 RETVAL_STRINGL(lauthzid->bv_val, lauthzid->bv_len);
4277 ldap_memfree(lauthzid->bv_val);
4278 ldap_memfree(lauthzid);
4279 }
4280}
4281/* }}} */
4282#endif
4283
4284#ifdef HAVE_LDAP_REFRESH_S
4285/* {{{ DDS refresh extended operation */
4287{
4288 zval *link;
4289 zend_long ttl;
4290 struct berval ldn;
4291 ber_int_t lttl;
4292 ber_int_t newttl;
4293 ldap_linkdata *ld;
4294 int rc;
4295
4296 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osl", &link, ldap_link_ce, &ldn.bv_val, &ldn.bv_len, &ttl) != SUCCESS) {
4297 RETURN_THROWS();
4298 }
4299
4300 ld = Z_LDAP_LINK_P(link);
4302
4303 lttl = (ber_int_t) ttl;
4304
4305 rc = ldap_refresh_s(ld->link, &ldn, lttl, &newttl, NULL, NULL);
4306 if (rc != LDAP_SUCCESS ) {
4307 php_error_docref(NULL, E_WARNING, "Refresh extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4309 }
4310
4311 RETURN_LONG(newttl);
4312}
4313/* }}} */
4314#endif
4315
4318 "ldap",
4319 ext_functions,
4320 PHP_MINIT(ldap),
4321 PHP_MSHUTDOWN(ldap),
4322 PHP_RINIT(ldap),
4323 NULL,
4324 PHP_MINFO(ldap),
4326 PHP_MODULE_GLOBALS(ldap),
4327 PHP_GINIT(ldap),
4328 NULL,
4329 NULL,
4331};
4332/* }}} */
size_t len
Definition apprentice.c:174
file_private const char ext[]
bool exception
Definition assert.c:30
count(Countable|array $value, int $mode=COUNT_NORMAL)
assert(mixed $assertion, Throwable|string|null $description=null)
link(string $target, string $link)
uint32_t v
Definition cdf.c:1237
error($message)
Definition ext_skel.php:22
zend_ffi_type * type
Definition ffi.c:3812
memcpy(ptr1, ptr2, size)
char * err
Definition ffi.c:3029
new_type attr
Definition ffi.c:4364
zval * val
Definition ffi.c:4262
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
again j
switch(IR_OPT_TYPE(opt))
Definition ir_fold.h:1194
#define Z_LDAP_RESULT_P(zv)
Definition ldap.c:155
void ldap_memvfree(void **v)
Definition ldap.c:67
#define PHP_LDAP_ESCAPE_FILTER
Definition ldap.c:53
#define VERIFY_LDAP_RESULT_OPEN(lr)
Definition ldap.c:229
#define VERIFY_LDAP_LINK_CONNECTED(ld)
Definition ldap.c:221
#define PHP_LD_FULL_ADD
Definition ldap.c:2229
#define Z_LDAP_LINK_P(zv)
Definition ldap.c:110
#define PHP_LDAP_ESCAPE_DN
Definition ldap.c:54
#define Z_LDAP_RESULT_ENTRY_P(zv)
Definition ldap.c:192
zend_module_entry ldap_module_entry
Definition ldap.c:4316
const LDAP_OPT_X_TLS_DHFILE
ldap_err2str(int $errno)
const LDAP_OPT_ERROR_NUMBER
const LDAP_OPT_ERROR_STRING
ldap_parse_exop(LDAP\Connection $ldap, LDAP\Result $result, &$response_data=null, &$response_oid=null)
const GSLC_SSL_NO_AUTH
ldap_mod_replace(LDAP\Connection $ldap, string $dn, array $entry, ?array $controls=null)
ldap_set_rebind_proc(LDAP\Connection $ldap, ?callable $callback)
const LDAP_OPT_X_TLS_CACERTFILE
ldap_compare(LDAP\Connection $ldap, string $dn, string $attribute, string $value, ?array $controls=null)
ldap_list($ldap, array|string $base, array|string $filter, array $attributes=[], int $attributes_only=0, int $sizelimit=-1, int $timelimit=-1, int $deref=LDAP_DEREF_NEVER, ?array $controls=null)
const LDAP_CONTROL_PAGEDRESULTS
ldap_connect_wallet(?string $uri=null, string $wallet, #[\SensitiveParameter] string $password, int $auth_mode=GSLC_SSL_NO_AUTH)
ldap_unbind(LDAP\Connection $ldap)
ldap_modify_batch(LDAP\Connection $ldap, string $dn, array $modifications_info, ?array $controls=null)
const LDAP_OPT_X_KEEPALIVE_IDLE
ldap_count_entries(LDAP\Connection $ldap, LDAP\Result $result)
ldap_first_reference(LDAP\Connection $ldap, LDAP\Result $result)
ldap_parse_result(LDAP\Connection $ldap, LDAP\Result $result, &$error_code, &$matched_dn=null, &$error_message=null, &$referrals=null, &$controls=null)
ldap_escape(string $value, string $ignore="", int $flags=0)
const LDAP_CONTROL_ASSERT
const LDAP_OPT_X_TLS_CACERTDIR
ldap_delete_ext(LDAP\Connection $ldap, string $dn, ?array $controls=null)
ldap_first_attribute(LDAP\Connection $ldap, LDAP\ResultEntry $entry)
const LDAP_CONTROL_PASSWORDPOLICYRESPONSE
ldap_next_entry(LDAP\Connection $ldap, LDAP\ResultEntry $entry)
ldap_start_tls(LDAP\Connection $ldap)
const LDAP_OPT_X_TLS_REQUIRE_CERT
const LDAP_CONTROL_POST_READ
const LDAP_OPT_HOST_NAME
ldap_read($ldap, array|string $base, array|string $filter, array $attributes=[], int $attributes_only=0, int $sizelimit=-1, int $timelimit=-1, int $deref=LDAP_DEREF_NEVER, ?array $controls=null)
const LDAP_OPT_PROTOCOL_VERSION
const LDAP_OPT_SIZELIMIT
Definition ldap.stub.php:73
const LDAP_OPT_X_TLS_CIPHER_SUITE
const LDAP_OPT_X_KEEPALIVE_INTERVAL
ldap_dn2ufn(string $dn)
ldap_connect(?string $uri=null, int $port=389, string $wallet=UNKNOWN, #[\SensitiveParameter] string $password=UNKNOWN, int $auth_mode=GSLC_SSL_NO_AUTH)
ldap_set_option(?LDAP\Connection $ldap, int $option, $value)
const LDAP_OPT_X_SASL_REALM
const LDAP_OPT_X_TLS_KEYFILE
ldap_free_result(LDAP\Result $result)
ldap_add(LDAP\Connection $ldap, string $dn, array $entry, ?array $controls=null)
ldap_mod_add(LDAP\Connection $ldap, string $dn, array $entry, ?array $controls=null)
const LDAP_OPT_RESTART
const LDAP_OPT_X_SASL_MECH
ldap_get_attributes(LDAP\Connection $ldap, LDAP\ResultEntry $entry)
ldap_exop_sync(LDAP\Connection $ldap, string $request_oid, ?string $request_data=null, ?array $controls=null, &$response_data=null, &$response_oid=null)
ldap_search($ldap, array|string $base, array|string $filter, array $attributes=[], int $attributes_only=0, int $sizelimit=-1, int $timelimit=-1, int $deref=LDAP_DEREF_NEVER, ?array $controls=null)
ldap_mod_replace_ext(LDAP\Connection $ldap, string $dn, array $entry, ?array $controls=null)
ldap_delete(LDAP\Connection $ldap, string $dn, ?array $controls=null)
const LDAP_CONTROL_PRE_READ
ldap_next_attribute(LDAP\Connection $ldap, LDAP\ResultEntry $entry)
ldap_parse_reference(LDAP\Connection $ldap, LDAP\ResultEntry $entry, &$referrals)
const LDAP_CONTROL_VLVRESPONSE
ldap_next_reference(LDAP\Connection $ldap, LDAP\ResultEntry $entry)
ldap_exop_passwd(LDAP\Connection $ldap, string $user="", #[\SensitiveParameter] string $old_password="", #[\SensitiveParameter] string $new_password="", &$controls=null)
const LDAP_OPT_X_TLS_PACKAGE
ldap_t61_to_8859(string $value)
ldap_8859_to_t61(string $value)
const LDAP_OPT_TIMELIMIT
Definition ldap.stub.php:78
ldap_mod_del_ext(LDAP\Connection $ldap, string $dn, array $entry, ?array $controls=null)
ldap_first_entry(LDAP\Connection $ldap, LDAP\Result $result)
ldap_rename_ext(LDAP\Connection $ldap, string $dn, string $new_rdn, string $new_parent, bool $delete_old_rdn, ?array $controls=null)
const LDAP_OPT_X_SASL_NOCANON
ldap_explode_dn(string $dn, int $with_attrib)
const LDAP_CONTROL_SORTREQUEST
const LDAP_OPT_X_SASL_AUTHCID
const LDAP_OPT_TIMEOUT
Definition ldap.stub.php:98
const LDAP_OPT_REFERRALS
const LDAP_OPT_CLIENT_CONTROLS
const LDAP_OPT_X_TLS_CRLFILE
ldap_exop(LDAP\Connection $ldap, string $request_oid, ?string $request_data=null, ?array $controls=null, &$response_data=UNKNOWN, &$response_oid=null)
const LDAP_OPT_X_TLS_PROTOCOL_MIN
const LDAP_OPT_SERVER_CONTROLS
ldap_get_entries(LDAP\Connection $ldap, LDAP\Result $result)
const LDAP_OPT_MATCHED_DN
const LDAP_OPT_X_SASL_USERNAME
const LDAP_CONTROL_VALUESRETURNFILTER
ldap_mod_add_ext(LDAP\Connection $ldap, string $dn, array $entry, ?array $controls=null)
ldap_bind_ext(LDAP\Connection $ldap, ?string $dn=null, #[\SensitiveParameter] ?string $password=null, ?array $controls=null)
const LDAP_OPT_X_TLS_CERTFILE
ldap_exop_refresh(LDAP\Connection $ldap, string $dn, int $ttl)
ldap_get_dn(LDAP\Connection $ldap, LDAP\ResultEntry $entry)
ldap_get_values_len(LDAP\Connection $ldap, LDAP\ResultEntry $entry, string $attribute)
const LDAP_OPT_X_TLS_RANDOM_FILE
ldap_sasl_bind(LDAP\Connection $ldap, ?string $dn=null, #[\SensitiveParameter] ?string $password=null, ?string $mech=null, ?string $realm=null, ?string $authc_id=null, ?string $authz_id=null, ?string $props=null)
const LDAP_CONTROL_VLVREQUEST
const LDAP_OPT_X_KEEPALIVE_PROBES
const LDAP_OPT_X_TLS_PROTOCOL_MAX
ldap_bind(LDAP\Connection $ldap, ?string $dn=null, #[\SensitiveParameter] ?string $password=null)
const LDAP_OPT_DEBUG_LEVEL
const LDAP_CONTROL_SORTRESPONSE
const LDAP_OPT_X_SASL_AUTHZID
ldap_mod_del(LDAP\Connection $ldap, string $dn, array $entry, ?array $controls=null)
ldap_error(LDAP\Connection $ldap)
ldap_get_option(LDAP\Connection $ldap, int $option, &$value=null)
const LDAP_OPT_X_TLS_CRLCHECK
const LDAP_OPT_NETWORK_TIMEOUT
Definition ldap.stub.php:84
ldap_exop_whoami(LDAP\Connection $ldap)
ldap_errno(LDAP\Connection $ldap)
const LDAP_OPT_DEREF
Definition ldap.stub.php:68
ldap_add_ext(LDAP\Connection $ldap, string $dn, array $entry, ?array $controls=null)
ldap_count_references(LDAP\Connection $ldap, LDAP\Result $result)
ldap_rename(LDAP\Connection $ldap, string $dn, string $new_rdn, string $new_parent, bool $delete_old_rdn, ?array $controls=null)
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_GINIT
Definition php.h:397
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MSHUTDOWN_FUNCTION
Definition php.h:401
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_RINIT
Definition php.h:394
#define PHP_MSHUTDOWN
Definition php.h:393
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_GINIT_FUNCTION
Definition php.h:405
#define PHP_RINIT_FUNCTION
Definition php.h:402
#define PHP_MINIT
Definition php.h:392
#define PHP_MODULE_GLOBALS
Definition php.h:408
unsigned const char * text
Definition php_ffi.h:53
#define STD_PHP_INI_ENTRY_EX
Definition php_ini.h:65
#define PHP_INI_BEGIN
Definition php_ini.h:52
#define PHP_INI_SYSTEM
Definition php_ini.h:43
#define PHP_INI_END
Definition php_ini.h:53
#define LDAP_MODIFY_BATCH_ATTRIB
Definition php_ldap.h:60
#define LDAP_MODIFY_BATCH_ADD
Definition php_ldap.h:55
#define LDAPG(v)
Definition php_ldap.h:50
#define LDAP_MODIFY_BATCH_MODTYPE
Definition php_ldap.h:61
zend_long num_links
Definition php_ldap.h:40
zend_long max_links
Definition php_ldap.h:41
#define LDAP_MODIFY_BATCH_REPLACE
Definition php_ldap.h:58
#define LDAP_MODIFY_BATCH_VALUES
Definition php_ldap.h:62
#define LDAP_MODIFY_BATCH_REMOVE_ALL
Definition php_ldap.h:57
#define LDAP_MODIFY_BATCH_REMOVE
Definition php_ldap.h:56
#define PHP_LDAP_VERSION
Definition php_ldap.h:32
bool tls_newctx
Definition php_ldap.h:42
unsigned char key[REFLECTION_KEY_LEN]
p
Definition session.c:1105
#define tmp1
Definition dce.c:49
LDAP * link
Definition ldap.c:74
zend_object std
Definition ldap.c:78
Definition ldap.c:86
LDAPMessage * data
Definition ldap.c:87
zend_object std
Definition ldap.c:90
BerElement * ber
Definition ldap.c:88
zval res
Definition ldap.c:89
zend_object std
Definition ldap.c:83
LDAPMessage * result
Definition ldap.c:82
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
Definition zend.c:1849
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
#define ZEND_TSRMLS_CACHE_UPDATE()
Definition zend.h:69
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
#define ZEND_TSRMLS_CACHE_DEFINE()
Definition zend.h:68
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API zend_result add_next_index_bool(zval *arg, bool b)
Definition zend_API.c:2150
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length)
Definition zend_API.c:2195
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API void add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length)
Definition zend_API.c:2096
ZEND_API void add_index_string(zval *arg, zend_ulong index, const char *str)
Definition zend_API.c:2087
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num)
Definition zend_API.c:443
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
ZEND_API zend_result add_next_index_string(zval *arg, const char *str)
Definition zend_API.c:2186
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
struct _zend_fcall_info_cache zend_fcall_info_cache
#define ZEND_TRY_ASSIGN_REF_STRINGL(zv, string, len)
Definition zend_API.h:1337
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define RETVAL_STRING(s)
Definition zend_API.h:1017
#define ZVAL_STRING(z, s)
Definition zend_API.h:956
#define ZEND_DECLARE_MODULE_GLOBALS(module_name)
Definition zend_API.h:268
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define ZEND_FCI_INITIALIZED(fci)
Definition zend_API.h:340
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define RETVAL_EMPTY_STRING()
Definition zend_API.h:1021
#define ZEND_TRY_ASSIGN_REF_LONG(zv, lval)
Definition zend_API.h:1205
#define Z_PARAM_ARRAY_HT_OR_STR(dest_ht, dest_str)
Definition zend_API.h:2151
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_NEW_STR(s)
Definition zend_API.h:1041
struct _zend_fcall_info zend_fcall_info
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETVAL_TRUE
Definition zend_API.h:1033
#define RETVAL_BOOL(b)
Definition zend_API.h:1009
#define ZEND_TRY_ASSIGN_REF_EMPTY_STRING(zv)
Definition zend_API.h:1249
#define call_user_function(function_table, object, function_name, retval_ptr, param_count, params)
Definition zend_API.h:687
#define RETVAL_LONG(l)
Definition zend_API.h:1011
#define Z_PARAM_ARRAY_EX(dest, check_null, separate)
Definition zend_API.h:1679
#define RETURN_EMPTY_STRING()
Definition zend_API.h:1047
#define Z_PARAM_ZVAL(dest)
Definition zend_API.h:2100
#define WRONG_PARAM_COUNT
Definition zend_API.h:529
#define ZEND_TRY_ASSIGN_REF_STRING(zv, string)
Definition zend_API.h:1315
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define RETVAL_STRINGL(s, l)
Definition zend_API.h:1018
#define array_init(arg)
Definition zend_API.h:537
#define estrndup(s, length)
Definition zend_alloc.h:165
#define efree(ptr)
Definition zend_alloc.h:155
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
strncmp(string $string1, string $string2, int $length)
strcmp(string $string1, string $string2)
#define snprintf
#define E_WARNING
Definition zend_errors.h:24
#define E_DEPRECATED
Definition zend_errors.h:37
ZEND_API const char * get_active_function_name(void)
union _zend_function zend_function
#define EG(v)
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:2689
ZEND_API zval *ZEND_FASTCALL zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData)
Definition zend_hash.c:1219
ZEND_API zval *ZEND_FASTCALL zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData)
Definition zend_hash.c:1031
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
Definition zend_hash.c:1808
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
Definition zend_hash.c:2668
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
#define HASH_KEY_IS_STRING
Definition zend_hash.h:29
#define HT_IS_PACKED(ht)
Definition zend_hash.h:59
#define ZEND_HASH_MAP_FOREACH_STR_KEY(ht, _key)
Definition zend_hash.h:1346
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define ZEND_HASH_FOREACH_VAL(ht, _val)
Definition zend_hash.h:1102
#define HASH_KEY_IS_LONG
Definition zend_hash.h:30
#define UNREGISTER_INI_ENTRIES()
Definition zend_ini.h:204
#define REGISTER_INI_ENTRIES()
Definition zend_ini.h:203
#define DISPLAY_INI_ENTRIES()
Definition zend_ini.h:205
int32_t zend_long
Definition zend_long.h:42
uint32_t zend_ulong
Definition zend_long.h:43
#define ZEND_LONG_FMT
Definition zend_long.h:87
struct _zend_string zend_string
#define STANDARD_MODULE_HEADER
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES_EX
ZEND_API int zend_objects_not_comparable(zval *o1, zval *o2)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length)
ZEND_API void ZEND_FASTCALL convert_to_long(zval *op)
#define convert_to_string(op)
#define ZEND_FALLTHROUGH
#define XtOffsetOf(s_type, field)
#define UNEXPECTED(condition)
struct _zend_array zend_array
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZEND_LONG_EXCEEDS_INT(zlong)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_MAX_LEN
#define ZSTR_KNOWN(idx)
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZVAL_UNDEF(z)
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_DEREF(z)
#define IS_STRING
Definition zend_types.h:606
struct _zend_array HashTable
Definition zend_types.h:386
#define IS_ARRAY
Definition zend_types.h:607
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
#define Z_OBJCE_P(zval_p)
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
#define ZVAL_COPY(z, v)
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define SEPARATE_ARRAY(zv)
#define Z_ARRVAL(zval)
Definition zend_types.h:986
#define Z_ARR_P(zval_p)
Definition zend_types.h:984
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define ZVAL_COPY_VALUE(z, v)
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval retval
zval * return_value
uint32_t arg_num
bool result
object
zval * ret
value
new_op_array scope
out($f, $s)