1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Amitay Isaacs <amitay@w-o-i.com> |
16 | Eric Warnke <ericw@albany.edu> |
17 | Rasmus Lerdorf <rasmus@php.net> |
18 | Gerrit Thomson <334647@swin.edu.au> |
19 | Jani Taskinen <sniper@iki.fi> |
20 | Stig Venaas <venaas@uninett.no> |
21 | Doug Goldstein <cardoe@cardoe.com> |
22 | Côme Chilliet <mcmic@php.net> |
23 | PHP 4.0 updates: Zeev Suraski <zeev@php.net> |
24 +----------------------------------------------------------------------+
25 */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "php.h"
32 #include "php_ini.h"
33
34 #include <stddef.h>
35
36 #include "ext/standard/dl.h"
37 #include "php_ldap.h"
38
39 #ifdef PHP_WIN32
40 #include <string.h>
41 #include "config.w32.h"
42 #define strdup _strdup
43 #undef WINDOWS
44 #undef strcasecmp
45 #undef strncasecmp
46 #define WINSOCK 1
47 #define __STDC__ 1
48 #endif
49
50 #include "ext/standard/php_string.h"
51 #include "ext/standard/info.h"
52
53 #ifdef HAVE_LDAP_SASL
54 #include <sasl/sasl.h>
55 #endif
56
57 #define PHP_LDAP_ESCAPE_FILTER 0x01
58 #define PHP_LDAP_ESCAPE_DN 0x02
59
60 #if defined(LDAP_CONTROL_PAGEDRESULTS) && !defined(HAVE_LDAP_CONTROL_FIND)
ldap_control_find(const char * oid,LDAPControl ** ctrls,LDAPControl *** nextctrlp)61 LDAPControl *ldap_control_find( const char *oid, LDAPControl **ctrls, LDAPControl ***nextctrlp)
62 {
63 assert(nextctrlp == NULL);
64 return ldap_find_control(oid, ctrls);
65 }
66 #endif
67
68 #if !defined(LDAP_API_FEATURE_X_OPENLDAP)
ldap_memvfree(void ** v)69 void ldap_memvfree(void **v)
70 {
71 ldap_value_free((char **)v);
72 }
73 #endif
74
75 typedef struct {
76 LDAP *link;
77 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
78 zval rebindproc;
79 #endif
80 } ldap_linkdata;
81
82 typedef struct {
83 LDAPMessage *data;
84 BerElement *ber;
85 zval res;
86 } ldap_resultentry;
87
88 ZEND_DECLARE_MODULE_GLOBALS(ldap)
89 static PHP_GINIT_FUNCTION(ldap);
90
91 static int le_link, le_result, le_result_entry;
92
93 #ifdef COMPILE_DL_LDAP
94 #ifdef ZTS
95 ZEND_TSRMLS_CACHE_DEFINE()
96 #endif
ZEND_GET_MODULE(ldap)97 ZEND_GET_MODULE(ldap)
98 #endif
99
100 static void _close_ldap_link(zend_resource *rsrc) /* {{{ */
101 {
102 ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr;
103
104 /* We use ldap_destroy rather than ldap_unbind here, because ldap_unbind
105 * will skip the destructor entirely if a critical client control is set. */
106 ldap_destroy(ld->link);
107
108 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
109 zval_ptr_dtor(&ld->rebindproc);
110 #endif
111
112 efree(ld);
113 LDAPG(num_links)--;
114 }
115 /* }}} */
116
_free_ldap_result(zend_resource * rsrc)117 static void _free_ldap_result(zend_resource *rsrc) /* {{{ */
118 {
119 LDAPMessage *result = (LDAPMessage *)rsrc->ptr;
120 ldap_msgfree(result);
121 }
122 /* }}} */
123
_free_ldap_result_entry(zend_resource * rsrc)124 static void _free_ldap_result_entry(zend_resource *rsrc) /* {{{ */
125 {
126 ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr;
127
128 if (entry->ber != NULL) {
129 ber_free(entry->ber, 0);
130 entry->ber = NULL;
131 }
132 zval_ptr_dtor(&entry->res);
133 efree(entry);
134 }
135 /* }}} */
136
137 /* {{{ Parse controls from and to arrays */
_php_ldap_control_to_array(LDAP * ld,LDAPControl * ctrl,zval * array,int request)138 static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, int request)
139 {
140 array_init(array);
141
142 add_assoc_string(array, "oid", ctrl->ldctl_oid);
143 if (request) {
144 /* iscritical field only makes sense in request controls (which may be obtained by ldap_get_option) */
145 add_assoc_bool(array, "iscritical", (ctrl->ldctl_iscritical != 0));
146 }
147
148 /* If it is a known oid, parse to values */
149 if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
150 int expire = 0, grace = 0, rc;
151 LDAPPasswordPolicyError pperr;
152 zval value;
153
154 rc = ldap_parse_passwordpolicy_control(ld, ctrl, &expire, &grace, &pperr);
155 if ( rc == LDAP_SUCCESS ) {
156 array_init(&value);
157 add_assoc_long(&value, "expire", expire);
158 add_assoc_long(&value, "grace", grace);
159
160 if ( pperr != PP_noError ) {
161 add_assoc_long(&value, "error", pperr);
162 }
163 add_assoc_zval(array, "value", &value);
164 } else {
165 add_assoc_null(array, "value");
166 }
167 } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) {
168 int lestimated, rc;
169 struct berval lcookie = { 0L, NULL };
170 zval value;
171
172 if (ctrl->ldctl_value.bv_len) {
173 /* ldap_parse_pageresponse_control() allocates lcookie.bv_val */
174 rc = ldap_parse_pageresponse_control(ld, ctrl, &lestimated, &lcookie);
175 } else {
176 /* ldap_parse_pageresponse_control will crash if value is empty */
177 rc = -1;
178 }
179
180 if ( rc == LDAP_SUCCESS ) {
181 array_init(&value);
182 add_assoc_long(&value, "size", lestimated);
183 add_assoc_stringl(&value, "cookie", lcookie.bv_val, lcookie.bv_len);
184 add_assoc_zval(array, "value", &value);
185 } else {
186 add_assoc_null(array, "value");
187 }
188
189 if (lcookie.bv_val) {
190 ldap_memfree(lcookie.bv_val);
191 }
192 } else if ((strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_POST_READ) == 0)) {
193 BerElement *ber;
194 struct berval bv;
195
196 ber = ber_init(&ctrl->ldctl_value);
197 if (ber == NULL) {
198 add_assoc_null(array, "value");
199 } else if (ber_scanf(ber, "{m{" /*}}*/, &bv) == LBER_ERROR) {
200 add_assoc_null(array, "value");
201 } else {
202 zval value;
203
204 array_init(&value);
205 add_assoc_stringl(&value, "dn", bv.bv_val, bv.bv_len);
206
207 while (ber_scanf(ber, "{m" /*}*/, &bv) != LBER_ERROR) {
208 int i;
209 BerVarray vals = NULL;
210 zval tmp;
211
212 if (ber_scanf(ber, "[W]", &vals) == LBER_ERROR || vals == NULL)
213 {
214 break;
215 }
216
217 array_init(&tmp);
218 for (i = 0; vals[i].bv_val != NULL; i++) {
219 add_next_index_stringl(&tmp, vals[i].bv_val, vals[i].bv_len);
220 }
221 add_assoc_zval(&value, bv.bv_val, &tmp);
222
223 ber_bvarray_free(vals);
224 }
225 add_assoc_zval(array, "value", &value);
226 }
227
228 if (ber != NULL) {
229 ber_free(ber, 1);
230 }
231 } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_SORTRESPONSE) == 0) {
232 zval value;
233 int errcode, rc;
234 char* attribute;
235
236 if (ctrl->ldctl_value.bv_len) {
237 rc = ldap_parse_sortresponse_control(ld, ctrl, &errcode, &attribute);
238 } else {
239 rc = -1;
240 }
241 if ( rc == LDAP_SUCCESS ) {
242 array_init(&value);
243 add_assoc_long(&value, "errcode", errcode);
244 if (attribute) {
245 add_assoc_string(&value, "attribute", attribute);
246 ldap_memfree(attribute);
247 }
248 add_assoc_zval(array, "value", &value);
249 } else {
250 add_assoc_null(array, "value");
251 }
252 } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_VLVRESPONSE) == 0) {
253 int target, count, errcode, rc;
254 struct berval *context;
255 zval value;
256
257 if (ctrl->ldctl_value.bv_len) {
258 rc = ldap_parse_vlvresponse_control(ld, ctrl, &target, &count, &context, &errcode);
259 } else {
260 rc = -1;
261 }
262 if ( rc == LDAP_SUCCESS ) {
263 array_init(&value);
264 add_assoc_long(&value, "target", target);
265 add_assoc_long(&value, "count", count);
266 add_assoc_long(&value, "errcode", errcode);
267 if ( context && (context->bv_len >= 0) ) {
268 add_assoc_stringl(&value, "context", context->bv_val, context->bv_len);
269 }
270 add_assoc_zval(array, "value", &value);
271 ber_bvfree(context);
272 } else {
273 add_assoc_null(array, "value");
274 }
275 } else {
276 if (ctrl->ldctl_value.bv_len) {
277 add_assoc_stringl(array, "value", ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len);
278 } else {
279 add_assoc_null(array, "value");
280 }
281 }
282 }
283
_php_ldap_control_from_array(LDAP * ld,LDAPControl ** ctrl,zval * array)284 static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* array)
285 {
286 zval* val;
287 zend_string *control_oid;
288 int control_iscritical = 0, rc = LDAP_SUCCESS;
289 char** ldap_attrs = NULL;
290 LDAPSortKey** sort_keys = NULL;
291 zend_string *tmpstring = NULL, **tmpstrings1 = NULL, **tmpstrings2 = NULL;
292 size_t num_tmpstrings1 = 0, num_tmpstrings2 = 0;
293
294 if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "oid", sizeof("oid") - 1)) == NULL) {
295 php_error_docref(NULL, E_WARNING, "Control must have an oid key");
296 return -1;
297 }
298
299 control_oid = zval_get_string(val);
300 if (EG(exception)) {
301 return -1;
302 }
303
304 if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "iscritical", sizeof("iscritical") - 1)) != NULL) {
305 control_iscritical = zend_is_true(val);
306 } else {
307 control_iscritical = 0;
308 }
309
310 BerElement *ber = NULL;
311 struct berval control_value = { 0L, NULL };
312 int control_value_alloc = 0;
313
314 if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "value", sizeof("value") - 1)) != NULL) {
315 if (Z_TYPE_P(val) != IS_ARRAY) {
316 tmpstring = zval_get_string(val);
317 if (EG(exception)) {
318 rc = -1;
319 goto failure;
320 }
321 control_value.bv_val = ZSTR_VAL(tmpstring);
322 control_value.bv_len = ZSTR_LEN(tmpstring);
323 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PAGEDRESULTS) == 0) {
324 zval* tmp;
325 int pagesize = 1;
326 struct berval cookie = { 0L, NULL };
327 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) {
328 pagesize = zval_get_long(tmp);
329 }
330 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "cookie", sizeof("cookie") - 1)) != NULL) {
331 tmpstring = zval_get_string(tmp);
332 if (EG(exception)) {
333 rc = -1;
334 goto failure;
335 }
336 cookie.bv_val = ZSTR_VAL(tmpstring);
337 cookie.bv_len = ZSTR_LEN(tmpstring);
338 }
339 /* ldap_create_page_control_value() allocates memory for control_value.bv_val */
340 control_value_alloc = 1;
341 rc = ldap_create_page_control_value(ld, pagesize, &cookie, &control_value);
342 if (rc != LDAP_SUCCESS) {
343 php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc);
344 }
345 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_ASSERT) == 0) {
346 zval* tmp;
347 zend_string* assert;
348 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) {
349 rc = -1;
350 php_error_docref(NULL, E_WARNING, "Filter missing from assert control value array");
351 } else {
352 assert = zval_get_string(tmp);
353 if (EG(exception)) {
354 rc = -1;
355 goto failure;
356 }
357 /* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
358 See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
359 int success = LDAP_SUCCESS;
360 ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
361 /* ldap_create_assertion_control_value() allocates memory for control_value.bv_val */
362 control_value_alloc = 1;
363 rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), &control_value);
364 if (rc != LDAP_SUCCESS) {
365 php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
366 }
367 zend_string_release(assert);
368 }
369 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VALUESRETURNFILTER) == 0) {
370 zval* tmp;
371 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) {
372 rc = -1;
373 php_error_docref(NULL, E_WARNING, "Filter missing from control value array");
374 } else {
375 ber = ber_alloc_t(LBER_USE_DER);
376 if (ber == NULL) {
377 rc = -1;
378 php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
379 } else {
380 tmpstring = zval_get_string(tmp);
381 if (EG(exception)) {
382 rc = -1;
383 goto failure;
384 }
385 if (ldap_put_vrFilter(ber, ZSTR_VAL(tmpstring)) == -1) {
386 rc = -1;
387 php_error_docref(NULL, E_WARNING, "Failed to create control value: Bad ValuesReturnFilter: %s", ZSTR_VAL(tmpstring));
388 } else if (ber_flatten2(ber, &control_value, control_value_alloc) == -1) {
389 rc = -1;
390 }
391 }
392 }
393 } else if ((strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_POST_READ) == 0)) {
394 zval* tmp;
395 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrs", sizeof("attrs") - 1)) == NULL) {
396 rc = -1;
397 php_error_docref(NULL, E_WARNING, "Attributes list missing from control value array");
398 } else {
399 ber = ber_alloc_t(LBER_USE_DER);
400
401 if (ber == NULL) {
402 rc = -1;
403 php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
404 } else {
405 int num_attribs, i;
406 zval* attr;
407
408 num_attribs = zend_hash_num_elements(Z_ARRVAL_P(tmp));
409 ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
410 tmpstrings1 = safe_emalloc(num_attribs, sizeof(zend_string*), 0);
411 num_tmpstrings1 = 0;
412
413 for (i = 0; i<num_attribs; i++) {
414 if ((attr = zend_hash_index_find(Z_ARRVAL_P(tmp), i)) == NULL) {
415 rc = -1;
416 php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
417 goto failure;
418 }
419
420 tmpstrings1[num_tmpstrings1] = zval_get_string(attr);
421 if (EG(exception)) {
422 rc = -1;
423 goto failure;
424 }
425 ldap_attrs[i] = ZSTR_VAL(tmpstrings1[num_tmpstrings1]);
426 ++num_tmpstrings1;
427 }
428 ldap_attrs[num_attribs] = NULL;
429
430 ber_init2( ber, NULL, LBER_USE_DER );
431
432 if (ber_printf(ber, "{v}", ldap_attrs) == -1) {
433 rc = -1;
434 php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
435 } else {
436 int err;
437 err = ber_flatten2(ber, &control_value, control_value_alloc);
438 if (err < 0) {
439 rc = -1;
440 php_error_docref(NULL, E_WARNING, "Failed to encode control value (%d)", err);
441 }
442 }
443 }
444 }
445 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_SORTREQUEST) == 0) {
446 int num_keys, i;
447 zval *sortkey, *tmp;
448
449 num_keys = zend_hash_num_elements(Z_ARRVAL_P(val));
450 sort_keys = safe_emalloc((num_keys+1), sizeof(LDAPSortKey*), 0);
451 tmpstrings1 = safe_emalloc(num_keys, sizeof(zend_string*), 0);
452 tmpstrings2 = safe_emalloc(num_keys, sizeof(zend_string*), 0);
453 num_tmpstrings1 = 0;
454 num_tmpstrings2 = 0;
455
456 for (i = 0; i<num_keys; i++) {
457 if ((sortkey = zend_hash_index_find(Z_ARRVAL_P(val), i)) == NULL) {
458 rc = -1;
459 php_error_docref(NULL, E_WARNING, "Failed to encode sort keys list");
460 goto failure;
461 }
462
463 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "attr", sizeof("attr") - 1)) == NULL) {
464 rc = -1;
465 php_error_docref(NULL, E_WARNING, "Sort key list missing field");
466 goto failure;
467 }
468 sort_keys[i] = emalloc(sizeof(LDAPSortKey));
469 tmpstrings1[num_tmpstrings1] = zval_get_string(tmp);
470 if (EG(exception)) {
471 rc = -1;
472 goto failure;
473 }
474 sort_keys[i]->attributeType = ZSTR_VAL(tmpstrings1[num_tmpstrings1]);
475 ++num_tmpstrings1;
476
477 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "oid", sizeof("oid") - 1)) != NULL) {
478 tmpstrings2[num_tmpstrings2] = zval_get_string(tmp);
479 if (EG(exception)) {
480 rc = -1;
481 goto failure;
482 }
483 sort_keys[i]->orderingRule = ZSTR_VAL(tmpstrings2[num_tmpstrings2]);
484 ++num_tmpstrings2;
485 } else {
486 sort_keys[i]->orderingRule = NULL;
487 }
488
489 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "reverse", sizeof("reverse") - 1)) != NULL) {
490 sort_keys[i]->reverseOrder = zend_is_true(tmp);
491 } else {
492 sort_keys[i]->reverseOrder = 0;
493 }
494 }
495 sort_keys[num_keys] = NULL;
496 /* ldap_create_sort_control_value() allocates memory for control_value.bv_val */
497 control_value_alloc = 1;
498 rc = ldap_create_sort_control_value(ld, sort_keys, &control_value);
499 if (rc != LDAP_SUCCESS) {
500 php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
501 }
502 } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VLVREQUEST) == 0) {
503 zval* tmp;
504 LDAPVLVInfo vlvInfo;
505 struct berval attrValue;
506 struct berval context;
507
508 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "before", sizeof("before") - 1)) != NULL) {
509 vlvInfo.ldvlv_before_count = zval_get_long(tmp);
510 } else {
511 rc = -1;
512 php_error_docref(NULL, E_WARNING, "Before key missing from array value for VLV control");
513 goto failure;
514 }
515
516 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "after", sizeof("after") - 1)) != NULL) {
517 vlvInfo.ldvlv_after_count = zval_get_long(tmp);
518 } else {
519 rc = -1;
520 php_error_docref(NULL, E_WARNING, "After key missing from array value for VLV control");
521 goto failure;
522 }
523
524 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrvalue", sizeof("attrvalue") - 1)) != NULL) {
525 tmpstring = zval_get_string(tmp);
526 if (EG(exception)) {
527 rc = -1;
528 goto failure;
529 }
530 attrValue.bv_val = ZSTR_VAL(tmpstring);
531 attrValue.bv_len = ZSTR_LEN(tmpstring);
532 vlvInfo.ldvlv_attrvalue = &attrValue;
533 } else if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "offset", sizeof("offset") - 1)) != NULL) {
534 vlvInfo.ldvlv_attrvalue = NULL;
535 vlvInfo.ldvlv_offset = zval_get_long(tmp);
536 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "count", sizeof("count") - 1)) != NULL) {
537 vlvInfo.ldvlv_count = zval_get_long(tmp);
538 } else {
539 rc = -1;
540 php_error_docref(NULL, E_WARNING, "Count key missing from array value for VLV control");
541 goto failure;
542 }
543 } else {
544 rc = -1;
545 php_error_docref(NULL, E_WARNING, "Missing either attrvalue or offset key from array value for VLV control");
546 goto failure;
547 }
548
549 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "context", sizeof("context") - 1)) != NULL) {
550 tmpstring = zval_get_string(tmp);
551 if (EG(exception)) {
552 rc = -1;
553 goto failure;
554 }
555 context.bv_val = ZSTR_VAL(tmpstring);
556 context.bv_len = ZSTR_LEN(tmpstring);
557 vlvInfo.ldvlv_context = &context;
558 } else {
559 vlvInfo.ldvlv_context = NULL;
560 }
561
562 /* ldap_create_vlv_control_value() allocates memory for control_value.bv_val */
563 control_value_alloc = 1;
564 rc = ldap_create_vlv_control_value(ld, &vlvInfo, &control_value);
565 if (rc != LDAP_SUCCESS) {
566 php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc);
567 }
568 } else {
569 php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", ZSTR_VAL(control_oid));
570 rc = -1;
571 }
572 }
573
574 if (rc == LDAP_SUCCESS) {
575 rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, &control_value, 1, ctrl);
576 }
577
578 failure:
579 zend_string_release(control_oid);
580 if (tmpstring != NULL) {
581 zend_string_release(tmpstring);
582 }
583 if (tmpstrings1 != NULL) {
584 int i;
585 for (i = 0; i < num_tmpstrings1; ++i) {
586 zend_string_release(tmpstrings1[i]);
587 }
588 efree(tmpstrings1);
589 }
590 if (tmpstrings2 != NULL) {
591 int i;
592 for (i = 0; i < num_tmpstrings2; ++i) {
593 zend_string_release(tmpstrings2[i]);
594 }
595 efree(tmpstrings2);
596 }
597 if (control_value.bv_val != NULL && control_value_alloc != 0) {
598 ber_memfree(control_value.bv_val);
599 }
600 if (ber != NULL) {
601 ber_free(ber, 1);
602 }
603 if (ldap_attrs != NULL) {
604 efree(ldap_attrs);
605 }
606 if (sort_keys != NULL) {
607 LDAPSortKey** sortp = sort_keys;
608 while (*sortp) {
609 efree(*sortp);
610 sortp++;
611 }
612 efree(sort_keys);
613 sort_keys = NULL;
614 }
615
616 if (rc == LDAP_SUCCESS) {
617 return LDAP_SUCCESS;
618 }
619
620 /* Failed */
621 *ctrl = NULL;
622 return -1;
623 }
624
_php_ldap_controls_to_array(LDAP * ld,LDAPControl ** ctrls,zval * array,int request)625 static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* array, int request)
626 {
627 zval tmp1;
628 LDAPControl **ctrlp;
629
630 array = zend_try_array_init(array);
631 if (!array) {
632 return;
633 }
634
635 if (ctrls == NULL) {
636 return;
637 }
638 ctrlp = ctrls;
639 while (*ctrlp != NULL) {
640 _php_ldap_control_to_array(ld, *ctrlp, &tmp1, request);
641 add_assoc_zval(array, (*ctrlp)->ldctl_oid, &tmp1);
642 ctrlp++;
643 }
644 ldap_controls_free(ctrls);
645 }
646
_php_ldap_controls_from_array(LDAP * ld,zval * array)647 static LDAPControl** _php_ldap_controls_from_array(LDAP *ld, zval* array)
648 {
649 int ncontrols;
650 LDAPControl** ctrlp, **ctrls = NULL;
651 zval* ctrlarray;
652 int error = 0;
653
654 ncontrols = zend_hash_num_elements(Z_ARRVAL_P(array));
655 ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0);
656 *ctrls = NULL;
657 ctrlp = ctrls;
658 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), ctrlarray) {
659 if (Z_TYPE_P(ctrlarray) != IS_ARRAY) {
660 php_error_docref(NULL, E_WARNING, "The array value must contain only arrays, where each array is a control");
661 error = 1;
662 break;
663 }
664
665 if (_php_ldap_control_from_array(ld, ctrlp, ctrlarray) == LDAP_SUCCESS) {
666 ++ctrlp;
667 } else {
668 error = 1;
669 break;
670 }
671
672 *ctrlp = NULL;
673 } ZEND_HASH_FOREACH_END();
674
675 if (error) {
676 ctrlp = ctrls;
677 while (*ctrlp) {
678 ldap_control_free(*ctrlp);
679 ctrlp++;
680 }
681 efree(ctrls);
682 ctrls = NULL;
683 }
684
685 return ctrls;
686 }
687
_php_ldap_controls_free(LDAPControl *** ctrls)688 static void _php_ldap_controls_free (LDAPControl*** ctrls)
689 {
690 LDAPControl **ctrlp;
691
692 if (*ctrls) {
693 ctrlp = *ctrls;
694 while (*ctrlp) {
695 ldap_control_free(*ctrlp);
696 ctrlp++;
697 }
698 efree(*ctrls);
699 *ctrls = NULL;
700 }
701 }
702 /* }}} */
703
704 /* {{{ PHP_INI_BEGIN
705 */
706 PHP_INI_BEGIN()
707 STD_PHP_INI_ENTRY_EX("ldap.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_ldap_globals, ldap_globals, display_link_numbers)
PHP_INI_END()708 PHP_INI_END()
709 /* }}} */
710
711 /* {{{ PHP_GINIT_FUNCTION
712 */
713 static PHP_GINIT_FUNCTION(ldap)
714 {
715 #if defined(COMPILE_DL_LDAP) && defined(ZTS)
716 ZEND_TSRMLS_CACHE_UPDATE();
717 #endif
718 ldap_globals->num_links = 0;
719 }
720 /* }}} */
721
722 /* {{{ PHP_MINIT_FUNCTION
723 */
PHP_MINIT_FUNCTION(ldap)724 PHP_MINIT_FUNCTION(ldap)
725 {
726 REGISTER_INI_ENTRIES();
727
728 /* Constants to be used with deref-parameter in php_ldap_do_search() */
729 REGISTER_LONG_CONSTANT("LDAP_DEREF_NEVER", LDAP_DEREF_NEVER, CONST_PERSISTENT | CONST_CS);
730 REGISTER_LONG_CONSTANT("LDAP_DEREF_SEARCHING", LDAP_DEREF_SEARCHING, CONST_PERSISTENT | CONST_CS);
731 REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, CONST_PERSISTENT | CONST_CS);
732 REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS);
733
734 /* Constants to be used with ldap_modify_batch() */
735 REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_ADD", LDAP_MODIFY_BATCH_ADD, CONST_PERSISTENT | CONST_CS);
736 REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE", LDAP_MODIFY_BATCH_REMOVE, CONST_PERSISTENT | CONST_CS);
737 REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE_ALL", LDAP_MODIFY_BATCH_REMOVE_ALL, CONST_PERSISTENT | CONST_CS);
738 REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REPLACE", LDAP_MODIFY_BATCH_REPLACE, CONST_PERSISTENT | CONST_CS);
739 REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_ATTRIB", LDAP_MODIFY_BATCH_ATTRIB, CONST_PERSISTENT | CONST_CS);
740 REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_MODTYPE", LDAP_MODIFY_BATCH_MODTYPE, CONST_PERSISTENT | CONST_CS);
741 REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_VALUES", LDAP_MODIFY_BATCH_VALUES, CONST_PERSISTENT | CONST_CS);
742
743 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP
744 /* LDAP options */
745 REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS);
746 REGISTER_LONG_CONSTANT("LDAP_OPT_SIZELIMIT", LDAP_OPT_SIZELIMIT, CONST_PERSISTENT | CONST_CS);
747 REGISTER_LONG_CONSTANT("LDAP_OPT_TIMELIMIT", LDAP_OPT_TIMELIMIT, CONST_PERSISTENT | CONST_CS);
748 #ifdef LDAP_OPT_NETWORK_TIMEOUT
749 REGISTER_LONG_CONSTANT("LDAP_OPT_NETWORK_TIMEOUT", LDAP_OPT_NETWORK_TIMEOUT, CONST_PERSISTENT | CONST_CS);
750 #elif defined (LDAP_X_OPT_CONNECT_TIMEOUT)
751 REGISTER_LONG_CONSTANT("LDAP_OPT_NETWORK_TIMEOUT", LDAP_X_OPT_CONNECT_TIMEOUT, CONST_PERSISTENT | CONST_CS);
752 #endif
753 #ifdef LDAP_OPT_TIMEOUT
754 REGISTER_LONG_CONSTANT("LDAP_OPT_TIMEOUT", LDAP_OPT_TIMEOUT, CONST_PERSISTENT | CONST_CS);
755 #endif
756 REGISTER_LONG_CONSTANT("LDAP_OPT_PROTOCOL_VERSION", LDAP_OPT_PROTOCOL_VERSION, CONST_PERSISTENT | CONST_CS);
757 REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_NUMBER", LDAP_OPT_ERROR_NUMBER, CONST_PERSISTENT | CONST_CS);
758 REGISTER_LONG_CONSTANT("LDAP_OPT_REFERRALS", LDAP_OPT_REFERRALS, CONST_PERSISTENT | CONST_CS);
759 #ifdef LDAP_OPT_RESTART
760 REGISTER_LONG_CONSTANT("LDAP_OPT_RESTART", LDAP_OPT_RESTART, CONST_PERSISTENT | CONST_CS);
761 #endif
762 #ifdef LDAP_OPT_HOST_NAME
763 REGISTER_LONG_CONSTANT("LDAP_OPT_HOST_NAME", LDAP_OPT_HOST_NAME, CONST_PERSISTENT | CONST_CS);
764 #endif
765 REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_STRING", LDAP_OPT_ERROR_STRING, CONST_PERSISTENT | CONST_CS);
766 #ifdef LDAP_OPT_MATCHED_DN
767 REGISTER_LONG_CONSTANT("LDAP_OPT_MATCHED_DN", LDAP_OPT_MATCHED_DN, CONST_PERSISTENT | CONST_CS);
768 #endif
769 REGISTER_LONG_CONSTANT("LDAP_OPT_SERVER_CONTROLS", LDAP_OPT_SERVER_CONTROLS, CONST_PERSISTENT | CONST_CS);
770 REGISTER_LONG_CONSTANT("LDAP_OPT_CLIENT_CONTROLS", LDAP_OPT_CLIENT_CONTROLS, CONST_PERSISTENT | CONST_CS);
771 #endif
772 #ifdef LDAP_OPT_DEBUG_LEVEL
773 REGISTER_LONG_CONSTANT("LDAP_OPT_DEBUG_LEVEL", LDAP_OPT_DEBUG_LEVEL, CONST_PERSISTENT | CONST_CS);
774 #endif
775
776 #ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE
777 REGISTER_LONG_CONSTANT("LDAP_OPT_DIAGNOSTIC_MESSAGE", LDAP_OPT_DIAGNOSTIC_MESSAGE, CONST_PERSISTENT | CONST_CS);
778 #endif
779
780 #ifdef HAVE_LDAP_SASL
781 REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_MECH", LDAP_OPT_X_SASL_MECH, CONST_PERSISTENT | CONST_CS);
782 REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_REALM", LDAP_OPT_X_SASL_REALM, CONST_PERSISTENT | CONST_CS);
783 REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHCID", LDAP_OPT_X_SASL_AUTHCID, CONST_PERSISTENT | CONST_CS);
784 REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHZID", LDAP_OPT_X_SASL_AUTHZID, CONST_PERSISTENT | CONST_CS);
785 #endif
786 #ifdef LDAP_OPT_X_SASL_NOCANON
787 REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_NOCANON", LDAP_OPT_X_SASL_NOCANON, CONST_PERSISTENT | CONST_CS);
788 #endif
789 #ifdef LDAP_OPT_X_SASL_USERNAME
790 REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_USERNAME", LDAP_OPT_X_SASL_USERNAME, CONST_PERSISTENT | CONST_CS);
791 #endif
792
793 #ifdef ORALDAP
794 REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT | CONST_CS);
795 REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS);
796 REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS);
797 #endif
798
799 #if (LDAP_API_VERSION > 2000)
800 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_REQUIRE_CERT", LDAP_OPT_X_TLS_REQUIRE_CERT, CONST_PERSISTENT | CONST_CS);
801
802 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_NEVER", LDAP_OPT_X_TLS_NEVER, CONST_PERSISTENT | CONST_CS);
803 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_HARD", LDAP_OPT_X_TLS_HARD, CONST_PERSISTENT | CONST_CS);
804 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_DEMAND", LDAP_OPT_X_TLS_DEMAND, CONST_PERSISTENT | CONST_CS);
805 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_ALLOW", LDAP_OPT_X_TLS_ALLOW, CONST_PERSISTENT | CONST_CS);
806 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_TRY", LDAP_OPT_X_TLS_TRY, CONST_PERSISTENT | CONST_CS);
807
808 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CACERTDIR", LDAP_OPT_X_TLS_CACERTDIR, CONST_PERSISTENT | CONST_CS);
809 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CACERTFILE", LDAP_OPT_X_TLS_CACERTFILE, CONST_PERSISTENT | CONST_CS);
810 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CERTFILE", LDAP_OPT_X_TLS_CERTFILE, CONST_PERSISTENT | CONST_CS);
811 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CIPHER_SUITE", LDAP_OPT_X_TLS_CIPHER_SUITE, CONST_PERSISTENT | CONST_CS);
812 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_KEYFILE", LDAP_OPT_X_TLS_KEYFILE, CONST_PERSISTENT | CONST_CS);
813 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_RANDOM_FILE", LDAP_OPT_X_TLS_RANDOM_FILE, CONST_PERSISTENT | CONST_CS);
814 #endif
815
816 #ifdef LDAP_OPT_X_TLS_CRLCHECK
817 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRLCHECK", LDAP_OPT_X_TLS_CRLCHECK, CONST_PERSISTENT | CONST_CS);
818
819 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRL_NONE", LDAP_OPT_X_TLS_CRL_NONE, CONST_PERSISTENT | CONST_CS);
820 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRL_PEER", LDAP_OPT_X_TLS_CRL_PEER, CONST_PERSISTENT | CONST_CS);
821 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRL_ALL", LDAP_OPT_X_TLS_CRL_ALL, CONST_PERSISTENT | CONST_CS);
822 #endif
823
824 #ifdef LDAP_OPT_X_TLS_DHFILE
825 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_DHFILE", LDAP_OPT_X_TLS_DHFILE, CONST_PERSISTENT | CONST_CS);
826 #endif
827
828 #ifdef LDAP_OPT_X_TLS_CRLFILE
829 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_CRLFILE", LDAP_OPT_X_TLS_CRLFILE, CONST_PERSISTENT | CONST_CS);
830 #endif
831
832 #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
833 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_MIN", LDAP_OPT_X_TLS_PROTOCOL_MIN, CONST_PERSISTENT | CONST_CS);
834
835 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_SSL2", LDAP_OPT_X_TLS_PROTOCOL_SSL2, CONST_PERSISTENT | CONST_CS);
836 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_SSL3", LDAP_OPT_X_TLS_PROTOCOL_SSL3, CONST_PERSISTENT | CONST_CS);
837 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_TLS1_0", LDAP_OPT_X_TLS_PROTOCOL_TLS1_0, CONST_PERSISTENT | CONST_CS);
838 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_TLS1_1", LDAP_OPT_X_TLS_PROTOCOL_TLS1_1, CONST_PERSISTENT | CONST_CS);
839 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PROTOCOL_TLS1_2", LDAP_OPT_X_TLS_PROTOCOL_TLS1_2, CONST_PERSISTENT | CONST_CS);
840 #endif
841
842 #ifdef LDAP_OPT_X_TLS_PACKAGE
843 REGISTER_LONG_CONSTANT("LDAP_OPT_X_TLS_PACKAGE", LDAP_OPT_X_TLS_PACKAGE, CONST_PERSISTENT | CONST_CS);
844 #endif
845
846 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
847 REGISTER_LONG_CONSTANT("LDAP_OPT_X_KEEPALIVE_IDLE", LDAP_OPT_X_KEEPALIVE_IDLE, CONST_PERSISTENT | CONST_CS);
848 REGISTER_LONG_CONSTANT("LDAP_OPT_X_KEEPALIVE_PROBES", LDAP_OPT_X_KEEPALIVE_PROBES, CONST_PERSISTENT | CONST_CS);
849 REGISTER_LONG_CONSTANT("LDAP_OPT_X_KEEPALIVE_INTERVAL", LDAP_OPT_X_KEEPALIVE_INTERVAL, CONST_PERSISTENT | CONST_CS);
850 #endif
851
852 REGISTER_LONG_CONSTANT("LDAP_ESCAPE_FILTER", PHP_LDAP_ESCAPE_FILTER, CONST_PERSISTENT | CONST_CS);
853 REGISTER_LONG_CONSTANT("LDAP_ESCAPE_DN", PHP_LDAP_ESCAPE_DN, CONST_PERSISTENT | CONST_CS);
854
855 #ifdef HAVE_LDAP_EXTENDED_OPERATION_S
856 REGISTER_STRING_CONSTANT("LDAP_EXOP_START_TLS", LDAP_EXOP_START_TLS, CONST_PERSISTENT | CONST_CS);
857 REGISTER_STRING_CONSTANT("LDAP_EXOP_MODIFY_PASSWD", LDAP_EXOP_MODIFY_PASSWD, CONST_PERSISTENT | CONST_CS);
858 REGISTER_STRING_CONSTANT("LDAP_EXOP_REFRESH", LDAP_EXOP_REFRESH, CONST_PERSISTENT | CONST_CS);
859 REGISTER_STRING_CONSTANT("LDAP_EXOP_WHO_AM_I", LDAP_EXOP_WHO_AM_I, CONST_PERSISTENT | CONST_CS);
860 REGISTER_STRING_CONSTANT("LDAP_EXOP_TURN", LDAP_EXOP_TURN, CONST_PERSISTENT | CONST_CS);
861 #endif
862
863 /* LDAP Controls */
864 /* standard track controls */
865 #ifdef LDAP_CONTROL_MANAGEDSAIT
866 /* RFC 3296 */
867 REGISTER_STRING_CONSTANT("LDAP_CONTROL_MANAGEDSAIT", LDAP_CONTROL_MANAGEDSAIT, CONST_PERSISTENT | CONST_CS);
868 #endif
869 #ifdef LDAP_CONTROL_PROXY_AUTHZ
870 /* RFC 4370 */
871 REGISTER_STRING_CONSTANT("LDAP_CONTROL_PROXY_AUTHZ", LDAP_CONTROL_PROXY_AUTHZ, CONST_PERSISTENT | CONST_CS);
872 #endif
873 #ifdef LDAP_CONTROL_SUBENTRIES
874 /* RFC 3672 */
875 REGISTER_STRING_CONSTANT("LDAP_CONTROL_SUBENTRIES", LDAP_CONTROL_SUBENTRIES, CONST_PERSISTENT | CONST_CS);
876 #endif
877 #ifdef LDAP_CONTROL_VALUESRETURNFILTER
878 /* RFC 3876 */
879 REGISTER_STRING_CONSTANT("LDAP_CONTROL_VALUESRETURNFILTER", LDAP_CONTROL_VALUESRETURNFILTER, CONST_PERSISTENT | CONST_CS);
880 #endif
881 #ifdef LDAP_CONTROL_ASSERT
882 /* RFC 4528 */
883 REGISTER_STRING_CONSTANT("LDAP_CONTROL_ASSERT", LDAP_CONTROL_ASSERT, CONST_PERSISTENT | CONST_CS);
884 /* RFC 4527 */
885 REGISTER_STRING_CONSTANT("LDAP_CONTROL_PRE_READ", LDAP_CONTROL_PRE_READ, CONST_PERSISTENT | CONST_CS);
886 REGISTER_STRING_CONSTANT("LDAP_CONTROL_POST_READ", LDAP_CONTROL_POST_READ, CONST_PERSISTENT | CONST_CS);
887 #endif
888 #ifdef LDAP_CONTROL_SORTREQUEST
889 /* RFC 2891 */
890 REGISTER_STRING_CONSTANT("LDAP_CONTROL_SORTREQUEST", LDAP_CONTROL_SORTREQUEST, CONST_PERSISTENT | CONST_CS);
891 REGISTER_STRING_CONSTANT("LDAP_CONTROL_SORTRESPONSE", LDAP_CONTROL_SORTRESPONSE, CONST_PERSISTENT | CONST_CS);
892 #endif
893 /* non-standard track controls */
894 #ifdef LDAP_CONTROL_PAGEDRESULTS
895 /* RFC 2696 */
896 REGISTER_STRING_CONSTANT("LDAP_CONTROL_PAGEDRESULTS", LDAP_CONTROL_PAGEDRESULTS, CONST_PERSISTENT | CONST_CS);
897 #endif
898 #ifdef LDAP_CONTROL_AUTHZID_REQUEST
899 /* RFC 3829 */
900 REGISTER_STRING_CONSTANT("LDAP_CONTROL_AUTHZID_REQUEST", LDAP_CONTROL_AUTHZID_REQUEST, CONST_PERSISTENT | CONST_CS);
901 REGISTER_STRING_CONSTANT("LDAP_CONTROL_AUTHZID_RESPONSE", LDAP_CONTROL_AUTHZID_RESPONSE, CONST_PERSISTENT | CONST_CS);
902 #endif
903 #ifdef LDAP_CONTROL_SYNC
904 /* LDAP Content Synchronization Operation -- RFC 4533 */
905 REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC", LDAP_CONTROL_SYNC, CONST_PERSISTENT | CONST_CS);
906 REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC_STATE", LDAP_CONTROL_SYNC_STATE, CONST_PERSISTENT | CONST_CS);
907 REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC_DONE", LDAP_CONTROL_SYNC_DONE, CONST_PERSISTENT | CONST_CS);
908 #endif
909 #ifdef LDAP_CONTROL_DONTUSECOPY
910 /* LDAP Don't Use Copy Control (RFC 6171) */
911 REGISTER_STRING_CONSTANT("LDAP_CONTROL_DONTUSECOPY", LDAP_CONTROL_DONTUSECOPY, CONST_PERSISTENT | CONST_CS);
912 #endif
913 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
914 /* Password policy Controls */
915 REGISTER_STRING_CONSTANT("LDAP_CONTROL_PASSWORDPOLICYREQUEST", LDAP_CONTROL_PASSWORDPOLICYREQUEST, CONST_PERSISTENT | CONST_CS);
916 REGISTER_STRING_CONSTANT("LDAP_CONTROL_PASSWORDPOLICYRESPONSE", LDAP_CONTROL_PASSWORDPOLICYRESPONSE, CONST_PERSISTENT | CONST_CS);
917 #endif
918 #ifdef LDAP_CONTROL_X_INCREMENTAL_VALUES
919 /* MS Active Directory controls */
920 REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_INCREMENTAL_VALUES", LDAP_CONTROL_X_INCREMENTAL_VALUES, CONST_PERSISTENT | CONST_CS);
921 REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_DOMAIN_SCOPE", LDAP_CONTROL_X_DOMAIN_SCOPE, CONST_PERSISTENT | CONST_CS);
922 REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_PERMISSIVE_MODIFY", LDAP_CONTROL_X_PERMISSIVE_MODIFY, CONST_PERSISTENT | CONST_CS);
923 REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_SEARCH_OPTIONS", LDAP_CONTROL_X_SEARCH_OPTIONS, CONST_PERSISTENT | CONST_CS);
924 REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_TREE_DELETE", LDAP_CONTROL_X_TREE_DELETE, CONST_PERSISTENT | CONST_CS);
925 REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_EXTENDED_DN", LDAP_CONTROL_X_EXTENDED_DN, CONST_PERSISTENT | CONST_CS);
926 #endif
927 #ifdef LDAP_CONTROL_VLVREQUEST
928 /* LDAP VLV */
929 REGISTER_STRING_CONSTANT("LDAP_CONTROL_VLVREQUEST", LDAP_CONTROL_VLVREQUEST, CONST_PERSISTENT | CONST_CS);
930 REGISTER_STRING_CONSTANT("LDAP_CONTROL_VLVRESPONSE", LDAP_CONTROL_VLVRESPONSE, CONST_PERSISTENT | CONST_CS);
931 #endif
932
933 le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number);
934 le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number);
935 le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number);
936
937 ldap_module_entry.type = type;
938
939 return SUCCESS;
940 }
941 /* }}} */
942
943 /* {{{ PHP_MSHUTDOWN_FUNCTION
944 */
PHP_MSHUTDOWN_FUNCTION(ldap)945 PHP_MSHUTDOWN_FUNCTION(ldap)
946 {
947 UNREGISTER_INI_ENTRIES();
948 return SUCCESS;
949 }
950 /* }}} */
951
952 /* {{{ PHP_MINFO_FUNCTION
953 */
PHP_MINFO_FUNCTION(ldap)954 PHP_MINFO_FUNCTION(ldap)
955 {
956 char tmp[32];
957
958 php_info_print_table_start();
959 php_info_print_table_row(2, "LDAP Support", "enabled");
960
961 if (LDAPG(max_links) == -1) {
962 snprintf(tmp, 31, ZEND_LONG_FMT "/unlimited", LDAPG(num_links));
963 } else {
964 snprintf(tmp, 31, ZEND_LONG_FMT "/" ZEND_LONG_FMT, LDAPG(num_links), LDAPG(max_links));
965 }
966 php_info_print_table_row(2, "Total Links", tmp);
967
968 #ifdef LDAP_API_VERSION
969 snprintf(tmp, 31, "%d", LDAP_API_VERSION);
970 php_info_print_table_row(2, "API Version", tmp);
971 #endif
972
973 #ifdef LDAP_VENDOR_NAME
974 php_info_print_table_row(2, "Vendor Name", LDAP_VENDOR_NAME);
975 #endif
976
977 #ifdef LDAP_VENDOR_VERSION
978 snprintf(tmp, 31, "%d", LDAP_VENDOR_VERSION);
979 php_info_print_table_row(2, "Vendor Version", tmp);
980 #endif
981
982 #ifdef HAVE_LDAP_SASL
983 php_info_print_table_row(2, "SASL Support", "Enabled");
984 #endif
985
986 php_info_print_table_end();
987 DISPLAY_INI_ENTRIES();
988 }
989 /* }}} */
990
991 /* {{{ proto resource ldap_connect([string host [, int port [, string wallet [, string wallet_passwd [, int authmode]]]]])
992 Connect to an LDAP server */
PHP_FUNCTION(ldap_connect)993 PHP_FUNCTION(ldap_connect)
994 {
995 char *host = NULL;
996 size_t hostlen = 0;
997 zend_long port = LDAP_PORT;
998 #ifdef HAVE_ORALDAP
999 char *wallet = NULL, *walletpasswd = NULL;
1000 size_t walletlen = 0, walletpasswdlen = 0;
1001 zend_long authmode = GSLC_SSL_NO_AUTH;
1002 int ssl=0;
1003 #endif
1004 ldap_linkdata *ld;
1005 LDAP *ldap = NULL;
1006
1007 #ifdef HAVE_ORALDAP
1008 if (ZEND_NUM_ARGS() == 3 || ZEND_NUM_ARGS() == 4) {
1009 WRONG_PARAM_COUNT;
1010 }
1011
1012 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|slssl", &host, &hostlen, &port, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) != SUCCESS) {
1013 RETURN_FALSE;
1014 }
1015
1016 if (ZEND_NUM_ARGS() == 5) {
1017 ssl = 1;
1018 }
1019 #else
1020 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sl", &host, &hostlen, &port) != SUCCESS) {
1021 RETURN_FALSE;
1022 }
1023 #endif
1024
1025 if (LDAPG(max_links) != -1 && LDAPG(num_links) >= LDAPG(max_links)) {
1026 php_error_docref(NULL, E_WARNING, "Too many open links (" ZEND_LONG_FMT ")", LDAPG(num_links));
1027 RETURN_FALSE;
1028 }
1029
1030 ld = ecalloc(1, sizeof(ldap_linkdata));
1031
1032 {
1033 int rc = LDAP_SUCCESS;
1034 char *url = host;
1035 if (url && !ldap_is_ldap_url(url)) {
1036 size_t urllen = hostlen + sizeof( "ldap://:65535" );
1037
1038 if (port <= 0 || port > 65535) {
1039 efree(ld);
1040 php_error_docref(NULL, E_WARNING, "invalid port number: " ZEND_LONG_FMT, port);
1041 RETURN_FALSE;
1042 }
1043
1044 url = emalloc(urllen);
1045 snprintf( url, urllen, "ldap://%s:" ZEND_LONG_FMT, host, port );
1046 }
1047
1048 #ifdef LDAP_API_FEATURE_X_OPENLDAP
1049 /* ldap_init() is deprecated, use ldap_initialize() instead.
1050 */
1051 rc = ldap_initialize(&ldap, url);
1052 #else /* ! LDAP_API_FEATURE_X_OPENLDAP */
1053 /* ldap_init does not support URLs.
1054 * We must try the original host and port information.
1055 */
1056 ldap = ldap_init(host, port);
1057 if (ldap == NULL) {
1058 efree(ld);
1059 php_error_docref(NULL, E_WARNING, "Could not create session handle");
1060 RETURN_FALSE;
1061 }
1062 #endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
1063 if (url != host) {
1064 efree(url);
1065 }
1066 if (rc != LDAP_SUCCESS) {
1067 efree(ld);
1068 php_error_docref(NULL, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
1069 RETURN_FALSE;
1070 }
1071 }
1072
1073 if (ldap == NULL) {
1074 efree(ld);
1075 RETURN_FALSE;
1076 } else {
1077 #ifdef HAVE_ORALDAP
1078 if (ssl) {
1079 if (ldap_init_SSL(&ldap->ld_sb, wallet, walletpasswd, authmode)) {
1080 efree(ld);
1081 php_error_docref(NULL, E_WARNING, "SSL init failed");
1082 RETURN_FALSE;
1083 }
1084 }
1085 #endif
1086 LDAPG(num_links)++;
1087 ld->link = ldap;
1088 RETURN_RES(zend_register_resource(ld, le_link));
1089 }
1090
1091 }
1092 /* }}} */
1093
1094 /* {{{ _get_lderrno
1095 */
_get_lderrno(LDAP * ldap)1096 static int _get_lderrno(LDAP *ldap)
1097 {
1098 #if LDAP_API_VERSION > 2000 || HAVE_ORALDAP
1099 int lderr;
1100
1101 /* New versions of OpenLDAP do it this way */
1102 ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr);
1103 return lderr;
1104 #else
1105 return ldap->ld_errno;
1106 #endif
1107 }
1108 /* }}} */
1109
1110 /* {{{ _set_lderrno
1111 */
_set_lderrno(LDAP * ldap,int lderr)1112 static void _set_lderrno(LDAP *ldap, int lderr)
1113 {
1114 #if LDAP_API_VERSION > 2000 || HAVE_ORALDAP
1115 /* New versions of OpenLDAP do it this way */
1116 ldap_set_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr);
1117 #else
1118 ldap->ld_errno = lderr;
1119 #endif
1120 }
1121 /* }}} */
1122
1123 /* {{{ proto bool ldap_bind(resource link [, string dn [, string password]])
1124 Bind to LDAP directory */
PHP_FUNCTION(ldap_bind)1125 PHP_FUNCTION(ldap_bind)
1126 {
1127 zval *link;
1128 char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
1129 size_t ldap_bind_dnlen, ldap_bind_pwlen;
1130 ldap_linkdata *ld;
1131 int rc;
1132
1133 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ss", &link, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen) != SUCCESS) {
1134 RETURN_FALSE;
1135 }
1136
1137 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1138 RETURN_FALSE;
1139 }
1140
1141 if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
1142 _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
1143 php_error_docref(NULL, E_WARNING, "DN contains a null byte");
1144 RETURN_FALSE;
1145 }
1146
1147 if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
1148 _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
1149 php_error_docref(NULL, E_WARNING, "Password contains a null byte");
1150 RETURN_FALSE;
1151 }
1152
1153 {
1154 #ifdef LDAP_API_FEATURE_X_OPENLDAP
1155 /* ldap_simple_bind_s() is deprecated, use ldap_sasl_bind_s() instead.
1156 */
1157 struct berval cred;
1158
1159 cred.bv_val = ldap_bind_pw;
1160 cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
1161 rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
1162 NULL, NULL, /* no controls right now */
1163 NULL); /* we don't care about the server's credentials */
1164 #else /* ! LDAP_API_FEATURE_X_OPENLDAP */
1165 rc = ldap_simple_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw);
1166 #endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
1167 }
1168 if ( rc != LDAP_SUCCESS) {
1169 php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
1170 RETURN_FALSE;
1171 } else {
1172 RETURN_TRUE;
1173 }
1174 }
1175 /* }}} */
1176
1177 /* {{{ proto resource ldap_bind_ext(resource link [, string dn [, string password [, serverctrls]]])
1178 Bind to LDAP directory */
PHP_FUNCTION(ldap_bind_ext)1179 PHP_FUNCTION(ldap_bind_ext)
1180 {
1181 zval *serverctrls = NULL;
1182 zval *link;
1183 char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
1184 size_t ldap_bind_dnlen, ldap_bind_pwlen;
1185 ldap_linkdata *ld;
1186 LDAPControl **lserverctrls = NULL;
1187 LDAPMessage *ldap_res;
1188 int rc;
1189
1190 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ssa", &link, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen, &serverctrls) != SUCCESS) {
1191 RETURN_FALSE;
1192 }
1193
1194 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1195 RETURN_FALSE;
1196 }
1197
1198 if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
1199 _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
1200 php_error_docref(NULL, E_WARNING, "DN contains a null byte");
1201 RETURN_FALSE;
1202 }
1203
1204 if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
1205 _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS);
1206 php_error_docref(NULL, E_WARNING, "Password contains a null byte");
1207 RETURN_FALSE;
1208 }
1209
1210 if (serverctrls) {
1211 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
1212 if (lserverctrls == NULL) {
1213 RETVAL_FALSE;
1214 goto cleanup;
1215 }
1216 }
1217
1218 {
1219 /* ldap_simple_bind() is deprecated, use ldap_sasl_bind() instead */
1220 struct berval cred;
1221 int msgid;
1222
1223 cred.bv_val = ldap_bind_pw;
1224 cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
1225 /* asynchronous call */
1226 rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
1227 lserverctrls, NULL, &msgid);
1228 if (rc != LDAP_SUCCESS ) {
1229 php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s (%d)", ldap_err2string(rc), rc);
1230 RETVAL_FALSE;
1231 goto cleanup;
1232 }
1233
1234 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
1235 if (rc == -1) {
1236 php_error_docref(NULL, E_WARNING, "Bind operation failed");
1237 RETVAL_FALSE;
1238 goto cleanup;
1239 }
1240
1241 /* return a PHP control object */
1242 RETVAL_RES(zend_register_resource(ldap_res, le_result));
1243 }
1244
1245 cleanup:
1246 if (lserverctrls) {
1247 _php_ldap_controls_free(&lserverctrls);
1248 }
1249
1250 return;
1251 }
1252 /* }}} */
1253
1254 #ifdef HAVE_LDAP_SASL
1255 typedef struct {
1256 char *mech;
1257 char *realm;
1258 char *authcid;
1259 char *passwd;
1260 char *authzid;
1261 } php_ldap_bictx;
1262
1263 /* {{{ _php_sasl_setdefs
1264 */
_php_sasl_setdefs(LDAP * ld,char * sasl_mech,char * sasl_realm,char * sasl_authc_id,char * passwd,char * sasl_authz_id)1265 static php_ldap_bictx *_php_sasl_setdefs(LDAP *ld, char *sasl_mech, char *sasl_realm, char *sasl_authc_id, char *passwd, char *sasl_authz_id)
1266 {
1267 php_ldap_bictx *ctx;
1268
1269 ctx = ber_memalloc(sizeof(php_ldap_bictx));
1270 ctx->mech = (sasl_mech) ? ber_strdup(sasl_mech) : NULL;
1271 ctx->realm = (sasl_realm) ? ber_strdup(sasl_realm) : NULL;
1272 ctx->authcid = (sasl_authc_id) ? ber_strdup(sasl_authc_id) : NULL;
1273 ctx->passwd = (passwd) ? ber_strdup(passwd) : NULL;
1274 ctx->authzid = (sasl_authz_id) ? ber_strdup(sasl_authz_id) : NULL;
1275
1276 if (ctx->mech == NULL) {
1277 ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &ctx->mech);
1278 }
1279 if (ctx->realm == NULL) {
1280 ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &ctx->realm);
1281 }
1282 if (ctx->authcid == NULL) {
1283 ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &ctx->authcid);
1284 }
1285 if (ctx->authzid == NULL) {
1286 ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &ctx->authzid);
1287 }
1288
1289 return ctx;
1290 }
1291 /* }}} */
1292
1293 /* {{{ _php_sasl_freedefs
1294 */
_php_sasl_freedefs(php_ldap_bictx * ctx)1295 static void _php_sasl_freedefs(php_ldap_bictx *ctx)
1296 {
1297 if (ctx->mech) ber_memfree(ctx->mech);
1298 if (ctx->realm) ber_memfree(ctx->realm);
1299 if (ctx->authcid) ber_memfree(ctx->authcid);
1300 if (ctx->passwd) ber_memfree(ctx->passwd);
1301 if (ctx->authzid) ber_memfree(ctx->authzid);
1302 ber_memfree(ctx);
1303 }
1304 /* }}} */
1305
1306 /* {{{ _php_sasl_interact
1307 Internal interact function for SASL */
_php_sasl_interact(LDAP * ld,unsigned flags,void * defaults,void * in)1308 static int _php_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
1309 {
1310 sasl_interact_t *interact = in;
1311 const char *p;
1312 php_ldap_bictx *ctx = defaults;
1313
1314 for (;interact->id != SASL_CB_LIST_END;interact++) {
1315 p = NULL;
1316 switch(interact->id) {
1317 case SASL_CB_GETREALM:
1318 p = ctx->realm;
1319 break;
1320 case SASL_CB_AUTHNAME:
1321 p = ctx->authcid;
1322 break;
1323 case SASL_CB_USER:
1324 p = ctx->authzid;
1325 break;
1326 case SASL_CB_PASS:
1327 p = ctx->passwd;
1328 break;
1329 }
1330 if (p) {
1331 interact->result = p;
1332 interact->len = strlen(interact->result);
1333 }
1334 }
1335 return LDAP_SUCCESS;
1336 }
1337 /* }}} */
1338
1339 /* {{{ proto bool ldap_sasl_bind(resource link [, string binddn [, string password [, string sasl_mech [, string sasl_realm [, string sasl_authc_id [, string sasl_authz_id [, string props]]]]]]])
1340 Bind to LDAP directory using SASL */
PHP_FUNCTION(ldap_sasl_bind)1341 PHP_FUNCTION(ldap_sasl_bind)
1342 {
1343 zval *link;
1344 ldap_linkdata *ld;
1345 char *binddn = NULL;
1346 char *passwd = NULL;
1347 char *sasl_mech = NULL;
1348 char *sasl_realm = NULL;
1349 char *sasl_authz_id = NULL;
1350 char *sasl_authc_id = NULL;
1351 char *props = NULL;
1352 size_t rc, dn_len, passwd_len, mech_len, realm_len, authc_id_len, authz_id_len, props_len;
1353 php_ldap_bictx *ctx;
1354
1355 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|sssssss", &link, &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) {
1356 RETURN_FALSE;
1357 }
1358
1359 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1360 RETURN_FALSE;
1361 }
1362
1363 ctx = _php_sasl_setdefs(ld->link, sasl_mech, sasl_realm, sasl_authc_id, passwd, sasl_authz_id);
1364
1365 if (props) {
1366 ldap_set_option(ld->link, LDAP_OPT_X_SASL_SECPROPS, props);
1367 }
1368
1369 rc = ldap_sasl_interactive_bind_s(ld->link, binddn, ctx->mech, NULL, NULL, LDAP_SASL_QUIET, _php_sasl_interact, ctx);
1370 if (rc != LDAP_SUCCESS) {
1371 php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
1372 RETVAL_FALSE;
1373 } else {
1374 RETVAL_TRUE;
1375 }
1376 _php_sasl_freedefs(ctx);
1377 }
1378 /* }}} */
1379 #endif /* HAVE_LDAP_SASL */
1380
1381 /* {{{ proto bool ldap_unbind(resource link)
1382 Unbind from LDAP directory */
PHP_FUNCTION(ldap_unbind)1383 PHP_FUNCTION(ldap_unbind)
1384 {
1385 zval *link;
1386 ldap_linkdata *ld;
1387
1388 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &link) != SUCCESS) {
1389 RETURN_FALSE;
1390 }
1391
1392 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1393 RETURN_FALSE;
1394 }
1395
1396 zend_list_close(Z_RES_P(link));
1397 RETURN_TRUE;
1398 }
1399 /* }}} */
1400
1401 /* {{{ php_set_opts
1402 */
php_set_opts(LDAP * ldap,int sizelimit,int timelimit,int deref,int * old_sizelimit,int * old_timelimit,int * old_deref)1403 static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, int *old_sizelimit, int *old_timelimit, int *old_deref)
1404 {
1405 /* sizelimit */
1406 if (sizelimit > -1) {
1407 #if (LDAP_API_VERSION >= 2004) || HAVE_ORALDAP
1408 ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_sizelimit);
1409 ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit);
1410 #else
1411 *old_sizelimit = ldap->ld_sizelimit;
1412 ldap->ld_sizelimit = sizelimit;
1413 #endif
1414 }
1415
1416 /* timelimit */
1417 if (timelimit > -1) {
1418 #if (LDAP_API_VERSION >= 2004) || HAVE_ORALDAP
1419 ldap_get_option(ldap, LDAP_OPT_TIMELIMIT, old_timelimit);
1420 ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit);
1421 #else
1422 *old_timelimit = ldap->ld_timelimit;
1423 ldap->ld_timelimit = timelimit;
1424 #endif
1425 }
1426
1427 /* deref */
1428 if (deref > -1) {
1429 #if (LDAP_API_VERSION >= 2004) || HAVE_ORALDAP
1430 ldap_get_option(ldap, LDAP_OPT_DEREF, old_deref);
1431 ldap_set_option(ldap, LDAP_OPT_DEREF, &deref);
1432 #else
1433 *old_deref = ldap->ld_deref;
1434 ldap->ld_deref = deref;
1435 #endif
1436 }
1437 }
1438 /* }}} */
1439
1440 /* {{{ php_ldap_do_search
1441 */
php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS,int scope)1442 static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
1443 {
1444 zval *link, *base_dn, *filter, *attrs = NULL, *attr, *serverctrls = NULL;
1445 zend_long attrsonly, sizelimit, timelimit, deref;
1446 zend_string *ldap_filter = NULL, *ldap_base_dn = NULL;
1447 char **ldap_attrs = NULL;
1448 ldap_linkdata *ld = NULL;
1449 LDAPMessage *ldap_res = NULL;
1450 LDAPControl **lserverctrls = NULL;
1451 int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1;
1452 int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
1453 int num_attribs = 0, ret = 1, i, errno, argcount = ZEND_NUM_ARGS();
1454
1455 if (zend_parse_parameters(argcount, "zzz|a/lllla/", &link, &base_dn, &filter, &attrs, &attrsonly,
1456 &sizelimit, &timelimit, &deref, &serverctrls) == FAILURE) {
1457 return;
1458 }
1459
1460 /* Reverse -> fall through */
1461 switch (argcount) {
1462 case 9:
1463 case 8:
1464 ldap_deref = deref;
1465 case 7:
1466 ldap_timelimit = timelimit;
1467 case 6:
1468 ldap_sizelimit = sizelimit;
1469 case 5:
1470 ldap_attrsonly = attrsonly;
1471 case 4:
1472 num_attribs = zend_hash_num_elements(Z_ARRVAL_P(attrs));
1473 ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
1474
1475 for (i = 0; i<num_attribs; i++) {
1476 if ((attr = zend_hash_index_find(Z_ARRVAL_P(attrs), i)) == NULL) {
1477 php_error_docref(NULL, E_WARNING, "Array initialization wrong");
1478 ret = 0;
1479 goto cleanup;
1480 }
1481
1482 convert_to_string(attr);
1483 if (EG(exception)) {
1484 ret = 0;
1485 goto cleanup;
1486 }
1487 ldap_attrs[i] = Z_STRVAL_P(attr);
1488 }
1489 ldap_attrs[num_attribs] = NULL;
1490 default:
1491 break;
1492 }
1493
1494 /* parallel search? */
1495 if (Z_TYPE_P(link) == IS_ARRAY) {
1496 int i, nlinks, nbases, nfilters, *rcs;
1497 ldap_linkdata **lds;
1498 zval *entry, resource;
1499
1500 nlinks = zend_hash_num_elements(Z_ARRVAL_P(link));
1501 if (nlinks == 0) {
1502 php_error_docref(NULL, E_WARNING, "No links in link array");
1503 ret = 0;
1504 goto cleanup;
1505 }
1506
1507 if (Z_TYPE_P(base_dn) == IS_ARRAY) {
1508 nbases = zend_hash_num_elements(Z_ARRVAL_P(base_dn));
1509 if (nbases != nlinks) {
1510 php_error_docref(NULL, E_WARNING, "Base must either be a string, or an array with the same number of elements as the links array");
1511 ret = 0;
1512 goto cleanup;
1513 }
1514 zend_hash_internal_pointer_reset(Z_ARRVAL_P(base_dn));
1515 } else {
1516 nbases = 0; /* this means string, not array */
1517 ldap_base_dn = zval_get_string(base_dn);
1518 if (EG(exception)) {
1519 ret = 0;
1520 goto cleanup;
1521 }
1522 }
1523
1524 if (Z_TYPE_P(filter) == IS_ARRAY) {
1525 nfilters = zend_hash_num_elements(Z_ARRVAL_P(filter));
1526 if (nfilters != nlinks) {
1527 php_error_docref(NULL, E_WARNING, "Filter must either be a string, or an array with the same number of elements as the links array");
1528 ret = 0;
1529 goto cleanup;
1530 }
1531 zend_hash_internal_pointer_reset(Z_ARRVAL_P(filter));
1532 } else {
1533 nfilters = 0; /* this means string, not array */
1534 ldap_filter = zval_get_string(filter);
1535 if (EG(exception)) {
1536 ret = 0;
1537 goto cleanup;
1538 }
1539 }
1540
1541 lds = safe_emalloc(nlinks, sizeof(ldap_linkdata), 0);
1542 rcs = safe_emalloc(nlinks, sizeof(*rcs), 0);
1543
1544 zend_hash_internal_pointer_reset(Z_ARRVAL_P(link));
1545 for (i=0; i<nlinks; i++) {
1546 entry = zend_hash_get_current_data(Z_ARRVAL_P(link));
1547
1548 ld = (ldap_linkdata *) zend_fetch_resource_ex(entry, "ldap link", le_link);
1549 if (ld == NULL) {
1550 ret = 0;
1551 goto cleanup_parallel;
1552 }
1553 if (nbases != 0) { /* base_dn an array? */
1554 entry = zend_hash_get_current_data(Z_ARRVAL_P(base_dn));
1555 zend_hash_move_forward(Z_ARRVAL_P(base_dn));
1556 ldap_base_dn = zval_get_string(entry);
1557 if (EG(exception)) {
1558 ret = 0;
1559 goto cleanup_parallel;
1560 }
1561 }
1562 if (nfilters != 0) { /* filter an array? */
1563 entry = zend_hash_get_current_data(Z_ARRVAL_P(filter));
1564 zend_hash_move_forward(Z_ARRVAL_P(filter));
1565 ldap_filter = zval_get_string(entry);
1566 if (EG(exception)) {
1567 ret = 0;
1568 goto cleanup_parallel;
1569 }
1570 }
1571
1572 if (argcount > 8) {
1573 /* We have to parse controls again for each link as they use it */
1574 _php_ldap_controls_free(&lserverctrls);
1575 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
1576 if (lserverctrls == NULL) {
1577 rcs[i] = -1;
1578 continue;
1579 }
1580 }
1581
1582 php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
1583
1584 /* Run the actual search */
1585 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]);
1586 lds[i] = ld;
1587 zend_hash_move_forward(Z_ARRVAL_P(link));
1588 }
1589
1590 array_init(return_value);
1591
1592 /* Collect results from the searches */
1593 for (i=0; i<nlinks; i++) {
1594 if (rcs[i] != -1) {
1595 rcs[i] = ldap_result(lds[i]->link, LDAP_RES_ANY, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
1596 }
1597 if (rcs[i] != -1) {
1598 ZVAL_RES(&resource, zend_register_resource(ldap_res, le_result));
1599 add_next_index_zval(return_value, &resource);
1600 } else {
1601 add_next_index_bool(return_value, 0);
1602 }
1603 }
1604
1605 cleanup_parallel:
1606 efree(lds);
1607 efree(rcs);
1608 } else {
1609 ldap_filter = zval_get_string(filter);
1610 if (EG(exception)) {
1611 ret = 0;
1612 goto cleanup;
1613 }
1614
1615 ldap_base_dn = zval_get_string(base_dn);
1616 if (EG(exception)) {
1617 ret = 0;
1618 goto cleanup;
1619 }
1620
1621 ld = (ldap_linkdata *) zend_fetch_resource_ex(link, "ldap link", le_link);
1622 if (ld == NULL) {
1623 ret = 0;
1624 goto cleanup;
1625 }
1626
1627 if (argcount > 8) {
1628 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
1629 if (lserverctrls == NULL) {
1630 ret = 0;
1631 goto cleanup;
1632 }
1633 }
1634
1635 php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
1636
1637 /* Run the actual search */
1638 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);
1639
1640 if (errno != LDAP_SUCCESS
1641 && errno != LDAP_SIZELIMIT_EXCEEDED
1642 #ifdef LDAP_ADMINLIMIT_EXCEEDED
1643 && errno != LDAP_ADMINLIMIT_EXCEEDED
1644 #endif
1645 #ifdef LDAP_REFERRAL
1646 && errno != LDAP_REFERRAL
1647 #endif
1648 ) {
1649 /* ldap_res should be freed regardless of return value of ldap_search_ext_s()
1650 * see: https://linux.die.net/man/3/ldap_search_ext_s */
1651 if (ldap_res != NULL) {
1652 ldap_msgfree(ldap_res);
1653 }
1654 php_error_docref(NULL, E_WARNING, "Search: %s", ldap_err2string(errno));
1655 ret = 0;
1656 } else {
1657 if (errno == LDAP_SIZELIMIT_EXCEEDED) {
1658 php_error_docref(NULL, E_WARNING, "Partial search results returned: Sizelimit exceeded");
1659 }
1660 #ifdef LDAP_ADMINLIMIT_EXCEEDED
1661 else if (errno == LDAP_ADMINLIMIT_EXCEEDED) {
1662 php_error_docref(NULL, E_WARNING, "Partial search results returned: Adminlimit exceeded");
1663 }
1664 #endif
1665
1666 RETVAL_RES(zend_register_resource(ldap_res, le_result));
1667 }
1668 }
1669
1670 cleanup:
1671 if (ld) {
1672 /* Restoring previous options */
1673 php_set_opts(ld->link, old_ldap_sizelimit, old_ldap_timelimit, old_ldap_deref, &ldap_sizelimit, &ldap_timelimit, &ldap_deref);
1674 }
1675 if (ldap_filter) {
1676 zend_string_release(ldap_filter);
1677 }
1678 if (ldap_base_dn) {
1679 zend_string_release(ldap_base_dn);
1680 }
1681 if (ldap_attrs != NULL) {
1682 efree(ldap_attrs);
1683 }
1684 if (!ret) {
1685 RETVAL_BOOL(ret);
1686 }
1687 if (lserverctrls) {
1688 _php_ldap_controls_free(&lserverctrls);
1689 }
1690 }
1691 /* }}} */
1692
1693 /* {{{ proto resource ldap_read(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]])
1694 Read an entry */
PHP_FUNCTION(ldap_read)1695 PHP_FUNCTION(ldap_read)
1696 {
1697 php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_BASE);
1698 }
1699 /* }}} */
1700
1701 /* {{{ proto resource ldap_list(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]])
1702 Single-level search */
PHP_FUNCTION(ldap_list)1703 PHP_FUNCTION(ldap_list)
1704 {
1705 php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_ONELEVEL);
1706 }
1707 /* }}} */
1708
1709 /* {{{ proto resource ldap_search(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]])
1710 Search LDAP tree under base_dn */
PHP_FUNCTION(ldap_search)1711 PHP_FUNCTION(ldap_search)
1712 {
1713 php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_SUBTREE);
1714 }
1715 /* }}} */
1716
1717 /* {{{ proto bool ldap_free_result(resource result)
1718 Free result memory */
PHP_FUNCTION(ldap_free_result)1719 PHP_FUNCTION(ldap_free_result)
1720 {
1721 zval *result;
1722 LDAPMessage *ldap_result;
1723
1724 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &result) != SUCCESS) {
1725 return;
1726 }
1727
1728 if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
1729 RETURN_FALSE;
1730 }
1731
1732 zend_list_close(Z_RES_P(result)); /* Delete list entry */
1733 RETVAL_TRUE;
1734 }
1735 /* }}} */
1736
1737 /* {{{ proto int ldap_count_entries(resource link, resource result)
1738 Count the number of entries in a search result */
PHP_FUNCTION(ldap_count_entries)1739 PHP_FUNCTION(ldap_count_entries)
1740 {
1741 zval *link, *result;
1742 ldap_linkdata *ld;
1743 LDAPMessage *ldap_result;
1744
1745 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &link, &result) != SUCCESS) {
1746 return;
1747 }
1748
1749 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1750 RETURN_FALSE;
1751 }
1752
1753 if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
1754 RETURN_FALSE;
1755 }
1756
1757 RETURN_LONG(ldap_count_entries(ld->link, ldap_result));
1758 }
1759 /* }}} */
1760
1761 /* {{{ proto resource ldap_first_entry(resource link, resource result)
1762 Return first result id */
PHP_FUNCTION(ldap_first_entry)1763 PHP_FUNCTION(ldap_first_entry)
1764 {
1765 zval *link, *result;
1766 ldap_linkdata *ld;
1767 ldap_resultentry *resultentry;
1768 LDAPMessage *ldap_result, *entry;
1769
1770 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &link, &result) != SUCCESS) {
1771 return;
1772 }
1773
1774 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1775 RETURN_FALSE;
1776 }
1777
1778 if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
1779 RETURN_FALSE;
1780 }
1781
1782 if ((entry = ldap_first_entry(ld->link, ldap_result)) == NULL) {
1783 RETVAL_FALSE;
1784 } else {
1785 resultentry = emalloc(sizeof(ldap_resultentry));
1786 RETVAL_RES(zend_register_resource(resultentry, le_result_entry));
1787 ZVAL_COPY(&resultentry->res, result);
1788 resultentry->data = entry;
1789 resultentry->ber = NULL;
1790 }
1791 }
1792 /* }}} */
1793
1794 /* {{{ proto resource ldap_next_entry(resource link, resource result_entry)
1795 Get next result entry */
PHP_FUNCTION(ldap_next_entry)1796 PHP_FUNCTION(ldap_next_entry)
1797 {
1798 zval *link, *result_entry;
1799 ldap_linkdata *ld;
1800 ldap_resultentry *resultentry, *resultentry_next;
1801 LDAPMessage *entry_next;
1802
1803 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &link, &result_entry) != SUCCESS) {
1804 return;
1805 }
1806
1807 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1808 RETURN_FALSE;
1809 }
1810 if ((resultentry = (ldap_resultentry *)zend_fetch_resource(Z_RES_P(result_entry), "ldap result entry", le_result_entry)) == NULL) {
1811 RETURN_FALSE;
1812 }
1813
1814 if ((entry_next = ldap_next_entry(ld->link, resultentry->data)) == NULL) {
1815 RETVAL_FALSE;
1816 } else {
1817 resultentry_next = emalloc(sizeof(ldap_resultentry));
1818 RETVAL_RES(zend_register_resource(resultentry_next, le_result_entry));
1819 ZVAL_COPY(&resultentry_next->res, &resultentry->res);
1820 resultentry_next->data = entry_next;
1821 resultentry_next->ber = NULL;
1822 }
1823 }
1824 /* }}} */
1825
1826 /* {{{ proto array ldap_get_entries(resource link, resource result)
1827 Get all result entries */
PHP_FUNCTION(ldap_get_entries)1828 PHP_FUNCTION(ldap_get_entries)
1829 {
1830 zval *link, *result;
1831 LDAPMessage *ldap_result, *ldap_result_entry;
1832 zval tmp1, tmp2;
1833 ldap_linkdata *ld;
1834 LDAP *ldap;
1835 int num_entries, num_attrib, num_values, i;
1836 BerElement *ber;
1837 char *attribute;
1838 size_t attr_len;
1839 struct berval **ldap_value;
1840 char *dn;
1841
1842 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &link, &result) != SUCCESS) {
1843 return;
1844 }
1845
1846 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1847 RETURN_FALSE;
1848 }
1849 if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
1850 RETURN_FALSE;
1851 }
1852
1853 ldap = ld->link;
1854 num_entries = ldap_count_entries(ldap, ldap_result);
1855
1856 array_init(return_value);
1857 add_assoc_long(return_value, "count", num_entries);
1858
1859 if (num_entries == 0) {
1860 return;
1861 }
1862
1863 ldap_result_entry = ldap_first_entry(ldap, ldap_result);
1864 if (ldap_result_entry == NULL) {
1865 zend_array_destroy(Z_ARR_P(return_value));
1866 RETURN_FALSE;
1867 }
1868
1869 num_entries = 0;
1870 while (ldap_result_entry != NULL) {
1871 array_init(&tmp1);
1872
1873 num_attrib = 0;
1874 attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber);
1875
1876 while (attribute != NULL) {
1877 ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute);
1878 num_values = ldap_count_values_len(ldap_value);
1879
1880 array_init(&tmp2);
1881 add_assoc_long(&tmp2, "count", num_values);
1882 for (i = 0; i < num_values; i++) {
1883 add_index_stringl(&tmp2, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len);
1884 }
1885 ldap_value_free_len(ldap_value);
1886
1887 attr_len = strlen(attribute);
1888 zend_hash_str_update(Z_ARRVAL(tmp1), php_strtolower(attribute, attr_len), attr_len, &tmp2);
1889 add_index_string(&tmp1, num_attrib, attribute);
1890
1891 num_attrib++;
1892 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
1893 ldap_memfree(attribute);
1894 #endif
1895 attribute = ldap_next_attribute(ldap, ldap_result_entry, ber);
1896 }
1897 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
1898 if (ber != NULL) {
1899 ber_free(ber, 0);
1900 }
1901 #endif
1902
1903 add_assoc_long(&tmp1, "count", num_attrib);
1904 dn = ldap_get_dn(ldap, ldap_result_entry);
1905 if (dn) {
1906 add_assoc_string(&tmp1, "dn", dn);
1907 } else {
1908 add_assoc_null(&tmp1, "dn");
1909 }
1910 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
1911 ldap_memfree(dn);
1912 #else
1913 free(dn);
1914 #endif
1915
1916 zend_hash_index_update(Z_ARRVAL_P(return_value), num_entries, &tmp1);
1917
1918 num_entries++;
1919 ldap_result_entry = ldap_next_entry(ldap, ldap_result_entry);
1920 }
1921
1922 add_assoc_long(return_value, "count", num_entries);
1923
1924 }
1925 /* }}} */
1926
1927 /* {{{ proto string ldap_first_attribute(resource link, resource result_entry)
1928 Return first attribute */
PHP_FUNCTION(ldap_first_attribute)1929 PHP_FUNCTION(ldap_first_attribute)
1930 {
1931 zval *link, *result_entry;
1932 ldap_linkdata *ld;
1933 ldap_resultentry *resultentry;
1934 char *attribute;
1935 zend_long dummy_ber;
1936
1937 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|l", &link, &result_entry, &dummy_ber) != SUCCESS) {
1938 return;
1939 }
1940
1941 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1942 RETURN_FALSE;
1943 }
1944
1945 if ((resultentry = (ldap_resultentry *)zend_fetch_resource(Z_RES_P(result_entry), "ldap result entry", le_result_entry)) == NULL) {
1946 RETURN_FALSE;
1947 }
1948
1949 if ((attribute = ldap_first_attribute(ld->link, resultentry->data, &resultentry->ber)) == NULL) {
1950 RETURN_FALSE;
1951 } else {
1952 RETVAL_STRING(attribute);
1953 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
1954 ldap_memfree(attribute);
1955 #endif
1956 }
1957 }
1958 /* }}} */
1959
1960 /* {{{ proto string ldap_next_attribute(resource link, resource result_entry)
1961 Get the next attribute in result */
PHP_FUNCTION(ldap_next_attribute)1962 PHP_FUNCTION(ldap_next_attribute)
1963 {
1964 zval *link, *result_entry;
1965 ldap_linkdata *ld;
1966 ldap_resultentry *resultentry;
1967 char *attribute;
1968 zend_long dummy_ber;
1969
1970 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|l", &link, &result_entry, &dummy_ber) != SUCCESS) {
1971 return;
1972 }
1973
1974 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
1975 RETURN_FALSE;
1976 }
1977
1978 if ((resultentry = (ldap_resultentry *)zend_fetch_resource(Z_RES_P(result_entry), "ldap result entry", le_result_entry)) == NULL) {
1979 RETURN_FALSE;
1980 }
1981
1982 if (resultentry->ber == NULL) {
1983 php_error_docref(NULL, E_WARNING, "called before calling ldap_first_attribute() or no attributes found in result entry");
1984 RETURN_FALSE;
1985 }
1986
1987 if ((attribute = ldap_next_attribute(ld->link, resultentry->data, resultentry->ber)) == NULL) {
1988 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
1989 if (resultentry->ber != NULL) {
1990 ber_free(resultentry->ber, 0);
1991 resultentry->ber = NULL;
1992 }
1993 #endif
1994 RETURN_FALSE;
1995 } else {
1996 RETVAL_STRING(attribute);
1997 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
1998 ldap_memfree(attribute);
1999 #endif
2000 }
2001 }
2002 /* }}} */
2003
2004 /* {{{ proto array ldap_get_attributes(resource link, resource result_entry)
2005 Get attributes from a search result entry */
PHP_FUNCTION(ldap_get_attributes)2006 PHP_FUNCTION(ldap_get_attributes)
2007 {
2008 zval *link, *result_entry;
2009 zval tmp;
2010 ldap_linkdata *ld;
2011 ldap_resultentry *resultentry;
2012 char *attribute;
2013 struct berval **ldap_value;
2014 int i, num_values, num_attrib;
2015 BerElement *ber;
2016
2017 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &link, &result_entry) != SUCCESS) {
2018 return;
2019 }
2020
2021 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2022 RETURN_FALSE;
2023 }
2024
2025 if ((resultentry = (ldap_resultentry *)zend_fetch_resource(Z_RES_P(result_entry), "ldap result entry", le_result_entry)) == NULL) {
2026 RETURN_FALSE;
2027 }
2028
2029 array_init(return_value);
2030 num_attrib = 0;
2031
2032 attribute = ldap_first_attribute(ld->link, resultentry->data, &ber);
2033 while (attribute != NULL) {
2034 ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute);
2035 num_values = ldap_count_values_len(ldap_value);
2036
2037 array_init(&tmp);
2038 add_assoc_long(&tmp, "count", num_values);
2039 for (i = 0; i < num_values; i++) {
2040 add_index_stringl(&tmp, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len);
2041 }
2042 ldap_value_free_len(ldap_value);
2043
2044 zend_hash_str_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute), &tmp);
2045 add_index_string(return_value, num_attrib, attribute);
2046
2047 num_attrib++;
2048 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
2049 ldap_memfree(attribute);
2050 #endif
2051 attribute = ldap_next_attribute(ld->link, resultentry->data, ber);
2052 }
2053 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
2054 if (ber != NULL) {
2055 ber_free(ber, 0);
2056 }
2057 #endif
2058
2059 add_assoc_long(return_value, "count", num_attrib);
2060 }
2061 /* }}} */
2062
2063 /* {{{ proto array ldap_get_values_len(resource link, resource result_entry, string attribute)
2064 Get all values with lengths from a result entry */
PHP_FUNCTION(ldap_get_values_len)2065 PHP_FUNCTION(ldap_get_values_len)
2066 {
2067 zval *link, *result_entry;
2068 ldap_linkdata *ld;
2069 ldap_resultentry *resultentry;
2070 char *attr;
2071 struct berval **ldap_value_len;
2072 int i, num_values;
2073 size_t attr_len;
2074
2075 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrs", &link, &result_entry, &attr, &attr_len) != SUCCESS) {
2076 return;
2077 }
2078
2079 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2080 RETURN_FALSE;
2081 }
2082
2083 if ((resultentry = (ldap_resultentry *)zend_fetch_resource(Z_RES_P(result_entry), "ldap result entry", le_result_entry)) == NULL) {
2084 RETURN_FALSE;
2085 }
2086
2087 if ((ldap_value_len = ldap_get_values_len(ld->link, resultentry->data, attr)) == NULL) {
2088 php_error_docref(NULL, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link)));
2089 RETURN_FALSE;
2090 }
2091
2092 num_values = ldap_count_values_len(ldap_value_len);
2093 array_init(return_value);
2094
2095 for (i=0; i<num_values; i++) {
2096 add_next_index_stringl(return_value, ldap_value_len[i]->bv_val, ldap_value_len[i]->bv_len);
2097 }
2098
2099 add_assoc_long(return_value, "count", num_values);
2100 ldap_value_free_len(ldap_value_len);
2101
2102 }
2103 /* }}} */
2104
2105 /* {{{ proto string ldap_get_dn(resource link, resource result_entry)
2106 Get the DN of a result entry */
PHP_FUNCTION(ldap_get_dn)2107 PHP_FUNCTION(ldap_get_dn)
2108 {
2109 zval *link, *result_entry;
2110 ldap_linkdata *ld;
2111 ldap_resultentry *resultentry;
2112 char *text;
2113
2114 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &link, &result_entry) != SUCCESS) {
2115 return;
2116 }
2117
2118 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2119 RETURN_FALSE;
2120 }
2121
2122 if ((resultentry = (ldap_resultentry *)zend_fetch_resource(Z_RES_P(result_entry), "ldap result entry", le_result_entry)) == NULL) {
2123 RETURN_FALSE;
2124 }
2125
2126 text = ldap_get_dn(ld->link, resultentry->data);
2127 if (text != NULL) {
2128 RETVAL_STRING(text);
2129 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
2130 ldap_memfree(text);
2131 #else
2132 free(text);
2133 #endif
2134 } else {
2135 RETURN_FALSE;
2136 }
2137 }
2138 /* }}} */
2139
2140 /* {{{ proto array ldap_explode_dn(string dn, int with_attrib)
2141 Splits DN into its component parts */
PHP_FUNCTION(ldap_explode_dn)2142 PHP_FUNCTION(ldap_explode_dn)
2143 {
2144 zend_long with_attrib;
2145 char *dn, **ldap_value;
2146 int i, count;
2147 size_t dn_len;
2148
2149 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &dn, &dn_len, &with_attrib) != SUCCESS) {
2150 return;
2151 }
2152
2153 if (!(ldap_value = ldap_explode_dn(dn, with_attrib))) {
2154 /* Invalid parameters were passed to ldap_explode_dn */
2155 RETURN_FALSE;
2156 }
2157
2158 i=0;
2159 while (ldap_value[i] != NULL) i++;
2160 count = i;
2161
2162 array_init(return_value);
2163
2164 add_assoc_long(return_value, "count", count);
2165 for (i = 0; i<count; i++) {
2166 add_index_string(return_value, i, ldap_value[i]);
2167 }
2168
2169 ldap_memvfree((void **)ldap_value);
2170 }
2171 /* }}} */
2172
2173 /* {{{ proto string ldap_dn2ufn(string dn)
2174 Convert DN to User Friendly Naming format */
PHP_FUNCTION(ldap_dn2ufn)2175 PHP_FUNCTION(ldap_dn2ufn)
2176 {
2177 char *dn, *ufn;
2178 size_t dn_len;
2179
2180 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &dn, &dn_len) != SUCCESS) {
2181 return;
2182 }
2183
2184 ufn = ldap_dn2ufn(dn);
2185
2186 if (ufn != NULL) {
2187 RETVAL_STRING(ufn);
2188 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP || WINDOWS
2189 ldap_memfree(ufn);
2190 #endif
2191 } else {
2192 RETURN_FALSE;
2193 }
2194 }
2195 /* }}} */
2196
2197
2198 /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */
2199 #define PHP_LD_FULL_ADD 0xff
2200 /* {{{ php_ldap_do_modify
2201 */
php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS,int oper,int ext)2202 static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext)
2203 {
2204 zval *serverctrls = NULL;
2205 zval *link, *entry, *value, *ivalue;
2206 ldap_linkdata *ld;
2207 char *dn;
2208 LDAPMod **ldap_mods;
2209 LDAPControl **lserverctrls = NULL;
2210 LDAPMessage *ldap_res;
2211 int i, j, num_attribs, num_values, msgid;
2212 size_t dn_len;
2213 int *num_berval;
2214 zend_string *attribute;
2215 zend_ulong index;
2216 int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */
2217
2218 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|a", &link, &dn, &dn_len, &entry, &serverctrls) != SUCCESS) {
2219 return;
2220 }
2221
2222 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2223 RETURN_FALSE;
2224 }
2225
2226 num_attribs = zend_hash_num_elements(Z_ARRVAL_P(entry));
2227 ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0);
2228 num_berval = safe_emalloc(num_attribs, sizeof(int), 0);
2229 zend_hash_internal_pointer_reset(Z_ARRVAL_P(entry));
2230
2231 /* added by gerrit thomson to fix ldap_add using ldap_mod_add */
2232 if (oper == PHP_LD_FULL_ADD) {
2233 oper = LDAP_MOD_ADD;
2234 is_full_add = 1;
2235 }
2236 /* end additional , gerrit thomson */
2237
2238 for (i = 0; i < num_attribs; i++) {
2239 ldap_mods[i] = emalloc(sizeof(LDAPMod));
2240 ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
2241 ldap_mods[i]->mod_type = NULL;
2242
2243 if (zend_hash_get_current_key(Z_ARRVAL_P(entry), &attribute, &index) == HASH_KEY_IS_STRING) {
2244 ldap_mods[i]->mod_type = estrndup(ZSTR_VAL(attribute), ZSTR_LEN(attribute));
2245 } else {
2246 php_error_docref(NULL, E_WARNING, "Unknown attribute in the data");
2247 /* Free allocated memory */
2248 while (i >= 0) {
2249 if (ldap_mods[i]->mod_type) {
2250 efree(ldap_mods[i]->mod_type);
2251 }
2252 efree(ldap_mods[i]);
2253 i--;
2254 }
2255 efree(num_berval);
2256 efree(ldap_mods);
2257 RETURN_FALSE;
2258 }
2259
2260 value = zend_hash_get_current_data(Z_ARRVAL_P(entry));
2261
2262 ZVAL_DEREF(value);
2263 if (Z_TYPE_P(value) != IS_ARRAY) {
2264 num_values = 1;
2265 } else {
2266 SEPARATE_ARRAY(value);
2267 num_values = zend_hash_num_elements(Z_ARRVAL_P(value));
2268 }
2269
2270 num_berval[i] = num_values;
2271 ldap_mods[i]->mod_bvalues = safe_emalloc((num_values + 1), sizeof(struct berval *), 0);
2272
2273 /* allow for arrays with one element, no allowance for arrays with none but probably not required, gerrit thomson. */
2274 if ((num_values == 1) && (Z_TYPE_P(value) != IS_ARRAY)) {
2275 convert_to_string(value);
2276 if (EG(exception)) {
2277 RETVAL_FALSE;
2278 goto cleanup;
2279 }
2280 ldap_mods[i]->mod_bvalues[0] = (struct berval *) emalloc (sizeof(struct berval));
2281 ldap_mods[i]->mod_bvalues[0]->bv_val = Z_STRVAL_P(value);
2282 ldap_mods[i]->mod_bvalues[0]->bv_len = Z_STRLEN_P(value);
2283 } else {
2284 for (j = 0; j < num_values; j++) {
2285 if ((ivalue = zend_hash_index_find(Z_ARRVAL_P(value), j)) == NULL) {
2286 php_error_docref(NULL, E_WARNING, "Value array must have consecutive indices 0, 1, ...");
2287 num_berval[i] = j;
2288 num_attribs = i + 1;
2289 RETVAL_FALSE;
2290 goto cleanup;
2291 }
2292 convert_to_string(ivalue);
2293 if (EG(exception)) {
2294 RETVAL_FALSE;
2295 goto cleanup;
2296 }
2297 ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval));
2298 ldap_mods[i]->mod_bvalues[j]->bv_val = Z_STRVAL_P(ivalue);
2299 ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_P(ivalue);
2300 }
2301 }
2302 ldap_mods[i]->mod_bvalues[num_values] = NULL;
2303 zend_hash_move_forward(Z_ARRVAL_P(entry));
2304 }
2305 ldap_mods[num_attribs] = NULL;
2306
2307 if (serverctrls) {
2308 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
2309 if (lserverctrls == NULL) {
2310 RETVAL_FALSE;
2311 goto cleanup;
2312 }
2313 }
2314
2315 /* check flag to see if do_mod was called to perform full add , gerrit thomson */
2316 if (is_full_add == 1) {
2317 if (ext) {
2318 i = ldap_add_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid);
2319 } else {
2320 i = ldap_add_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL);
2321 }
2322 if (i != LDAP_SUCCESS) {
2323 php_error_docref(NULL, E_WARNING, "Add: %s", ldap_err2string(i));
2324 RETVAL_FALSE;
2325 } else if (ext) {
2326 i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
2327 if (i == -1) {
2328 php_error_docref(NULL, E_WARNING, "Add operation failed");
2329 RETVAL_FALSE;
2330 goto cleanup;
2331 }
2332
2333 /* return a PHP control object */
2334 RETVAL_RES(zend_register_resource(ldap_res, le_result));
2335 } else RETVAL_TRUE;
2336 } else {
2337 if (ext) {
2338 i = ldap_modify_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid);
2339 } else {
2340 i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL);
2341 }
2342 if (i != LDAP_SUCCESS) {
2343 php_error_docref(NULL, E_WARNING, "Modify: %s", ldap_err2string(i));
2344 RETVAL_FALSE;
2345 } else if (ext) {
2346 i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
2347 if (i == -1) {
2348 php_error_docref(NULL, E_WARNING, "Modify operation failed");
2349 RETVAL_FALSE;
2350 goto cleanup;
2351 }
2352
2353 /* return a PHP control object */
2354 RETVAL_RES(zend_register_resource(ldap_res, le_result));
2355 } else RETVAL_TRUE;
2356 }
2357
2358 cleanup:
2359 for (i = 0; i < num_attribs; i++) {
2360 efree(ldap_mods[i]->mod_type);
2361 for (j = 0; j < num_berval[i]; j++) {
2362 efree(ldap_mods[i]->mod_bvalues[j]);
2363 }
2364 efree(ldap_mods[i]->mod_bvalues);
2365 efree(ldap_mods[i]);
2366 }
2367 efree(num_berval);
2368 efree(ldap_mods);
2369
2370 if (lserverctrls) {
2371 _php_ldap_controls_free(&lserverctrls);
2372 }
2373
2374 return;
2375 }
2376 /* }}} */
2377
2378 /* {{{ proto bool ldap_add(resource link, string dn, array entry [, array servercontrols])
2379 Add entries to LDAP directory */
PHP_FUNCTION(ldap_add)2380 PHP_FUNCTION(ldap_add)
2381 {
2382 /* 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 */
2383 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0);
2384 }
2385 /* }}} */
2386
2387 /* {{{ proto resource ldap_add_ext(resource link, string dn, array entry [, array servercontrols])
2388 Add entries to LDAP directory */
PHP_FUNCTION(ldap_add_ext)2389 PHP_FUNCTION(ldap_add_ext)
2390 {
2391 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 1);
2392 }
2393 /* }}} */
2394
2395 /* three functions for attribute base modifications, gerrit Thomson */
2396
2397 /* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry [, array servercontrols])
2398 Replace attribute values with new ones */
PHP_FUNCTION(ldap_mod_replace)2399 PHP_FUNCTION(ldap_mod_replace)
2400 {
2401 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 0);
2402 }
2403 /* }}} */
2404
2405 /* {{{ proto resource ldap_mod_replace_ext(resource link, string dn, array entry [, array servercontrols])
2406 Replace attribute values with new ones */
PHP_FUNCTION(ldap_mod_replace_ext)2407 PHP_FUNCTION(ldap_mod_replace_ext)
2408 {
2409 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 1);
2410 }
2411 /* }}} */
2412
2413 /* {{{ proto bool ldap_mod_add(resource link, string dn, array entry [, array servercontrols])
2414 Add attribute values to current */
PHP_FUNCTION(ldap_mod_add)2415 PHP_FUNCTION(ldap_mod_add)
2416 {
2417 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 0);
2418 }
2419 /* }}} */
2420
2421 /* {{{ proto resource ldap_mod_add(resource link, string dn, array entry [, array servercontrols])
2422 Add attribute values to current */
PHP_FUNCTION(ldap_mod_add_ext)2423 PHP_FUNCTION(ldap_mod_add_ext)
2424 {
2425 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1);
2426 }
2427 /* }}} */
2428
2429 /* {{{ proto bool ldap_mod_del(resource link, string dn, array entry [, array servercontrols])
2430 Delete attribute values */
PHP_FUNCTION(ldap_mod_del)2431 PHP_FUNCTION(ldap_mod_del)
2432 {
2433 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 0);
2434 }
2435 /* }}} */
2436
2437 /* {{{ proto resource ldap_mod_del_ext(resource link, string dn, array entry [, array servercontrols])
2438 Delete attribute values */
PHP_FUNCTION(ldap_mod_del_ext)2439 PHP_FUNCTION(ldap_mod_del_ext)
2440 {
2441 php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1);
2442 }
2443 /* }}} */
2444
2445 /* {{{ php_ldap_do_delete
2446 */
php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS,int ext)2447 static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext)
2448 {
2449 zval *serverctrls = NULL;
2450 zval *link;
2451 ldap_linkdata *ld;
2452 LDAPControl **lserverctrls = NULL;
2453 LDAPMessage *ldap_res;
2454 char *dn;
2455 int rc, msgid;
2456 size_t dn_len;
2457
2458 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|a", &link, &dn, &dn_len, &serverctrls) != SUCCESS) {
2459 return;
2460 }
2461
2462 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2463 RETURN_FALSE;
2464 }
2465
2466 if (serverctrls) {
2467 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
2468 if (lserverctrls == NULL) {
2469 RETVAL_FALSE;
2470 goto cleanup;
2471 }
2472 }
2473
2474 if (ext) {
2475 rc = ldap_delete_ext(ld->link, dn, lserverctrls, NULL, &msgid);
2476 } else {
2477 rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, NULL);
2478 }
2479 if (rc != LDAP_SUCCESS) {
2480 php_error_docref(NULL, E_WARNING, "Delete: %s", ldap_err2string(rc));
2481 RETVAL_FALSE;
2482 goto cleanup;
2483 } else if (ext) {
2484 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
2485 if (rc == -1) {
2486 php_error_docref(NULL, E_WARNING, "Delete operation failed");
2487 RETVAL_FALSE;
2488 goto cleanup;
2489 }
2490
2491 /* return a PHP control object */
2492 RETVAL_RES(zend_register_resource(ldap_res, le_result));
2493 } else {
2494 RETVAL_TRUE;
2495 }
2496
2497 cleanup:
2498 if (lserverctrls) {
2499 _php_ldap_controls_free(&lserverctrls);
2500 }
2501
2502 return;
2503 }
2504 /* }}} */
2505
2506 /* {{{ proto bool ldap_delete(resource link, string dn [, array servercontrols])
2507 Delete an entry from a directory */
PHP_FUNCTION(ldap_delete)2508 PHP_FUNCTION(ldap_delete)
2509 {
2510 php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2511 }
2512 /* }}} */
2513
2514 /* {{{ proto resource ldap_delete_ext(resource link, string dn [, array servercontrols])
2515 Delete an entry from a directory */
PHP_FUNCTION(ldap_delete_ext)2516 PHP_FUNCTION(ldap_delete_ext)
2517 {
2518 php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2519 }
2520 /* }}} */
2521
2522 /* {{{ _ldap_str_equal_to_const
2523 */
_ldap_str_equal_to_const(const char * str,size_t str_len,const char * cstr)2524 static size_t _ldap_str_equal_to_const(const char *str, size_t str_len, const char *cstr)
2525 {
2526 size_t i;
2527
2528 if (strlen(cstr) != str_len)
2529 return 0;
2530
2531 for (i = 0; i < str_len; ++i) {
2532 if (str[i] != cstr[i]) {
2533 return 0;
2534 }
2535 }
2536
2537 return 1;
2538 }
2539 /* }}} */
2540
2541 /* {{{ _ldap_strlen_max
2542 */
_ldap_strlen_max(const char * str,size_t max_len)2543 static size_t _ldap_strlen_max(const char *str, size_t max_len)
2544 {
2545 size_t i;
2546
2547 for (i = 0; i < max_len; ++i) {
2548 if (str[i] == '\0') {
2549 return i;
2550 }
2551 }
2552
2553 return max_len;
2554 }
2555 /* }}} */
2556
2557 /* {{{ _ldap_hash_fetch
2558 */
_ldap_hash_fetch(zval * hashTbl,const char * key,zval ** out)2559 static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out)
2560 {
2561 *out = zend_hash_str_find(Z_ARRVAL_P(hashTbl), key, strlen(key));
2562 }
2563 /* }}} */
2564
2565 /* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs [, array servercontrols])
2566 Perform multiple modifications as part of one operation */
PHP_FUNCTION(ldap_modify_batch)2567 PHP_FUNCTION(ldap_modify_batch)
2568 {
2569 zval *serverctrls = NULL;
2570 ldap_linkdata *ld;
2571 zval *link, *mods, *mod, *modinfo;
2572 zend_string *modval;
2573 zval *attrib, *modtype, *vals;
2574 zval *fetched;
2575 char *dn;
2576 size_t dn_len;
2577 int i, j, k;
2578 int num_mods, num_modprops, num_modvals;
2579 LDAPMod **ldap_mods;
2580 LDAPControl **lserverctrls = NULL;
2581 uint32_t oper;
2582
2583 /*
2584 $mods = array(
2585 array(
2586 "attrib" => "unicodePwd",
2587 "modtype" => LDAP_MODIFY_BATCH_REMOVE,
2588 "values" => array($oldpw)
2589 ),
2590 array(
2591 "attrib" => "unicodePwd",
2592 "modtype" => LDAP_MODIFY_BATCH_ADD,
2593 "values" => array($newpw)
2594 ),
2595 array(
2596 "attrib" => "userPrincipalName",
2597 "modtype" => LDAP_MODIFY_BATCH_REPLACE,
2598 "values" => array("janitor@corp.contoso.com")
2599 ),
2600 array(
2601 "attrib" => "userCert",
2602 "modtype" => LDAP_MODIFY_BATCH_REMOVE_ALL
2603 )
2604 );
2605 */
2606
2607 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|a", &link, &dn, &dn_len, &mods, &serverctrls) != SUCCESS) {
2608 return;
2609 }
2610
2611 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2612 RETURN_FALSE;
2613 }
2614
2615 /* perform validation */
2616 {
2617 zend_string *modkey;
2618 zend_long modtype;
2619
2620 /* to store the wrongly-typed keys */
2621 zend_ulong tmpUlong;
2622
2623 /* make sure the DN contains no NUL bytes */
2624 if (_ldap_strlen_max(dn, dn_len) != dn_len) {
2625 php_error_docref(NULL, E_WARNING, "DN must not contain NUL bytes");
2626 RETURN_FALSE;
2627 }
2628
2629 /* make sure the top level is a normal array */
2630 zend_hash_internal_pointer_reset(Z_ARRVAL_P(mods));
2631 if (zend_hash_get_current_key_type(Z_ARRVAL_P(mods)) != HASH_KEY_IS_LONG) {
2632 php_error_docref(NULL, E_WARNING, "Modifications array must not be string-indexed");
2633 RETURN_FALSE;
2634 }
2635
2636 num_mods = zend_hash_num_elements(Z_ARRVAL_P(mods));
2637
2638 for (i = 0; i < num_mods; i++) {
2639 /* is the numbering consecutive? */
2640 if ((fetched = zend_hash_index_find(Z_ARRVAL_P(mods), i)) == NULL) {
2641 php_error_docref(NULL, E_WARNING, "Modifications array must have consecutive indices 0, 1, ...");
2642 RETURN_FALSE;
2643 }
2644 mod = fetched;
2645
2646 /* is it an array? */
2647 if (Z_TYPE_P(mod) != IS_ARRAY) {
2648 php_error_docref(NULL, E_WARNING, "Each entry of modifications array must be an array itself");
2649 RETURN_FALSE;
2650 }
2651
2652 SEPARATE_ARRAY(mod);
2653 /* for the modification hashtable... */
2654 zend_hash_internal_pointer_reset(Z_ARRVAL_P(mod));
2655 num_modprops = zend_hash_num_elements(Z_ARRVAL_P(mod));
2656
2657 for (j = 0; j < num_modprops; j++) {
2658 /* are the keys strings? */
2659 if (zend_hash_get_current_key(Z_ARRVAL_P(mod), &modkey, &tmpUlong) != HASH_KEY_IS_STRING) {
2660 php_error_docref(NULL, E_WARNING, "Each entry of modifications array must be string-indexed");
2661 RETURN_FALSE;
2662 }
2663
2664 /* is this a valid entry? */
2665 if (
2666 !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_ATTRIB) &&
2667 !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_MODTYPE) &&
2668 !_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_VALUES)
2669 ) {
2670 php_error_docref(NULL, E_WARNING, "The only allowed keys in entries of the modifications array are '" LDAP_MODIFY_BATCH_ATTRIB "', '" LDAP_MODIFY_BATCH_MODTYPE "' and '" LDAP_MODIFY_BATCH_VALUES "'");
2671 RETURN_FALSE;
2672 }
2673
2674 fetched = zend_hash_get_current_data(Z_ARRVAL_P(mod));
2675 modinfo = fetched;
2676
2677 /* does the value type match the key? */
2678 if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_ATTRIB)) {
2679 if (Z_TYPE_P(modinfo) != IS_STRING) {
2680 php_error_docref(NULL, E_WARNING, "A '" LDAP_MODIFY_BATCH_ATTRIB "' value must be a string");
2681 RETURN_FALSE;
2682 }
2683
2684 if (Z_STRLEN_P(modinfo) != _ldap_strlen_max(Z_STRVAL_P(modinfo), Z_STRLEN_P(modinfo))) {
2685 php_error_docref(NULL, E_WARNING, "A '" LDAP_MODIFY_BATCH_ATTRIB "' value must not contain NUL bytes");
2686 RETURN_FALSE;
2687 }
2688 }
2689 else if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_MODTYPE)) {
2690 if (Z_TYPE_P(modinfo) != IS_LONG) {
2691 php_error_docref(NULL, E_WARNING, "A '" LDAP_MODIFY_BATCH_MODTYPE "' value must be a long");
2692 RETURN_FALSE;
2693 }
2694
2695 /* is the value in range? */
2696 modtype = Z_LVAL_P(modinfo);
2697 if (
2698 modtype != LDAP_MODIFY_BATCH_ADD &&
2699 modtype != LDAP_MODIFY_BATCH_REMOVE &&
2700 modtype != LDAP_MODIFY_BATCH_REPLACE &&
2701 modtype != LDAP_MODIFY_BATCH_REMOVE_ALL
2702 ) {
2703 php_error_docref(NULL, E_WARNING, "The '" LDAP_MODIFY_BATCH_MODTYPE "' value must match one of the LDAP_MODIFY_BATCH_* constants");
2704 RETURN_FALSE;
2705 }
2706
2707 /* if it's REMOVE_ALL, there must not be a values array; otherwise, there must */
2708 if (modtype == LDAP_MODIFY_BATCH_REMOVE_ALL) {
2709 if (zend_hash_str_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES))) {
2710 php_error_docref(NULL, E_WARNING, "If '" LDAP_MODIFY_BATCH_MODTYPE "' is LDAP_MODIFY_BATCH_REMOVE_ALL, a '" LDAP_MODIFY_BATCH_VALUES "' array must not be provided");
2711 RETURN_FALSE;
2712 }
2713 }
2714 else {
2715 if (!zend_hash_str_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES))) {
2716 php_error_docref(NULL, E_WARNING, "If '" LDAP_MODIFY_BATCH_MODTYPE "' is not LDAP_MODIFY_BATCH_REMOVE_ALL, a '" LDAP_MODIFY_BATCH_VALUES "' array must be provided");
2717 RETURN_FALSE;
2718 }
2719 }
2720 }
2721 else if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_VALUES)) {
2722 if (Z_TYPE_P(modinfo) != IS_ARRAY) {
2723 php_error_docref(NULL, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' value must be an array");
2724 RETURN_FALSE;
2725 }
2726
2727 SEPARATE_ARRAY(modinfo);
2728 /* is the array not empty? */
2729 zend_hash_internal_pointer_reset(Z_ARRVAL_P(modinfo));
2730 num_modvals = zend_hash_num_elements(Z_ARRVAL_P(modinfo));
2731 if (num_modvals == 0) {
2732 php_error_docref(NULL, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must have at least one element");
2733 RETURN_FALSE;
2734 }
2735
2736 /* are its keys integers? */
2737 if (zend_hash_get_current_key_type(Z_ARRVAL_P(modinfo)) != HASH_KEY_IS_LONG) {
2738 php_error_docref(NULL, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must not be string-indexed");
2739 RETURN_FALSE;
2740 }
2741
2742 /* are the keys consecutive? */
2743 for (k = 0; k < num_modvals; k++) {
2744 if ((fetched = zend_hash_index_find(Z_ARRVAL_P(modinfo), k)) == NULL) {
2745 php_error_docref(NULL, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must have consecutive indices 0, 1, ...");
2746 RETURN_FALSE;
2747 }
2748 }
2749 }
2750
2751 zend_hash_move_forward(Z_ARRVAL_P(mod));
2752 }
2753 }
2754 }
2755 /* validation was successful */
2756
2757 /* allocate array of modifications */
2758 ldap_mods = safe_emalloc((num_mods+1), sizeof(LDAPMod *), 0);
2759
2760 /* for each modification */
2761 for (i = 0; i < num_mods; i++) {
2762 /* allocate the modification struct */
2763 ldap_mods[i] = safe_emalloc(1, sizeof(LDAPMod), 0);
2764
2765 /* fetch the relevant data */
2766 fetched = zend_hash_index_find(Z_ARRVAL_P(mods), i);
2767 mod = fetched;
2768
2769 _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_ATTRIB, &attrib);
2770 _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_MODTYPE, &modtype);
2771 _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_VALUES, &vals);
2772
2773 /* map the modification type */
2774 switch (Z_LVAL_P(modtype)) {
2775 case LDAP_MODIFY_BATCH_ADD:
2776 oper = LDAP_MOD_ADD;
2777 break;
2778 case LDAP_MODIFY_BATCH_REMOVE:
2779 case LDAP_MODIFY_BATCH_REMOVE_ALL:
2780 oper = LDAP_MOD_DELETE;
2781 break;
2782 case LDAP_MODIFY_BATCH_REPLACE:
2783 oper = LDAP_MOD_REPLACE;
2784 break;
2785 default:
2786 zend_throw_error(NULL, "Unknown and uncaught modification type.");
2787 RETVAL_FALSE;
2788 efree(ldap_mods[i]);
2789 num_mods = i;
2790 goto cleanup;
2791 }
2792
2793 /* fill in the basic info */
2794 ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
2795 ldap_mods[i]->mod_type = estrndup(Z_STRVAL_P(attrib), Z_STRLEN_P(attrib));
2796
2797 if (Z_LVAL_P(modtype) == LDAP_MODIFY_BATCH_REMOVE_ALL) {
2798 /* no values */
2799 ldap_mods[i]->mod_bvalues = NULL;
2800 }
2801 else {
2802 /* allocate space for the values as part of this modification */
2803 num_modvals = zend_hash_num_elements(Z_ARRVAL_P(vals));
2804 ldap_mods[i]->mod_bvalues = safe_emalloc((num_modvals+1), sizeof(struct berval *), 0);
2805
2806 /* for each value */
2807 for (j = 0; j < num_modvals; j++) {
2808 /* fetch it */
2809 fetched = zend_hash_index_find(Z_ARRVAL_P(vals), j);
2810 modval = zval_get_string(fetched);
2811 if (EG(exception)) {
2812 RETVAL_FALSE;
2813 ldap_mods[i]->mod_bvalues[j] = NULL;
2814 num_mods = i + 1;
2815 goto cleanup;
2816 }
2817
2818 /* allocate the data struct */
2819 ldap_mods[i]->mod_bvalues[j] = safe_emalloc(1, sizeof(struct berval), 0);
2820
2821 /* fill it */
2822 ldap_mods[i]->mod_bvalues[j]->bv_len = ZSTR_LEN(modval);
2823 ldap_mods[i]->mod_bvalues[j]->bv_val = estrndup(ZSTR_VAL(modval), ZSTR_LEN(modval));
2824 zend_string_release(modval);
2825 }
2826
2827 /* NULL-terminate values */
2828 ldap_mods[i]->mod_bvalues[num_modvals] = NULL;
2829 }
2830 }
2831
2832 /* NULL-terminate modifications */
2833 ldap_mods[num_mods] = NULL;
2834
2835 if (serverctrls) {
2836 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
2837 if (lserverctrls == NULL) {
2838 RETVAL_FALSE;
2839 goto cleanup;
2840 }
2841 }
2842
2843 /* perform (finally) */
2844 if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) {
2845 php_error_docref(NULL, E_WARNING, "Batch Modify: %s", ldap_err2string(i));
2846 RETVAL_FALSE;
2847 } else RETVAL_TRUE;
2848
2849 /* clean up */
2850 cleanup: {
2851 for (i = 0; i < num_mods; i++) {
2852 /* attribute */
2853 efree(ldap_mods[i]->mod_type);
2854
2855 if (ldap_mods[i]->mod_bvalues != NULL) {
2856 /* each BER value */
2857 for (j = 0; ldap_mods[i]->mod_bvalues[j] != NULL; j++) {
2858 /* free the data bytes */
2859 efree(ldap_mods[i]->mod_bvalues[j]->bv_val);
2860
2861 /* free the bvalue struct */
2862 efree(ldap_mods[i]->mod_bvalues[j]);
2863 }
2864
2865 /* the BER value array */
2866 efree(ldap_mods[i]->mod_bvalues);
2867 }
2868
2869 /* the modification */
2870 efree(ldap_mods[i]);
2871 }
2872
2873 /* the modifications array */
2874 efree(ldap_mods);
2875
2876 if (lserverctrls) {
2877 _php_ldap_controls_free(&lserverctrls);
2878 }
2879 }
2880 }
2881 /* }}} */
2882
2883 /* {{{ proto int ldap_errno(resource link)
2884 Get the current ldap error number */
PHP_FUNCTION(ldap_errno)2885 PHP_FUNCTION(ldap_errno)
2886 {
2887 zval *link;
2888 ldap_linkdata *ld;
2889
2890 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &link) != SUCCESS) {
2891 return;
2892 }
2893
2894 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2895 RETURN_FALSE;
2896 }
2897
2898 RETURN_LONG(_get_lderrno(ld->link));
2899 }
2900 /* }}} */
2901
2902 /* {{{ proto string ldap_err2str(int errno)
2903 Convert error number to error string */
PHP_FUNCTION(ldap_err2str)2904 PHP_FUNCTION(ldap_err2str)
2905 {
2906 zend_long perrno;
2907
2908 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &perrno) != SUCCESS) {
2909 return;
2910 }
2911
2912 RETURN_STRING(ldap_err2string(perrno));
2913 }
2914 /* }}} */
2915
2916 /* {{{ proto string ldap_error(resource link)
2917 Get the current ldap error string */
PHP_FUNCTION(ldap_error)2918 PHP_FUNCTION(ldap_error)
2919 {
2920 zval *link;
2921 ldap_linkdata *ld;
2922 int ld_errno;
2923
2924 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &link) != SUCCESS) {
2925 return;
2926 }
2927
2928 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2929 RETURN_FALSE;
2930 }
2931
2932 ld_errno = _get_lderrno(ld->link);
2933
2934 RETURN_STRING(ldap_err2string(ld_errno));
2935 }
2936 /* }}} */
2937
2938 /* {{{ proto bool ldap_compare(resource link, string dn, string attr, string value)
2939 Determine if an entry has a specific value for one of its attributes */
PHP_FUNCTION(ldap_compare)2940 PHP_FUNCTION(ldap_compare)
2941 {
2942 zval *serverctrls = NULL;
2943 zval *link;
2944 char *dn, *attr, *value;
2945 size_t dn_len, attr_len, value_len;
2946 ldap_linkdata *ld;
2947 LDAPControl **lserverctrls = NULL;
2948 int errno;
2949 struct berval lvalue;
2950
2951 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsss|a", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &serverctrls) != SUCCESS) {
2952 return;
2953 }
2954
2955 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
2956 RETURN_FALSE;
2957 }
2958
2959 if (serverctrls) {
2960 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
2961 if (lserverctrls == NULL) {
2962 RETVAL_FALSE;
2963 goto cleanup;
2964 }
2965 }
2966
2967 lvalue.bv_val = value;
2968 lvalue.bv_len = value_len;
2969
2970 errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, lserverctrls, NULL);
2971
2972 switch (errno) {
2973 case LDAP_COMPARE_TRUE:
2974 RETVAL_TRUE;
2975 break;
2976
2977 case LDAP_COMPARE_FALSE:
2978 RETVAL_FALSE;
2979 break;
2980
2981 default:
2982 php_error_docref(NULL, E_WARNING, "Compare: %s", ldap_err2string(errno));
2983 RETVAL_LONG(-1);
2984 }
2985
2986 cleanup:
2987 if (lserverctrls) {
2988 _php_ldap_controls_free(&lserverctrls);
2989 }
2990
2991 return;
2992 }
2993 /* }}} */
2994
2995 /* {{{ proto bool ldap_sort(resource link, resource result, string sortfilter)
2996 Sort LDAP result entries */
PHP_FUNCTION(ldap_sort)2997 PHP_FUNCTION(ldap_sort)
2998 {
2999 zval *link, *result;
3000 ldap_linkdata *ld;
3001 char *sortfilter;
3002 size_t sflen;
3003 zend_resource *le;
3004
3005 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrs", &link, &result, &sortfilter, &sflen) != SUCCESS) {
3006 RETURN_FALSE;
3007 }
3008
3009 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3010 RETURN_FALSE;
3011 }
3012
3013 le = Z_RES_P(result);
3014 if (le->type != le_result) {
3015 php_error_docref(NULL, E_WARNING, "Supplied resource is not a valid ldap result resource");
3016 RETURN_FALSE;
3017 }
3018
3019 if (ldap_sort_entries(ld->link, (LDAPMessage **) &le->ptr, sflen ? sortfilter : NULL, strcmp) != LDAP_SUCCESS) {
3020 php_error_docref(NULL, E_WARNING, "%s", ldap_err2string(errno));
3021 RETURN_FALSE;
3022 }
3023
3024 RETURN_TRUE;
3025 }
3026 /* }}} */
3027
3028 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP
3029 /* {{{ proto bool ldap_get_option(resource link, int option, mixed retval)
3030 Get the current value of various session-wide parameters */
PHP_FUNCTION(ldap_get_option)3031 PHP_FUNCTION(ldap_get_option)
3032 {
3033 zval *link, *retval;
3034 ldap_linkdata *ld;
3035 zend_long option;
3036
3037 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &link, &option, &retval) != SUCCESS) {
3038 return;
3039 }
3040
3041 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3042 RETURN_FALSE;
3043 }
3044
3045 switch (option) {
3046 /* options with int value */
3047 case LDAP_OPT_DEREF:
3048 case LDAP_OPT_SIZELIMIT:
3049 case LDAP_OPT_TIMELIMIT:
3050 case LDAP_OPT_PROTOCOL_VERSION:
3051 case LDAP_OPT_ERROR_NUMBER:
3052 case LDAP_OPT_REFERRALS:
3053 #ifdef LDAP_OPT_RESTART
3054 case LDAP_OPT_RESTART:
3055 #endif
3056 #ifdef LDAP_OPT_X_SASL_NOCANON
3057 case LDAP_OPT_X_SASL_NOCANON:
3058 #endif
3059 #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
3060 case LDAP_OPT_X_TLS_REQUIRE_CERT:
3061 #endif
3062 #ifdef LDAP_OPT_X_TLS_CRLCHECK
3063 case LDAP_OPT_X_TLS_CRLCHECK:
3064 #endif
3065 #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
3066 case LDAP_OPT_X_TLS_PROTOCOL_MIN:
3067 #endif
3068 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
3069 case LDAP_OPT_X_KEEPALIVE_IDLE:
3070 case LDAP_OPT_X_KEEPALIVE_PROBES:
3071 case LDAP_OPT_X_KEEPALIVE_INTERVAL:
3072 #endif
3073 {
3074 int val;
3075
3076 if (ldap_get_option(ld->link, option, &val)) {
3077 RETURN_FALSE;
3078 }
3079 ZEND_TRY_ASSIGN_REF_LONG(retval, val);
3080 } break;
3081 #ifdef LDAP_OPT_NETWORK_TIMEOUT
3082 case LDAP_OPT_NETWORK_TIMEOUT:
3083 {
3084 struct timeval *timeout = NULL;
3085
3086 if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
3087 if (timeout) {
3088 ldap_memfree(timeout);
3089 }
3090 RETURN_FALSE;
3091 }
3092 if (!timeout) {
3093 RETURN_FALSE;
3094 }
3095 ZEND_TRY_ASSIGN_REF_LONG(retval, timeout->tv_sec);
3096 ldap_memfree(timeout);
3097 } break;
3098 #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
3099 case LDAP_X_OPT_CONNECT_TIMEOUT:
3100 {
3101 int timeout;
3102
3103 if (ldap_get_option(ld->link, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
3104 RETURN_FALSE;
3105 }
3106 ZEND_TRY_ASSIGN_REF_LONG(retval, (timeout / 1000));
3107 } break;
3108 #endif
3109 #ifdef LDAP_OPT_TIMEOUT
3110 case LDAP_OPT_TIMEOUT:
3111 {
3112 struct timeval *timeout = NULL;
3113
3114 if (ldap_get_option(ld->link, LDAP_OPT_TIMEOUT, (void *) &timeout)) {
3115 if (timeout) {
3116 ldap_memfree(timeout);
3117 }
3118 RETURN_FALSE;
3119 }
3120 if (!timeout) {
3121 RETURN_FALSE;
3122 }
3123 ZEND_TRY_ASSIGN_REF_LONG(retval, timeout->tv_sec);
3124 ldap_memfree(timeout);
3125 } break;
3126 #endif
3127 /* options with string value */
3128 case LDAP_OPT_ERROR_STRING:
3129 #ifdef LDAP_OPT_HOST_NAME
3130 case LDAP_OPT_HOST_NAME:
3131 #endif
3132 #ifdef HAVE_LDAP_SASL
3133 case LDAP_OPT_X_SASL_MECH:
3134 case LDAP_OPT_X_SASL_REALM:
3135 case LDAP_OPT_X_SASL_AUTHCID:
3136 case LDAP_OPT_X_SASL_AUTHZID:
3137 #endif
3138 #ifdef LDAP_OPT_X_SASL_USERNAME
3139 case LDAP_OPT_X_SASL_USERNAME:
3140 #endif
3141 #if (LDAP_API_VERSION > 2000)
3142 case LDAP_OPT_X_TLS_CACERTDIR:
3143 case LDAP_OPT_X_TLS_CACERTFILE:
3144 case LDAP_OPT_X_TLS_CERTFILE:
3145 case LDAP_OPT_X_TLS_CIPHER_SUITE:
3146 case LDAP_OPT_X_TLS_KEYFILE:
3147 case LDAP_OPT_X_TLS_RANDOM_FILE:
3148 #endif
3149 #ifdef LDAP_OPT_X_TLS_PACKAGE
3150 case LDAP_OPT_X_TLS_PACKAGE:
3151 #endif
3152 #ifdef LDAP_OPT_X_TLS_CRLFILE
3153 case LDAP_OPT_X_TLS_CRLFILE:
3154 #endif
3155 #ifdef LDAP_OPT_X_TLS_DHFILE
3156 case LDAP_OPT_X_TLS_DHFILE:
3157 #endif
3158 #ifdef LDAP_OPT_MATCHED_DN
3159 case LDAP_OPT_MATCHED_DN:
3160 #endif
3161 {
3162 char *val = NULL;
3163
3164 if (ldap_get_option(ld->link, option, &val) || val == NULL || *val == '\0') {
3165 if (val) {
3166 ldap_memfree(val);
3167 }
3168 RETURN_FALSE;
3169 }
3170 ZEND_TRY_ASSIGN_REF_STRING(retval, val);
3171 ldap_memfree(val);
3172 } break;
3173 case LDAP_OPT_SERVER_CONTROLS:
3174 case LDAP_OPT_CLIENT_CONTROLS:
3175 {
3176 LDAPControl **ctrls = NULL;
3177
3178 if (ldap_get_option(ld->link, option, &ctrls) || ctrls == NULL) {
3179 if (ctrls) {
3180 ldap_memfree(ctrls);
3181 }
3182 RETURN_FALSE;
3183 }
3184 _php_ldap_controls_to_array(ld->link, ctrls, retval, 1);
3185 } break;
3186 /* options not implemented
3187 case LDAP_OPT_API_INFO:
3188 case LDAP_OPT_API_FEATURE_INFO:
3189 */
3190 default:
3191 RETURN_FALSE;
3192 }
3193 RETURN_TRUE;
3194 }
3195 /* }}} */
3196
3197 /* {{{ proto bool ldap_set_option(resource link, int option, mixed newval)
3198 Set the value of various session-wide parameters */
PHP_FUNCTION(ldap_set_option)3199 PHP_FUNCTION(ldap_set_option)
3200 {
3201 zval *link, *newval;
3202 ldap_linkdata *ld;
3203 LDAP *ldap;
3204 zend_long option;
3205
3206 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zlz", &link, &option, &newval) != SUCCESS) {
3207 return;
3208 }
3209
3210 if (Z_TYPE_P(link) == IS_NULL) {
3211 ldap = NULL;
3212 } else {
3213 if ((ld = (ldap_linkdata *)zend_fetch_resource_ex(link, "ldap link", le_link)) == NULL) {
3214 RETURN_FALSE;
3215 }
3216 ldap = ld->link;
3217 }
3218
3219 switch (option) {
3220 /* options with int value */
3221 case LDAP_OPT_DEREF:
3222 case LDAP_OPT_SIZELIMIT:
3223 case LDAP_OPT_TIMELIMIT:
3224 case LDAP_OPT_PROTOCOL_VERSION:
3225 case LDAP_OPT_ERROR_NUMBER:
3226 #ifdef LDAP_OPT_DEBUG_LEVEL
3227 case LDAP_OPT_DEBUG_LEVEL:
3228 #endif
3229 #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
3230 case LDAP_OPT_X_TLS_REQUIRE_CERT:
3231 #endif
3232 #ifdef LDAP_OPT_X_TLS_CRLCHECK
3233 case LDAP_OPT_X_TLS_CRLCHECK:
3234 #endif
3235 #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
3236 case LDAP_OPT_X_TLS_PROTOCOL_MIN:
3237 #endif
3238 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
3239 case LDAP_OPT_X_KEEPALIVE_IDLE:
3240 case LDAP_OPT_X_KEEPALIVE_PROBES:
3241 case LDAP_OPT_X_KEEPALIVE_INTERVAL:
3242 #endif
3243 {
3244 int val;
3245
3246 convert_to_long_ex(newval);
3247 if (ZEND_LONG_EXCEEDS_INT(Z_LVAL_P(newval))) {
3248 php_error_docref(NULL, E_WARNING, "Option value is too big");
3249 RETURN_FALSE;
3250 }
3251 val = (int)Z_LVAL_P(newval);
3252 if (ldap_set_option(ldap, option, &val)) {
3253 RETURN_FALSE;
3254 }
3255 } break;
3256 #ifdef LDAP_OPT_NETWORK_TIMEOUT
3257 case LDAP_OPT_NETWORK_TIMEOUT:
3258 {
3259 struct timeval timeout;
3260
3261 convert_to_long_ex(newval);
3262 timeout.tv_sec = Z_LVAL_P(newval);
3263 timeout.tv_usec = 0;
3264 if (ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
3265 RETURN_FALSE;
3266 }
3267 } break;
3268 #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
3269 case LDAP_X_OPT_CONNECT_TIMEOUT:
3270 {
3271 int timeout;
3272
3273 convert_to_long_ex(newval);
3274 timeout = 1000 * Z_LVAL_P(newval); /* Convert to milliseconds */
3275 if (ldap_set_option(ldap, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
3276 RETURN_FALSE;
3277 }
3278 } break;
3279 #endif
3280 #ifdef LDAP_OPT_TIMEOUT
3281 case LDAP_OPT_TIMEOUT:
3282 {
3283 struct timeval timeout;
3284
3285 convert_to_long_ex(newval);
3286 timeout.tv_sec = Z_LVAL_P(newval);
3287 timeout.tv_usec = 0;
3288 if (ldap_set_option(ldap, LDAP_OPT_TIMEOUT, (void *) &timeout)) {
3289 RETURN_FALSE;
3290 }
3291 } break;
3292 #endif
3293 /* options with string value */
3294 case LDAP_OPT_ERROR_STRING:
3295 #ifdef LDAP_OPT_HOST_NAME
3296 case LDAP_OPT_HOST_NAME:
3297 #endif
3298 #ifdef HAVE_LDAP_SASL
3299 case LDAP_OPT_X_SASL_MECH:
3300 case LDAP_OPT_X_SASL_REALM:
3301 case LDAP_OPT_X_SASL_AUTHCID:
3302 case LDAP_OPT_X_SASL_AUTHZID:
3303 #endif
3304 #if (LDAP_API_VERSION > 2000)
3305 case LDAP_OPT_X_TLS_CACERTDIR:
3306 case LDAP_OPT_X_TLS_CACERTFILE:
3307 case LDAP_OPT_X_TLS_CERTFILE:
3308 case LDAP_OPT_X_TLS_CIPHER_SUITE:
3309 case LDAP_OPT_X_TLS_KEYFILE:
3310 case LDAP_OPT_X_TLS_RANDOM_FILE:
3311 #endif
3312 #ifdef LDAP_OPT_X_TLS_CRLFILE
3313 case LDAP_OPT_X_TLS_CRLFILE:
3314 #endif
3315 #ifdef LDAP_OPT_X_TLS_DHFILE
3316 case LDAP_OPT_X_TLS_DHFILE:
3317 #endif
3318 #ifdef LDAP_OPT_MATCHED_DN
3319 case LDAP_OPT_MATCHED_DN:
3320 #endif
3321 {
3322 zend_string *val;
3323 val = zval_get_string(newval);
3324 if (EG(exception)) {
3325 RETURN_FALSE;
3326 }
3327 if (ldap_set_option(ldap, option, ZSTR_VAL(val))) {
3328 zend_string_release(val);
3329 RETURN_FALSE;
3330 }
3331 zend_string_release(val);
3332 } break;
3333 /* options with boolean value */
3334 case LDAP_OPT_REFERRALS:
3335 #ifdef LDAP_OPT_RESTART
3336 case LDAP_OPT_RESTART:
3337 #endif
3338 #ifdef LDAP_OPT_X_SASL_NOCANON
3339 case LDAP_OPT_X_SASL_NOCANON:
3340 #endif
3341 {
3342 void *val;
3343 val = zend_is_true(newval) ? LDAP_OPT_ON : LDAP_OPT_OFF;
3344 if (ldap_set_option(ldap, option, val)) {
3345 RETURN_FALSE;
3346 }
3347 } break;
3348 /* options with control list value */
3349 case LDAP_OPT_SERVER_CONTROLS:
3350 case LDAP_OPT_CLIENT_CONTROLS:
3351 {
3352 LDAPControl **ctrls;
3353 int rc;
3354
3355 if (Z_TYPE_P(newval) != IS_ARRAY) {
3356 php_error_docref(NULL, E_WARNING, "Expected array value for this option");
3357 RETURN_FALSE;
3358 }
3359
3360 ctrls = _php_ldap_controls_from_array(ldap, newval);
3361
3362 if (ctrls == NULL) {
3363 RETURN_FALSE;
3364 } else {
3365 rc = ldap_set_option(ldap, option, ctrls);
3366 _php_ldap_controls_free(&ctrls);
3367 if (rc != LDAP_SUCCESS) {
3368 RETURN_FALSE;
3369 }
3370 }
3371 } break;
3372 default:
3373 RETURN_FALSE;
3374 }
3375 RETURN_TRUE;
3376 }
3377 /* }}} */
3378
3379 #ifdef HAVE_LDAP_PARSE_RESULT
3380 /* {{{ proto bool ldap_parse_result(resource link, resource result, int &errcode [, string &matcheddn [, string &errmsg [, array &referrals [, array &controls]]]])
3381 Extract information from result */
PHP_FUNCTION(ldap_parse_result)3382 PHP_FUNCTION(ldap_parse_result)
3383 {
3384 zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals, *serverctrls;
3385 ldap_linkdata *ld;
3386 LDAPMessage *ldap_result;
3387 LDAPControl **lserverctrls = NULL;
3388 char **lreferrals, **refp;
3389 char *lmatcheddn, *lerrmsg;
3390 int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
3391
3392 if (zend_parse_parameters(myargcount, "rrz|zzzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) {
3393 return;
3394 }
3395
3396 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3397 RETURN_FALSE;
3398 }
3399
3400 if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
3401 RETURN_FALSE;
3402 }
3403
3404 rc = ldap_parse_result(ld->link, ldap_result, &lerrcode,
3405 myargcount > 3 ? &lmatcheddn : NULL,
3406 myargcount > 4 ? &lerrmsg : NULL,
3407 myargcount > 5 ? &lreferrals : NULL,
3408 myargcount > 6 ? &lserverctrls : NULL,
3409 0);
3410 if (rc != LDAP_SUCCESS) {
3411 php_error_docref(NULL, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
3412 RETURN_FALSE;
3413 }
3414
3415 ZEND_TRY_ASSIGN_REF_LONG(errcode, lerrcode);
3416
3417 /* Reverse -> fall through */
3418 switch (myargcount) {
3419 case 7:
3420 _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;
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 }
3434 case 5:
3435 if (lerrmsg == NULL) {
3436 ZEND_TRY_ASSIGN_REF_EMPTY_STRING(errmsg);
3437 } else {
3438 ZEND_TRY_ASSIGN_REF_STRING(errmsg, lerrmsg);
3439 ldap_memfree(lerrmsg);
3440 }
3441 case 4:
3442 if (lmatcheddn == NULL) {
3443 ZEND_TRY_ASSIGN_REF_EMPTY_STRING(matcheddn);
3444 } else {
3445 ZEND_TRY_ASSIGN_REF_STRING(matcheddn, lmatcheddn);
3446 ldap_memfree(lmatcheddn);
3447 }
3448 }
3449 RETURN_TRUE;
3450 }
3451 /* }}} */
3452 #endif
3453
3454 /* {{{ Extended operation response parsing, Pierangelo Masarati */
3455 #ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
3456 /* {{{ proto bool ldap_parse_exop(resource link, resource result [, string &retdata [, string &retoid]])
3457 Extract information from extended operation result */
PHP_FUNCTION(ldap_parse_exop)3458 PHP_FUNCTION(ldap_parse_exop)
3459 {
3460 zval *link, *result, *retdata, *retoid;
3461 ldap_linkdata *ld;
3462 LDAPMessage *ldap_result;
3463 char *lretoid;
3464 struct berval *lretdata;
3465 int rc, myargcount = ZEND_NUM_ARGS();
3466
3467 if (zend_parse_parameters(myargcount, "rr|zz", &link, &result, &retdata, &retoid) != SUCCESS) {
3468 WRONG_PARAM_COUNT;
3469 }
3470
3471 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3472 RETURN_FALSE;
3473 }
3474
3475 if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
3476 RETURN_FALSE;
3477 }
3478
3479 rc = ldap_parse_extended_result(ld->link, ldap_result,
3480 myargcount > 3 ? &lretoid: NULL,
3481 myargcount > 2 ? &lretdata: NULL,
3482 0);
3483 if (rc != LDAP_SUCCESS) {
3484 php_error_docref(NULL, E_WARNING, "Unable to parse extended operation result: %s", ldap_err2string(rc));
3485 RETURN_FALSE;
3486 }
3487
3488 /* Reverse -> fall through */
3489 switch (myargcount) {
3490 case 4:
3491 if (lretoid == NULL) {
3492 ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retoid);
3493 } else {
3494 ZEND_TRY_ASSIGN_REF_STRING(retoid, lretoid);
3495 ldap_memfree(lretoid);
3496 }
3497 case 3:
3498 /* use arg #3 as the data returned by the server */
3499 if (lretdata == NULL) {
3500 ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retdata);
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 }
3507 RETURN_TRUE;
3508 }
3509 /* }}} */
3510 #endif
3511 /* }}} */
3512
3513 /* {{{ proto resource ldap_first_reference(resource link, resource result)
3514 Return first reference */
PHP_FUNCTION(ldap_first_reference)3515 PHP_FUNCTION(ldap_first_reference)
3516 {
3517 zval *link, *result;
3518 ldap_linkdata *ld;
3519 ldap_resultentry *resultentry;
3520 LDAPMessage *ldap_result, *entry;
3521
3522 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &link, &result) != SUCCESS) {
3523 return;
3524 }
3525
3526 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3527 RETURN_FALSE;
3528 }
3529
3530 if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
3531 RETURN_FALSE;
3532 }
3533
3534 if ((entry = ldap_first_reference(ld->link, ldap_result)) == NULL) {
3535 RETVAL_FALSE;
3536 } else {
3537 resultentry = emalloc(sizeof(ldap_resultentry));
3538 RETVAL_RES(zend_register_resource(resultentry, le_result_entry));
3539 ZVAL_COPY(&resultentry->res, result);
3540 resultentry->data = entry;
3541 resultentry->ber = NULL;
3542 }
3543 }
3544 /* }}} */
3545
3546 /* {{{ proto resource ldap_next_reference(resource link, resource reference_entry)
3547 Get next reference */
PHP_FUNCTION(ldap_next_reference)3548 PHP_FUNCTION(ldap_next_reference)
3549 {
3550 zval *link, *result_entry;
3551 ldap_linkdata *ld;
3552 ldap_resultentry *resultentry, *resultentry_next;
3553 LDAPMessage *entry_next;
3554
3555 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &link, &result_entry) != SUCCESS) {
3556 return;
3557 }
3558
3559 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3560 RETURN_FALSE;
3561 }
3562
3563 if ((resultentry = (ldap_resultentry *)zend_fetch_resource(Z_RES_P(result_entry), "ldap result entry", le_result_entry)) == NULL) {
3564 RETURN_FALSE;
3565 }
3566
3567 if ((entry_next = ldap_next_reference(ld->link, resultentry->data)) == NULL) {
3568 RETVAL_FALSE;
3569 } else {
3570 resultentry_next = emalloc(sizeof(ldap_resultentry));
3571 RETVAL_RES(zend_register_resource(resultentry_next, le_result_entry));
3572 ZVAL_COPY(&resultentry_next->res, &resultentry->res);
3573 resultentry_next->data = entry_next;
3574 resultentry_next->ber = NULL;
3575 }
3576 }
3577 /* }}} */
3578
3579 #ifdef HAVE_LDAP_PARSE_REFERENCE
3580 /* {{{ proto bool ldap_parse_reference(resource link, resource reference_entry, array &referrals)
3581 Extract information from reference entry */
PHP_FUNCTION(ldap_parse_reference)3582 PHP_FUNCTION(ldap_parse_reference)
3583 {
3584 zval *link, *result_entry, *referrals;
3585 ldap_linkdata *ld;
3586 ldap_resultentry *resultentry;
3587 char **lreferrals, **refp;
3588
3589 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrz", &link, &result_entry, &referrals) != SUCCESS) {
3590 return;
3591 }
3592
3593 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3594 RETURN_FALSE;
3595 }
3596
3597 if ((resultentry = (ldap_resultentry *)zend_fetch_resource(Z_RES_P(result_entry), "ldap result entry", le_result_entry)) == NULL) {
3598 RETURN_FALSE;
3599 }
3600
3601 if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
3602 RETURN_FALSE;
3603 }
3604
3605 referrals = zend_try_array_init(referrals);
3606 if (!referrals) {
3607 return;
3608 }
3609
3610 if (lreferrals != NULL) {
3611 refp = lreferrals;
3612 while (*refp) {
3613 add_next_index_string(referrals, *refp);
3614 refp++;
3615 }
3616 ldap_memvfree((void**)lreferrals);
3617 }
3618 RETURN_TRUE;
3619 }
3620 /* }}} */
3621 #endif
3622
3623 /* {{{ php_ldap_do_rename
3624 */
php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS,int ext)3625 static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, int ext)
3626 {
3627 zval *serverctrls = NULL;
3628 zval *link;
3629 ldap_linkdata *ld;
3630 LDAPControl **lserverctrls = NULL;
3631 LDAPMessage *ldap_res;
3632 int rc, msgid;
3633 char *dn, *newrdn, *newparent;
3634 size_t dn_len, newrdn_len, newparent_len;
3635 zend_bool deleteoldrdn;
3636
3637 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsssb|a", &link, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn, &serverctrls) != SUCCESS) {
3638 return;
3639 }
3640
3641 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3642 RETURN_FALSE;
3643 }
3644
3645 if (newparent_len == 0) {
3646 newparent = NULL;
3647 }
3648
3649 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP
3650 if (serverctrls) {
3651 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
3652 if (lserverctrls == NULL) {
3653 RETVAL_FALSE;
3654 goto cleanup;
3655 }
3656 }
3657
3658 if (ext) {
3659 rc = ldap_rename(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL, &msgid);
3660 } else {
3661 rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL);
3662 }
3663 #else
3664 if (newparent_len != 0) {
3665 php_error_docref(NULL, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN");
3666 RETURN_FALSE;
3667 }
3668 if (serverctrls) {
3669 php_error_docref(NULL, E_WARNING, "You are using old LDAP API, controls are not supported");
3670 RETURN_FALSE;
3671 }
3672 if (ext) {
3673 php_error_docref(NULL, E_WARNING, "You are using old LDAP API, ldap_rename_ext is not supported");
3674 RETURN_FALSE;
3675 }
3676 /* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */
3677 rc = ldap_modrdn2_s(ld->link, dn, newrdn, deleteoldrdn);
3678 #endif
3679
3680 if (rc != LDAP_SUCCESS) {
3681 RETVAL_FALSE;
3682 } else if (ext) {
3683 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
3684 if (rc == -1) {
3685 php_error_docref(NULL, E_WARNING, "Rename operation failed");
3686 RETVAL_FALSE;
3687 goto cleanup;
3688 }
3689
3690 /* return a PHP control object */
3691 RETVAL_RES(zend_register_resource(ldap_res, le_result));
3692 } else {
3693 RETVAL_TRUE;
3694 }
3695
3696 cleanup:
3697 if (lserverctrls) {
3698 _php_ldap_controls_free(&lserverctrls);
3699 }
3700
3701 return;
3702 }
3703 /* }}} */
3704
3705 /* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols])
3706 Modify the name of an entry */
PHP_FUNCTION(ldap_rename)3707 PHP_FUNCTION(ldap_rename)
3708 {
3709 php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3710 }
3711 /* }}} */
3712
3713 /* {{{ proto resource ldap_rename_ext(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols])
3714 Modify the name of an entry */
PHP_FUNCTION(ldap_rename_ext)3715 PHP_FUNCTION(ldap_rename_ext)
3716 {
3717 php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3718 }
3719 /* }}} */
3720
3721 #ifdef HAVE_LDAP_START_TLS_S
3722 /* {{{ proto bool ldap_start_tls(resource link)
3723 Start TLS */
PHP_FUNCTION(ldap_start_tls)3724 PHP_FUNCTION(ldap_start_tls)
3725 {
3726 zval *link;
3727 ldap_linkdata *ld;
3728 int rc, protocol = LDAP_VERSION3;
3729
3730 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &link) != SUCCESS) {
3731 return;
3732 }
3733
3734 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3735 RETURN_FALSE;
3736 }
3737
3738 if (((rc = ldap_set_option(ld->link, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) ||
3739 ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS)
3740 ) {
3741 php_error_docref(NULL, E_WARNING,"Unable to start TLS: %s", ldap_err2string(rc));
3742 RETURN_FALSE;
3743 } else {
3744 RETURN_TRUE;
3745 }
3746 }
3747 /* }}} */
3748 #endif
3749 #endif /* (LDAP_API_VERSION > 2000) || HAVE_ORALDAP */
3750
3751 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
3752 /* {{{ _ldap_rebind_proc()
3753 */
_ldap_rebind_proc(LDAP * ldap,const char * url,ber_tag_t req,ber_int_t msgid,void * params)3754 int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params)
3755 {
3756 ldap_linkdata *ld;
3757 int retval;
3758 zval cb_args[2];
3759 zval cb_retval;
3760 zval *cb_link = (zval *) params;
3761
3762 ld = (ldap_linkdata *) zend_fetch_resource_ex(cb_link, "ldap link", le_link);
3763
3764 /* link exists and callback set? */
3765 if (ld == NULL || Z_ISUNDEF(ld->rebindproc)) {
3766 php_error_docref(NULL, E_WARNING, "Link not found or no callback set");
3767 return LDAP_OTHER;
3768 }
3769
3770 /* callback */
3771 ZVAL_COPY_VALUE(&cb_args[0], cb_link);
3772 ZVAL_STRING(&cb_args[1], url);
3773 if (call_user_function_ex(EG(function_table), NULL, &ld->rebindproc, &cb_retval, 2, cb_args, 0, NULL) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
3774 retval = zval_get_long(&cb_retval);
3775 zval_ptr_dtor(&cb_retval);
3776 } else {
3777 php_error_docref(NULL, E_WARNING, "rebind_proc PHP callback failed");
3778 retval = LDAP_OTHER;
3779 }
3780 zval_ptr_dtor(&cb_args[1]);
3781 return retval;
3782 }
3783 /* }}} */
3784
3785 /* {{{ proto bool ldap_set_rebind_proc(resource link, string callback)
3786 Set a callback function to do re-binds on referral chasing. */
PHP_FUNCTION(ldap_set_rebind_proc)3787 PHP_FUNCTION(ldap_set_rebind_proc)
3788 {
3789 zval *link, *callback;
3790 ldap_linkdata *ld;
3791
3792 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &link, &callback) != SUCCESS) {
3793 RETURN_FALSE;
3794 }
3795
3796 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
3797 RETURN_FALSE;
3798 }
3799
3800 if (Z_TYPE_P(callback) == IS_STRING && Z_STRLEN_P(callback) == 0) {
3801 /* unregister rebind procedure */
3802 if (!Z_ISUNDEF(ld->rebindproc)) {
3803 zval_ptr_dtor(&ld->rebindproc);
3804 ZVAL_UNDEF(&ld->rebindproc);
3805 ldap_set_rebind_proc(ld->link, NULL, NULL);
3806 }
3807 RETURN_TRUE;
3808 }
3809
3810 /* callable? */
3811 if (!zend_is_callable(callback, 0, NULL)) {
3812 zend_string *callback_name = zend_get_callable_name(callback);
3813 php_error_docref(NULL, E_WARNING, "Two arguments expected for '%s' to be a valid callback", ZSTR_VAL(callback_name));
3814 zend_string_release_ex(callback_name, 0);
3815 RETURN_FALSE;
3816 }
3817
3818 /* register rebind procedure */
3819 if (Z_ISUNDEF(ld->rebindproc)) {
3820 ldap_set_rebind_proc(ld->link, _ldap_rebind_proc, (void *) link);
3821 } else {
3822 zval_ptr_dtor(&ld->rebindproc);
3823 }
3824
3825 ZVAL_COPY(&ld->rebindproc, callback);
3826 RETURN_TRUE;
3827 }
3828 /* }}} */
3829 #endif
3830
php_ldap_do_escape(const zend_bool * map,const char * value,size_t valuelen,zend_long flags)3831 static zend_string* php_ldap_do_escape(const zend_bool *map, const char *value, size_t valuelen, zend_long flags)
3832 {
3833 char hex[] = "0123456789abcdef";
3834 size_t i, p = 0;
3835 size_t len = 0;
3836 zend_string *ret;
3837
3838 for (i = 0; i < valuelen; i++) {
3839 len += (map[(unsigned char) value[i]]) ? 3 : 1;
3840 }
3841 /* Per RFC 4514, a leading and trailing space must be escaped */
3842 if ((flags & PHP_LDAP_ESCAPE_DN) && (value[0] == ' ')) {
3843 len += 2;
3844 }
3845 if ((flags & PHP_LDAP_ESCAPE_DN) && ((valuelen > 1) && (value[valuelen - 1] == ' '))) {
3846 len += 2;
3847 }
3848
3849 ret = zend_string_alloc(len, 0);
3850
3851 for (i = 0; i < valuelen; i++) {
3852 unsigned char v = (unsigned char) value[i];
3853
3854 if (map[v] || ((flags & PHP_LDAP_ESCAPE_DN) && ((i == 0) || (i + 1 == valuelen)) && (v == ' '))) {
3855 ZSTR_VAL(ret)[p++] = '\\';
3856 ZSTR_VAL(ret)[p++] = hex[v >> 4];
3857 ZSTR_VAL(ret)[p++] = hex[v & 0x0f];
3858 } else {
3859 ZSTR_VAL(ret)[p++] = v;
3860 }
3861 }
3862
3863 ZSTR_VAL(ret)[p] = '\0';
3864 ZSTR_LEN(ret) = p;
3865 return ret;
3866 }
3867
php_ldap_escape_map_set_chars(zend_bool * map,const char * chars,const size_t charslen,char escape)3868 static void php_ldap_escape_map_set_chars(zend_bool *map, const char *chars, const size_t charslen, char escape)
3869 {
3870 size_t i = 0;
3871 while (i < charslen) {
3872 map[(unsigned char) chars[i++]] = escape;
3873 }
3874 }
3875
PHP_FUNCTION(ldap_escape)3876 PHP_FUNCTION(ldap_escape)
3877 {
3878 char *value, *ignores;
3879 size_t valuelen = 0, ignoreslen = 0;
3880 int i;
3881 zend_long flags = 0;
3882 zend_bool map[256] = {0}, havecharlist = 0;
3883
3884 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sl", &value, &valuelen, &ignores, &ignoreslen, &flags) != SUCCESS) {
3885 return;
3886 }
3887
3888 if (!valuelen) {
3889 RETURN_EMPTY_STRING();
3890 }
3891
3892 if (flags & PHP_LDAP_ESCAPE_FILTER) {
3893 havecharlist = 1;
3894 php_ldap_escape_map_set_chars(map, "\\*()\0", sizeof("\\*()\0") - 1, 1);
3895 }
3896
3897 if (flags & PHP_LDAP_ESCAPE_DN) {
3898 havecharlist = 1;
3899 php_ldap_escape_map_set_chars(map, "\\,=+<>;\"#\r", sizeof("\\,=+<>;\"#\r") - 1, 1);
3900 }
3901
3902 if (!havecharlist) {
3903 for (i = 0; i < 256; i++) {
3904 map[i] = 1;
3905 }
3906 }
3907
3908 if (ignoreslen) {
3909 php_ldap_escape_map_set_chars(map, ignores, ignoreslen, 0);
3910 }
3911
3912 RETURN_NEW_STR(php_ldap_do_escape(map, value, valuelen, flags));
3913 }
3914
3915 #ifdef STR_TRANSLATION
3916 /* {{{ php_ldap_do_translate
3917 */
php_ldap_do_translate(INTERNAL_FUNCTION_PARAMETERS,int way)3918 static void php_ldap_do_translate(INTERNAL_FUNCTION_PARAMETERS, int way)
3919 {
3920 char *value;
3921 size_t value_len;
3922 int result;
3923
3924 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &value, &value_len) != SUCCESS) {
3925 return;
3926 }
3927
3928 if (value_len == 0) {
3929 RETURN_FALSE;
3930 }
3931
3932 if (way == 1) {
3933 result = ldap_8859_to_t61(&value, &value_len, 0);
3934 } else {
3935 result = ldap_t61_to_8859(&value, &value_len, 0);
3936 }
3937
3938 if (result == LDAP_SUCCESS) {
3939 RETVAL_STRINGL(value, value_len);
3940 free(value);
3941 } else {
3942 php_error_docref(NULL, E_WARNING, "Conversion from iso-8859-1 to t61 failed: %s", ldap_err2string(result));
3943 RETVAL_FALSE;
3944 }
3945 }
3946 /* }}} */
3947
3948 /* {{{ proto string ldap_t61_to_8859(string value)
3949 Translate t61 characters to 8859 characters */
PHP_FUNCTION(ldap_t61_to_8859)3950 PHP_FUNCTION(ldap_t61_to_8859)
3951 {
3952 php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3953 }
3954 /* }}} */
3955
3956 /* {{{ proto string ldap_8859_to_t61(string value)
3957 Translate 8859 characters to t61 characters */
PHP_FUNCTION(ldap_8859_to_t61)3958 PHP_FUNCTION(ldap_8859_to_t61)
3959 {
3960 php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3961 }
3962 /* }}} */
3963 #endif
3964
3965 #ifdef LDAP_CONTROL_PAGEDRESULTS
3966 /* {{{ proto mixed ldap_control_paged_result(resource link, int pagesize [, bool iscritical [, string cookie]])
3967 Inject paged results control*/
PHP_FUNCTION(ldap_control_paged_result)3968 PHP_FUNCTION(ldap_control_paged_result)
3969 {
3970 zend_long pagesize;
3971 zend_bool iscritical;
3972 zval *link;
3973 char *cookie = NULL;
3974 size_t cookie_len = 0;
3975 struct berval lcookie = { 0L, NULL };
3976 ldap_linkdata *ld;
3977 LDAP *ldap;
3978 BerElement *ber = NULL;
3979 LDAPControl ctrl, *ctrlsp[2];
3980 int rc, myargcount = ZEND_NUM_ARGS();
3981
3982 if (zend_parse_parameters(myargcount, "rl|bs", &link, &pagesize, &iscritical, &cookie, &cookie_len) != SUCCESS) {
3983 return;
3984 }
3985
3986 if (Z_TYPE_P(link) == IS_NULL) {
3987 ldap = NULL;
3988 } else {
3989 if ((ld = (ldap_linkdata *)zend_fetch_resource_ex(link, "ldap link", le_link)) == NULL) {
3990 RETURN_FALSE;
3991 }
3992 ldap = ld->link;
3993 }
3994
3995 ber = ber_alloc_t(LBER_USE_DER);
3996 if (ber == NULL) {
3997 php_error_docref(NULL, E_WARNING, "Unable to alloc BER encoding resources for paged results control");
3998 RETURN_FALSE;
3999 }
4000
4001 ctrl.ldctl_iscritical = 0;
4002
4003 switch (myargcount) {
4004 case 4:
4005 lcookie.bv_val = cookie;
4006 lcookie.bv_len = cookie_len;
4007 /* fallthru */
4008 case 3:
4009 ctrl.ldctl_iscritical = (int)iscritical;
4010 /* fallthru */
4011 }
4012
4013 if (ber_printf(ber, "{iO}", (int)pagesize, &lcookie) == LBER_ERROR) {
4014 php_error_docref(NULL, E_WARNING, "Unable to BER printf paged results control");
4015 RETVAL_FALSE;
4016 goto lcpr_error_out;
4017 }
4018 rc = ber_flatten2(ber, &ctrl.ldctl_value, 0);
4019 if (rc == LBER_ERROR) {
4020 php_error_docref(NULL, E_WARNING, "Unable to BER encode paged results control");
4021 RETVAL_FALSE;
4022 goto lcpr_error_out;
4023 }
4024
4025 ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
4026
4027 if (ldap) {
4028 /* directly set the option */
4029 ctrlsp[0] = &ctrl;
4030 ctrlsp[1] = NULL;
4031
4032 rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp);
4033 if (rc != LDAP_SUCCESS) {
4034 php_error_docref(NULL, E_WARNING, "Unable to set paged results control: %s (%d)", ldap_err2string(rc), rc);
4035 RETVAL_FALSE;
4036 goto lcpr_error_out;
4037 }
4038 RETVAL_TRUE;
4039 } else {
4040 /* return a PHP control object */
4041 array_init(return_value);
4042
4043 add_assoc_string(return_value, "oid", ctrl.ldctl_oid);
4044 if (ctrl.ldctl_value.bv_len) {
4045 add_assoc_stringl(return_value, "value", ctrl.ldctl_value.bv_val, ctrl.ldctl_value.bv_len);
4046 }
4047 if (ctrl.ldctl_iscritical) {
4048 add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical);
4049 }
4050 }
4051
4052 lcpr_error_out:
4053 if (ber != NULL) {
4054 ber_free(ber, 1);
4055 }
4056 return;
4057 }
4058 /* }}} */
4059
4060 /* {{{ proto bool ldap_control_paged_result_response(resource link, resource result [, string &cookie [, int &estimated]])
4061 Extract paged results control response */
PHP_FUNCTION(ldap_control_paged_result_response)4062 PHP_FUNCTION(ldap_control_paged_result_response)
4063 {
4064 zval *link, *result, *cookie, *estimated;
4065 struct berval lcookie;
4066 int lestimated;
4067 ldap_linkdata *ld;
4068 LDAPMessage *ldap_result;
4069 LDAPControl **lserverctrls, *lctrl;
4070 BerElement *ber;
4071 ber_tag_t tag;
4072 int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
4073
4074 if (zend_parse_parameters(myargcount, "rr|zz", &link, &result, &cookie, &estimated) != SUCCESS) {
4075 return;
4076 }
4077
4078 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
4079 RETURN_FALSE;
4080 }
4081
4082 if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
4083 RETURN_FALSE;
4084 }
4085
4086 rc = ldap_parse_result(ld->link,
4087 ldap_result,
4088 &lerrcode,
4089 NULL, /* matcheddn */
4090 NULL, /* errmsg */
4091 NULL, /* referrals */
4092 &lserverctrls,
4093 0);
4094
4095 if (rc != LDAP_SUCCESS) {
4096 php_error_docref(NULL, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc);
4097 RETURN_FALSE;
4098 }
4099
4100 if (lerrcode != LDAP_SUCCESS) {
4101 php_error_docref(NULL, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode);
4102 RETURN_FALSE;
4103 }
4104
4105 if (lserverctrls == NULL) {
4106 php_error_docref(NULL, E_WARNING, "No server controls in result");
4107 RETURN_FALSE;
4108 }
4109
4110 lctrl = ldap_control_find(LDAP_CONTROL_PAGEDRESULTS, lserverctrls, NULL);
4111 if (lctrl == NULL) {
4112 ldap_controls_free(lserverctrls);
4113 php_error_docref(NULL, E_WARNING, "No paged results control response in result");
4114 RETURN_FALSE;
4115 }
4116
4117 ber = ber_init(&lctrl->ldctl_value);
4118 if (ber == NULL) {
4119 ldap_controls_free(lserverctrls);
4120 php_error_docref(NULL, E_WARNING, "Unable to alloc BER decoding resources for paged results control response");
4121 RETURN_FALSE;
4122 }
4123
4124 tag = ber_scanf(ber, "{io}", &lestimated, &lcookie);
4125 (void)ber_free(ber, 1);
4126
4127 if (tag == LBER_ERROR) {
4128 ldap_controls_free(lserverctrls);
4129 php_error_docref(NULL, E_WARNING, "Unable to decode paged results control response");
4130 RETURN_FALSE;
4131 }
4132
4133 if (lestimated < 0) {
4134 ldap_controls_free(lserverctrls);
4135 php_error_docref(NULL, E_WARNING, "Invalid paged results control response value");
4136 RETURN_FALSE;
4137 }
4138
4139 ldap_controls_free(lserverctrls);
4140 if (myargcount == 4) {
4141 ZEND_TRY_ASSIGN_REF_LONG(estimated, lestimated);
4142 }
4143
4144 if (lcookie.bv_len == 0) {
4145 ZEND_TRY_ASSIGN_REF_EMPTY_STRING(cookie);
4146 } else {
4147 ZEND_TRY_ASSIGN_REF_STRINGL(cookie, lcookie.bv_val, lcookie.bv_len);
4148 }
4149 ldap_memfree(lcookie.bv_val);
4150
4151 RETURN_TRUE;
4152 }
4153 /* }}} */
4154 #endif
4155
4156 /* {{{ Extended operations, Pierangelo Masarati */
4157 #ifdef HAVE_LDAP_EXTENDED_OPERATION_S
4158 /* {{{ proto resource ldap_exop(resource link, string reqoid [, string reqdata [, array servercontrols [, string &retdata [, string &retoid]]]])
4159 Extended operation */
PHP_FUNCTION(ldap_exop)4160 PHP_FUNCTION(ldap_exop)
4161 {
4162 zval *serverctrls = NULL;
4163 zval *link, *retdata = NULL, *retoid = NULL;
4164 char *lretoid = NULL;
4165 zend_string *reqoid, *reqdata = NULL;
4166 struct berval lreqdata, *lretdata = NULL;
4167 ldap_linkdata *ld;
4168 LDAPMessage *ldap_res;
4169 LDAPControl **lserverctrls = NULL;
4170 int rc, msgid;
4171
4172 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rS|S!a!zz", &link, &reqoid, &reqdata, &serverctrls, &retdata, &retoid) != SUCCESS) {
4173 return;
4174 }
4175
4176 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
4177 RETURN_FALSE;
4178 }
4179
4180 if (reqdata) {
4181 lreqdata.bv_val = ZSTR_VAL(reqdata);
4182 lreqdata.bv_len = ZSTR_LEN(reqdata);
4183 } else {
4184 lreqdata.bv_len = 0;
4185 }
4186
4187 if (serverctrls) {
4188 lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
4189 if (lserverctrls == NULL) {
4190 RETVAL_FALSE;
4191 goto cleanup;
4192 }
4193 }
4194
4195 if (retdata) {
4196 /* synchronous call */
4197 rc = ldap_extended_operation_s(ld->link, ZSTR_VAL(reqoid),
4198 lreqdata.bv_len > 0 ? &lreqdata: NULL,
4199 lserverctrls,
4200 NULL,
4201 retoid ? &lretoid : NULL,
4202 &lretdata );
4203 if (rc != LDAP_SUCCESS ) {
4204 php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc);
4205 RETVAL_FALSE;
4206 goto cleanup;
4207 }
4208
4209 if (retoid) {
4210 if (lretoid) {
4211 ZEND_TRY_ASSIGN_REF_STRING(retoid, lretoid);
4212 ldap_memfree(lretoid);
4213 } else {
4214 ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retoid);
4215 }
4216 }
4217
4218 if (lretdata) {
4219 ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
4220 ldap_memfree(lretdata->bv_val);
4221 ldap_memfree(lretdata);
4222 } else {
4223 ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retdata);
4224 }
4225
4226 RETVAL_TRUE;
4227 goto cleanup;
4228 }
4229
4230 /* asynchronous call */
4231 rc = ldap_extended_operation(ld->link, ZSTR_VAL(reqoid),
4232 lreqdata.bv_len > 0 ? &lreqdata: NULL,
4233 lserverctrls,
4234 NULL,
4235 &msgid);
4236 if (rc != LDAP_SUCCESS ) {
4237 php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc);
4238 RETVAL_FALSE;
4239 goto cleanup;
4240 }
4241
4242 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
4243 if (rc == -1) {
4244 php_error_docref(NULL, E_WARNING, "Extended operation %s failed", ZSTR_VAL(reqoid));
4245 RETVAL_FALSE;
4246 goto cleanup;
4247 }
4248
4249 /* return a PHP control object */
4250 RETVAL_RES(zend_register_resource(ldap_res, le_result));
4251
4252 cleanup:
4253 if (lserverctrls) {
4254 _php_ldap_controls_free(&lserverctrls);
4255 }
4256 }
4257 /* }}} */
4258 #endif
4259
4260 #ifdef HAVE_LDAP_PASSWD
4261 /* {{{ proto bool|string ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw [, array ctrls]]]])
4262 Passwd modify extended operation */
PHP_FUNCTION(ldap_exop_passwd)4263 PHP_FUNCTION(ldap_exop_passwd)
4264 {
4265 zval *link, *serverctrls;
4266 struct berval luser = { 0L, NULL };
4267 struct berval loldpw = { 0L, NULL };
4268 struct berval lnewpw = { 0L, NULL };
4269 struct berval lgenpasswd = { 0L, NULL };
4270 LDAPControl *ctrl, **lserverctrls = NULL, *requestctrls[2] = { NULL, NULL };
4271 LDAPMessage* ldap_res = NULL;
4272 ldap_linkdata *ld;
4273 int rc, myargcount = ZEND_NUM_ARGS(), msgid, err;
4274 char* errmsg = NULL;
4275
4276 if (zend_parse_parameters(myargcount, "r|sssz/", &link, &luser.bv_val, &luser.bv_len, &loldpw.bv_val, &loldpw.bv_len, &lnewpw.bv_val, &lnewpw.bv_len, &serverctrls) == FAILURE) {
4277 return;
4278 }
4279
4280 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
4281 RETVAL_FALSE;
4282 goto cleanup;
4283 }
4284
4285 switch (myargcount) {
4286 case 5:
4287 /* ldap_create_passwordpolicy_control() allocates ctrl */
4288 if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) {
4289 requestctrls[0] = ctrl;
4290 }
4291 }
4292
4293 /* asynchronous call to get result and controls */
4294 rc = ldap_passwd(ld->link, &luser,
4295 loldpw.bv_len > 0 ? &loldpw : NULL,
4296 lnewpw.bv_len > 0 ? &lnewpw : NULL,
4297 requestctrls,
4298 NULL, &msgid);
4299
4300 if (requestctrls[0] != NULL) {
4301 ldap_control_free(requestctrls[0]);
4302 }
4303
4304 if (rc != LDAP_SUCCESS ) {
4305 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4306 RETVAL_FALSE;
4307 goto cleanup;
4308 }
4309
4310 rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
4311 if ((rc < 0) || !ldap_res) {
4312 rc = _get_lderrno(ld->link);
4313 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4314 RETVAL_FALSE;
4315 goto cleanup;
4316 }
4317
4318 rc = ldap_parse_passwd(ld->link, ldap_res, &lgenpasswd);
4319 if( rc != LDAP_SUCCESS ) {
4320 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4321 RETVAL_FALSE;
4322 goto cleanup;
4323 }
4324
4325 rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 0);
4326 if( rc != LDAP_SUCCESS ) {
4327 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4328 RETVAL_FALSE;
4329 goto cleanup;
4330 }
4331
4332 if (myargcount > 4) {
4333 _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
4334 }
4335
4336 /* return */
4337 if (lnewpw.bv_len == 0) {
4338 if (lgenpasswd.bv_len == 0) {
4339 RETVAL_EMPTY_STRING();
4340 } else {
4341 RETVAL_STRINGL(lgenpasswd.bv_val, lgenpasswd.bv_len);
4342 }
4343 } else if (err == LDAP_SUCCESS) {
4344 RETVAL_TRUE;
4345 } else {
4346 php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", (errmsg ? errmsg : ldap_err2string(err)), err);
4347 RETVAL_FALSE;
4348 }
4349
4350 cleanup:
4351 if (lgenpasswd.bv_val != NULL) {
4352 ldap_memfree(lgenpasswd.bv_val);
4353 }
4354 if (ldap_res != NULL) {
4355 ldap_msgfree(ldap_res);
4356 }
4357 if (errmsg != NULL) {
4358 ldap_memfree(errmsg);
4359 }
4360 }
4361 /* }}} */
4362 #endif
4363
4364 #ifdef HAVE_LDAP_WHOAMI_S
4365 /* {{{ proto bool|string ldap_exop_whoami(resource link)
4366 Whoami extended operation */
PHP_FUNCTION(ldap_exop_whoami)4367 PHP_FUNCTION(ldap_exop_whoami)
4368 {
4369 zval *link;
4370 struct berval *lauthzid;
4371 ldap_linkdata *ld;
4372 int rc;
4373
4374 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &link) == FAILURE) {
4375 WRONG_PARAM_COUNT;
4376 }
4377
4378 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
4379 RETURN_FALSE;
4380 }
4381
4382 /* synchronous call */
4383 rc = ldap_whoami_s(ld->link, &lauthzid, NULL, NULL);
4384 if (rc != LDAP_SUCCESS ) {
4385 php_error_docref(NULL, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4386 RETURN_FALSE;
4387 }
4388
4389 if (lauthzid == NULL) {
4390 RETVAL_EMPTY_STRING();
4391 } else {
4392 RETVAL_STRINGL(lauthzid->bv_val, lauthzid->bv_len);
4393 ldap_memfree(lauthzid->bv_val);
4394 ldap_memfree(lauthzid);
4395 }
4396 }
4397 /* }}} */
4398 #endif
4399
4400 #ifdef HAVE_LDAP_REFRESH_S
4401 /* {{{ proto bool|int ldap_exop_refresh(resource link , string dn , int ttl)
4402 DDS refresh extended operation */
PHP_FUNCTION(ldap_exop_refresh)4403 PHP_FUNCTION(ldap_exop_refresh)
4404 {
4405 zval *link, *ttl;
4406 struct berval ldn;
4407 ber_int_t lttl;
4408 ber_int_t newttl;
4409 ldap_linkdata *ld;
4410 int rc;
4411
4412 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz", &link, &ldn.bv_val, &ldn.bv_len, &ttl) != SUCCESS) {
4413 WRONG_PARAM_COUNT;
4414 }
4415
4416 if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
4417 RETURN_FALSE;
4418 }
4419
4420 lttl = (ber_int_t)zval_get_long(ttl);
4421
4422 rc = ldap_refresh_s(ld->link, &ldn, lttl, &newttl, NULL, NULL);
4423 if (rc != LDAP_SUCCESS ) {
4424 php_error_docref(NULL, E_WARNING, "Refresh extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4425 RETURN_FALSE;
4426 }
4427
4428 RETURN_LONG(newttl);
4429 }
4430 /* }}} */
4431 #endif
4432
4433 /* }}} */
4434
4435 /* {{{ arginfo */
4436 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0)
4437 ZEND_ARG_INFO(0, hostname)
4438 ZEND_ARG_INFO(0, port)
4439 #ifdef HAVE_ORALDAP
4440 ZEND_ARG_INFO(0, wallet)
4441 ZEND_ARG_INFO(0, wallet_passwd)
4442 ZEND_ARG_INFO(0, authmode)
4443 #endif
4444 ZEND_END_ARG_INFO()
4445
4446 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_resource, 0, 0, 1)
4447 ZEND_ARG_INFO(0, link_identifier)
4448 ZEND_END_ARG_INFO()
4449
4450 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind, 0, 0, 1)
4451 ZEND_ARG_INFO(0, link_identifier)
4452 ZEND_ARG_INFO(0, bind_rdn)
4453 ZEND_ARG_INFO(0, bind_password)
4454 ZEND_END_ARG_INFO()
4455
4456 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind_ext, 0, 0, 1)
4457 ZEND_ARG_INFO(0, link_identifier)
4458 ZEND_ARG_INFO(0, bind_rdn)
4459 ZEND_ARG_INFO(0, bind_password)
4460 ZEND_ARG_INFO(0, servercontrols)
4461 ZEND_END_ARG_INFO()
4462
4463 #ifdef HAVE_LDAP_SASL
4464 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sasl_bind, 0, 0, 1)
4465 ZEND_ARG_INFO(0, link)
4466 ZEND_ARG_INFO(0, binddn)
4467 ZEND_ARG_INFO(0, password)
4468 ZEND_ARG_INFO(0, sasl_mech)
4469 ZEND_ARG_INFO(0, sasl_realm)
4470 ZEND_ARG_INFO(0, sasl_authz_id)
4471 ZEND_ARG_INFO(0, props)
4472 ZEND_END_ARG_INFO()
4473 #endif
4474
4475 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3)
4476 ZEND_ARG_INFO(0, link_identifier)
4477 ZEND_ARG_INFO(0, base_dn)
4478 ZEND_ARG_INFO(0, filter)
4479 ZEND_ARG_INFO(0, attributes)
4480 ZEND_ARG_INFO(0, attrsonly)
4481 ZEND_ARG_INFO(0, sizelimit)
4482 ZEND_ARG_INFO(0, timelimit)
4483 ZEND_ARG_INFO(0, deref)
4484 ZEND_ARG_INFO(0, servercontrols)
4485 ZEND_END_ARG_INFO()
4486
4487 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3)
4488 ZEND_ARG_INFO(0, link_identifier)
4489 ZEND_ARG_INFO(0, base_dn)
4490 ZEND_ARG_INFO(0, filter)
4491 ZEND_ARG_INFO(0, attributes)
4492 ZEND_ARG_INFO(0, attrsonly)
4493 ZEND_ARG_INFO(0, sizelimit)
4494 ZEND_ARG_INFO(0, timelimit)
4495 ZEND_ARG_INFO(0, deref)
4496 ZEND_ARG_INFO(0, servercontrols)
4497 ZEND_END_ARG_INFO()
4498
4499 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3)
4500 ZEND_ARG_INFO(0, link_identifier)
4501 ZEND_ARG_INFO(0, base_dn)
4502 ZEND_ARG_INFO(0, filter)
4503 ZEND_ARG_INFO(0, attributes)
4504 ZEND_ARG_INFO(0, attrsonly)
4505 ZEND_ARG_INFO(0, sizelimit)
4506 ZEND_ARG_INFO(0, timelimit)
4507 ZEND_ARG_INFO(0, deref)
4508 ZEND_ARG_INFO(0, servercontrols)
4509 ZEND_END_ARG_INFO()
4510
4511 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_count_entries, 0, 0, 2)
4512 ZEND_ARG_INFO(0, link_identifier)
4513 ZEND_ARG_INFO(0, result_identifier)
4514 ZEND_END_ARG_INFO()
4515
4516 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_first_entry, 0, 0, 2)
4517 ZEND_ARG_INFO(0, link_identifier)
4518 ZEND_ARG_INFO(0, result_identifier)
4519 ZEND_END_ARG_INFO()
4520
4521 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_next_entry, 0, 0, 2)
4522 ZEND_ARG_INFO(0, link_identifier)
4523 ZEND_ARG_INFO(0, result_identifier)
4524 ZEND_END_ARG_INFO()
4525
4526 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_entries, 0, 0, 2)
4527 ZEND_ARG_INFO(0, link_identifier)
4528 ZEND_ARG_INFO(0, result_identifier)
4529 ZEND_END_ARG_INFO()
4530
4531 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_first_attribute, 0, 0, 2)
4532 ZEND_ARG_INFO(0, link_identifier)
4533 ZEND_ARG_INFO(0, result_entry_identifier)
4534 ZEND_END_ARG_INFO()
4535
4536 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_next_attribute, 0, 0, 2)
4537 ZEND_ARG_INFO(0, link_identifier)
4538 ZEND_ARG_INFO(0, result_entry_identifier)
4539 ZEND_END_ARG_INFO()
4540
4541 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_attributes, 0, 0, 2)
4542 ZEND_ARG_INFO(0, link_identifier)
4543 ZEND_ARG_INFO(0, result_entry_identifier)
4544 ZEND_END_ARG_INFO()
4545
4546 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_values, 0, 0, 3)
4547 ZEND_ARG_INFO(0, link_identifier)
4548 ZEND_ARG_INFO(0, result_entry_identifier)
4549 ZEND_ARG_INFO(0, attribute)
4550 ZEND_END_ARG_INFO()
4551
4552 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_values_len, 0, 0, 3)
4553 ZEND_ARG_INFO(0, link_identifier)
4554 ZEND_ARG_INFO(0, result_entry_identifier)
4555 ZEND_ARG_INFO(0, attribute)
4556 ZEND_END_ARG_INFO()
4557
4558 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_dn, 0, 0, 2)
4559 ZEND_ARG_INFO(0, link_identifier)
4560 ZEND_ARG_INFO(0, result_entry_identifier)
4561 ZEND_END_ARG_INFO()
4562
4563 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_explode_dn, 0, 0, 2)
4564 ZEND_ARG_INFO(0, dn)
4565 ZEND_ARG_INFO(0, with_attrib)
4566 ZEND_END_ARG_INFO()
4567
4568 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_dn2ufn, 0, 0, 1)
4569 ZEND_ARG_INFO(0, dn)
4570 ZEND_END_ARG_INFO()
4571
4572 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add, 0, 0, 3)
4573 ZEND_ARG_INFO(0, link_identifier)
4574 ZEND_ARG_INFO(0, dn)
4575 ZEND_ARG_INFO(0, entry)
4576 ZEND_ARG_INFO(0, servercontrols)
4577 ZEND_END_ARG_INFO()
4578
4579 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add_ext, 0, 0, 3)
4580 ZEND_ARG_INFO(0, link_identifier)
4581 ZEND_ARG_INFO(0, dn)
4582 ZEND_ARG_INFO(0, entry)
4583 ZEND_ARG_INFO(0, servercontrols)
4584 ZEND_END_ARG_INFO()
4585
4586 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete, 0, 0, 2)
4587 ZEND_ARG_INFO(0, link_identifier)
4588 ZEND_ARG_INFO(0, dn)
4589 ZEND_ARG_INFO(0, servercontrols)
4590 ZEND_END_ARG_INFO()
4591
4592 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete_ext, 0, 0, 2)
4593 ZEND_ARG_INFO(0, link_identifier)
4594 ZEND_ARG_INFO(0, dn)
4595 ZEND_ARG_INFO(0, servercontrols)
4596 ZEND_END_ARG_INFO()
4597
4598 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3)
4599 ZEND_ARG_INFO(0, link_identifier)
4600 ZEND_ARG_INFO(0, dn)
4601 ZEND_ARG_INFO(0, entry)
4602 ZEND_ARG_INFO(0, servercontrols)
4603 ZEND_END_ARG_INFO()
4604
4605 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify_batch, 0, 0, 3)
4606 ZEND_ARG_INFO(0, link_identifier)
4607 ZEND_ARG_INFO(0, dn)
4608 ZEND_ARG_ARRAY_INFO(0, modifications_info, 0)
4609 ZEND_ARG_INFO(0, servercontrols)
4610 ZEND_END_ARG_INFO()
4611
4612 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3)
4613 ZEND_ARG_INFO(0, link_identifier)
4614 ZEND_ARG_INFO(0, dn)
4615 ZEND_ARG_INFO(0, entry)
4616 ZEND_ARG_INFO(0, servercontrols)
4617 ZEND_END_ARG_INFO()
4618
4619 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add_ext, 0, 0, 3)
4620 ZEND_ARG_INFO(0, link_identifier)
4621 ZEND_ARG_INFO(0, dn)
4622 ZEND_ARG_INFO(0, entry)
4623 ZEND_ARG_INFO(0, servercontrols)
4624 ZEND_END_ARG_INFO()
4625
4626 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace, 0, 0, 3)
4627 ZEND_ARG_INFO(0, link_identifier)
4628 ZEND_ARG_INFO(0, dn)
4629 ZEND_ARG_INFO(0, entry)
4630 ZEND_ARG_INFO(0, servercontrols)
4631 ZEND_END_ARG_INFO()
4632
4633 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace_ext, 0, 0, 3)
4634 ZEND_ARG_INFO(0, link_identifier)
4635 ZEND_ARG_INFO(0, dn)
4636 ZEND_ARG_INFO(0, entry)
4637 ZEND_ARG_INFO(0, servercontrols)
4638 ZEND_END_ARG_INFO()
4639
4640 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del, 0, 0, 3)
4641 ZEND_ARG_INFO(0, link_identifier)
4642 ZEND_ARG_INFO(0, dn)
4643 ZEND_ARG_INFO(0, entry)
4644 ZEND_ARG_INFO(0, servercontrols)
4645 ZEND_END_ARG_INFO()
4646
4647 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del_ext, 0, 0, 3)
4648 ZEND_ARG_INFO(0, link_identifier)
4649 ZEND_ARG_INFO(0, dn)
4650 ZEND_ARG_INFO(0, entry)
4651 ZEND_ARG_INFO(0, servercontrols)
4652 ZEND_END_ARG_INFO()
4653
4654 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_err2str, 0, 0, 1)
4655 ZEND_ARG_INFO(0, errno)
4656 ZEND_END_ARG_INFO()
4657
4658 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_compare, 0, 0, 4)
4659 ZEND_ARG_INFO(0, link_identifier)
4660 ZEND_ARG_INFO(0, dn)
4661 ZEND_ARG_INFO(0, attribute)
4662 ZEND_ARG_INFO(0, value)
4663 ZEND_ARG_INFO(0, servercontrols)
4664 ZEND_END_ARG_INFO()
4665
4666 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sort, 0, 0, 3)
4667 ZEND_ARG_INFO(0, link)
4668 ZEND_ARG_INFO(0, result)
4669 ZEND_ARG_INFO(0, sortfilter)
4670 ZEND_END_ARG_INFO()
4671
4672 #ifdef LDAP_CONTROL_PAGEDRESULTS
4673 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_control_paged_result, 0, 0, 2)
4674 ZEND_ARG_INFO(0, link)
4675 ZEND_ARG_INFO(0, pagesize)
4676 ZEND_ARG_INFO(0, iscritical)
4677 ZEND_ARG_INFO(0, cookie)
4678 ZEND_END_ARG_INFO();
4679
4680 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_control_paged_result_response, 0, 0, 2)
4681 ZEND_ARG_INFO(0, link)
4682 ZEND_ARG_INFO(0, result)
4683 ZEND_ARG_INFO(1, cookie)
4684 ZEND_ARG_INFO(1, estimated)
4685 ZEND_END_ARG_INFO();
4686 #endif
4687
4688 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP
4689 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename, 0, 0, 5)
4690 ZEND_ARG_INFO(0, link_identifier)
4691 ZEND_ARG_INFO(0, dn)
4692 ZEND_ARG_INFO(0, newrdn)
4693 ZEND_ARG_INFO(0, newparent)
4694 ZEND_ARG_INFO(0, deleteoldrdn)
4695 ZEND_ARG_INFO(0, servercontrols)
4696 ZEND_END_ARG_INFO()
4697
4698 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename_ext, 0, 0, 5)
4699 ZEND_ARG_INFO(0, link_identifier)
4700 ZEND_ARG_INFO(0, dn)
4701 ZEND_ARG_INFO(0, newrdn)
4702 ZEND_ARG_INFO(0, newparent)
4703 ZEND_ARG_INFO(0, deleteoldrdn)
4704 ZEND_ARG_INFO(0, servercontrols)
4705 ZEND_END_ARG_INFO()
4706
4707 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_option, 0, 0, 3)
4708 ZEND_ARG_INFO(0, link_identifier)
4709 ZEND_ARG_INFO(0, option)
4710 ZEND_ARG_INFO(1, retval)
4711 ZEND_END_ARG_INFO()
4712
4713 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_set_option, 0, 0, 3)
4714 ZEND_ARG_INFO(0, link_identifier)
4715 ZEND_ARG_INFO(0, option)
4716 ZEND_ARG_INFO(0, newval)
4717 ZEND_END_ARG_INFO()
4718
4719 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_first_reference, 0, 0, 2)
4720 ZEND_ARG_INFO(0, link)
4721 ZEND_ARG_INFO(0, result)
4722 ZEND_END_ARG_INFO()
4723
4724 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_next_reference, 0, 0, 2)
4725 ZEND_ARG_INFO(0, link)
4726 ZEND_ARG_INFO(0, entry)
4727 ZEND_END_ARG_INFO()
4728
4729 #ifdef HAVE_LDAP_PARSE_REFERENCE
4730 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_parse_reference, 0, 0, 3)
4731 ZEND_ARG_INFO(0, link)
4732 ZEND_ARG_INFO(0, entry)
4733 ZEND_ARG_INFO(1, referrals)
4734 ZEND_END_ARG_INFO()
4735 #endif
4736
4737
4738 #ifdef HAVE_LDAP_PARSE_RESULT
4739 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_parse_result, 0, 0, 3)
4740 ZEND_ARG_INFO(0, link)
4741 ZEND_ARG_INFO(0, result)
4742 ZEND_ARG_INFO(1, errcode)
4743 ZEND_ARG_INFO(1, matcheddn)
4744 ZEND_ARG_INFO(1, errmsg)
4745 ZEND_ARG_INFO(1, referrals)
4746 ZEND_ARG_INFO(1, serverctrls)
4747 ZEND_END_ARG_INFO()
4748 #endif
4749 #endif
4750
4751 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
4752 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_set_rebind_proc, 0, 0, 2)
4753 ZEND_ARG_INFO(0, link)
4754 ZEND_ARG_INFO(0, callback)
4755 ZEND_END_ARG_INFO()
4756 #endif
4757
4758 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_escape, 0, 0, 1)
4759 ZEND_ARG_INFO(0, value)
4760 ZEND_ARG_INFO(0, ignore)
4761 ZEND_ARG_INFO(0, flags)
4762 ZEND_END_ARG_INFO()
4763
4764 #ifdef STR_TRANSLATION
4765 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_t61_to_8859, 0, 0, 1)
4766 ZEND_ARG_INFO(0, value)
4767 ZEND_END_ARG_INFO()
4768
4769 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_8859_to_t61, 0, 0, 1)
4770 ZEND_ARG_INFO(0, value)
4771 ZEND_END_ARG_INFO()
4772 #endif
4773
4774 #ifdef HAVE_LDAP_EXTENDED_OPERATION_S
4775 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop, 0, 0, 2)
4776 ZEND_ARG_INFO(0, link)
4777 ZEND_ARG_INFO(0, reqoid)
4778 ZEND_ARG_INFO(0, reqdata)
4779 ZEND_ARG_INFO(0, servercontrols)
4780 ZEND_ARG_INFO(1, retdata)
4781 ZEND_ARG_INFO(1, retoid)
4782 ZEND_END_ARG_INFO()
4783 #endif
4784
4785 #ifdef HAVE_LDAP_PASSWD
4786 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_passwd, 0, 0, 1)
4787 ZEND_ARG_INFO(0, link)
4788 ZEND_ARG_INFO(0, user)
4789 ZEND_ARG_INFO(0, oldpw)
4790 ZEND_ARG_INFO(0, newpw)
4791 ZEND_ARG_INFO(1, serverctrls)
4792 ZEND_END_ARG_INFO()
4793 #endif
4794
4795 #ifdef HAVE_LDAP_WHOAMI_S
4796 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_whoami, 0, 0, 1)
4797 ZEND_ARG_INFO(0, link)
4798 ZEND_END_ARG_INFO()
4799 #endif
4800
4801 #ifdef HAVE_LDAP_REFRESH_S
4802 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_refresh, 0, 0, 3)
4803 ZEND_ARG_INFO(0, link)
4804 ZEND_ARG_INFO(0, dn)
4805 ZEND_ARG_INFO(0, ttl)
4806 ZEND_END_ARG_INFO()
4807 #endif
4808
4809 #ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
4810 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_parse_exop, 0, 0, 4)
4811 ZEND_ARG_INFO(0, link)
4812 ZEND_ARG_INFO(0, result)
4813 ZEND_ARG_INFO(1, retdata)
4814 ZEND_ARG_INFO(1, retoid)
4815 ZEND_END_ARG_INFO()
4816 #endif
4817 /* }}} */
4818
4819 /*
4820 This is just a small subset of the functionality provided by the LDAP library. All the
4821 operations are synchronous. Referrals are not handled automatically.
4822 */
4823 /* {{{ ldap_functions[]
4824 */
4825 static const zend_function_entry ldap_functions[] = {
4826 PHP_FE(ldap_connect, arginfo_ldap_connect)
4827 PHP_FALIAS(ldap_close, ldap_unbind, arginfo_ldap_resource)
4828 PHP_FE(ldap_bind, arginfo_ldap_bind)
4829 PHP_FE(ldap_bind_ext, arginfo_ldap_bind_ext)
4830 #ifdef HAVE_LDAP_SASL
4831 PHP_FE(ldap_sasl_bind, arginfo_ldap_sasl_bind)
4832 #endif
4833 PHP_FE(ldap_unbind, arginfo_ldap_resource)
4834 PHP_FE(ldap_read, arginfo_ldap_read)
4835 PHP_FE(ldap_list, arginfo_ldap_list)
4836 PHP_FE(ldap_search, arginfo_ldap_search)
4837 PHP_FE(ldap_free_result, arginfo_ldap_resource)
4838 PHP_FE(ldap_count_entries, arginfo_ldap_count_entries)
4839 PHP_FE(ldap_first_entry, arginfo_ldap_first_entry)
4840 PHP_FE(ldap_next_entry, arginfo_ldap_next_entry)
4841 PHP_FE(ldap_get_entries, arginfo_ldap_get_entries)
4842 PHP_FE(ldap_first_attribute, arginfo_ldap_first_attribute)
4843 PHP_FE(ldap_next_attribute, arginfo_ldap_next_attribute)
4844 PHP_FE(ldap_get_attributes, arginfo_ldap_get_attributes)
4845 PHP_FALIAS(ldap_get_values, ldap_get_values_len, arginfo_ldap_get_values)
4846 PHP_FE(ldap_get_values_len, arginfo_ldap_get_values_len)
4847 PHP_FE(ldap_get_dn, arginfo_ldap_get_dn)
4848 PHP_FE(ldap_explode_dn, arginfo_ldap_explode_dn)
4849 PHP_FE(ldap_dn2ufn, arginfo_ldap_dn2ufn)
4850 PHP_FE(ldap_add, arginfo_ldap_add)
4851 PHP_FE(ldap_add_ext, arginfo_ldap_add_ext)
4852 PHP_FE(ldap_delete, arginfo_ldap_delete)
4853 PHP_FE(ldap_delete_ext, arginfo_ldap_delete_ext)
4854 PHP_FE(ldap_modify_batch, arginfo_ldap_modify_batch)
4855 PHP_FALIAS(ldap_modify, ldap_mod_replace, arginfo_ldap_modify)
4856
4857 /* additional functions for attribute based modifications, Gerrit Thomson */
4858 PHP_FE(ldap_mod_add, arginfo_ldap_mod_add)
4859 PHP_FE(ldap_mod_add_ext, arginfo_ldap_mod_add_ext)
4860 PHP_FE(ldap_mod_replace, arginfo_ldap_mod_replace)
4861 PHP_FE(ldap_mod_replace_ext, arginfo_ldap_mod_replace_ext)
4862 PHP_FE(ldap_mod_del, arginfo_ldap_mod_del)
4863 PHP_FE(ldap_mod_del_ext, arginfo_ldap_mod_del_ext)
4864 /* end gjt mod */
4865
4866 PHP_FE(ldap_errno, arginfo_ldap_resource)
4867 PHP_FE(ldap_err2str, arginfo_ldap_err2str)
4868 PHP_FE(ldap_error, arginfo_ldap_resource)
4869 PHP_FE(ldap_compare, arginfo_ldap_compare)
4870 PHP_DEP_FE(ldap_sort, arginfo_ldap_sort)
4871
4872 #if (LDAP_API_VERSION > 2000) || HAVE_ORALDAP
4873 PHP_FE(ldap_rename, arginfo_ldap_rename)
4874 PHP_FE(ldap_rename_ext, arginfo_ldap_rename_ext)
4875 PHP_FE(ldap_get_option, arginfo_ldap_get_option)
4876 PHP_FE(ldap_set_option, arginfo_ldap_set_option)
4877 PHP_FE(ldap_first_reference, arginfo_ldap_first_reference)
4878 PHP_FE(ldap_next_reference, arginfo_ldap_next_reference)
4879 #ifdef HAVE_LDAP_PARSE_REFERENCE
4880 PHP_FE(ldap_parse_reference, arginfo_ldap_parse_reference)
4881 #endif
4882 #ifdef HAVE_LDAP_PARSE_RESULT
4883 PHP_FE(ldap_parse_result, arginfo_ldap_parse_result)
4884 #endif
4885 #ifdef HAVE_LDAP_START_TLS_S
4886 PHP_FE(ldap_start_tls, arginfo_ldap_resource)
4887 #endif
4888 #ifdef HAVE_LDAP_EXTENDED_OPERATION_S
4889 PHP_FE(ldap_exop, arginfo_ldap_exop)
4890 #endif
4891 #ifdef HAVE_LDAP_PASSWD
4892 PHP_FE(ldap_exop_passwd, arginfo_ldap_exop_passwd)
4893 #endif
4894 #ifdef HAVE_LDAP_WHOAMI_S
4895 PHP_FE(ldap_exop_whoami, arginfo_ldap_exop_whoami)
4896 #endif
4897 #ifdef HAVE_LDAP_REFRESH_S
4898 PHP_FE(ldap_exop_refresh, arginfo_ldap_exop_refresh)
4899 #endif
4900 #ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
4901 PHP_FE(ldap_parse_exop, arginfo_ldap_parse_exop)
4902 #endif
4903 #endif
4904
4905 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
4906 PHP_FE(ldap_set_rebind_proc, arginfo_ldap_set_rebind_proc)
4907 #endif
4908
4909 PHP_FE(ldap_escape, arginfo_ldap_escape)
4910
4911 #ifdef STR_TRANSLATION
4912 PHP_FE(ldap_t61_to_8859, arginfo_ldap_t61_to_8859)
4913 PHP_FE(ldap_8859_to_t61, arginfo_ldap_8859_to_t61)
4914 #endif
4915
4916 #ifdef LDAP_CONTROL_PAGEDRESULTS
4917 PHP_DEP_FE(ldap_control_paged_result, arginfo_ldap_control_paged_result)
4918 PHP_DEP_FE(ldap_control_paged_result_response, arginfo_ldap_control_paged_result_response)
4919 #endif
4920 PHP_FE_END
4921 };
4922 /* }}} */
4923
4924 zend_module_entry ldap_module_entry = { /* {{{ */
4925 STANDARD_MODULE_HEADER,
4926 "ldap",
4927 ldap_functions,
4928 PHP_MINIT(ldap),
4929 PHP_MSHUTDOWN(ldap),
4930 NULL,
4931 NULL,
4932 PHP_MINFO(ldap),
4933 PHP_LDAP_VERSION,
4934 PHP_MODULE_GLOBALS(ldap),
4935 PHP_GINIT(ldap),
4936 NULL,
4937 NULL,
4938 STANDARD_MODULE_PROPERTIES_EX
4939 };
4940 /* }}} */
4941