pkgsrc/databases/php-ldap/files/ldap-ctrl-exop.patch
2009-09-13 19:45:42 +00:00

2285 lines
67 KiB
Diff
Executable file

$NetBSD: ldap-ctrl-exop.patch,v 1.2 2009/09/13 19:45:42 manu Exp $
/*
* Copyright (c) 2007-2009 Pierangelo Masarati
* Copyright (c) 2009 Emmanuel Dreyfus
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
--- ext/ldap/ldap.c.orig 2009-06-15 15:18:48.000000000 +0000
+++ ext/ldap/ldap.c 2009-09-05 07:10:18.000000000 +0000
@@ -81,8 +81,35 @@
ZEND_DECLARE_MODULE_GLOBALS(ldap)
static PHP_GINIT_FUNCTION(ldap);
+/* {{{ argXtoYofZ_force_ref - reference args helpers */
+static
+ ZEND_BEGIN_ARG_INFO(arg5of5_force_ref, 0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_END_ARG_INFO();
+
+static
+ ZEND_BEGIN_ARG_INFO(arg3to4of4_force_ref, 0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_END_ARG_INFO();
+
+static
+ ZEND_BEGIN_ARG_INFO(arg4to5of5_force_ref, 0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_END_ARG_INFO();
+
static
ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(0)
@@ -91,8 +118,20 @@
ZEND_ARG_PASS_INFO(1)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
+static
+ ZEND_BEGIN_ARG_INFO(arg3to7of7_force_ref, 0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_ARG_PASS_INFO(1)
+ ZEND_END_ARG_INFO();
+/* }}} */
+
static int le_link, le_result, le_result_entry;
/*
This is just a small subset of the functionality provided by the LDAP library. All the
@@ -133,8 +172,22 @@
PHP_FE(ldap_mod_replace, NULL)
PHP_FE(ldap_mod_del, NULL)
/* end gjt mod */
+/* Operations that return the result for further manipulation, Pierangelo Masarati */
+ PHP_FE(ldap_bind_ext, NULL)
+ PHP_FE(ldap_add_ext, NULL)
+ PHP_FE(ldap_delete_ext, NULL)
+ PHP_FALIAS(ldap_modify_ext, ldap_mod_replace_ext, NULL)
+ PHP_FE(ldap_mod_add_ext, NULL)
+ PHP_FE(ldap_mod_replace_ext, NULL)
+ PHP_FE(ldap_mod_del_ext, NULL)
+ PHP_FE(ldap_compare_ext, NULL)
+#if ando_0
+ PHP_FE(ldap_rename_ext, NULL)
+#endif
+/* end of ando's mod */
+
PHP_FE(ldap_errno, NULL)
PHP_FE(ldap_err2str, NULL)
PHP_FE(ldap_error, NULL)
PHP_FE(ldap_compare, NULL)
@@ -146,16 +199,32 @@
PHP_FE(ldap_set_option, NULL)
PHP_FE(ldap_first_reference, NULL)
PHP_FE(ldap_next_reference, NULL)
#ifdef HAVE_LDAP_PARSE_REFERENCE
- PHP_FE(ldap_parse_reference, third_arg_force_ref)
+ PHP_FE(ldap_parse_reference, arg3to4of4_force_ref)
#endif
#ifdef HAVE_LDAP_PARSE_RESULT
- PHP_FE(ldap_parse_result, arg3to6of6_force_ref)
+ PHP_FE(ldap_parse_result, arg3to7of7_force_ref)
#endif
+/* LDAPv3 extended operations, Pierangelo Masarati */
+#ifdef HAVE_LDAP_EXTENDED_OPERATION_S
+ PHP_FE(ldap_exop, arg4to5of5_force_ref)
+ PHP_FE(ldap_exop_passwd, arg5of5_force_ref)
+ PHP_FE(ldap_exop_whoami, second_arg_force_ref)
#ifdef HAVE_LDAP_START_TLS_S
PHP_FE(ldap_start_tls, NULL)
#endif
+#ifdef HAVE_LDAP_REFRESH
+ PHP_FE(ldap_refresh,
+ NULL)
+#endif
+#endif
+#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
+ PHP_FE(ldap_parse_exop, arg3to4of4_force_ref)
+ PHP_FE(ldap_parse_exop_passwd, third_arg_force_ref)
+ PHP_FE(ldap_parse_exop_whoami, third_arg_force_ref)
+#endif
+/* end of ando mod */
#endif
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
PHP_FE(ldap_set_rebind_proc, NULL)
@@ -165,8 +234,31 @@
PHP_FE(ldap_t61_to_8859, NULL)
PHP_FE(ldap_8859_to_t61, NULL)
#endif
+/* routines to handle standard track controls, Pierangelo Masarati */
+#ifdef LDAP_CONTROL_MANAGEDSAIT
+ PHP_FE(ldap_ctrl_manageDSAit, NULL)
+#endif
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ PHP_FE(ldap_ctrl_paged_results, fourth_arg_force_ref)
+ PHP_FE(ldap_ctrl_paged_results_resp, arg3to4of4_force_ref)
+#endif
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+ PHP_FE(ldap_ctrl_ppolicy, NULL)
+ PHP_FE(ldap_ctrl_ppolicy_resp, arg3to6of6_force_ref)
+#endif
+#ifdef LDAP_CONTROL_NOOP
+ PHP_FE(ldap_ctrl_noop, NULL)
+#endif
+#ifdef LDAP_CONTROL_MANAGEDIT
+ PHP_FE(ldap_ctrl_manageDIT, NULL)
+#endif
+#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
+ PHP_FE(ldap_ctrl_permissive_modify, NULL)
+#endif
+/* end of ando mod */
+
{NULL, NULL, NULL}
};
/* }}} */
@@ -193,29 +285,43 @@
# include "zend_arg_defs.c"
# endif
#endif
+/* {{{ proto void _close_ldap_link()
+ close a connection and free LDAP resources */
static void _close_ldap_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr;
- ldap_unbind_s(ld->link);
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
+ /* ldap_unbind_s() is deprecated;
+ * the distinction between ldap_unbind() and ldap_unbind_s() is moot */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ ldap_unbind_ext(ld->link, NULL, NULL);
+#ifdef HAVE_3ARG_SETREBINDPROC
if (ld->rebindproc != NULL) {
zval_dtor(ld->rebindproc);
FREE_ZVAL(ld->rebindproc);
}
#endif
+#else /* ! LDAP_API_FEATURE_X_OPENLDAP */
+ ldap_unbind_s(ld->link);
+#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
efree(ld);
LDAPG(num_links)--;
}
+/* }}} */
+/* {{{ proto void _free_ldap_result()
+ free the result of an LDAP operation */
static void _free_ldap_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
LDAPMessage *result = (LDAPMessage *)rsrc->ptr;
ldap_msgfree(result);
}
+/* }}} */
+/* {{{ proto void _free_ldap_result_entry()
+ free an entry resulting from an LDAP search operation */
static void _free_ldap_result_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr;
@@ -224,8 +330,162 @@
}
zend_list_delete(entry->id);
efree(entry);
}
+/* }}} */
+
+/* {{{ proto int _php_parse_referrals_resp()
+ parse an array of LDAP referrals into a zval array */
+static int _php_parse_referrals_resp(char ***lreferralsp, zval **referrals)
+{
+ int num_referrals = 0;
+
+ if (*lreferralsp != NULL) {
+ char **refp = *lreferralsp;
+
+ while (*refp) {
+ add_next_index_string(*referrals, *refp, 1);
+ refp++;
+ num_referrals++;
+ }
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ ber_memvfree((void **)*lreferralsp);
+#else
+ ldap_value_free(*lreferralsp);
+#endif
+ *lreferralsp = NULL;
+ }
+
+ return num_referrals;
+}
+/* }}} */
+
+/* {{{ proto int _php_parse_controls()
+ parse an array of zvals into an array of LDAP controls */
+static int _php_parse_controls(zval **ctrls, LDAPControl ***lctrlsp)
+{
+ LDAPControl *lctrl, **lctrls, **lctrlp;
+ zval **ctrlval, **val;
+ int ncontrols;
+ char error = 0;
+
+ if ((Z_TYPE_PP(ctrls) != IS_ARRAY) || !(ncontrols = zend_hash_num_elements(Z_ARRVAL_PP(ctrls)))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected non-empty array value");
+ return 0;
+ }
+
+ lctrls = safe_emalloc((1 + ncontrols), sizeof(*lctrls), 0);
+ *lctrls = NULL;
+ lctrlp = lctrls;
+ zend_hash_internal_pointer_reset(Z_ARRVAL_PP(ctrls));
+ while (zend_hash_get_current_data(Z_ARRVAL_PP(ctrls), (void**)&ctrlval) == SUCCESS) {
+ if (Z_TYPE_PP(ctrlval) != IS_ARRAY) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array value must contain only arrays, where each array is a control");
+ error = 1;
+ break;
+ }
+ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "oid", sizeof("oid"), (void **) &val) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Control must have an oid key");
+ error = 1;
+ break;
+ }
+ lctrl = *lctrlp = emalloc(sizeof(**lctrlp));
+ convert_to_string_ex(val);
+ lctrl->ldctl_oid = Z_STRVAL_PP(val);
+ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "value", sizeof("value"), (void **) &val) == SUCCESS) {
+ convert_to_string_ex(val);
+ lctrl->ldctl_value.bv_val = Z_STRVAL_PP(val);
+ lctrl->ldctl_value.bv_len = Z_STRLEN_PP(val);
+ } else {
+ lctrl->ldctl_value.bv_val = NULL;
+ lctrl->ldctl_value.bv_len = 0;
+ }
+ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "iscritical", sizeof("iscritical"), (void **) &val) == SUCCESS) {
+ convert_to_boolean_ex(val);
+ lctrl->ldctl_iscritical = Z_BVAL_PP(val);
+ } else {
+ lctrl->ldctl_iscritical = 0;
+ }
+
+ ++lctrlp;
+ *lctrlp = NULL;
+ zend_hash_move_forward(Z_ARRVAL_PP(ctrls));
+ }
+ if (!error) {
+ *lctrlsp = lctrls;
+ }
+ return ncontrols;
+}
+/* }}} */
+
+/* {{{ proto void _php_free_controls()
+ frees an array of LDAP controls as parsed (and malloc'ed) by _php_parse_controls */
+static void _php_free_controls(LDAPControl ***lctrlsp)
+{
+ LDAPControl **lctrlp;
+
+ for (lctrlp = *lctrlsp; *lctrlp; lctrlp++) {
+ efree(*lctrlp);
+ }
+ efree(*lctrlsp);
+ *lctrlsp = NULL;
+}
+/* }}} */
+
+/* {{{ proto void _php_parse_controls_resp()
+ parse an array of LDAP controls into a zval array */
+static int _php_parse_controls_resp(LDAPControl ***lctrlsp, zval **ctrls)
+{
+ int num_ctrls = 0;
+
+ if (*lctrlsp != NULL) {
+ int error = 0;
+ LDAPControl **ctrlp = *lctrlsp;
+
+ while (*ctrlp) {
+ zval *ctrlval = NULL;
+
+ if ( (*ctrlp)->ldctl_oid == NULL ) {
+ error = 1;
+ break;
+ }
+
+ MAKE_STD_ZVAL(ctrlval);
+ array_init(ctrlval);
+
+ add_assoc_string(ctrlval, "oid", (*ctrlp)->ldctl_oid, 1);
+ if ( (*ctrlp)->ldctl_value.bv_len ) {
+ add_assoc_stringl(ctrlval, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len, 1);
+ }
+
+ /* As per <draft-ietf-ldapbis-protocol>:
+ *
+ * 4.1.11
+
+ The criticality field only has meaning in controls attached to
+ request messages (except UnbindRequest). For controls attached to
+ response messages and the UnbindRequest, the criticality field SHOULD
+ be FALSE, and MUST be ignored by the receiving protocol peer.
+
+ */
+
+ add_next_index_zval(*ctrls, ctrlval);
+
+ num_ctrls++;
+ ctrlp++;
+ }
+ ldap_controls_free(*lctrlsp);
+ *lctrlsp = NULL;
+
+ if (error) {
+ /* ... */
+ return -1;
+ }
+ }
+
+ return num_ctrls;
+}
+/* }}} */
/* {{{ PHP_INI_BEGIN
*/
PHP_INI_BEGIN()
@@ -290,8 +550,21 @@
REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS);
#endif
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+ REGISTER_LONG_CONSTANT("PP_passwordExpired", PP_passwordExpired, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_accountLocked", PP_accountLocked, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_changeAfterReset", PP_changeAfterReset, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_passwordModNotAllowed", PP_passwordModNotAllowed, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_mustSupplyOldPassword", PP_mustSupplyOldPassword, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_insufficientPasswordQuality", PP_insufficientPasswordQuality, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_passwordTooShort", PP_passwordTooShort, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_passwordTooYoung", PP_passwordTooYoung, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_passwordInHistory", PP_passwordInHistory, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("PP_noError", PP_noError, CONST_PERSISTENT | CONST_CS);
+#endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */
+
le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number);
le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number);
le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number);
@@ -377,9 +650,15 @@
PHP_FUNCTION(ldap_connect)
{
char *host = NULL;
int hostlen;
- long port = 389; /* Default port */
+ int port =
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ LDAP_PORT
+#else /* ! LDAP_API_FEATURE_X_OPENLDAP */
+ 389 /* Default port */
+#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
+ ;
#ifdef HAVE_ORALDAP
char *wallet = NULL, *walletpasswd = NULL;
int walletlen = 0, walletpasswdlen = 0;
long authmode = GSLC_SSL_NO_AUTH;
@@ -413,23 +692,41 @@
ld = ecalloc(1, sizeof(ldap_linkdata));
#ifdef LDAP_API_FEATURE_X_OPENLDAP
- if (host != NULL && strchr(host, '/')) {
- int rc;
+ /* OpenLDAP provides a specific call to detect valid LDAP URIs;
+ * ldap_init()/ldap_open() is deprecated, use ldap_initialize() instead.
+ */
+ {
+ int rc;
+ char *url = host;
+
+ if (!ldap_is_ldap_url(url)) {
+ int urllen = hostlen + sizeof( "ldap://:65535" );
+
+ if (port <= 0 || port > 65535) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid port number: %ld", port);
+ RETURN_FALSE;
+ }
+
+ url = emalloc(urllen);
+ snprintf( url, urllen, "ldap://%s:%d", host ? host : "", port );
+ }
- rc = ldap_initialize(&ldap, host);
+ rc = ldap_initialize(&ldap, url);
if (rc != LDAP_SUCCESS) {
efree(ld);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
RETURN_FALSE;
}
- } else {
- ldap = ldap_init(host, port);
+
+ if (url != host) {
+ efree(url);
+ }
}
-#else
+#else /* ! LDAP_API_FEATURE_X_OPENLDAP */
ldap = ldap_open(host, port);
-#endif
+#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
if (ldap == NULL) {
efree(ld);
RETURN_FALSE;
@@ -486,17 +783,32 @@
}
ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
- if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ {
+ struct berval cred;
+
+ /* ldap_bind_s() is deprecated; use ldap_sasl_bind_s() instead */
+ cred.bv_val = ldap_bind_pw;
+ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
+ rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, /* no controls right now */
+ NULL); /* we don't care about the server's credentials */
+ }
+#else
+ rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE);
+#endif
+ if ( rc != LDAP_SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
RETURN_FALSE;
} else {
RETURN_TRUE;
}
}
/* }}} */
+/* {{{ SASL bind stuff */
#ifdef HAVE_LDAP_SASL
typedef struct {
char *mech;
char *realm;
@@ -570,15 +882,21 @@
break;
case SASL_CB_PASS:
p = ctx->passwd;
break;
+ case SASL_CB_NOECHOPROMPT:
+ /* FALLTHROUGH */
+ case SASL_CB_ECHOPROMPT:
+ if (interact->challenge != NULL)
+ p = ctx->passwd;
+ break;
}
if (p) {
interact->result = p;
interact->len = strlen(interact->result);
}
}
- return LDAP_SUCCESS;
+ return SASL_OK;
}
/* }}} */
/* {{{ 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]]]]]]])
@@ -619,8 +937,9 @@
_php_sasl_freedefs(ctx);
}
/* }}} */
#endif /* HAVE_LDAP_SASL */
+/* }}} */
/* {{{ proto bool ldap_unbind(resource link)
Unbind from LDAP directory */
PHP_FUNCTION(ldap_unbind)
@@ -638,8 +957,9 @@
RETURN_TRUE;
}
/* }}} */
+#ifndef HAVE_LDAP_SEARCH_EXT_S
/* {{{ php_set_opts
*/
static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, int *old_sizelimit, int *old_timelimit, int *old_deref)
{
@@ -676,8 +996,9 @@
#endif
}
}
/* }}} */
+#endif /* HAVE_LDAP_SEARCH_EXT_S */
/* {{{ php_ldap_do_search
*/
static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
@@ -1344,9 +1665,14 @@
for (i = 0; i<count; i++) {
add_index_string(return_value, i, ldap_value[i], 1);
}
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ /* ldap_value_free() is deprecated */
+ ber_memvfree((void **)ldap_value);
+#else /* ! LDAP_API_FEATURE_X_OPENLDAP */
ldap_value_free(ldap_value);
+#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */
}
/* }}} */
/* {{{ proto string ldap_dn2ufn(string dn)
@@ -1379,29 +1705,61 @@
/* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */
#define PHP_LD_FULL_ADD 0xff
/* {{{ php_ldap_do_modify
*/
-static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper)
+static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext)
{
- zval **link, **dn, **entry, **value, **ivalue;
+ zval **link, **dn, **entry, **value, **ivalue, **sctrls, **cctrls;
ldap_linkdata *ld;
char *ldap_dn;
LDAPMod **ldap_mods;
int i, j, num_attribs, num_values;
int *num_berval;
char *attribute;
ulong index;
int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */
-
- if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &dn, &entry) == FAILURE) {
- WRONG_PARAM_COUNT;
- }
+ int rc, msgid, myargcount = ZEND_NUM_ARGS();
+ LDAPMessage *ldap_res;
+ LDAPControl **lsctrls = NULL, **lcctrls = NULL;
+
+ if (ext) {
+ if (myargcount < 3 || myargcount > 5 || zend_get_parameters_ex(myargcount, &link, &dn, &entry, &sctrls, &cctrls) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ } else {
+ if (myargcount != 3 || zend_get_parameters_ex(3, &link, &dn, &entry) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ }
if (Z_TYPE_PP(entry) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected Array as the last element");
RETURN_FALSE;
}
+ /* added by gerrit thomson to fix ldap_add using ldap_mod_add */
+ if (oper == PHP_LD_FULL_ADD) {
+ oper = LDAP_MOD_ADD;
+ is_full_add = 1;
+ }
+ /* end additional , gerrit thomson */
+
+ if (myargcount > 3) {
+ if (is_full_add) {
+#ifndef HAVE_LDAP_ADD_EXT_S
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ldap_add_ext not available");
+ RETURN_FALSE;
+#endif /* ! HAVE_LDAP_ADD_EXT_S */
+
+ } else {
+#ifndef HAVE_LDAP_MODIFY_EXT_S
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ldap_modify_ext not available");
+ RETURN_FALSE;
+#endif /* ! HAVE_LDAP_MODIFY_EXT_S */
+ }
+ }
+
ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
convert_to_string_ex(dn);
ldap_dn = Z_STRVAL_PP(dn);
@@ -1410,15 +1768,8 @@
ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0);
num_berval = safe_emalloc(num_attribs, sizeof(int), 0);
zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry));
- /* added by gerrit thomson to fix ldap_add using ldap_mod_add */
- if (oper == PHP_LD_FULL_ADD) {
- oper = LDAP_MOD_ADD;
- is_full_add = 1;
- }
- /* end additional , gerrit thomson */
-
for (i = 0; i < num_attribs; i++) {
ldap_mods[i] = emalloc(sizeof(LDAPMod));
ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
@@ -1471,19 +1822,78 @@
zend_hash_move_forward(Z_ARRVAL_PP(entry));
}
ldap_mods[num_attribs] = NULL;
+ if (ext) {
+ switch (myargcount) {
+ case 5:
+ if (_php_parse_controls(cctrls, &lcctrls) == 0) {
+ RETVAL_FALSE;
+ goto errexit;
+ }
+
+ case 4:
+ if (_php_parse_controls(sctrls, &lsctrls) == 0) {
+ RETVAL_FALSE;
+ goto errexit;
+ }
+ }
+ }
+
/* check flag to see if do_mod was called to perform full add , gerrit thomson */
if (is_full_add == 1) {
- if ((i = ldap_add_s(ld->link, ldap_dn, ldap_mods)) != LDAP_SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Add: %s", ldap_err2string(i));
- RETVAL_FALSE;
- } else RETVAL_TRUE;
- } else {
- if ((i = ldap_modify_s(ld->link, ldap_dn, ldap_mods)) != LDAP_SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modify: %s", ldap_err2string(i));
- RETVAL_FALSE;
- } else RETVAL_TRUE;
+#ifdef HAVE_LDAP_ADD_EXT_S
+ if (ext) {
+ rc = ldap_add_ext(ld->link, ldap_dn, ldap_mods, lsctrls, lcctrls, &msgid);
+
+ } else {
+ rc = ldap_add_ext_s(ld->link, ldap_dn, ldap_mods, NULL, NULL);
+ }
+#else /* ! HAVE_LDAP_ADD_EXT_S */
+ rc = ldap_add_s(ld->link, ldap_dn, ldap_mods);
+#endif /* ! HAVE_LDAP_ADD_EXT_S */
+
+ } else {
+#ifdef HAVE_LDAP_MODIFY_EXT_S
+ if (ext) {
+ rc = ldap_modify_ext(ld->link, ldap_dn, ldap_mods, lsctrls, lcctrls, &msgid);
+
+ } else {
+ rc = ldap_modify_ext_s(ld->link, ldap_dn, ldap_mods, NULL, NULL);
+ }
+#else /* ! HAVE_LDAP_MODIFY_EXT_S */
+ rc = ldap_modify_s(ld->link, ldap_dn, ldap_mods);
+#endif /* ! HAVE_LDAP_MODIFY_EXT_S */
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", is_full_add ? "Add" : "Modify", ldap_err2string(i));
+ RETVAL_FALSE;
+
+ } else {
+ if (ext) {
+ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res);
+ if ((is_full_add && rc != LDAP_RES_ADD) || (!is_full_add && rc != LDAP_RES_MODIFY)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: unable to collect result", is_full_add ? "Add" : "Modify");
+ RETVAL_FALSE;
+
+ } else {
+ int lerr;
+
+ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
+ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0);
+ if (rc == LDAP_SUCCESS) {
+ rc = lerr;
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s failed: %s", is_full_add ? "Add" : "Modify", ldap_err2string(rc));
+ }
+ }
+
+ } else {
+ RETVAL_TRUE;
+ }
}
errexit:
for (i = 0; i < num_attribs; i++) {
@@ -1496,46 +1906,57 @@
}
efree(num_berval);
efree(ldap_mods);
+ if (ext) {
+ if (lsctrls) {
+ _php_free_controls(&lsctrls);
+ }
+ if (lcctrls) {
+ _php_free_controls(&lcctrls);
+ }
+ }
+
return;
}
/* }}} */
/* {{{ proto bool ldap_add(resource link, string dn, array entry)
Add entries to LDAP directory */
PHP_FUNCTION(ldap_add)
{
- /* 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 */
- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD);
+ /* 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 */
+ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0);
}
/* }}} */
-/* three functions for attribute base modifications, gerrit Thomson */
+/* {{{ Three functions for attribute base modifications, gerrit Thomson */
/* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry)
Replace attribute values with new ones */
PHP_FUNCTION(ldap_mod_replace)
{
- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE);
+ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 0);
}
/* }}} */
/* {{{ proto bool ldap_mod_add(resource link, string dn, array entry)
Add attribute values to current */
PHP_FUNCTION(ldap_mod_add)
{
- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD);
+ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 0);
}
/* }}} */
/* {{{ proto bool ldap_mod_del(resource link, string dn, array entry)
+
Delete attribute values */
PHP_FUNCTION(ldap_mod_del)
{
- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE);
+ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 0);
}
/* }}} */
+/* }}} */
/* {{{ proto bool ldap_delete(resource link, string dn)
Delete an entry from a directory */
PHP_FUNCTION(ldap_delete)
@@ -1553,9 +1974,14 @@
convert_to_string_ex(dn);
ldap_dn = Z_STRVAL_PP(dn);
- if ((rc = ldap_delete_s(ld->link, ldap_dn)) != LDAP_SUCCESS) {
+#ifdef HAVE_LDAP_DELETE_EXT_S
+ rc = ldap_delete_ext_s(ld->link, ldap_dn, NULL, NULL);
+#else /* ! HAVE_LDAP_DELETE_EXT_S */
+ rc = ldap_delete_s(ld->link, ldap_dn);
+#endif /* ! HAVE_LDAP_DELETE_EXT_S */
+ if (rc != LDAP_SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: %s", ldap_err2string(rc));
RETURN_FALSE;
}
@@ -1614,19 +2040,27 @@
RETURN_STRING(ldap_err2string(ld_errno), 1);
}
/* }}} */
-/* {{{ proto bool ldap_compare(resource link, string dn, string attr, string value)
- Determine if an entry has a specific value for one of its attributes */
-PHP_FUNCTION(ldap_compare)
+/* {{{ proto void php_ldap_do_compare */
+void php_ldap_do_compare(INTERNAL_FUNCTION_PARAMETERS, int ext)
{
- zval **link, **dn, **attr, **value;
- char *ldap_dn, *ldap_attr, *ldap_value;
+ zval **link, **dn, **attr, **value, **sctrls, **cctrls;
+ char *ldap_dn, *ldap_attr;
ldap_linkdata *ld;
- int errno;
+ int rc, msgid, lerr, myargcount = ZEND_NUM_ARGS();
+ LDAPMessage *ldap_res;
+ LDAPControl **lsctrls = NULL, **lcctrls = NULL;
- if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &link, &dn, &attr, &value) == FAILURE) {
- WRONG_PARAM_COUNT;
+ if (ext) {
+ if (myargcount < 4 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &dn, &attr, &value, &sctrls, &cctrls) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ } else {
+ if (myargcount != 4 || zend_get_parameters_ex(myargcount, &link, &dn, &attr, &value) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
}
ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
@@ -1635,25 +2069,91 @@
convert_to_string_ex(value);
ldap_dn = Z_STRVAL_PP(dn);
ldap_attr = Z_STRVAL_PP(attr);
- ldap_value = Z_STRVAL_PP(value);
- errno = ldap_compare_s(ld->link, ldap_dn, ldap_attr, ldap_value);
+ if (ext) {
+ struct berval ldap_bvalue;
- switch (errno) {
- case LDAP_COMPARE_TRUE:
- RETURN_TRUE;
- break;
+ switch (myargcount) {
+ case 6:
+ _php_parse_controls(cctrls, &lcctrls);
+
+ case 5:
+ _php_parse_controls(sctrls, &lsctrls);
+ }
- case LDAP_COMPARE_FALSE:
+ ldap_bvalue.bv_val = Z_STRVAL_PP(value);
+ ldap_bvalue.bv_len = Z_STRLEN_PP(value);
+ rc = ldap_compare_ext(ld->link, ldap_dn, ldap_attr, &ldap_bvalue, lsctrls, lcctrls, &msgid);
+ if (lsctrls) {
+ _php_free_controls(&lsctrls);
+ }
+ if (lcctrls) {
+ _php_free_controls(&lcctrls);
+ }
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(rc));
RETURN_FALSE;
- break;
- }
+ }
+
+ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res);
+ if (rc != LDAP_RES_COMPARE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: unable to get result");
+ RETURN_FALSE;
+ }
+
+ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
+ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0);
+ if (rc == LDAP_SUCCESS) {
+ rc = lerr;
+ }
+
+ switch (rc) {
+ case LDAP_COMPARE_TRUE:
+ case LDAP_COMPARE_FALSE:
+ break;
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare failed: %s", ldap_err2string(rc));
+ break;
+ }
+
+ } else {
+#ifdef HAVE_LDAP_COMPARE_EXT_S
+ struct berval ldap_bvalue;
+
+ ldap_bvalue.bv_val = Z_STRVAL_PP(value);
+ ldap_bvalue.bv_len = Z_STRLEN_PP(value);
+ rc = ldap_compare_ext_s(ld->link, ldap_dn, ldap_attr, &ldap_bvalue, NULL, NULL);
+#else /* ! HAVE_LDAP_COMPARE_EXT_S */
+ char *ldap_value;
+
+ ldap_value = Z_STRVAL_PP(value);
+ rc = ldap_compare_s(ld->link, ldap_dn, ldap_attr, ldap_value);
+#endif /* ! HAVE_LDAP_COMPARE_EXT_S */
+
+ switch (rc) {
+ case LDAP_COMPARE_TRUE:
+ RETURN_TRUE;
+ break;
+
+ case LDAP_COMPARE_FALSE:
+ RETURN_FALSE;
+ break;
+ }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(errno));
- RETURN_LONG(-1);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(rc));
+ RETURN_LONG(-1);
+ }
+}
+/* }}} */
+/* {{{ proto bool ldap_compare(resource link, string dn, string attr, string value)
+ Determine if an entry has a specific value for one of its attributes */
+PHP_FUNCTION(ldap_compare)
+{
+ php_ldap_do_compare(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
/* {{{ proto bool ldap_sort(resource link, resource result, string sortfilter)
@@ -1685,12 +2185,175 @@
RETURN_TRUE;
}
/* }}} */
-#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
-/* {{{ proto bool ldap_get_option(resource link, int option, mixed retval)
- Get the current value of various session-wide parameters */
-PHP_FUNCTION(ldap_get_option)
+/* {{{ Extended API that returns result instead of just bool
+ * to allow further manipulation by the ldap_parse_*() funcs,
+ * Pierangelo Masarati */
+
+/* {{{ proto result ldap_bind_ext(resource link [, string dn, string password])
+ Bind to LDAP directory */
+PHP_FUNCTION(ldap_bind_ext)
+{
+ zval *link;
+ char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
+ int ldap_bind_dnlen, ldap_bind_pwlen;
+ ldap_linkdata *ld;
+ int rc, msgid, lerr;
+ LDAPMessage *ldap_res;
+
+ 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) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
+
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ {
+ struct berval cred;
+
+ /* ldap_bind() is deprecated; use ldap_sasl_bind() instead */
+ cred.bv_val = ldap_bind_pw;
+ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
+
+ rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, /* no controls right now */
+ &msgid);
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind: %s", ldap_err2string(rc));
+ RETURN_FALSE;
+ }
+ }
+#else
+ msgid = ldap_bind(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE);
+ if (msgid == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind");
+ RETURN_FALSE;
+ }
+#endif
+
+ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res);
+ if (rc != LDAP_RES_BIND) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to get bind result: %s", ldap_err2string(rc));
+ RETURN_FALSE;
+ }
+
+ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
+ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0);
+ if (rc == LDAP_SUCCESS) {
+ rc = lerr;
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
+ }
+}
+/* }}} */
+
+/* {{{ proto result ldap_add_ext(resource link, string dn, array entry)
+ Add entries to LDAP directory; returns result */
+PHP_FUNCTION(ldap_add_ext)
+{
+ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 1);
+}
+/* }}} */
+
+/* {{{ proto result ldap_mod_replace_ext(resource link, string dn, array entry)
+ Replace attribute values with new ones */
+PHP_FUNCTION(ldap_mod_replace_ext)
+{
+ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 1);
+}
+/* }}} */
+
+/* {{{ proto result ldap_mod_add_ext(resource link, string dn, array entry)
+ Add attribute values to current */
+PHP_FUNCTION(ldap_mod_add_ext)
+{
+ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1);
+}
+/* }}} */
+
+/* {{{ proto result ldap_mod_del_ext(resource link, string dn, array entry)
+ Delete attribute values */
+PHP_FUNCTION(ldap_mod_del_ext)
+{
+ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1);
+}
+/* }}} */
+
+/* {{{ proto result ldap_delete_ext(resource link, string dn)
+ Delete an entry from a directory */
+PHP_FUNCTION(ldap_delete_ext)
+{
+ zval **link, **dn, **sctrls, **cctrls;
+ ldap_linkdata *ld;
+ char *ldap_dn;
+ int rc, msgid, lerr, myargcount = ZEND_NUM_ARGS();
+ LDAPMessage *ldap_res;
+ LDAPControl **lsctrls = NULL, **lcctrls = NULL;
+
+ if (myargcount < 2 || myargcount > 4 || zend_get_parameters_ex(myargcount, &link, &dn, &sctrls, &cctrls) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ switch (myargcount) {
+ case 4:
+ _php_parse_controls(cctrls, &lcctrls);
+
+ case 3:
+ _php_parse_controls(sctrls, &lsctrls);
+ }
+
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+
+ convert_to_string_ex(dn);
+ ldap_dn = Z_STRVAL_PP(dn);
+
+ rc = ldap_delete_ext(ld->link, ldap_dn, lsctrls, lcctrls, &msgid);
+ if (lsctrls) {
+ _php_free_controls(&lsctrls);
+ }
+ if (lcctrls) {
+ _php_free_controls(&lcctrls);
+ }
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: %s", ldap_err2string(rc));
+ RETURN_FALSE;
+ }
+
+ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res);
+ if (rc != LDAP_RES_DELETE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: unable to get result");
+ RETURN_FALSE;
+ }
+
+ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
+ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0);
+ if (rc == LDAP_SUCCESS) {
+ rc = lerr;
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete failed: %s", ldap_err2string(rc));
+ }
+}
+/* }}} */
+
+/* {{{ proto result ldap_compare_ext(resource link, string dn, string attr, string value)
+ Determine if an entry has a specific value for one of its attributes */
+PHP_FUNCTION(ldap_compare_ext)
+{
+ php_ldap_do_compare(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* }}} End of extended API, Pierangelo Masarati */
+
+#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
+/* {{{ proto bool ldap_get_option(resource link, int option, mixed retval)
+ Get the current value of various session-wide parameters */
+PHP_FUNCTION(ldap_get_option)
{
zval **link, **option, **retval;
ldap_linkdata *ld;
int opt;
@@ -1910,20 +2573,21 @@
}
/* }}} */
#ifdef HAVE_LDAP_PARSE_RESULT
-/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals)
+/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode [, string matcheddn [, string errmsg [, array referrals [, array serverctrls]]]])
Extract information from result */
PHP_FUNCTION(ldap_parse_result)
{
- zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals;
+ zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals, **serverctrls;
ldap_linkdata *ld;
LDAPMessage *ldap_result;
- char **lreferrals, **refp;
+ LDAPControl **lserverctrls;
+ char **lreferrals;
char *lmatcheddn, *lerrmsg;
int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
- if (myargcount < 3 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals) == FAILURE) {
+ if (myargcount < 3 || myargcount > 7 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}
ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
@@ -1932,9 +2596,9 @@
rc = ldap_parse_result(ld->link, ldap_result, &lerrcode,
myargcount > 3 ? &lmatcheddn : NULL,
myargcount > 4 ? &lerrmsg : NULL,
myargcount > 5 ? &lreferrals : NULL,
- NULL /* &serverctrls */,
+ myargcount > 6 ? &lserverctrls : NULL,
0);
if (rc != LDAP_SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
RETURN_FALSE;
@@ -1944,19 +2608,17 @@
ZVAL_LONG(*errcode, lerrcode);
/* Reverse -> fall through */
switch (myargcount) {
+ case 7:
+ /* use arg #7 as the array of controls returned by the server */
+ zval_dtor(*serverctrls);
+ array_init(*serverctrls);
+ _php_parse_controls_resp(&lserverctrls, serverctrls);
case 6:
zval_dtor(*referrals);
array_init(*referrals);
- if (lreferrals != NULL) {
- refp = lreferrals;
- while (*refp) {
- add_next_index_string(*referrals, *refp, 1);
- refp++;
- }
- ldap_value_free(lreferrals);
- }
+ _php_parse_referrals_resp(&lreferrals, referrals);
case 5:
zval_dtor(*errmsg);
if (lerrmsg == NULL) {
ZVAL_EMPTY_STRING(*errmsg);
@@ -1977,8 +2639,142 @@
}
/* }}} */
#endif
+/* {{{ Extended operation response parsing, Pierangelo Masarati */
+#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
+/* {{{ proto bool ldap_parse_exop(resource link, resource result [, string retoid [, string retdata]])
+ Extract information from extended operation result */
+PHP_FUNCTION(ldap_parse_exop)
+{
+ zval **link, **result, **retoid, **retdata;
+ ldap_linkdata *ld;
+ LDAPMessage *ldap_result;
+ char *lretoid;
+ struct berval *lretdata;
+ int rc, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 2 || myargcount > 4 || zend_get_parameters_ex(myargcount, &link, &result, &retoid, &retdata) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
+
+ rc = ldap_parse_extended_result(ld->link, ldap_result,
+ myargcount > 2 ? &lretoid: NULL,
+ myargcount > 3 ? &lretdata: NULL,
+ 0);
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse extended operation result: %s", ldap_err2string(rc));
+ RETURN_FALSE;
+ }
+
+ /* Reverse -> fall through */
+ switch (myargcount) {
+ case 4:
+ /* use arg #4 as the data returned by the server */
+ zval_dtor(*retdata);
+ if (lretdata == NULL) {
+ ZVAL_EMPTY_STRING(*retdata);
+ } else {
+ ZVAL_STRINGL(*retdata, lretdata->bv_val, lretdata->bv_len, 1);
+ ldap_memfree(lretdata->bv_val);
+ ldap_memfree(lretdata);
+ }
+ case 3:
+ zval_dtor(*retoid);
+ if (lretoid == NULL) {
+ ZVAL_EMPTY_STRING(*retoid);
+ } else {
+ ZVAL_STRING(*retoid, lretoid, 1);
+ ldap_memfree(lretoid);
+ }
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+#ifdef HAVE_LDAP_PARSE_PASSWD
+/* {{{ proto bool ldap_parse_exop_passwd(resource link, resource result, string newpasswd)
+ Extract information from RFC 3062 password modify extended operation result */
+PHP_FUNCTION(ldap_parse_exop_passwd)
+{
+ zval **link, **result, **newpasswd;
+ ldap_linkdata *ld;
+ LDAPMessage *ldap_result;
+ struct berval lnewpasswd;
+ int rc, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount != 3 || zend_get_parameters_ex(myargcount, &link, &result, &newpasswd) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
+
+ rc = ldap_parse_passwd(ld->link, ldap_result, &lnewpasswd);
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse passwd modify extended operation result: %s", ldap_err2string(rc));
+ RETURN_FALSE;
+ }
+
+ zval_dtor(*newpasswd);
+ if (lnewpasswd.bv_len == 0) {
+ ZVAL_EMPTY_STRING(*newpasswd);
+ } else {
+ ZVAL_STRINGL(*newpasswd, lnewpasswd.bv_val, lnewpasswd.bv_len, 1);
+ ldap_memfree(lnewpasswd.bv_val);
+ }
+
+ RETURN_TRUE;
+}
+#else
+/* TODO: implement based on ldap_parse_exop() */
+/* }}} */
+#endif
+
+#ifdef HAVE_LDAP_PARSE_WHOAMI
+/* {{{ proto bool ldap_parse_exop_whoami(resource link, resource result, string authzid)
+ Extract information from <draft-zeilenga-ldap-authzid> whoami extended operation result (a Work in Progress) */
+PHP_FUNCTION(ldap_parse_exop_whoami)
+{
+ zval **link, **result, **authzid;
+ ldap_linkdata *ld;
+ LDAPMessage *ldap_result;
+ struct berval *lauthzid;
+ int rc, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount != 3 || zend_get_parameters_ex(myargcount, &link, &result, &authzid) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
+
+ rc = ldap_parse_whoami(ld->link, ldap_result, &lauthzid );
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse whoami extended operation result: %s", ldap_err2string(rc));
+ RETURN_FALSE;
+ }
+
+ zval_dtor(*authzid);
+ if (lauthzid == NULL) {
+ ZVAL_EMPTY_STRING(*authzid);
+ } else {
+ ZVAL_STRINGL(*authzid, lauthzid->bv_val, lauthzid->bv_len, 1);
+ ldap_memfree(lauthzid->bv_val);
+ ldap_memfree(lauthzid);
+ }
+ RETURN_TRUE;
+}
+#else
+/* TODO: implement based on ldap_parse_extended_result() */
+/* }}} */
+#endif
+/* }}} */
+#endif
+
/* {{{ proto resource ldap_first_reference(resource link, resource result)
Return first reference */
PHP_FUNCTION(ldap_first_reference)
{
@@ -2038,34 +2834,40 @@
/* {{{ proto bool ldap_parse_reference(resource link, resource reference_entry, array referrals)
Extract information from reference entry */
PHP_FUNCTION(ldap_parse_reference)
{
- zval **link, **result_entry, **referrals;
+ zval **link, **result_entry, **referrals, **serverctrls;
ldap_linkdata *ld;
ldap_resultentry *resultentry;
- char **lreferrals, **refp;
+ char **lreferrals;
+ LDAPControl **lserverctrls;
+ int myargcount = ZEND_NUM_ARGS();
- if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &referrals) == FAILURE) {
+ if (myargcount < 3 || myargcount > 4 || zend_get_parameters_ex(4, &link, &result_entry, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}
ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
- if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
+ if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, &lserverctrls, 0) != LDAP_SUCCESS) {
RETURN_FALSE;
}
- zval_dtor(*referrals);
- array_init(*referrals);
- if (lreferrals != NULL) {
- refp = lreferrals;
- while (*refp) {
- add_next_index_string(*referrals, *refp, 1);
- refp++;
- }
- ldap_value_free(lreferrals);
+
+ /* Reverse -> fall through */
+ switch (myargcount) {
+ case 4:
+ /* use arg #4 as the array of controls returned by the server */
+ zval_dtor(*serverctrls);
+ array_init(*serverctrls);
+ _php_parse_controls_resp(&lserverctrls, serverctrls);
+ case 3:
+ zval_dtor(*referrals);
+ array_init(*referrals);
+ _php_parse_referrals_resp(&lreferrals, referrals);
}
+
RETURN_TRUE;
}
/* }}} */
#endif
@@ -2281,8 +3083,699 @@
}
/* }}} */
#endif
+/* {{{ Extended operations, Pierangelo Masarati */
+#ifdef HAVE_LDAP_EXTENDED_OPERATION_S
+/* {{{ proto ? ldap_exop(resource link, string reqoid [, string reqdata [, string retoid [, string retdata]]])
+ Extended operation */
+PHP_FUNCTION(ldap_exop)
+{
+ zval **link, **reqoid, **reqdata, **retoid, **retdata;
+ char *lreqoid, *lretoid = NULL;
+ struct berval lreqdata, *lretdata = NULL;
+ ldap_linkdata *ld;
+ LDAP *ldap;
+ LDAPMessage *ldap_res;
+ int rc, msgid, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 2 || myargcount > 5 || zend_get_parameters_ex(myargcount, &link, &reqoid, &reqdata, &retoid, &retdata) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (Z_TYPE_PP(link) == IS_NULL) {
+ ldap = NULL;
+ } else {
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ldap = ld->link;
+ }
+
+ switch (myargcount) {
+ case 5:
+ case 4:
+ case 3:
+ convert_to_string_ex(reqdata);
+ lreqdata.bv_val = Z_STRVAL_PP(reqdata);
+ lreqdata.bv_len = Z_STRLEN_PP(reqdata);
+ /* fallthru */
+ case 2:
+ convert_to_string_ex(reqoid);
+ lreqoid = Z_STRVAL_PP(reqoid);
+ }
+
+ if (myargcount > 3) {
+ /* synchronous call */
+ rc = ldap_extended_operation_s(ld->link, lreqoid,
+ lreqdata.bv_len > 0 ? &lreqdata: NULL,
+ NULL,
+ NULL,
+ &lretoid,
+ myargcount > 4 ? &lretdata : NULL );
+ if (rc != LDAP_SUCCESS ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed: %s (%d)", lreqoid, ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ /* Reverse -> fall through */
+ switch (myargcount) {
+ case 5:
+ /* use arg #4 as the data returned by the server */
+ zval_dtor(*retdata);
+ if (lretdata == NULL) {
+ ZVAL_EMPTY_STRING(*retdata);
+ } else {
+ ZVAL_STRINGL(*retdata, lretdata->bv_val, lretdata->bv_len, 1);
+ ldap_memfree(lretdata->bv_val);
+ ldap_memfree(lretdata);
+ }
+ case 4:
+ zval_dtor(*retoid);
+ if (lretoid == NULL) {
+ ZVAL_EMPTY_STRING(*retoid);
+ } else {
+ ZVAL_STRING(*retoid, lretoid, 1);
+ ldap_memfree(lretoid);
+ }
+ }
+
+ RETURN_TRUE;
+ }
+
+ /* asynchronous call */
+ rc = ldap_extended_operation(ld->link, lreqoid,
+ lreqdata.bv_len > 0 ? &lreqdata: NULL,
+ NULL, NULL, &msgid);
+ if (rc != LDAP_SUCCESS ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed: %s (%d)", lreqoid, ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
+ if (rc == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed", lreqoid);
+ RETURN_FALSE;
+ }
+
+ /* return a PHP control object */
+ array_init(return_value);
+
+ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
+}
+/* }}} */
+
+#ifdef HAVE_LDAP_PASSWD_S
+/* {{{ proto ? ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw [, string newpasswd ]]]])
+ Passwd modify extended operation */
+PHP_FUNCTION(ldap_exop_passwd)
+{
+ zval **link, **user, **newpw, **oldpw, **newpasswd;
+ struct berval luser, loldpw, lnewpw, lnewpasswd;
+ ldap_linkdata *ld;
+ LDAP *ldap;
+ LDAPMessage *ldap_res;
+ int rc, msgid, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 1 || myargcount > 5 || zend_get_parameters_ex(myargcount, &link, &user, &oldpw, &newpw, &newpasswd) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (Z_TYPE_PP(link) == IS_NULL) {
+ ldap = NULL;
+ } else {
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ldap = ld->link;
+ }
+
+ luser.bv_len = 0;
+ loldpw.bv_len = 0;
+ lnewpw.bv_len = 0;
+
+ switch (myargcount) {
+ case 5:
+ case 4:
+ convert_to_string_ex(newpw);
+ lnewpw.bv_val = Z_STRVAL_PP(newpw);
+ lnewpw.bv_len = Z_STRLEN_PP(newpw);
+
+ case 3:
+ convert_to_string_ex(oldpw);
+ loldpw.bv_val = Z_STRVAL_PP(oldpw);
+ loldpw.bv_len = Z_STRLEN_PP(oldpw);
+
+ case 2:
+ convert_to_string_ex(user);
+ luser.bv_val = Z_STRVAL_PP(user);
+ luser.bv_len = Z_STRLEN_PP(user);
+ }
+
+ if (myargcount > 4 || lnewpw.bv_len > 0) {
+ /* synchronous call */
+ rc = ldap_passwd_s(ld->link, &luser,
+ loldpw.bv_len > 0 ? &loldpw : NULL,
+ lnewpw.bv_len > 0 ? &lnewpw : NULL,
+ &lnewpasswd, NULL, NULL);
+ if (rc != LDAP_SUCCESS ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ if (myargcount > 4) {
+ zval_dtor(*newpasswd);
+ if (lnewpasswd.bv_len == 0) {
+ ZVAL_EMPTY_STRING(*newpasswd);
+ } else {
+ ZVAL_STRINGL(*newpasswd, lnewpasswd.bv_val, lnewpasswd.bv_len, 1);
+ }
+ }
+
+ ldap_memfree(lnewpasswd.bv_val);
+
+ RETURN_TRUE;
+ }
+
+ /* asynchronous call */
+ rc = ldap_passwd(ld->link, &luser,
+ loldpw.bv_len > 0 ? &loldpw : NULL,
+ lnewpw.bv_len > 0 ? &lnewpw : NULL,
+ NULL, NULL, &msgid);
+ if (rc != LDAP_SUCCESS ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
+ if (rc == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed");
+ RETURN_FALSE;
+ }
+
+ /* return a PHP control object */
+ array_init(return_value);
+
+ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
+}
+#else
+/* TODO: implement based on ldap_extended_operation_s() */
+/* }}} */
+#endif
+
+#ifdef HAVE_LDAP_WHOAMI_S
+/* {{{ proto ? ldap_exop_whoami(resource link [, string authzid])
+ Whoami extended operation */
+PHP_FUNCTION(ldap_exop_whoami)
+{
+ zval **link, **authzid;
+ struct berval *lauthzid;
+ ldap_linkdata *ld;
+ LDAP *ldap;
+ LDAPMessage *ldap_res;
+ int rc, msgid, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 1 || myargcount > 2 || zend_get_parameters_ex(myargcount, &link, &authzid) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (Z_TYPE_PP(link) == IS_NULL) {
+ ldap = NULL;
+ } else {
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ldap = ld->link;
+ }
+
+ if (myargcount == 2) {
+ /* synchronous call */
+ rc = ldap_whoami_s(ld->link, &lauthzid, NULL, NULL);
+ if (rc != LDAP_SUCCESS ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ zval_dtor(*authzid);
+ if (lauthzid == NULL) {
+ ZVAL_EMPTY_STRING(*authzid);
+ } else {
+ ZVAL_STRINGL(*authzid, lauthzid->bv_val, lauthzid->bv_len, 1);
+ ldap_memfree(lauthzid->bv_val);
+ ldap_memfree(lauthzid);
+ }
+
+ RETURN_TRUE;
+ }
+
+ /* asynchronous call */
+ rc = ldap_whoami(ld->link, NULL, NULL, &msgid);
+ if (rc != LDAP_SUCCESS ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
+ if (rc == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed");
+ RETURN_FALSE;
+ }
+
+ /* return a PHP control object */
+ array_init(return_value);
+
+ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
+}
+#else
+/* TODO: implement based on ldap_extended_operation_s() */
+#endif
+/* }}} */
+#endif
+/* }}} */
+
+/* {{{ LDAP controls encoding/decoding, Pierangelo Masarati */
+/* {{{ php_set_no_value_server_ctrl
+ */
+static void php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAMETERS, const char *oid, const char *msg)
+{
+ zval **link, **iscritical;
+ ldap_linkdata *ld;
+ LDAP *ldap;
+ LDAPControl ctrl = { 0 }, *ctrlsp[2];
+ int rc, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 1 || myargcount > 2 || zend_get_parameters_ex(myargcount, &link, &iscritical) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (Z_TYPE_PP(link) == IS_NULL) {
+ ldap = NULL;
+
+ } else {
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ldap = ld->link;
+ }
+
+ if (myargcount == 2) {
+ convert_to_boolean_ex(iscritical);
+ ctrl.ldctl_iscritical = Z_BVAL_PP(iscritical);
+ }
+
+ ctrl.ldctl_oid = (char *)oid;
+
+ if (ldap) {
+ /* directly set the option */
+ ctrlsp[0] = &ctrl;
+ ctrlsp[1] = NULL;
+
+ rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp);
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set %s control: %s (%d)", msg, ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ } else {
+ /* return a PHP control object */
+ array_init(return_value);
+
+ add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1);
+ if (ctrl.ldctl_iscritical) {
+ add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical);
+ }
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+#ifdef LDAP_CONTROL_MANAGEDSAIT
+/* {{{ proto bool ldap_ctrl_manageDSAit(resource link [, bool iscritical])
+ Inject manageDSAit control */
+PHP_FUNCTION(ldap_ctrl_manageDSAit)
+{
+ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_MANAGEDSAIT, "manageDSAit");
+}
+/* }}} */
+#endif
+
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+/* {{{ proto bool ldap_ctrl_paged_results(resource link, int pagesize [, bool iscritical [, string cookie]])
+ Inject paged results control*/
+PHP_FUNCTION(ldap_ctrl_paged_results)
+{
+ zval **link, **pagesize, **iscritical, **cookie;
+ int lpagesize = 0;
+ struct berval lcookie = { 0, NULL };
+ ldap_linkdata *ld;
+ LDAP *ldap;
+ BerElement *ber = NULL;
+ LDAPControl ctrl, *ctrlsp[2];
+ int rc, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 2 || myargcount > 4 || zend_get_parameters_ex(myargcount, &link, &pagesize, &iscritical, &cookie) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (Z_TYPE_PP(link) == IS_NULL) {
+ ldap = NULL;
+ } else {
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ldap = ld->link;
+ }
+
+ ber = ber_alloc_t(LBER_USE_DER);
+ if (ber == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER encoding resources for paged results control");
+ RETURN_FALSE;
+ }
+
+ ctrl.ldctl_iscritical = 0;
+
+ switch (myargcount) {
+ case 4:
+ convert_to_string_ex(cookie);
+ lcookie.bv_val = Z_STRVAL_PP(cookie);
+ lcookie.bv_len = Z_STRLEN_PP(cookie);
+ /* fallthru */
+ case 3:
+ convert_to_boolean_ex(iscritical);
+ ctrl.ldctl_iscritical = Z_BVAL_PP(iscritical);
+ /* fallthru */
+ }
+ convert_to_long_ex(pagesize);
+ lpagesize = Z_LVAL_PP(pagesize);
+
+ ber_printf(ber, "{iO}", lpagesize, &lcookie );
+ rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 );
+ if ( rc == -1 ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER encode paged results control");
+ RETURN_FALSE;
+ }
+
+ ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+
+ if (ldap) {
+ /* directly set the option */
+ ctrlsp[0] = &ctrl;
+ ctrlsp[1] = NULL;
+
+ rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp);
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set paged results control: %s (%d)", ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ } else {
+ /* return a PHP control object */
+ array_init(return_value);
+
+ add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1);
+ if ( ctrl.ldctl_value.bv_len ) {
+ add_assoc_stringl(return_value, "value", ctrl.ldctl_value.bv_val, ctrl.ldctl_value.bv_len, 1);
+ }
+ if (ctrl.ldctl_iscritical) {
+ add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical);
+ }
+ }
+
+ if (ber != NULL) {
+ ber_free(ber, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ldap_ctrl_paged_results_resp(resource link, resource result [, string cookie [, int estimated]])
+ Extract paged results control response */
+PHP_FUNCTION(ldap_ctrl_paged_results_resp)
+{
+ zval **link, **result, **cookie, **estimated;
+ struct berval lcookie;
+ int lestimated;
+ ldap_linkdata *ld;
+ LDAPMessage *ldap_result;
+ LDAPControl **lserverctrls, *lctrl;
+ BerElement *ber;
+ ber_tag_t tag;
+ int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 3 || myargcount > 4 || zend_get_parameters_ex(myargcount, &link, &result, &cookie, &estimated) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
+
+ rc = ldap_parse_result(ld->link,
+ ldap_result,
+ &lerrcode,
+ NULL, /* matcheddn */
+ NULL, /* errmsg */
+ NULL, /* referrals */
+ &lserverctrls,
+ 0);
+
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ if (lerrcode != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode);
+ RETURN_FALSE;
+ }
+
+ if (lserverctrls == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result");
+ RETURN_FALSE;
+ }
+
+ lctrl = ldap_find_control(LDAP_CONTROL_PAGEDRESULTS, lserverctrls);
+ if (lctrl == NULL) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control response in result");
+ RETURN_FALSE;
+ }
+
+ ber = ber_init(&lctrl->ldctl_value);
+ if (ber == NULL) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER decoding resources for paged results control response");
+ RETURN_FALSE;
+ }
+
+ tag = ber_scanf(ber, "{io}", &lestimated, &lcookie );
+ (void)ber_free(ber, 1);
+
+ if (tag == LBER_ERROR) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response");
+ RETURN_FALSE;
+ }
+
+ if (lestimated < 0) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid paged results control response value");
+ RETURN_FALSE;
+ }
+
+ ldap_controls_free(lserverctrls);
+
+ if (myargcount == 4) {
+ zval_dtor(*estimated);
+ ZVAL_LONG(*estimated, lestimated);
+ }
+
+ zval_dtor(*cookie);
+ if (lcookie.bv_len == 0) {
+ ZVAL_EMPTY_STRING(*cookie);
+ } else {
+ ZVAL_STRINGL(*cookie, lcookie.bv_val, lcookie.bv_len, 1);
+ }
+ ldap_memfree(lcookie.bv_val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+#endif
+
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+/* {{{ proto bool ldap_ctrl_ppolicy(resource link [, bool iscritical])
+ Inject password policy control */
+PHP_FUNCTION(ldap_ctrl_ppolicy)
+{
+ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_PASSWORDPOLICYREQUEST, "passwordPolicy");
+}
+/* }}} */
+
+/* {{{ proto bool ldap_ctrl_ppolicy_resp(resource link, resource result [, expire [, grace [, error[, errmsg]]]])
+ Extract password policy control response */
+PHP_FUNCTION(ldap_ctrl_ppolicy_resp)
+{
+ zval **link, **result, **ppexpire, **ppgrace, **pperror, **pperrmsg;
+ int lexpire, lgrace;
+ LDAPPasswordPolicyError lerror;
+ ldap_linkdata *ld;
+ LDAPMessage *ldap_result;
+ LDAPControl **lserverctrls, *lctrl;
+ int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 3 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &result, &ppexpire, &ppgrace, &pperror, &pperrmsg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
+
+ rc = ldap_parse_result(ld->link,
+ ldap_result,
+ &lerrcode,
+ NULL, /* matcheddn */
+ NULL, /* errmsg */
+ NULL, /* referrals */
+ &lserverctrls,
+ 0);
+
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ if (lerrcode != LDAP_SUCCESS && lerrcode != LDAP_INVALID_CREDENTIALS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode);
+ RETURN_FALSE;
+ }
+
+ if (lserverctrls == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result");
+ RETURN_FALSE;
+ }
+
+ lctrl = ldap_find_control(LDAP_CONTROL_PASSWORDPOLICYRESPONSE, lserverctrls);
+ if (lctrl == NULL) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No password policy control response in result");
+ RETURN_FALSE;
+ }
+
+ lerrcode = ldap_parse_passwordpolicy_control(ld->link, lctrl, &lexpire, &lgrace, &lerror);
+ ldap_controls_free(lserverctrls);
+ if (lerrcode != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse password policy control response: %s (%d)", ldap_err2string(lerrcode), lerrcode);
+ RETURN_FALSE;
+ }
+
+ switch (myargcount) {
+ case 6:
+ zval_dtor(*pperrmsg);
+ ZVAL_STRING(*pperrmsg, (char *)ldap_passwordpolicy_err2txt(lerror), 1);
+
+ case 5:
+ zval_dtor(*pperror);
+ ZVAL_LONG(*pperror, (long)lerror);
+
+ case 4:
+ zval_dtor(*ppgrace);
+ ZVAL_LONG(*ppgrace, (long)lgrace);
+ }
+
+ zval_dtor(*ppexpire);
+ ZVAL_LONG(*ppexpire, (long)lexpire);
+
+ RETURN_TRUE;
+}
+/* }}} */
+#endif
+
+#ifdef LDAP_CONTROL_NOOP
+/* {{{ proto bool ldap_ctrl_noop(resource link, bool iscritical)
+ Inject control*/
+PHP_FUNCTION(ldap_ctrl_noop)
+{
+ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_NOOP, "no-op");
+}
+/* }}} */
+#endif
+
+#ifdef LDAP_CONTROL_MANAGEDIT
+/* {{{ proto bool ldap_ctrl_manageDIT(resource link [, bool iscritical])
+ Inject control*/
+PHP_FUNCTION(ldap_ctrl_manageDIT)
+{
+ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_MANAGEDIT, "manageDIT");
+}
+/* }}} */
+#endif
+
+#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
+/* {{{ proto bool ldap_ctrl_permissive_modify(resource link [, bool iscritical])
+ Inject control*/
+PHP_FUNCTION(ldap_ctrl_permissive_modify)
+{
+ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_X_PERMISSIVE_MODIFY, "permissive modify");
+}
+/* }}} */
+#endif
+/* }}} */
+
+#ifdef HAVE_LDAP_REFRESH
+/* {{{ proto ? ldap_refresh(resource link , string dn , int ttl, [int *newttl])
+ DDS refresh extended operation */
+PHP_FUNCTION(ldap_refresh)
+{
+ zval **link, **dn, **ttl, **newttl;
+ struct berval ldn;
+ ber_int_t lttl;
+ ber_int_t lnewttl;
+ ldap_linkdata *ld;
+ LDAP *ldap;
+ LDAPMessage *ldap_res;
+ int rc, msgid, myargcount = ZEND_NUM_ARGS();
+
+ switch (myargcount) {
+ case 3:
+ if (zend_get_parameters_ex(myargcount, &link,
+ &dn, &ttl) == FAILURE)
+ WRONG_PARAM_COUNT;
+ break;
+ case 4:
+ if (zend_get_parameters_ex(myargcount, &link,
+ &dn, &ttl, &newttl) == FAILURE)
+ WRONG_PARAM_COUNT;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ }
+
+ if (Z_TYPE_PP(link) == IS_NULL) {
+ ldap = NULL;
+ } else {
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *,
+ link, -1, "ldap link", le_link);
+ ldap = ld->link;
+ }
+
+ ldn.bv_len = 0;
+ convert_to_string_ex(dn);
+ ldn.bv_val = Z_STRVAL_PP(dn);
+ ldn.bv_len = Z_STRLEN_PP(dn);
+
+ convert_to_long_ex(ttl);
+ lttl = (ber_int_t)Z_LVAL_PP(ttl);
+
+ /* asynchronous call */
+ rc = ldap_refresh_s(ld->link, &ldn, lttl, &lnewttl, NULL, NULL);
+ if (rc != LDAP_SUCCESS ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Refresh extended operation failed: %s (%d)",
+ ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ if (myargcount == 4) {
+ zval_dtor(*newttl);
+ ZVAL_LONG(*newttl, (long)lnewttl);
+ }
+ RETURN_TRUE;
+}
+#else
+/* TODO: implement based on ldap_extended_operation_s() */
+/* }}} */
+#endif
+
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
--- ext/ldap/config.m4.orig 2007-08-08 11:37:44.000000000 +0000
+++ ext/ldap/config.m4 2009-09-05 07:07:43.000000000 +0000
@@ -172,9 +172,11 @@
fi
dnl Solaris 2.8 claims to be 2004 API, but doesn't have
dnl ldap_parse_reference() nor ldap_start_tls_s()
- AC_CHECK_FUNCS([ldap_parse_result ldap_parse_reference ldap_start_tls_s])
+ AC_CHECK_FUNCS([ldap_parse_result ldap_parse_extended_result ldap_parse_whoami ldap_parse_passwd ldap_parse_reference])
+ AC_CHECK_FUNCS([ldap_extended_operation_s ldap_start_tls_s ldap_whoami_s ldap_passwd_s ldap_refresh])
+ #AC_CHECK_FUNCS_XXXnotyet([ldap_search_ext_s ldap_add_ext_s ldap_modify_ext_s ldap_delete_ext_s ldap_compare_ext_s])
dnl
dnl SASL check
dnl
--- ext/ldap/php_ldap.h.orig 2008-12-31 11:17:39.000000000 +0000
+++ ext/ldap/php_ldap.h 2009-09-05 07:07:43.000000000 +0000
@@ -68,8 +68,16 @@
PHP_FUNCTION(ldap_error);
PHP_FUNCTION(ldap_compare);
PHP_FUNCTION(ldap_sort);
+PHP_FUNCTION(ldap_bind_ext);
+PHP_FUNCTION(ldap_add_ext);
+PHP_FUNCTION(ldap_delete_ext);
+PHP_FUNCTION(ldap_mod_add_ext);
+PHP_FUNCTION(ldap_mod_replace_ext);
+PHP_FUNCTION(ldap_mod_del_ext);
+PHP_FUNCTION(ldap_compare_ext);
+
#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
PHP_FUNCTION(ldap_get_option);
PHP_FUNCTION(ldap_set_option);
PHP_FUNCTION(ldap_first_reference);
@@ -83,10 +91,23 @@
#endif
#endif
#if LDAP_API_VERSION > 2000
+#ifdef HAVE_LDAP_EXTENDED_OPERATION_S
+PHP_FUNCTION(ldap_exop);
+PHP_FUNCTION(ldap_exop_passwd);
+PHP_FUNCTION(ldap_exop_whoami);
PHP_FUNCTION(ldap_start_tls);
#endif
+#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
+PHP_FUNCTION(ldap_parse_exop);
+PHP_FUNCTION(ldap_parse_exop_passwd);
+PHP_FUNCTION(ldap_parse_exop_whoami);
+#endif
+#ifdef HAVE_LDAP_REFRESH
+PHP_FUNCTION(ldap_refresh);
+#endif
+#endif
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
PHP_FUNCTION(ldap_set_rebind_proc);
#endif
@@ -95,8 +116,121 @@
PHP_FUNCTION(ldap_t61_to_8859);
PHP_FUNCTION(ldap_8859_to_t61);
#endif
+#ifdef HAVE_LDAP_EXTENDED_OPERATION
+
+#endif
+
+#ifdef LDAP_CONTROL_MANAGEDSAIT
+/* RFC 3296 */
+PHP_FUNCTION(ldap_ctrl_manageDSAit);
+#endif
+#ifdef LDAP_CONTROL_PROXY_AUTHZ
+/* <draft-weltman-ldapv3-proxy> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_proxy_authz);
+#endif
+#ifdef LDAP_CONTROL_SUBENTRIES
+/* RFC 3672 */
+PHP_FUNCTION(ldap_ctrl_subentries);
+#endif
+#ifdef LDAP_CONTROL_VALUESRETURNFILTER
+/* RFC 3876 */
+PHP_FUNCTION(ldap_ctrl_vlv);
+#endif
+#ifdef LDAP_CONTROL_ASSERT
+/* <draft-zeilenga-ldap-assert> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_assert);
+#endif
+#ifdef LDAP_CONTROL_PRE_READ
+/* <draft-zeilenga-ldap-readentry> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_preread);
+PHP_FUNCTION(ldap_ctrl_postread);
+#endif
+#ifdef LDAP_CONTROL_SORTREQUEST
+/* RFC 2891 */
+PHP_FUNCTION(ldap_ctrl_sort);
+PHP_FUNCTION(ldap_ctrl_sort_resp);
+#endif
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+/* RFC 2696 */
+PHP_FUNCTION(ldap_ctrl_paged_results);
+PHP_FUNCTION(ldap_ctrl_paged_results_resp);
+#endif
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+/* <draft-behera-ldap-password-policy> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_ppolicy);
+PHP_FUNCTION(ldap_ctrl_ppolicy_resp);
+#endif
+#ifdef LDAP_CONTROL_NOOP
+/* <draft-zeilenga-ldap-noop> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_noop);
+#endif
+#ifdef LDAP_CONTROL_NO_SUBORDINATES
+/* don't know anything about it */
+#endif
+#ifdef LDAP_CONTROL_MANAGEDIT
+/* no spec; partially implemented in OpenLDAP 2.3 */
+PHP_FUNCTION(ldap_ctrl_manageDIT);
+#endif
+#ifdef LDAP_CONTROL_SLURP
+/* don't know anything about it */
+#endif
+#ifdef LDAP_CONTROL_VALSORT
+/* <> */
+PHP_FUNCTION(ldap_ctrl_valsort);
+#endif
+#ifdef LDAP_CONTROL_SYNC
+/* <draft-zeilenga-ldup-sync> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_sync);
+PHP_FUNCTION(ldap_ctrl_sync_state);
+PHP_FUNCTION(ldap_ctrl_sync_done);
+/* TODO: need to handle the SYNC intermediate response message (LDAPIRM) */
+#endif
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+/* <draft-sermersheim-ldap-chaining> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_chaining);
+#endif
+#ifdef LDAP_CONTROL_X_INCREMENTAL_VALUES
+/* MS Active Directory */
+PHP_FUNCTION(ldap_ctrl_incremental_values);
+#endif
+#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
+/* MS Active Directory */
+PHP_FUNCTION(ldap_ctrl_domain_scope);
+#endif
+#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
+/* MS Active Directory */
+PHP_FUNCTION(ldap_ctrl_permissive_modify);
+#endif
+#ifdef LDAP_CONTROL_X_SEARCH_OPTIONS
+/* MS Active Directory */
+PHP_FUNCTION(ldap_ctrl_search_options);
+#endif
+#ifdef LDAP_CONTROL_X_TREE_DELETE
+/* MS Active Directory */
+PHP_FUNCTION(ldap_ctrl_tree_delete);
+#endif
+#ifdef LDAP_CONTROL_X_EXTENDED_DN
+/* MS Active Directory */
+PHP_FUNCTION(ldap_ctrl_extended_dn);
+#endif
+#ifdef LDAP_CONTROL_DUPENT
+/* <draft-ietf-ldapext-ldapv3-dupent> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_dupent);
+PHP_FUNCTION(ldap_ctrl_dupent_resp);
+PHP_FUNCTION(ldap_ctrl_dupent_done_resp);
+#endif
+#ifdef LDAP_CONTROL_PERSIST_REQUEST
+/* ? */
+#endif
+#ifdef LDAP_CONTROL_VLVREQUEST
+/* <draft-ietf-ldapext-ldapv3-vlv> (a Work in Progress) */
+PHP_FUNCTION(ldap_ctrl_vlv);
+PHP_FUNCTION(ldap_ctrl_vlv_resp);
+#endif
+
+
ZEND_BEGIN_MODULE_GLOBALS(ldap)
long num_links;
long max_links;
ZEND_END_MODULE_GLOBALS(ldap)