1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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 : | PHP 4.0 updates: Zeev Suraski <zeev@zend.com> |
23 : +----------------------------------------------------------------------+
24 : */
25 :
26 : /* $Id: ldap.c 287936 2009-09-01 08:42:10Z patrickallaert $ */
27 : #define IS_EXT_MODULE
28 :
29 : #ifdef HAVE_CONFIG_H
30 : #include "config.h"
31 : #endif
32 :
33 : /* Additional headers for NetWare */
34 : #if defined(NETWARE) && (NEW_LIBC)
35 : #include <sys/select.h>
36 : #include <sys/timeval.h>
37 : #endif
38 :
39 : #include "php.h"
40 : #include "php_ini.h"
41 :
42 : #include <stddef.h>
43 :
44 : #include "ext/standard/dl.h"
45 : #include "php_ldap.h"
46 :
47 : #ifdef PHP_WIN32
48 : #include <string.h>
49 : #if HAVE_NSLDAP
50 : #include <winsock2.h>
51 : #endif
52 : #define strdup _strdup
53 : #undef WINDOWS
54 : #undef strcasecmp
55 : #undef strncasecmp
56 : #define WINSOCK 1
57 : #define __STDC__ 1
58 : #endif
59 :
60 : #include "ext/standard/php_string.h"
61 : #include "ext/standard/info.h"
62 :
63 : #ifdef HAVE_LDAP_SASL_H
64 : #include <sasl.h>
65 : #elif defined(HAVE_LDAP_SASL_SASL_H)
66 : #include <sasl/sasl.h>
67 : #endif
68 :
69 : typedef struct {
70 : LDAP *link;
71 : #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
72 : zval *rebindproc;
73 : #endif
74 : } ldap_linkdata;
75 :
76 : typedef struct {
77 : LDAPMessage *data;
78 : BerElement *ber;
79 : int id;
80 : } ldap_resultentry;
81 :
82 : ZEND_DECLARE_MODULE_GLOBALS(ldap)
83 : static PHP_GINIT_FUNCTION(ldap);
84 :
85 : static
86 : ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0)
87 : ZEND_ARG_PASS_INFO(0)
88 : ZEND_ARG_PASS_INFO(0)
89 : ZEND_ARG_PASS_INFO(1)
90 : ZEND_ARG_PASS_INFO(1)
91 : ZEND_ARG_PASS_INFO(1)
92 : ZEND_ARG_PASS_INFO(1)
93 : ZEND_END_ARG_INFO();
94 :
95 : static int le_link, le_result, le_result_entry;
96 :
97 : /*
98 : This is just a small subset of the functionality provided by the LDAP library. All the
99 : operations are synchronous. Referrals are not handled automatically.
100 : */
101 : /* {{{ ldap_functions[]
102 : */
103 : zend_function_entry ldap_functions[] = {
104 : PHP_FE(ldap_connect, NULL)
105 : PHP_FALIAS(ldap_close, ldap_unbind, NULL)
106 : PHP_FE(ldap_bind, NULL)
107 : #ifdef HAVE_LDAP_SASL
108 : PHP_FE(ldap_sasl_bind, NULL)
109 : #endif
110 : PHP_FE(ldap_unbind, NULL)
111 : PHP_FE(ldap_read, NULL)
112 : PHP_FE(ldap_list, NULL)
113 : PHP_FE(ldap_search, NULL)
114 : PHP_FE(ldap_free_result, NULL)
115 : PHP_FE(ldap_count_entries, NULL)
116 : PHP_FE(ldap_first_entry, NULL)
117 : PHP_FE(ldap_next_entry, NULL)
118 : PHP_FE(ldap_get_entries, NULL)
119 : PHP_FE(ldap_first_attribute, third_arg_force_ref)
120 : PHP_FE(ldap_next_attribute, third_arg_force_ref)
121 : PHP_FE(ldap_get_attributes, NULL)
122 : PHP_FALIAS(ldap_get_values, ldap_get_values_len, NULL)
123 : PHP_FE(ldap_get_values_len, NULL)
124 : PHP_FE(ldap_get_dn, NULL)
125 : PHP_FE(ldap_explode_dn, NULL)
126 : PHP_FE(ldap_dn2ufn, NULL)
127 : PHP_FE(ldap_add, NULL)
128 : PHP_FE(ldap_delete, NULL)
129 : PHP_FALIAS(ldap_modify, ldap_mod_replace, NULL)
130 :
131 : /* additional functions for attribute based modifications, Gerrit Thomson */
132 : PHP_FE(ldap_mod_add, NULL)
133 : PHP_FE(ldap_mod_replace, NULL)
134 : PHP_FE(ldap_mod_del, NULL)
135 : /* end gjt mod */
136 :
137 : PHP_FE(ldap_errno, NULL)
138 : PHP_FE(ldap_err2str, NULL)
139 : PHP_FE(ldap_error, NULL)
140 : PHP_FE(ldap_compare, NULL)
141 : PHP_FE(ldap_sort, NULL)
142 :
143 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
144 : PHP_FE(ldap_rename, NULL)
145 : PHP_FE(ldap_get_option, third_arg_force_ref)
146 : PHP_FE(ldap_set_option, NULL)
147 : PHP_FE(ldap_first_reference, NULL)
148 : PHP_FE(ldap_next_reference, NULL)
149 : #ifdef HAVE_LDAP_PARSE_REFERENCE
150 : PHP_FE(ldap_parse_reference, third_arg_force_ref)
151 : #endif
152 : #ifdef HAVE_LDAP_PARSE_RESULT
153 : PHP_FE(ldap_parse_result, arg3to6of6_force_ref)
154 : #endif
155 : #ifdef HAVE_LDAP_START_TLS_S
156 : PHP_FE(ldap_start_tls, NULL)
157 : #endif
158 : #endif
159 :
160 : #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
161 : PHP_FE(ldap_set_rebind_proc, NULL)
162 : #endif
163 :
164 : #ifdef STR_TRANSLATION
165 : PHP_FE(ldap_t61_to_8859, NULL)
166 : PHP_FE(ldap_8859_to_t61, NULL)
167 : #endif
168 :
169 : {NULL, NULL, NULL}
170 : };
171 : /* }}} */
172 :
173 : zend_module_entry ldap_module_entry = {
174 : STANDARD_MODULE_HEADER,
175 : "ldap",
176 : ldap_functions,
177 : PHP_MINIT(ldap),
178 : PHP_MSHUTDOWN(ldap),
179 : NULL,
180 : NULL,
181 : PHP_MINFO(ldap),
182 : NO_VERSION_YET,
183 : PHP_MODULE_GLOBALS(ldap),
184 : PHP_GINIT(ldap),
185 : NULL,
186 : NULL,
187 : STANDARD_MODULE_PROPERTIES_EX
188 : };
189 :
190 : #ifdef COMPILE_DL_LDAP
191 : ZEND_GET_MODULE(ldap)
192 : # ifdef PHP_WIN32
193 : # include "zend_arg_defs.c"
194 : # endif
195 : #endif
196 :
197 : static void _close_ldap_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
198 182 : {
199 182 : ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr;
200 :
201 182 : ldap_unbind_s(ld->link);
202 : #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
203 182 : if (ld->rebindproc != NULL) {
204 1 : zval_dtor(ld->rebindproc);
205 1 : FREE_ZVAL(ld->rebindproc);
206 : }
207 : #endif
208 182 : efree(ld);
209 182 : LDAPG(num_links)--;
210 182 : }
211 :
212 : static void _free_ldap_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
213 46 : {
214 46 : LDAPMessage *result = (LDAPMessage *)rsrc->ptr;
215 46 : ldap_msgfree(result);
216 46 : }
217 :
218 : static void _free_ldap_result_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
219 14 : {
220 14 : ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr;
221 :
222 14 : if (entry->ber != NULL) {
223 1 : ber_free(entry->ber, 0);
224 1 : entry->ber = NULL;
225 : }
226 14 : zend_list_delete(entry->id);
227 14 : efree(entry);
228 14 : }
229 :
230 : /* {{{ PHP_INI_BEGIN
231 : */
232 : PHP_INI_BEGIN()
233 : STD_PHP_INI_ENTRY_EX("ldap.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_ldap_globals, ldap_globals, display_link_numbers)
234 : PHP_INI_END()
235 : /* }}} */
236 :
237 : /* {{{ PHP_GINIT_FUNCTION
238 : */
239 : static PHP_GINIT_FUNCTION(ldap)
240 13565 : {
241 13565 : ldap_globals->num_links = 0;
242 13565 : }
243 : /* }}} */
244 :
245 : /* {{{ PHP_MINIT_FUNCTION
246 : */
247 : PHP_MINIT_FUNCTION(ldap)
248 13565 : {
249 13565 : REGISTER_INI_ENTRIES();
250 :
251 : /* Constants to be used with deref-parameter in php_ldap_do_search() */
252 13565 : REGISTER_LONG_CONSTANT("LDAP_DEREF_NEVER", LDAP_DEREF_NEVER, CONST_PERSISTENT | CONST_CS);
253 13565 : REGISTER_LONG_CONSTANT("LDAP_DEREF_SEARCHING", LDAP_DEREF_SEARCHING, CONST_PERSISTENT | CONST_CS);
254 13565 : REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, CONST_PERSISTENT | CONST_CS);
255 13565 : REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS);
256 :
257 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
258 : /* LDAP options */
259 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS);
260 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_SIZELIMIT", LDAP_OPT_SIZELIMIT, CONST_PERSISTENT | CONST_CS);
261 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_TIMELIMIT", LDAP_OPT_TIMELIMIT, CONST_PERSISTENT | CONST_CS);
262 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_PROTOCOL_VERSION", LDAP_OPT_PROTOCOL_VERSION, CONST_PERSISTENT | CONST_CS);
263 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_NUMBER", LDAP_OPT_ERROR_NUMBER, CONST_PERSISTENT | CONST_CS);
264 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_REFERRALS", LDAP_OPT_REFERRALS, CONST_PERSISTENT | CONST_CS);
265 : #ifdef LDAP_OPT_RESTART
266 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_RESTART", LDAP_OPT_RESTART, CONST_PERSISTENT | CONST_CS);
267 : #endif
268 : #ifdef LDAP_OPT_HOST_NAME
269 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_HOST_NAME", LDAP_OPT_HOST_NAME, CONST_PERSISTENT | CONST_CS);
270 : #endif
271 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_STRING", LDAP_OPT_ERROR_STRING, CONST_PERSISTENT | CONST_CS);
272 : #ifdef LDAP_OPT_MATCHED_DN
273 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_MATCHED_DN", LDAP_OPT_MATCHED_DN, CONST_PERSISTENT | CONST_CS);
274 : #endif
275 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_SERVER_CONTROLS", LDAP_OPT_SERVER_CONTROLS, CONST_PERSISTENT | CONST_CS);
276 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_CLIENT_CONTROLS", LDAP_OPT_CLIENT_CONTROLS, CONST_PERSISTENT | CONST_CS);
277 : #endif
278 : #ifdef LDAP_OPT_DEBUG_LEVEL
279 13565 : REGISTER_LONG_CONSTANT("LDAP_OPT_DEBUG_LEVEL", LDAP_OPT_DEBUG_LEVEL, CONST_PERSISTENT | CONST_CS);
280 : #endif
281 :
282 : #ifdef HAVE_LDAP_SASL
283 : REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_MECH", LDAP_OPT_X_SASL_MECH, CONST_PERSISTENT | CONST_CS);
284 : REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_REALM", LDAP_OPT_X_SASL_REALM, CONST_PERSISTENT | CONST_CS);
285 : REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHCID", LDAP_OPT_X_SASL_AUTHCID, CONST_PERSISTENT | CONST_CS);
286 : REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHZID", LDAP_OPT_X_SASL_AUTHZID, CONST_PERSISTENT | CONST_CS);
287 : #endif
288 :
289 : #ifdef ORALDAP
290 : REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT | CONST_CS);
291 : REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS);
292 : REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS);
293 : #endif
294 :
295 13565 : le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number);
296 13565 : le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number);
297 13565 : le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number);
298 :
299 13565 : Z_TYPE(ldap_module_entry) = type;
300 :
301 13565 : return SUCCESS;
302 : }
303 : /* }}} */
304 :
305 : /* {{{ PHP_MSHUTDOWN_FUNCTION
306 : */
307 : PHP_MSHUTDOWN_FUNCTION(ldap)
308 13597 : {
309 13597 : UNREGISTER_INI_ENTRIES();
310 13597 : return SUCCESS;
311 : }
312 : /* }}} */
313 :
314 : /* {{{ PHP_MINFO_FUNCTION
315 : */
316 : PHP_MINFO_FUNCTION(ldap)
317 6 : {
318 : char tmp[32];
319 : #if HAVE_NSLDAP
320 : LDAPVersion ver;
321 : double SDKVersion;
322 : #endif
323 :
324 6 : php_info_print_table_start();
325 6 : php_info_print_table_row(2, "LDAP Support", "enabled");
326 6 : php_info_print_table_row(2, "RCS Version", "$Id: ldap.c 287936 2009-09-01 08:42:10Z patrickallaert $");
327 :
328 6 : if (LDAPG(max_links) == -1) {
329 6 : snprintf(tmp, 31, "%ld/unlimited", LDAPG(num_links));
330 : } else {
331 0 : snprintf(tmp, 31, "%ld/%ld", LDAPG(num_links), LDAPG(max_links));
332 : }
333 6 : php_info_print_table_row(2, "Total Links", tmp);
334 :
335 : #ifdef LDAP_API_VERSION
336 6 : snprintf(tmp, 31, "%d", LDAP_API_VERSION);
337 6 : php_info_print_table_row(2, "API Version", tmp);
338 : #endif
339 :
340 : #ifdef LDAP_VENDOR_NAME
341 6 : php_info_print_table_row(2, "Vendor Name", LDAP_VENDOR_NAME);
342 : #endif
343 :
344 : #ifdef LDAP_VENDOR_VERSION
345 6 : snprintf(tmp, 31, "%d", LDAP_VENDOR_VERSION);
346 6 : php_info_print_table_row(2, "Vendor Version", tmp);
347 : #endif
348 :
349 : #if HAVE_NSLDAP
350 : SDKVersion = ldap_version(&ver);
351 : snprintf(tmp, 31, "%F", SDKVersion/100.0);
352 : php_info_print_table_row(2, "SDK Version", tmp);
353 :
354 : snprintf(tmp, 31, "%F", ver.protocol_version/100.0);
355 : php_info_print_table_row(2, "Highest LDAP Protocol Supported", tmp);
356 :
357 : snprintf(tmp, 31, "%F", ver.SSL_version/100.0);
358 : php_info_print_table_row(2, "SSL Level Supported", tmp);
359 :
360 : if (ver.security_level != LDAP_SECURITY_NONE) {
361 : snprintf(tmp, 31, "%d", ver.security_level);
362 : } else {
363 : strcpy(tmp, "SSL not enabled");
364 : }
365 : php_info_print_table_row(2, "Level of Encryption", tmp);
366 : #endif
367 :
368 : #ifdef HAVE_LDAP_SASL
369 : php_info_print_table_row(2, "SASL Support", "Enabled");
370 : #endif
371 :
372 6 : php_info_print_table_end();
373 6 : }
374 : /* }}} */
375 :
376 : /* {{{ proto resource ldap_connect([string host [, int port]])
377 : Connect to an LDAP server */
378 : PHP_FUNCTION(ldap_connect)
379 185 : {
380 185 : char *host = NULL;
381 : int hostlen;
382 185 : long port = 389; /* Default port */
383 : #ifdef HAVE_ORALDAP
384 : char *wallet = NULL, *walletpasswd = NULL;
385 : int walletlen = 0, walletpasswdlen = 0;
386 : long authmode = GSLC_SSL_NO_AUTH;
387 : int ssl=0;
388 : #endif
389 : ldap_linkdata *ld;
390 : LDAP *ldap;
391 :
392 : #ifdef HAVE_ORALDAP
393 : if (ZEND_NUM_ARGS() == 3 || ZEND_NUM_ARGS() == 4) {
394 : WRONG_PARAM_COUNT;
395 : }
396 :
397 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|slssl", &host, &hostlen, &port, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) == FAILURE) {
398 : RETURN_FALSE;
399 : }
400 :
401 : if (ZEND_NUM_ARGS() == 5) {
402 : ssl = 1;
403 : }
404 : #else
405 185 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &host, &hostlen, &port) == FAILURE) {
406 1 : RETURN_FALSE;
407 : }
408 : #endif
409 :
410 184 : if (LDAPG(max_links) != -1 && LDAPG(num_links) >= LDAPG(max_links)) {
411 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", LDAPG(num_links));
412 1 : RETURN_FALSE;
413 : }
414 :
415 183 : ld = ecalloc(1, sizeof(ldap_linkdata));
416 :
417 : #ifdef LDAP_API_FEATURE_X_OPENLDAP
418 185 : if (host != NULL && strchr(host, '/')) {
419 : int rc;
420 :
421 3 : rc = ldap_initialize(&ldap, host);
422 3 : if (rc != LDAP_SUCCESS) {
423 1 : efree(ld);
424 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
425 1 : RETURN_FALSE;
426 : }
427 : } else {
428 180 : ldap = ldap_init(host, port);
429 : }
430 : #else
431 : ldap = ldap_open(host, port);
432 : #endif
433 :
434 182 : if (ldap == NULL) {
435 0 : efree(ld);
436 0 : RETURN_FALSE;
437 : } else {
438 : #ifdef HAVE_ORALDAP
439 : if (ssl) {
440 : if (ldap_init_SSL(&ldap->ld_sb, wallet, walletpasswd, authmode)) {
441 : efree(ld);
442 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL init failed");
443 : RETURN_FALSE;
444 : }
445 : }
446 : #endif
447 182 : LDAPG(num_links)++;
448 182 : ld->link = ldap;
449 182 : ZEND_REGISTER_RESOURCE(return_value, ld, le_link);
450 : }
451 :
452 : }
453 : /* }}} */
454 :
455 : /* {{{ _get_lderrno
456 : */
457 : static int _get_lderrno(LDAP *ldap)
458 15 : {
459 : #if !HAVE_NSLDAP
460 : #if LDAP_API_VERSION > 2000 || HAVE_ORALDAP_10
461 : int lderr;
462 :
463 : /* New versions of OpenLDAP do it this way */
464 15 : ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr);
465 15 : return lderr;
466 : #else
467 : return ldap->ld_errno;
468 : #endif
469 : #else
470 : return ldap_get_lderrno(ldap, NULL, NULL);
471 : #endif
472 : }
473 : /* }}} */
474 :
475 : /* {{{ proto bool ldap_bind(resource link [, string dn [, string password]])
476 : Bind to LDAP directory */
477 : PHP_FUNCTION(ldap_bind)
478 152 : {
479 : zval *link;
480 152 : char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
481 : int ldap_bind_dnlen, ldap_bind_pwlen;
482 : ldap_linkdata *ld;
483 : int rc;
484 :
485 152 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ss", &link, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen) == FAILURE) {
486 1 : RETURN_FALSE;
487 : }
488 :
489 151 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
490 :
491 151 : if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
492 2 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
493 2 : RETURN_FALSE;
494 : } else {
495 149 : RETURN_TRUE;
496 : }
497 : }
498 : /* }}} */
499 :
500 : #ifdef HAVE_LDAP_SASL
501 : typedef struct {
502 : char *mech;
503 : char *realm;
504 : char *authcid;
505 : char *passwd;
506 : char *authzid;
507 : } php_ldap_bictx;
508 :
509 : /* {{{ _php_sasl_setdefs
510 : */
511 : 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)
512 : {
513 : php_ldap_bictx *ctx;
514 :
515 : ctx = ber_memalloc(sizeof(php_ldap_bictx));
516 : ctx->mech = (sasl_mech) ? ber_strdup(sasl_mech) : NULL;
517 : ctx->realm = (sasl_realm) ? ber_strdup(sasl_realm) : NULL;
518 : ctx->authcid = (sasl_authc_id) ? ber_strdup(sasl_authc_id) : NULL;
519 : ctx->passwd = (passwd) ? ber_strdup(passwd) : NULL;
520 : ctx->authzid = (sasl_authz_id) ? ber_strdup(sasl_authz_id) : NULL;
521 :
522 : if (ctx->mech == NULL) {
523 : ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &ctx->mech);
524 : }
525 : if (ctx->realm == NULL) {
526 : ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &ctx->realm);
527 : }
528 : if (ctx->authcid == NULL) {
529 : ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &ctx->authcid);
530 : }
531 : if (ctx->authzid == NULL) {
532 : ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &ctx->authzid);
533 : }
534 :
535 : return ctx;
536 : }
537 : /* }}} */
538 :
539 : /* {{{ _php_sasl_freedefs
540 : */
541 : static void _php_sasl_freedefs(php_ldap_bictx *ctx)
542 : {
543 : if (ctx->mech) ber_memfree(ctx->mech);
544 : if (ctx->realm) ber_memfree(ctx->realm);
545 : if (ctx->authcid) ber_memfree(ctx->authcid);
546 : if (ctx->passwd) ber_memfree(ctx->passwd);
547 : if (ctx->authzid) ber_memfree(ctx->authzid);
548 : ber_memfree(ctx);
549 : }
550 : /* }}} */
551 :
552 : /* {{{ _php_sasl_interact
553 : Internal interact function for SASL */
554 : static int _php_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
555 : {
556 : sasl_interact_t *interact = in;
557 : const char *p;
558 : php_ldap_bictx *ctx = defaults;
559 :
560 : for (;interact->id != SASL_CB_LIST_END;interact++) {
561 : p = NULL;
562 : switch(interact->id) {
563 : case SASL_CB_GETREALM:
564 : p = ctx->realm;
565 : break;
566 : case SASL_CB_AUTHNAME:
567 : p = ctx->authcid;
568 : break;
569 : case SASL_CB_USER:
570 : p = ctx->authzid;
571 : break;
572 : case SASL_CB_PASS:
573 : p = ctx->passwd;
574 : break;
575 : }
576 : if (p) {
577 : interact->result = p;
578 : interact->len = strlen(interact->result);
579 : }
580 : }
581 : return LDAP_SUCCESS;
582 : }
583 : /* }}} */
584 :
585 : /* {{{ 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]]]]]]])
586 : Bind to LDAP directory using SASL */
587 : PHP_FUNCTION(ldap_sasl_bind)
588 : {
589 : zval *link;
590 : ldap_linkdata *ld;
591 : char *binddn = NULL;
592 : char *passwd = NULL;
593 : char *sasl_mech = NULL;
594 : char *sasl_realm = NULL;
595 : char *sasl_authz_id = NULL;
596 : char *sasl_authc_id = NULL;
597 : char *props = NULL;
598 : int rc, dn_len, passwd_len, mech_len, realm_len, authc_id_len, authz_id_len, props_len;
599 : php_ldap_bictx *ctx;
600 :
601 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "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) == FAILURE) {
602 : RETURN_FALSE;
603 : }
604 :
605 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
606 :
607 : ctx = _php_sasl_setdefs(ld->link, sasl_mech, sasl_realm, sasl_authc_id, passwd, sasl_authz_id);
608 :
609 : if (props) {
610 : ldap_set_option(ld->link, LDAP_OPT_X_SASL_SECPROPS, props);
611 : }
612 :
613 : rc = ldap_sasl_interactive_bind_s(ld->link, binddn, ctx->mech, NULL, NULL, LDAP_SASL_QUIET, _php_sasl_interact, ctx);
614 : if (rc != LDAP_SUCCESS) {
615 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
616 : RETVAL_FALSE;
617 : } else {
618 : RETVAL_TRUE;
619 : }
620 : _php_sasl_freedefs(ctx);
621 : }
622 : /* }}} */
623 : #endif /* HAVE_LDAP_SASL */
624 :
625 : /* {{{ proto bool ldap_unbind(resource link)
626 : Unbind from LDAP directory */
627 : PHP_FUNCTION(ldap_unbind)
628 60 : {
629 : zval *link;
630 : ldap_linkdata *ld;
631 :
632 60 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &link) == FAILURE) {
633 3 : RETURN_FALSE;
634 : }
635 :
636 57 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
637 :
638 56 : zend_list_delete(Z_LVAL_P(link));
639 56 : RETURN_TRUE;
640 : }
641 : /* }}} */
642 :
643 : /* {{{ php_set_opts
644 : */
645 : static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, int *old_sizelimit, int *old_timelimit, int *old_deref)
646 93 : {
647 : /* sizelimit */
648 93 : if (sizelimit > -1) {
649 : #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
650 14 : ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_sizelimit);
651 14 : ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit);
652 : #else
653 : *old_sizelimit = ldap->ld_sizelimit;
654 : ldap->ld_sizelimit = sizelimit;
655 : #endif
656 : }
657 :
658 : /* timelimit */
659 93 : if (timelimit > -1) {
660 : #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
661 10 : ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_timelimit);
662 10 : ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit);
663 : #else
664 : *old_timelimit = ldap->ld_timelimit;
665 : ldap->ld_timelimit = timelimit;
666 : #endif
667 : }
668 :
669 : /* deref */
670 93 : if (deref > -1) {
671 : #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
672 8 : ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_deref);
673 8 : ldap_set_option(ldap, LDAP_OPT_DEREF, &deref);
674 : #else
675 : *old_deref = ldap->ld_deref;
676 : ldap->ld_deref = deref;
677 : #endif
678 : }
679 93 : }
680 : /* }}} */
681 :
682 : /* {{{ php_ldap_do_search
683 : */
684 : static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
685 60 : {
686 : zval **link, **base_dn, **filter, **attrs, **attr, **attrsonly, **sizelimit, **timelimit, **deref;
687 60 : char *ldap_base_dn = NULL;
688 60 : char *ldap_filter = NULL;
689 60 : char **ldap_attrs = NULL;
690 60 : ldap_linkdata *ld = NULL;
691 : LDAPMessage *ldap_res;
692 60 : int ldap_attrsonly = 0;
693 60 : int ldap_sizelimit = -1;
694 60 : int ldap_timelimit = -1;
695 60 : int ldap_deref = -1;
696 60 : int old_ldap_sizelimit = -1;
697 60 : int old_ldap_timelimit = -1;
698 60 : int old_ldap_deref = -1;
699 60 : int num_attribs = 0;
700 : int i, errno;
701 60 : int myargcount = ZEND_NUM_ARGS();
702 60 : int ret = 1;
703 :
704 60 : if (myargcount < 3 || myargcount > 8 || zend_get_parameters_ex(myargcount, &link, &base_dn, &filter, &attrs, &attrsonly, &sizelimit, &timelimit, &deref) == FAILURE) {
705 9 : WRONG_PARAM_COUNT;
706 : }
707 :
708 : /* Reverse -> fall through */
709 51 : switch (myargcount) {
710 : case 8 :
711 4 : convert_to_long_ex(deref);
712 4 : ldap_deref = Z_LVAL_PP(deref);
713 :
714 : case 7 :
715 5 : convert_to_long_ex(timelimit);
716 5 : ldap_timelimit = Z_LVAL_PP(timelimit);
717 :
718 : case 6 :
719 7 : convert_to_long_ex(sizelimit);
720 7 : ldap_sizelimit = Z_LVAL_PP(sizelimit);
721 :
722 : case 5 :
723 8 : convert_to_long_ex(attrsonly);
724 8 : ldap_attrsonly = Z_LVAL_PP(attrsonly);
725 :
726 : case 4 :
727 21 : if (Z_TYPE_PP(attrs) != IS_ARRAY) {
728 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected Array as last element");
729 1 : ret = 0;
730 1 : goto cleanup;
731 : }
732 :
733 20 : num_attribs = zend_hash_num_elements(Z_ARRVAL_PP(attrs));
734 20 : ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
735 :
736 43 : for (i = 0; i<num_attribs; i++) {
737 24 : if (zend_hash_index_find(Z_ARRVAL_PP(attrs), i, (void **) &attr) == FAILURE) {
738 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array initialization wrong");
739 1 : ret = 0;
740 1 : goto cleanup;
741 : }
742 :
743 23 : SEPARATE_ZVAL(attr);
744 23 : convert_to_string_ex(attr);
745 23 : ldap_attrs[i] = Z_STRVAL_PP(attr);
746 : }
747 19 : ldap_attrs[num_attribs] = NULL;
748 :
749 : case 3 :
750 :
751 : break;
752 :
753 : default:
754 0 : WRONG_PARAM_COUNT;
755 : break;
756 : }
757 :
758 : /* parallel search? */
759 49 : if (Z_TYPE_PP(link) == IS_ARRAY) {
760 : int i, nlinks, nbases, nfilters, *rcs;
761 : ldap_linkdata **lds;
762 : zval **entry, *resource;
763 :
764 6 : nlinks = zend_hash_num_elements(Z_ARRVAL_PP(link));
765 6 : if (nlinks == 0) {
766 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "No links in link array");
767 1 : ret = 0;
768 1 : goto cleanup;
769 : }
770 :
771 5 : if (Z_TYPE_PP(base_dn) == IS_ARRAY) {
772 1 : nbases = zend_hash_num_elements(Z_ARRVAL_PP(base_dn));
773 1 : if (nbases != nlinks) {
774 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Base must either be a string, or an array with the same number of elements as the links array");
775 1 : ret = 0;
776 1 : goto cleanup;
777 : }
778 0 : zend_hash_internal_pointer_reset(Z_ARRVAL_PP(base_dn));
779 : } else {
780 4 : nbases = 0; /* this means string, not array */
781 : /* If anything else than string is passed, ldap_base_dn = NULL */
782 4 : if (Z_TYPE_PP(base_dn) == IS_STRING) {
783 2 : ldap_base_dn = Z_STRVAL_PP(base_dn);
784 : } else {
785 2 : ldap_base_dn = NULL;
786 : }
787 : }
788 :
789 4 : if (Z_TYPE_PP(filter) == IS_ARRAY) {
790 2 : nfilters = zend_hash_num_elements(Z_ARRVAL_PP(filter));
791 2 : if (nfilters != nlinks) {
792 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter must either be a string, or an array with the same number of elements as the links array");
793 1 : ret = 0;
794 1 : goto cleanup;
795 : }
796 1 : zend_hash_internal_pointer_reset(Z_ARRVAL_PP(filter));
797 : } else {
798 2 : nfilters = 0; /* this means string, not array */
799 2 : convert_to_string_ex(filter);
800 2 : ldap_filter = Z_STRVAL_PP(filter);
801 : }
802 :
803 3 : lds = safe_emalloc(nlinks, sizeof(ldap_linkdata), 0);
804 3 : rcs = safe_emalloc(nlinks, sizeof(*rcs), 0);
805 :
806 3 : zend_hash_internal_pointer_reset(Z_ARRVAL_PP(link));
807 9 : for (i=0; i<nlinks; i++) {
808 6 : zend_hash_get_current_data(Z_ARRVAL_PP(link), (void **)&entry);
809 :
810 6 : ld = (ldap_linkdata *) zend_fetch_resource(entry TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
811 6 : if (ld == NULL) {
812 0 : ret = 0;
813 0 : goto cleanup_parallel;
814 : }
815 6 : if (nbases != 0) { /* base_dn an array? */
816 0 : zend_hash_get_current_data(Z_ARRVAL_PP(base_dn), (void **)&entry);
817 0 : zend_hash_move_forward(Z_ARRVAL_PP(base_dn));
818 :
819 : /* If anything else than string is passed, ldap_base_dn = NULL */
820 0 : if (Z_TYPE_PP(entry) == IS_STRING) {
821 0 : ldap_base_dn = Z_STRVAL_PP(entry);
822 : } else {
823 0 : ldap_base_dn = NULL;
824 : }
825 : }
826 6 : if (nfilters != 0) { /* filter an array? */
827 2 : zend_hash_get_current_data(Z_ARRVAL_PP(filter), (void **)&entry);
828 2 : zend_hash_move_forward(Z_ARRVAL_PP(filter));
829 2 : convert_to_string_ex(entry);
830 2 : ldap_filter = Z_STRVAL_PP(entry);
831 : }
832 :
833 6 : php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
834 :
835 : /* Run the actual search */
836 6 : rcs[i] = ldap_search(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly);
837 6 : lds[i] = ld;
838 6 : zend_hash_move_forward(Z_ARRVAL_PP(link));
839 : }
840 :
841 3 : array_init(return_value);
842 :
843 : /* Collect results from the searches */
844 9 : for (i=0; i<nlinks; i++) {
845 6 : MAKE_STD_ZVAL(resource);
846 6 : if (rcs[i] != -1) {
847 6 : rcs[i] = ldap_result(lds[i]->link, LDAP_RES_ANY, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
848 : }
849 6 : if (rcs[i] != -1) {
850 6 : ZEND_REGISTER_RESOURCE(resource, ldap_res, le_result);
851 6 : add_next_index_zval(return_value, resource);
852 : } else {
853 0 : add_next_index_bool(return_value, 0);
854 : }
855 : }
856 :
857 3 : cleanup_parallel:
858 3 : efree(lds);
859 3 : efree(rcs);
860 : } else {
861 43 : convert_to_string_ex(filter);
862 43 : ldap_filter = Z_STRVAL_PP(filter);
863 :
864 : /* If anything else than string is passed, ldap_base_dn = NULL */
865 43 : if (Z_TYPE_PP(base_dn) == IS_STRING) {
866 42 : ldap_base_dn = Z_STRVAL_PP(base_dn);
867 : }
868 :
869 43 : ld = (ldap_linkdata *) zend_fetch_resource(link TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
870 43 : if (ld == NULL) {
871 1 : ret = 0;
872 1 : goto cleanup;
873 : }
874 :
875 42 : php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
876 :
877 : /* Run the actual search */
878 42 : errno = ldap_search_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, &ldap_res);
879 :
880 44 : if (errno != LDAP_SUCCESS
881 : && errno != LDAP_SIZELIMIT_EXCEEDED
882 : #ifdef LDAP_ADMINLIMIT_EXCEEDED
883 : && errno != LDAP_ADMINLIMIT_EXCEEDED
884 : #endif
885 : #ifdef LDAP_REFERRAL
886 : && errno != LDAP_REFERRAL
887 : #endif
888 : ) {
889 2 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Search: %s", ldap_err2string(errno));
890 2 : ret = 0;
891 : } else {
892 40 : if (errno == LDAP_SIZELIMIT_EXCEEDED) {
893 6 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Partial search results returned: Sizelimit exceeded");
894 : }
895 : #ifdef LDAP_ADMINLIMIT_EXCEEDED
896 34 : else if (errno == LDAP_ADMINLIMIT_EXCEEDED) {
897 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Partial search results returned: Adminlimit exceeded");
898 : }
899 : #endif
900 :
901 40 : ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
902 : }
903 : }
904 :
905 51 : cleanup:
906 51 : if (ld) {
907 : /* Restoring previous options */
908 45 : php_set_opts(ld->link, old_ldap_sizelimit, old_ldap_timelimit, old_ldap_deref, &ldap_sizelimit, &ldap_timelimit, &ldap_deref);
909 : }
910 51 : if (ldap_attrs != NULL) {
911 20 : efree(ldap_attrs);
912 : }
913 51 : if (!ret) {
914 8 : RETVAL_BOOL(ret);
915 : }
916 : }
917 : /* }}} */
918 :
919 : /* {{{ proto resource ldap_read(resource link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
920 : Read an entry */
921 : PHP_FUNCTION(ldap_read)
922 6 : {
923 6 : php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_BASE);
924 6 : }
925 : /* }}} */
926 :
927 : /* {{{ proto resource ldap_list(resource link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
928 : Single-level search */
929 : PHP_FUNCTION(ldap_list)
930 6 : {
931 6 : php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_ONELEVEL);
932 6 : }
933 : /* }}} */
934 :
935 : /* {{{ proto resource ldap_search(resource link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
936 : Search LDAP tree under base_dn */
937 : PHP_FUNCTION(ldap_search)
938 48 : {
939 48 : php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_SUBTREE);
940 48 : }
941 : /* }}} */
942 :
943 : /* {{{ proto bool ldap_free_result(resource result)
944 : Free result memory */
945 : PHP_FUNCTION(ldap_free_result)
946 3 : {
947 : zval **result;
948 : LDAPMessage *ldap_result;
949 :
950 3 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &result) == FAILURE) {
951 1 : WRONG_PARAM_COUNT;
952 : }
953 :
954 2 : ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
955 :
956 1 : zend_list_delete(Z_LVAL_PP(result)); /* Delete list entry and call registered destructor function */
957 1 : RETVAL_TRUE;
958 : }
959 : /* }}} */
960 :
961 : /* {{{ proto int ldap_count_entries(resource link, resource result)
962 : Count the number of entries in a search result */
963 : PHP_FUNCTION(ldap_count_entries)
964 3 : {
965 : zval **link, **result;
966 : ldap_linkdata *ld;
967 : LDAPMessage *ldap_result;
968 :
969 3 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
970 1 : WRONG_PARAM_COUNT;
971 : }
972 :
973 2 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
974 2 : ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
975 :
976 1 : RETURN_LONG(ldap_count_entries(ld->link, ldap_result));
977 : }
978 : /* }}} */
979 :
980 : /* {{{ proto resource ldap_first_entry(resource link, resource result)
981 : Return first result id */
982 : PHP_FUNCTION(ldap_first_entry)
983 12 : {
984 : zval **link, **result;
985 : ldap_linkdata *ld;
986 : ldap_resultentry *resultentry;
987 : LDAPMessage *ldap_result, *entry;
988 :
989 12 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
990 2 : WRONG_PARAM_COUNT;
991 : }
992 :
993 10 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
994 10 : ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
995 :
996 9 : if ((entry = ldap_first_entry(ld->link, ldap_result)) == NULL) {
997 0 : RETVAL_FALSE;
998 : } else {
999 9 : resultentry = emalloc(sizeof(ldap_resultentry));
1000 9 : ZEND_REGISTER_RESOURCE(return_value, resultentry, le_result_entry);
1001 9 : resultentry->id = Z_LVAL_PP(result);
1002 9 : zend_list_addref(resultentry->id);
1003 9 : resultentry->data = entry;
1004 9 : resultentry->ber = NULL;
1005 : }
1006 : }
1007 : /* }}} */
1008 :
1009 : /* {{{ proto resource ldap_next_entry(resource link, resource result_entry)
1010 : Get next result entry */
1011 : PHP_FUNCTION(ldap_next_entry)
1012 5 : {
1013 : zval **link, **result_entry;
1014 : ldap_linkdata *ld;
1015 : ldap_resultentry *resultentry, *resultentry_next;
1016 : LDAPMessage *entry_next;
1017 :
1018 5 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
1019 2 : WRONG_PARAM_COUNT;
1020 : }
1021 :
1022 3 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1023 3 : ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
1024 :
1025 2 : if ((entry_next = ldap_next_entry(ld->link, resultentry->data)) == NULL) {
1026 1 : RETVAL_FALSE;
1027 : } else {
1028 1 : resultentry_next = emalloc(sizeof(ldap_resultentry));
1029 1 : ZEND_REGISTER_RESOURCE(return_value, resultentry_next, le_result_entry);
1030 1 : resultentry_next->id = resultentry->id;
1031 1 : zend_list_addref(resultentry->id);
1032 1 : resultentry_next->data = entry_next;
1033 1 : resultentry_next->ber = NULL;
1034 : }
1035 : }
1036 : /* }}} */
1037 :
1038 : /* {{{ proto array ldap_get_entries(resource link, resource result)
1039 : Get all result entries */
1040 : PHP_FUNCTION(ldap_get_entries)
1041 33 : {
1042 : zval **link, **result;
1043 : LDAPMessage *ldap_result, *ldap_result_entry;
1044 : zval *tmp1, *tmp2;
1045 : ldap_linkdata *ld;
1046 : LDAP *ldap;
1047 : int num_entries, num_attrib, num_values, i;
1048 : BerElement *ber;
1049 : char *attribute;
1050 : size_t attr_len;
1051 : struct berval **ldap_value;
1052 : char *dn;
1053 :
1054 33 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
1055 2 : WRONG_PARAM_COUNT;
1056 : }
1057 :
1058 31 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1059 31 : ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
1060 :
1061 30 : ldap = ld->link;
1062 30 : num_entries = ldap_count_entries(ldap, ldap_result);
1063 :
1064 30 : if (num_entries == 0) return;
1065 24 : num_entries = 0;
1066 :
1067 24 : ldap_result_entry = ldap_first_entry(ldap, ldap_result);
1068 24 : if (ldap_result_entry == NULL) RETURN_FALSE;
1069 :
1070 24 : array_init(return_value);
1071 24 : add_assoc_long(return_value, "count", num_entries);
1072 :
1073 97 : while (ldap_result_entry != NULL) {
1074 :
1075 49 : MAKE_STD_ZVAL(tmp1);
1076 49 : array_init(tmp1);
1077 :
1078 49 : num_attrib = 0;
1079 49 : attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber);
1080 :
1081 215 : while (attribute != NULL) {
1082 117 : ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute);
1083 117 : num_values = ldap_count_values_len(ldap_value);
1084 :
1085 117 : MAKE_STD_ZVAL(tmp2);
1086 117 : array_init(tmp2);
1087 117 : add_assoc_long(tmp2, "count", num_values);
1088 232 : for (i = 0; i < num_values; i++) {
1089 115 : add_index_stringl(tmp2, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1);
1090 : }
1091 117 : ldap_value_free_len(ldap_value);
1092 :
1093 117 : attr_len = strlen(attribute);
1094 117 : zend_hash_update(Z_ARRVAL_P(tmp1), php_strtolower(attribute, attr_len), attr_len+1, (void *) &tmp2, sizeof(zval *), NULL);
1095 117 : add_index_string(tmp1, num_attrib, attribute, 1);
1096 :
1097 117 : num_attrib++;
1098 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1099 117 : ldap_memfree(attribute);
1100 : #endif
1101 117 : attribute = ldap_next_attribute(ldap, ldap_result_entry, ber);
1102 : }
1103 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1104 49 : if (ber != NULL) {
1105 49 : ber_free(ber, 0);
1106 : }
1107 : #endif
1108 :
1109 49 : add_assoc_long(tmp1, "count", num_attrib);
1110 49 : dn = ldap_get_dn(ldap, ldap_result_entry);
1111 49 : add_assoc_string(tmp1, "dn", dn, 1);
1112 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1113 49 : ldap_memfree(dn);
1114 : #else
1115 : free(dn);
1116 : #endif
1117 :
1118 49 : zend_hash_index_update(Z_ARRVAL_P(return_value), num_entries, (void *) &tmp1, sizeof(zval *), NULL);
1119 :
1120 49 : num_entries++;
1121 49 : ldap_result_entry = ldap_next_entry(ldap, ldap_result_entry);
1122 : }
1123 :
1124 24 : add_assoc_long(return_value, "count", num_entries);
1125 :
1126 : }
1127 : /* }}} */
1128 :
1129 : /* {{{ proto string ldap_first_attribute(resource link, resource result_entry)
1130 : Return first attribute */
1131 : PHP_FUNCTION(ldap_first_attribute)
1132 4 : {
1133 : zval **link, **result_entry;
1134 : ldap_linkdata *ld;
1135 : ldap_resultentry *resultentry;
1136 : char *attribute;
1137 4 : int argc = ZEND_NUM_ARGS();
1138 :
1139 4 : if ((argc < 2 || argc > 3) || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
1140 1 : WRONG_PARAM_COUNT;
1141 : }
1142 :
1143 3 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1144 3 : ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
1145 :
1146 2 : if ((attribute = ldap_first_attribute(ld->link, resultentry->data, &resultentry->ber)) == NULL) {
1147 0 : RETURN_FALSE;
1148 : } else {
1149 2 : RETVAL_STRING(attribute, 1);
1150 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1151 2 : ldap_memfree(attribute);
1152 : #endif
1153 : }
1154 : }
1155 : /* }}} */
1156 :
1157 : /* {{{ proto string ldap_next_attribute(resource link, resource result_entry)
1158 : Get the next attribute in result */
1159 : PHP_FUNCTION(ldap_next_attribute)
1160 6 : {
1161 : zval **link, **result_entry;
1162 : ldap_linkdata *ld;
1163 : ldap_resultentry *resultentry;
1164 : char *attribute;
1165 6 : int argc = ZEND_NUM_ARGS();
1166 :
1167 6 : if ((argc < 2 || argc > 3) || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
1168 1 : WRONG_PARAM_COUNT;
1169 : }
1170 :
1171 5 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1172 5 : ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
1173 :
1174 4 : if (resultentry->ber == NULL) {
1175 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "called before calling ldap_first_attribute() or no attributes found in result entry");
1176 1 : RETURN_FALSE;
1177 : }
1178 :
1179 3 : if ((attribute = ldap_next_attribute(ld->link, resultentry->data, resultentry->ber)) == NULL) {
1180 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1181 1 : if (resultentry->ber != NULL) {
1182 1 : ber_free(resultentry->ber, 0);
1183 1 : resultentry->ber = NULL;
1184 : }
1185 : #endif
1186 1 : RETURN_FALSE;
1187 : } else {
1188 2 : RETVAL_STRING(attribute, 1);
1189 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1190 2 : ldap_memfree(attribute);
1191 : #endif
1192 : }
1193 : }
1194 : /* }}} */
1195 :
1196 : /* {{{ proto array ldap_get_attributes(resource link, resource result_entry)
1197 : Get attributes from a search result entry */
1198 : PHP_FUNCTION(ldap_get_attributes)
1199 3 : {
1200 : zval **link, **result_entry;
1201 : zval *tmp;
1202 : ldap_linkdata *ld;
1203 : ldap_resultentry *resultentry;
1204 : char *attribute;
1205 : struct berval **ldap_value;
1206 : int i, num_values, num_attrib;
1207 : BerElement *ber;
1208 :
1209 3 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
1210 1 : WRONG_PARAM_COUNT;
1211 : }
1212 :
1213 2 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1214 2 : ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
1215 :
1216 1 : array_init(return_value);
1217 1 : num_attrib = 0;
1218 :
1219 1 : attribute = ldap_first_attribute(ld->link, resultentry->data, &ber);
1220 5 : while (attribute != NULL) {
1221 3 : ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute);
1222 3 : num_values = ldap_count_values_len(ldap_value);
1223 :
1224 3 : MAKE_STD_ZVAL(tmp);
1225 3 : array_init(tmp);
1226 3 : add_assoc_long(tmp, "count", num_values);
1227 8 : for (i = 0; i < num_values; i++) {
1228 5 : add_index_stringl(tmp, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1);
1229 : }
1230 3 : ldap_value_free_len(ldap_value);
1231 :
1232 3 : zend_hash_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute)+1, (void *) &tmp, sizeof(zval *), NULL);
1233 3 : add_index_string(return_value, num_attrib, attribute, 1);
1234 :
1235 3 : num_attrib++;
1236 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1237 3 : ldap_memfree(attribute);
1238 : #endif
1239 3 : attribute = ldap_next_attribute(ld->link, resultentry->data, ber);
1240 : }
1241 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1242 1 : if (ber != NULL) {
1243 1 : ber_free(ber, 0);
1244 : }
1245 : #endif
1246 :
1247 1 : add_assoc_long(return_value, "count", num_attrib);
1248 : }
1249 : /* }}} */
1250 :
1251 : /* {{{ proto array ldap_get_values_len(resource link, resource result_entry, string attribute)
1252 : Get all values with lengths from a result entry */
1253 : PHP_FUNCTION(ldap_get_values_len)
1254 7 : {
1255 : zval **link, **result_entry, **attr;
1256 : ldap_linkdata *ld;
1257 : ldap_resultentry *resultentry;
1258 : char* attribute;
1259 : struct berval **ldap_value_len;
1260 : int i, num_values;
1261 :
1262 7 : if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &attr) == FAILURE) {
1263 3 : WRONG_PARAM_COUNT;
1264 : }
1265 :
1266 4 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1267 4 : ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
1268 :
1269 4 : convert_to_string_ex(attr);
1270 4 : attribute = Z_STRVAL_PP(attr);
1271 :
1272 4 : if ((ldap_value_len = ldap_get_values_len(ld->link, resultentry->data, attribute)) == NULL) {
1273 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link)));
1274 1 : RETURN_FALSE;
1275 : }
1276 :
1277 3 : num_values = ldap_count_values_len(ldap_value_len);
1278 3 : array_init(return_value);
1279 :
1280 6 : for (i=0; i<num_values; i++) {
1281 3 : add_next_index_stringl(return_value, ldap_value_len[i]->bv_val, ldap_value_len[i]->bv_len, 1);
1282 : }
1283 :
1284 3 : add_assoc_long(return_value, "count", num_values);
1285 3 : ldap_value_free_len(ldap_value_len);
1286 :
1287 : }
1288 : /* }}} */
1289 :
1290 : /* {{{ proto string ldap_get_dn(resource link, resource result_entry)
1291 : Get the DN of a result entry */
1292 : PHP_FUNCTION(ldap_get_dn)
1293 3 : {
1294 : zval **link, **result_entry;
1295 : ldap_linkdata *ld;
1296 : ldap_resultentry *resultentry;
1297 : char *text;
1298 :
1299 3 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
1300 1 : WRONG_PARAM_COUNT;
1301 : }
1302 :
1303 2 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1304 2 : ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
1305 :
1306 1 : text = ldap_get_dn(ld->link, resultentry->data);
1307 1 : if (text != NULL) {
1308 1 : RETVAL_STRING(text, 1);
1309 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1310 1 : ldap_memfree(text);
1311 : #else
1312 : free(text);
1313 : #endif
1314 : } else {
1315 0 : RETURN_FALSE;
1316 : }
1317 : }
1318 : /* }}} */
1319 :
1320 : /* {{{ proto array ldap_explode_dn(string dn, int with_attrib)
1321 : Splits DN into its component parts */
1322 : PHP_FUNCTION(ldap_explode_dn)
1323 10 : {
1324 : zval **dn, **with_attrib;
1325 : char **ldap_value;
1326 : int i, count;
1327 :
1328 10 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &dn, &with_attrib) == FAILURE) {
1329 2 : WRONG_PARAM_COUNT;
1330 : }
1331 :
1332 8 : convert_to_string_ex(dn);
1333 8 : convert_to_long_ex(with_attrib);
1334 :
1335 8 : if (!(ldap_value = ldap_explode_dn(Z_STRVAL_PP(dn), Z_LVAL_PP(with_attrib)))) {
1336 : /* Invalid parameters were passed to ldap_explode_dn */
1337 4 : RETURN_FALSE;
1338 : }
1339 :
1340 4 : i=0;
1341 4 : while (ldap_value[i] != NULL) i++;
1342 4 : count = i;
1343 :
1344 4 : array_init(return_value);
1345 :
1346 4 : add_assoc_long(return_value, "count", count);
1347 18 : for (i = 0; i<count; i++) {
1348 14 : add_index_string(return_value, i, ldap_value[i], 1);
1349 : }
1350 :
1351 4 : ldap_value_free(ldap_value);
1352 : }
1353 : /* }}} */
1354 :
1355 : /* {{{ proto string ldap_dn2ufn(string dn)
1356 : Convert DN to User Friendly Naming format */
1357 : PHP_FUNCTION(ldap_dn2ufn)
1358 5 : {
1359 : zval **dn;
1360 : char *ufn;
1361 :
1362 5 : if (ZEND_NUM_ARGS() !=1 || zend_get_parameters_ex(1, &dn)==FAILURE) {
1363 1 : WRONG_PARAM_COUNT;
1364 : }
1365 :
1366 4 : convert_to_string_ex(dn);
1367 :
1368 4 : ufn = ldap_dn2ufn(Z_STRVAL_PP(dn));
1369 :
1370 4 : if (ufn !=NULL) {
1371 2 : RETVAL_STRING(ufn, 1);
1372 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1373 2 : ldap_memfree(ufn);
1374 : #endif
1375 : } else {
1376 2 : RETURN_FALSE;
1377 : }
1378 : }
1379 : /* }}} */
1380 :
1381 :
1382 : /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */
1383 : #define PHP_LD_FULL_ADD 0xff
1384 : /* {{{ php_ldap_do_modify
1385 : */
1386 : static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper)
1387 206 : {
1388 : zval **link, **dn, **entry, **value, **ivalue;
1389 : ldap_linkdata *ld;
1390 : char *ldap_dn;
1391 : LDAPMod **ldap_mods;
1392 : int i, j, num_attribs, num_values;
1393 : int *num_berval;
1394 : char *attribute;
1395 : ulong index;
1396 206 : int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */
1397 :
1398 206 : if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &dn, &entry) == FAILURE) {
1399 20 : WRONG_PARAM_COUNT;
1400 : }
1401 :
1402 186 : if (Z_TYPE_PP(entry) != IS_ARRAY) {
1403 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected Array as the last element");
1404 0 : RETURN_FALSE;
1405 : }
1406 :
1407 186 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1408 :
1409 186 : convert_to_string_ex(dn);
1410 186 : ldap_dn = Z_STRVAL_PP(dn);
1411 :
1412 186 : num_attribs = zend_hash_num_elements(Z_ARRVAL_PP(entry));
1413 186 : ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0);
1414 186 : num_berval = safe_emalloc(num_attribs, sizeof(int), 0);
1415 186 : zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry));
1416 :
1417 : /* added by gerrit thomson to fix ldap_add using ldap_mod_add */
1418 186 : if (oper == PHP_LD_FULL_ADD) {
1419 168 : oper = LDAP_MOD_ADD;
1420 168 : is_full_add = 1;
1421 : }
1422 : /* end additional , gerrit thomson */
1423 :
1424 929 : for (i = 0; i < num_attribs; i++) {
1425 747 : ldap_mods[i] = emalloc(sizeof(LDAPMod));
1426 747 : ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
1427 :
1428 747 : if (zend_hash_get_current_key(Z_ARRVAL_PP(entry), &attribute, &index, 0) == HASH_KEY_IS_STRING) {
1429 744 : ldap_mods[i]->mod_type = estrdup(attribute);
1430 : } else {
1431 3 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown attribute in the data");
1432 : /* Free allocated memory */
1433 9 : while (i >= 0) {
1434 3 : efree(ldap_mods[i--]);
1435 : }
1436 3 : efree(num_berval);
1437 3 : efree(ldap_mods);
1438 3 : RETURN_FALSE;
1439 : }
1440 :
1441 744 : zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&value);
1442 :
1443 744 : if (Z_TYPE_PP(value) != IS_ARRAY) {
1444 688 : num_values = 1;
1445 : } else {
1446 56 : num_values = zend_hash_num_elements(Z_ARRVAL_PP(value));
1447 : }
1448 :
1449 744 : num_berval[i] = num_values;
1450 744 : ldap_mods[i]->mod_bvalues = safe_emalloc((num_values + 1), sizeof(struct berval *), 0);
1451 :
1452 : /* allow for arrays with one element, no allowance for arrays with none but probably not required, gerrit thomson. */
1453 1432 : if ((num_values == 1) && (Z_TYPE_PP(value) != IS_ARRAY)) {
1454 688 : convert_to_string_ex(value);
1455 688 : ldap_mods[i]->mod_bvalues[0] = (struct berval *) emalloc (sizeof(struct berval));
1456 688 : ldap_mods[i]->mod_bvalues[0]->bv_len = Z_STRLEN_PP(value);
1457 688 : ldap_mods[i]->mod_bvalues[0]->bv_val = Z_STRVAL_PP(value);
1458 : } else {
1459 217 : for (j = 0; j < num_values; j++) {
1460 162 : if (zend_hash_index_find(Z_ARRVAL_PP(value), j, (void **) &ivalue) == FAILURE) {
1461 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Value array must have consecutive indices 0, 1, ...");
1462 1 : num_berval[i] = j;
1463 1 : num_attribs = i + 1;
1464 1 : RETVAL_FALSE;
1465 1 : goto errexit;
1466 : }
1467 161 : convert_to_string_ex(ivalue);
1468 161 : ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval));
1469 161 : ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_PP(ivalue);
1470 161 : ldap_mods[i]->mod_bvalues[j]->bv_val = Z_STRVAL_PP(ivalue);
1471 : }
1472 : }
1473 743 : ldap_mods[i]->mod_bvalues[num_values] = NULL;
1474 743 : zend_hash_move_forward(Z_ARRVAL_PP(entry));
1475 : }
1476 182 : ldap_mods[num_attribs] = NULL;
1477 :
1478 : /* check flag to see if do_mod was called to perform full add , gerrit thomson */
1479 182 : if (is_full_add == 1) {
1480 166 : if ((i = ldap_add_s(ld->link, ldap_dn, ldap_mods)) != LDAP_SUCCESS) {
1481 6 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Add: %s", ldap_err2string(i));
1482 6 : RETVAL_FALSE;
1483 160 : } else RETVAL_TRUE;
1484 : } else {
1485 16 : if ((i = ldap_modify_s(ld->link, ldap_dn, ldap_mods)) != LDAP_SUCCESS) {
1486 12 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modify: %s", ldap_err2string(i));
1487 12 : RETVAL_FALSE;
1488 4 : } else RETVAL_TRUE;
1489 : }
1490 :
1491 183 : errexit:
1492 927 : for (i = 0; i < num_attribs; i++) {
1493 744 : efree(ldap_mods[i]->mod_type);
1494 1593 : for (j = 0; j < num_berval[i]; j++) {
1495 849 : efree(ldap_mods[i]->mod_bvalues[j]);
1496 : }
1497 744 : efree(ldap_mods[i]->mod_bvalues);
1498 744 : efree(ldap_mods[i]);
1499 : }
1500 183 : efree(num_berval);
1501 183 : efree(ldap_mods);
1502 :
1503 183 : return;
1504 : }
1505 : /* }}} */
1506 :
1507 : /* {{{ proto bool ldap_add(resource link, string dn, array entry)
1508 : Add entries to LDAP directory */
1509 : PHP_FUNCTION(ldap_add)
1510 172 : {
1511 : /* 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 */
1512 172 : php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD);
1513 172 : }
1514 : /* }}} */
1515 :
1516 : /* three functions for attribute base modifications, gerrit Thomson */
1517 :
1518 : /* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry)
1519 : Replace attribute values with new ones */
1520 : PHP_FUNCTION(ldap_mod_replace)
1521 17 : {
1522 17 : php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE);
1523 17 : }
1524 : /* }}} */
1525 :
1526 : /* {{{ proto bool ldap_mod_add(resource link, string dn, array entry)
1527 : Add attribute values to current */
1528 : PHP_FUNCTION(ldap_mod_add)
1529 9 : {
1530 9 : php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD);
1531 9 : }
1532 : /* }}} */
1533 :
1534 : /* {{{ proto bool ldap_mod_del(resource link, string dn, array entry)
1535 : Delete attribute values */
1536 : PHP_FUNCTION(ldap_mod_del)
1537 8 : {
1538 8 : php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE);
1539 8 : }
1540 : /* }}} */
1541 :
1542 : /* {{{ proto bool ldap_delete(resource link, string dn)
1543 : Delete an entry from a directory */
1544 : PHP_FUNCTION(ldap_delete)
1545 168 : {
1546 : zval **link, **dn;
1547 : ldap_linkdata *ld;
1548 : char *ldap_dn;
1549 : int rc;
1550 :
1551 168 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &dn) == FAILURE) {
1552 3 : WRONG_PARAM_COUNT;
1553 : }
1554 :
1555 165 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1556 :
1557 165 : convert_to_string_ex(dn);
1558 165 : ldap_dn = Z_STRVAL_PP(dn);
1559 :
1560 165 : if ((rc = ldap_delete_s(ld->link, ldap_dn)) != LDAP_SUCCESS) {
1561 5 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: %s", ldap_err2string(rc));
1562 5 : RETURN_FALSE;
1563 : }
1564 :
1565 160 : RETURN_TRUE;
1566 : }
1567 : /* }}} */
1568 :
1569 : /* {{{ proto int ldap_errno(resource link)
1570 : Get the current ldap error number */
1571 : PHP_FUNCTION(ldap_errno)
1572 9 : {
1573 : zval **link;
1574 : ldap_linkdata *ld;
1575 :
1576 9 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ht, &link) == FAILURE) {
1577 2 : WRONG_PARAM_COUNT;
1578 : }
1579 :
1580 7 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1581 :
1582 7 : RETURN_LONG(_get_lderrno(ld->link));
1583 : }
1584 : /* }}} */
1585 :
1586 : /* {{{ proto string ldap_err2str(int errno)
1587 : Convert error number to error string */
1588 : PHP_FUNCTION(ldap_err2str)
1589 3 : {
1590 : zval **perrno;
1591 :
1592 3 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ht, &perrno) == FAILURE) {
1593 2 : WRONG_PARAM_COUNT;
1594 : }
1595 :
1596 1 : convert_to_long_ex(perrno);
1597 1 : RETURN_STRING(ldap_err2string(Z_LVAL_PP(perrno)), 1);
1598 : }
1599 : /* }}} */
1600 :
1601 : /* {{{ proto string ldap_error(resource link)
1602 : Get the current ldap error string */
1603 : PHP_FUNCTION(ldap_error)
1604 9 : {
1605 : zval **link;
1606 : ldap_linkdata *ld;
1607 : int ld_errno;
1608 :
1609 9 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ht, &link) == FAILURE) {
1610 2 : WRONG_PARAM_COUNT;
1611 : }
1612 :
1613 7 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1614 :
1615 7 : ld_errno = _get_lderrno(ld->link);
1616 :
1617 7 : RETURN_STRING(ldap_err2string(ld_errno), 1);
1618 : }
1619 : /* }}} */
1620 :
1621 : /* {{{ proto bool ldap_compare(resource link, string dn, string attr, string value)
1622 : Determine if an entry has a specific value for one of its attributes */
1623 : PHP_FUNCTION(ldap_compare)
1624 7 : {
1625 : zval **link, **dn, **attr, **value;
1626 : char *ldap_dn, *ldap_attr, *ldap_value;
1627 : ldap_linkdata *ld;
1628 : int errno;
1629 :
1630 7 : if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &link, &dn, &attr, &value) == FAILURE) {
1631 4 : WRONG_PARAM_COUNT;
1632 : }
1633 :
1634 3 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1635 :
1636 3 : convert_to_string_ex(dn);
1637 3 : convert_to_string_ex(attr);
1638 3 : convert_to_string_ex(value);
1639 :
1640 3 : ldap_dn = Z_STRVAL_PP(dn);
1641 3 : ldap_attr = Z_STRVAL_PP(attr);
1642 3 : ldap_value = Z_STRVAL_PP(value);
1643 :
1644 3 : errno = ldap_compare_s(ld->link, ldap_dn, ldap_attr, ldap_value);
1645 :
1646 3 : switch (errno) {
1647 : case LDAP_COMPARE_TRUE:
1648 1 : RETURN_TRUE;
1649 : break;
1650 :
1651 : case LDAP_COMPARE_FALSE:
1652 1 : RETURN_FALSE;
1653 : break;
1654 : }
1655 :
1656 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(errno));
1657 1 : RETURN_LONG(-1);
1658 :
1659 : }
1660 : /* }}} */
1661 :
1662 : /* {{{ proto bool ldap_sort(resource link, resource result, string sortfilter)
1663 : Sort LDAP result entries */
1664 : PHP_FUNCTION(ldap_sort)
1665 7 : {
1666 : zval *link, *result;
1667 : ldap_linkdata *ld;
1668 : char *sortfilter;
1669 : int sflen;
1670 : zend_rsrc_list_entry *le;
1671 :
1672 7 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrs", &link, &result, &sortfilter, &sflen) == FAILURE) {
1673 4 : RETURN_FALSE;
1674 : }
1675 :
1676 3 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1677 :
1678 3 : if (zend_hash_index_find(&EG(regular_list), Z_LVAL_P(result), (void **) &le) == FAILURE || le->type != le_result) {
1679 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied resource is not a valid ldap result resource");
1680 1 : RETURN_FALSE;
1681 : }
1682 :
1683 2 : if (ldap_sort_entries(ld->link, (LDAPMessage **) &le->ptr, sflen ? sortfilter : NULL, strcmp) != LDAP_SUCCESS) {
1684 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ldap_err2string(errno));
1685 0 : RETURN_FALSE;
1686 : }
1687 :
1688 2 : RETURN_TRUE;
1689 : }
1690 : /* }}} */
1691 :
1692 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
1693 : /* {{{ proto bool ldap_get_option(resource link, int option, mixed retval)
1694 : Get the current value of various session-wide parameters */
1695 : PHP_FUNCTION(ldap_get_option)
1696 21 : {
1697 : zval **link, **option, **retval;
1698 : ldap_linkdata *ld;
1699 : int opt;
1700 :
1701 21 : if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &option, &retval) == FAILURE) {
1702 4 : WRONG_PARAM_COUNT;
1703 : }
1704 :
1705 17 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1706 :
1707 17 : convert_to_long_ex(option);
1708 17 : opt = Z_LVAL_PP(option);
1709 :
1710 17 : switch (opt) {
1711 : /* options with int value */
1712 : case LDAP_OPT_DEREF:
1713 : case LDAP_OPT_SIZELIMIT:
1714 : case LDAP_OPT_TIMELIMIT:
1715 : case LDAP_OPT_PROTOCOL_VERSION:
1716 : case LDAP_OPT_ERROR_NUMBER:
1717 : case LDAP_OPT_REFERRALS:
1718 : #ifdef LDAP_OPT_RESTART
1719 : case LDAP_OPT_RESTART:
1720 : #endif
1721 : {
1722 : int val;
1723 12 : if (ldap_get_option(ld->link, opt, &val)) {
1724 0 : RETURN_FALSE;
1725 : }
1726 12 : zval_dtor(*retval);
1727 12 : ZVAL_LONG(*retval, val);
1728 12 : } break;
1729 : /* options with string value */
1730 : case LDAP_OPT_ERROR_STRING:
1731 : #ifdef LDAP_OPT_HOST_NAME
1732 : case LDAP_OPT_HOST_NAME:
1733 : #endif
1734 : #ifdef HAVE_LDAP_SASL
1735 : case LDAP_OPT_X_SASL_MECH:
1736 : case LDAP_OPT_X_SASL_REALM:
1737 : case LDAP_OPT_X_SASL_AUTHCID:
1738 : case LDAP_OPT_X_SASL_AUTHZID:
1739 : #endif
1740 : #ifdef LDAP_OPT_MATCHED_DN
1741 : case LDAP_OPT_MATCHED_DN:
1742 : #endif
1743 : {
1744 1 : char *val = NULL;
1745 :
1746 1 : if (ldap_get_option(ld->link, opt, &val) || val == NULL || *val == '\0') {
1747 0 : if (val) {
1748 0 : ldap_memfree(val);
1749 : }
1750 0 : RETURN_FALSE;
1751 : }
1752 1 : zval_dtor(*retval);
1753 1 : ZVAL_STRING(*retval, val, 1);
1754 1 : ldap_memfree(val);
1755 1 : } break;
1756 : /* options not implemented
1757 : case LDAP_OPT_SERVER_CONTROLS:
1758 : case LDAP_OPT_CLIENT_CONTROLS:
1759 : case LDAP_OPT_API_INFO:
1760 : case LDAP_OPT_API_FEATURE_INFO:
1761 : */
1762 : default:
1763 4 : RETURN_FALSE;
1764 : }
1765 13 : RETURN_TRUE;
1766 : }
1767 : /* }}} */
1768 :
1769 : /* {{{ proto bool ldap_set_option(resource link, int option, mixed newval)
1770 : Set the value of various session-wide parameters */
1771 : PHP_FUNCTION(ldap_set_option)
1772 185 : {
1773 : zval **link, **option, **newval;
1774 : ldap_linkdata *ld;
1775 : LDAP *ldap;
1776 : int opt;
1777 :
1778 185 : if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &option, &newval) == FAILURE) {
1779 4 : WRONG_PARAM_COUNT;
1780 : }
1781 :
1782 181 : if (Z_TYPE_PP(link) == IS_NULL) {
1783 0 : ldap = NULL;
1784 : } else {
1785 181 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1786 181 : ldap = ld->link;
1787 : }
1788 :
1789 181 : convert_to_long_ex(option);
1790 181 : opt = Z_LVAL_PP(option);
1791 :
1792 181 : switch (opt) {
1793 : /* options with int value */
1794 : case LDAP_OPT_DEREF:
1795 : case LDAP_OPT_SIZELIMIT:
1796 : case LDAP_OPT_TIMELIMIT:
1797 : case LDAP_OPT_PROTOCOL_VERSION:
1798 : case LDAP_OPT_ERROR_NUMBER:
1799 : #ifdef LDAP_OPT_DEBUG_LEVEL
1800 : case LDAP_OPT_DEBUG_LEVEL:
1801 : #endif
1802 : {
1803 : int val;
1804 164 : convert_to_long_ex(newval);
1805 164 : val = Z_LVAL_PP(newval);
1806 164 : if (ldap_set_option(ldap, opt, &val)) {
1807 1 : RETURN_FALSE;
1808 : }
1809 163 : } break;
1810 : /* options with string value */
1811 : case LDAP_OPT_ERROR_STRING:
1812 : #ifdef LDAP_OPT_HOST_NAME
1813 : case LDAP_OPT_HOST_NAME:
1814 : #endif
1815 : #ifdef HAVE_LDAP_SASL
1816 : case LDAP_OPT_X_SASL_MECH:
1817 : case LDAP_OPT_X_SASL_REALM:
1818 : case LDAP_OPT_X_SASL_AUTHCID:
1819 : case LDAP_OPT_X_SASL_AUTHZID:
1820 : #endif
1821 : #ifdef LDAP_OPT_MATCHED_DN
1822 : case LDAP_OPT_MATCHED_DN:
1823 : #endif
1824 : {
1825 : char *val;
1826 1 : convert_to_string_ex(newval);
1827 1 : val = Z_STRVAL_PP(newval);
1828 1 : if (ldap_set_option(ldap, opt, val)) {
1829 0 : RETURN_FALSE;
1830 : }
1831 1 : } break;
1832 : /* options with boolean value */
1833 : case LDAP_OPT_REFERRALS:
1834 : #ifdef LDAP_OPT_RESTART
1835 : case LDAP_OPT_RESTART:
1836 : #endif
1837 : {
1838 : void *val;
1839 4 : convert_to_boolean_ex(newval);
1840 4 : val = Z_LVAL_PP(newval)
1841 : ? LDAP_OPT_ON : LDAP_OPT_OFF;
1842 4 : if (ldap_set_option(ldap, opt, val)) {
1843 0 : RETURN_FALSE;
1844 : }
1845 4 : } break;
1846 : /* options with control list value */
1847 : case LDAP_OPT_SERVER_CONTROLS:
1848 : case LDAP_OPT_CLIENT_CONTROLS:
1849 : {
1850 : LDAPControl *ctrl, **ctrls, **ctrlp;
1851 : zval **ctrlval, **val;
1852 : int ncontrols;
1853 11 : char error=0;
1854 :
1855 11 : if ((Z_TYPE_PP(newval) != IS_ARRAY) || !(ncontrols = zend_hash_num_elements(Z_ARRVAL_PP(newval)))) {
1856 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected non-empty array value for this option");
1857 1 : RETURN_FALSE;
1858 : }
1859 10 : ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0);
1860 10 : *ctrls = NULL;
1861 10 : ctrlp = ctrls;
1862 10 : zend_hash_internal_pointer_reset(Z_ARRVAL_PP(newval));
1863 34 : while (zend_hash_get_current_data(Z_ARRVAL_PP(newval), (void**)&ctrlval) == SUCCESS) {
1864 16 : if (Z_TYPE_PP(ctrlval) != IS_ARRAY) {
1865 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array value must contain only arrays, where each array is a control");
1866 1 : error = 1;
1867 1 : break;
1868 : }
1869 15 : if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "oid", sizeof("oid"), (void **) &val) == FAILURE) {
1870 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Control must have an oid key");
1871 1 : error = 1;
1872 1 : break;
1873 : }
1874 14 : ctrl = *ctrlp = emalloc(sizeof(**ctrlp));
1875 14 : convert_to_string_ex(val);
1876 14 : ctrl->ldctl_oid = Z_STRVAL_PP(val);
1877 14 : if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "value", sizeof("value"), (void **) &val) == SUCCESS) {
1878 5 : convert_to_string_ex(val);
1879 5 : ctrl->ldctl_value.bv_val = Z_STRVAL_PP(val);
1880 5 : ctrl->ldctl_value.bv_len = Z_STRLEN_PP(val);
1881 : } else {
1882 9 : ctrl->ldctl_value.bv_val = NULL;
1883 9 : ctrl->ldctl_value.bv_len = 0;
1884 : }
1885 14 : if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "iscritical", sizeof("iscritical"), (void **) &val) == SUCCESS) {
1886 5 : convert_to_boolean_ex(val);
1887 5 : ctrl->ldctl_iscritical = Z_BVAL_PP(val);
1888 : } else {
1889 9 : ctrl->ldctl_iscritical = 0;
1890 : }
1891 :
1892 14 : ++ctrlp;
1893 14 : *ctrlp = NULL;
1894 14 : zend_hash_move_forward(Z_ARRVAL_PP(newval));
1895 : }
1896 10 : if (!error) {
1897 8 : error = ldap_set_option(ldap, opt, ctrls);
1898 : }
1899 10 : ctrlp = ctrls;
1900 34 : while (*ctrlp) {
1901 14 : efree(*ctrlp);
1902 14 : ctrlp++;
1903 : }
1904 10 : efree(ctrls);
1905 10 : if (error) {
1906 2 : RETURN_FALSE;
1907 : }
1908 8 : } break;
1909 : default:
1910 1 : RETURN_FALSE;
1911 : }
1912 176 : RETURN_TRUE;
1913 : }
1914 : /* }}} */
1915 :
1916 : #ifdef HAVE_LDAP_PARSE_RESULT
1917 : /* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals)
1918 : Extract information from result */
1919 : PHP_FUNCTION(ldap_parse_result)
1920 2 : {
1921 : zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals;
1922 : ldap_linkdata *ld;
1923 : LDAPMessage *ldap_result;
1924 : char **lreferrals, **refp;
1925 : char *lmatcheddn, *lerrmsg;
1926 2 : int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
1927 :
1928 2 : if (myargcount < 3 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals) == FAILURE) {
1929 1 : WRONG_PARAM_COUNT;
1930 : }
1931 :
1932 1 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1933 1 : ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
1934 :
1935 1 : rc = ldap_parse_result(ld->link, ldap_result, &lerrcode,
1936 : myargcount > 3 ? &lmatcheddn : NULL,
1937 : myargcount > 4 ? &lerrmsg : NULL,
1938 : myargcount > 5 ? &lreferrals : NULL,
1939 : NULL /* &serverctrls */,
1940 : 0);
1941 1 : if (rc != LDAP_SUCCESS) {
1942 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
1943 0 : RETURN_FALSE;
1944 : }
1945 :
1946 1 : zval_dtor(*errcode);
1947 1 : ZVAL_LONG(*errcode, lerrcode);
1948 :
1949 : /* Reverse -> fall through */
1950 1 : switch (myargcount) {
1951 : case 6:
1952 1 : zval_dtor(*referrals);
1953 1 : array_init(*referrals);
1954 1 : if (lreferrals != NULL) {
1955 1 : refp = lreferrals;
1956 3 : while (*refp) {
1957 1 : add_next_index_string(*referrals, *refp, 1);
1958 1 : refp++;
1959 : }
1960 1 : ldap_value_free(lreferrals);
1961 : }
1962 : case 5:
1963 1 : zval_dtor(*errmsg);
1964 1 : if (lerrmsg == NULL) {
1965 0 : ZVAL_EMPTY_STRING(*errmsg);
1966 : } else {
1967 1 : ZVAL_STRING(*errmsg, lerrmsg, 1);
1968 1 : ldap_memfree(lerrmsg);
1969 : }
1970 : case 4:
1971 1 : zval_dtor(*matcheddn);
1972 1 : if (lmatcheddn == NULL) {
1973 0 : ZVAL_EMPTY_STRING(*matcheddn);
1974 : } else {
1975 1 : ZVAL_STRING(*matcheddn, lmatcheddn, 1);
1976 1 : ldap_memfree(lmatcheddn);
1977 : }
1978 : }
1979 1 : RETURN_TRUE;
1980 : }
1981 : /* }}} */
1982 : #endif
1983 :
1984 : /* {{{ proto resource ldap_first_reference(resource link, resource result)
1985 : Return first reference */
1986 : PHP_FUNCTION(ldap_first_reference)
1987 6 : {
1988 : zval **link, **result;
1989 : ldap_linkdata *ld;
1990 : ldap_resultentry *resultentry;
1991 : LDAPMessage *ldap_result, *entry;
1992 :
1993 6 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
1994 2 : WRONG_PARAM_COUNT;
1995 : }
1996 :
1997 4 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
1998 4 : ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
1999 :
2000 3 : if ((entry = ldap_first_reference(ld->link, ldap_result)) == NULL) {
2001 0 : RETVAL_FALSE;
2002 : } else {
2003 3 : resultentry = emalloc(sizeof(ldap_resultentry));
2004 3 : ZEND_REGISTER_RESOURCE(return_value, resultentry, le_result_entry);
2005 3 : resultentry->id = Z_LVAL_PP(result);
2006 3 : zend_list_addref(resultentry->id);
2007 3 : resultentry->data = entry;
2008 : }
2009 : }
2010 : /* }}} */
2011 :
2012 : /* {{{ proto resource ldap_next_reference(resource link, resource reference_entry)
2013 : Get next reference */
2014 : PHP_FUNCTION(ldap_next_reference)
2015 4 : {
2016 : zval **link, **result_entry;
2017 : ldap_linkdata *ld;
2018 : ldap_resultentry *resultentry, *resultentry_next;
2019 : LDAPMessage *entry_next;
2020 :
2021 4 : if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
2022 2 : WRONG_PARAM_COUNT;
2023 : }
2024 :
2025 2 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
2026 2 : ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
2027 :
2028 1 : if ((entry_next = ldap_next_reference(ld->link, resultentry->data)) == NULL) {
2029 0 : RETVAL_FALSE;
2030 : } else {
2031 1 : resultentry_next = emalloc(sizeof(ldap_resultentry));
2032 1 : ZEND_REGISTER_RESOURCE(return_value, resultentry_next, le_result_entry);
2033 1 : resultentry_next->id = resultentry->id;
2034 1 : zend_list_addref(resultentry->id);
2035 1 : resultentry_next->data = entry_next;
2036 : }
2037 : }
2038 : /* }}} */
2039 :
2040 : #ifdef HAVE_LDAP_PARSE_REFERENCE
2041 : /* {{{ proto bool ldap_parse_reference(resource link, resource reference_entry, array referrals)
2042 : Extract information from reference entry */
2043 : PHP_FUNCTION(ldap_parse_reference)
2044 6 : {
2045 : zval **link, **result_entry, **referrals;
2046 : ldap_linkdata *ld;
2047 : ldap_resultentry *resultentry;
2048 : char **lreferrals, **refp;
2049 :
2050 6 : if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &referrals) == FAILURE) {
2051 2 : WRONG_PARAM_COUNT;
2052 : }
2053 :
2054 4 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
2055 4 : ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
2056 :
2057 3 : if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
2058 0 : RETURN_FALSE;
2059 : }
2060 :
2061 3 : zval_dtor(*referrals);
2062 3 : array_init(*referrals);
2063 3 : if (lreferrals != NULL) {
2064 3 : refp = lreferrals;
2065 9 : while (*refp) {
2066 3 : add_next_index_string(*referrals, *refp, 1);
2067 3 : refp++;
2068 : }
2069 3 : ldap_value_free(lreferrals);
2070 : }
2071 3 : RETURN_TRUE;
2072 : }
2073 : /* }}} */
2074 : #endif
2075 :
2076 : /* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn);
2077 : Modify the name of an entry */
2078 : PHP_FUNCTION(ldap_rename)
2079 4 : {
2080 : zval **link, **dn, **newrdn, **newparent, **deleteoldrdn;
2081 : ldap_linkdata *ld;
2082 : int rc;
2083 4 : char *newp = NULL;
2084 :
2085 4 : if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &link, &dn, &newrdn, &newparent, &deleteoldrdn) == FAILURE) {
2086 1 : WRONG_PARAM_COUNT;
2087 : }
2088 :
2089 3 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
2090 :
2091 3 : convert_to_string_ex(dn);
2092 3 : convert_to_string_ex(newrdn);
2093 3 : convert_to_string_ex(newparent);
2094 3 : convert_to_boolean_ex(deleteoldrdn);
2095 :
2096 3 : newp = (Z_STRLEN_PP(newparent) > 0) ? Z_STRVAL_PP(newparent) : NULL;
2097 :
2098 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
2099 3 : rc = ldap_rename_s(ld->link, Z_STRVAL_PP(dn), Z_STRVAL_PP(newrdn), newp, Z_BVAL_PP(deleteoldrdn), NULL, NULL);
2100 : #else
2101 : if (newp != NULL) {
2102 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN");
2103 : RETURN_FALSE;
2104 : }
2105 : /* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */
2106 : rc = ldap_modrdn2_s(ld->link, Z_STRVAL_PP(dn), Z_STRVAL_PP(newrdn), Z_BVAL_PP(deleteoldrdn));
2107 : #endif
2108 :
2109 3 : if (rc == LDAP_SUCCESS) {
2110 2 : RETURN_TRUE;
2111 : }
2112 1 : RETURN_FALSE;
2113 : }
2114 : /* }}} */
2115 :
2116 : #ifdef HAVE_LDAP_START_TLS_S
2117 : /* {{{ proto bool ldap_start_tls(resource link)
2118 : Start TLS */
2119 : PHP_FUNCTION(ldap_start_tls)
2120 3 : {
2121 : zval **link;
2122 : ldap_linkdata *ld;
2123 3 : int rc, protocol = LDAP_VERSION3;
2124 :
2125 3 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &link) == FAILURE) {
2126 2 : WRONG_PARAM_COUNT;
2127 : }
2128 :
2129 1 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
2130 :
2131 1 : if (((rc = ldap_set_option(ld->link, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) ||
2132 : ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS)
2133 : ) {
2134 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Unable to start TLS: %s", ldap_err2string(rc));
2135 0 : RETURN_FALSE;
2136 : } else {
2137 1 : RETURN_TRUE;
2138 : }
2139 : }
2140 : /* }}} */
2141 : #endif
2142 : #endif /* (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 */
2143 :
2144 : #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
2145 : /* {{{ _ldap_rebind_proc()
2146 : */
2147 : int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params)
2148 0 : {
2149 : ldap_linkdata *ld;
2150 : int retval;
2151 : zval *cb_url;
2152 : zval **cb_args[2];
2153 : zval *cb_retval;
2154 0 : zval *cb_link = (zval *) params;
2155 : TSRMLS_FETCH();
2156 :
2157 0 : ld = (ldap_linkdata *) zend_fetch_resource(&cb_link TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
2158 :
2159 : /* link exists and callback set? */
2160 0 : if (ld == NULL || ld->rebindproc == NULL) {
2161 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link not found or no callback set");
2162 0 : return LDAP_OTHER;
2163 : }
2164 :
2165 : /* callback */
2166 0 : MAKE_STD_ZVAL(cb_url);
2167 0 : ZVAL_STRING(cb_url, estrdup(url), 0);
2168 0 : cb_args[0] = &cb_link;
2169 0 : cb_args[1] = &cb_url;
2170 0 : if (call_user_function_ex(EG(function_table), NULL, ld->rebindproc, &cb_retval, 2, cb_args, 0, NULL TSRMLS_CC) == SUCCESS && cb_retval) {
2171 0 : convert_to_long_ex(&cb_retval);
2172 0 : retval = Z_LVAL_P(cb_retval);
2173 0 : zval_ptr_dtor(&cb_retval);
2174 : } else {
2175 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "rebind_proc PHP callback failed");
2176 0 : retval = LDAP_OTHER;
2177 : }
2178 0 : zval_dtor(cb_url);
2179 0 : FREE_ZVAL(cb_url);
2180 0 : return retval;
2181 : }
2182 : /* }}} */
2183 :
2184 : /* {{{ proto bool ldap_set_rebind_proc(resource link, string callback)
2185 : Set a callback function to do re-binds on referral chasing. */
2186 : PHP_FUNCTION(ldap_set_rebind_proc)
2187 6 : {
2188 : zval *link, *callback;
2189 : ldap_linkdata *ld;
2190 : char *callback_name;
2191 :
2192 6 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &link, &callback) == FAILURE) {
2193 2 : RETURN_FALSE;
2194 : }
2195 :
2196 4 : ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2197 :
2198 4 : if (Z_TYPE_P(callback) == IS_STRING && Z_STRLEN_P(callback) == 0) {
2199 : /* unregister rebind procedure */
2200 1 : if (ld->rebindproc != NULL) {
2201 1 : zval_dtor(ld->rebindproc);
2202 1 : ld->rebindproc = NULL;
2203 1 : ldap_set_rebind_proc(ld->link, NULL, NULL);
2204 : }
2205 1 : RETURN_TRUE;
2206 : }
2207 :
2208 : /* callable? */
2209 3 : if (!zend_is_callable(callback, 0, &callback_name)) {
2210 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Two arguments expected for '%s' to be a valid callback", callback_name);
2211 1 : efree(callback_name);
2212 1 : RETURN_FALSE;
2213 : }
2214 2 : efree(callback_name);
2215 :
2216 : /* register rebind procedure */
2217 2 : if (ld->rebindproc == NULL) {
2218 2 : ldap_set_rebind_proc(ld->link, _ldap_rebind_proc, (void *) link);
2219 : } else {
2220 0 : zval_dtor(ld->rebindproc);
2221 : }
2222 :
2223 2 : ALLOC_ZVAL(ld->rebindproc);
2224 2 : *ld->rebindproc = *callback;
2225 2 : zval_copy_ctor(ld->rebindproc);
2226 2 : RETURN_TRUE;
2227 : }
2228 : /* }}} */
2229 : #endif
2230 :
2231 : #ifdef STR_TRANSLATION
2232 : /* {{{ php_ldap_do_translate
2233 : */
2234 : static void php_ldap_do_translate(INTERNAL_FUNCTION_PARAMETERS, int way)
2235 : {
2236 : zval **value;
2237 : char *ldap_buf;
2238 : unsigned long ldap_len;
2239 : int result;
2240 :
2241 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &value) == FAILURE) {
2242 : WRONG_PARAM_COUNT;
2243 : }
2244 :
2245 : convert_to_string_ex(value);
2246 : ldap_buf = Z_STRVAL_PP(value);
2247 : ldap_len = Z_STRLEN_PP(value);
2248 :
2249 : if (ldap_len == 0) {
2250 : RETURN_FALSE;
2251 : }
2252 :
2253 : if (way == 1) {
2254 : result = ldap_8859_to_t61(&ldap_buf, &ldap_len, 0);
2255 : } else {
2256 : result = ldap_t61_to_8859(&ldap_buf, &ldap_len, 0);
2257 : }
2258 :
2259 : if (result == LDAP_SUCCESS) {
2260 : RETVAL_STRINGL(ldap_buf, ldap_len, 1);
2261 : free(ldap_buf);
2262 : } else {
2263 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Conversion from iso-8859-1 to t61 failed: %s", ldap_err2string(result));
2264 : RETVAL_FALSE;
2265 : }
2266 :
2267 : return;
2268 : }
2269 : /* }}} */
2270 :
2271 : /* {{{ proto string ldap_t61_to_8859(string value)
2272 : Translate t61 characters to 8859 characters */
2273 : PHP_FUNCTION(ldap_t61_to_8859)
2274 : {
2275 : php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2276 : }
2277 : /* }}} */
2278 :
2279 : /* {{{ proto string ldap_8859_to_t61(string value)
2280 : Translate 8859 characters to t61 characters */
2281 : PHP_FUNCTION(ldap_8859_to_t61)
2282 : {
2283 : php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2284 : }
2285 : /* }}} */
2286 : #endif
2287 :
2288 : /*
2289 : * Local variables:
2290 : * tab-width: 4
2291 : * c-basic-offset: 4
2292 : * End:
2293 : * vim600: sw=4 ts=4 fdm=marker
2294 : * vim<600: sw=4 ts=4
2295 : */
|