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