Jani, this is the latest version of the LDAP API extension patch; it should be preceded by the OpenLDAP C API cleanup patch:
<php-devel-2005-12-10.misc.patch> which should be otherwise harmless, but I strongly recommend it to avoid issues, e.g., with 64 bit archs and the likely. The main patch is <php-devel-2005-12-10.controls-exops.patch> and it is accompanied by a test script (please feel free to improve): <exops.php> which requires some limited manual intervention, and OpenLDAP 2.3, to run. Comments and rationale are available inside each patch; they also contain a statement about the applicable license, which of course is the PHP license. I'd appreciate if you can comment about the proposed enhancements, and integrate them at your convenience in PHP repository. If you like, I'd be happy to be granted limited CVS write access to maintain that portion of software myself, as it appears essentially unmaintained since long time ago. As soon as it gets integrated, I'll keep posting further development with the missing controls. Sincerely, p. Ing. Pierangelo Masarati Responsabile Open Solution SysNet s.n.c. Via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it ------------------------------------------ Office: +39.02.23998309 Mobile: +39.333.4963172 Email: [EMAIL PROTECTED] ------------------------------------------
This patch provides misc cleanup of the LDAP extension of PHP according to the current status and evolution trends of the OpenLDAP API as of 2.3 and above. It is intended for PHP HEAD code as of December 2005, but it is known to apply without relevant issues to PHP 5 and 4. It __should__ be backward compatible at least with OpenLDAP 2.2. All requested features are detected at compile time, so it __should__ not cause problem with any other LDAP API; simply, the extensions will not be available. Author: Pierangelo Masarati <[EMAIL PROTECTED]>, <[EMAIL PROTECTED]> This software is released under the terms of the PHP license for inclusion in PHP software. Index: ext/ldap/ldap.c =================================================================== RCS file: /repository/php-src/ext/ldap/ldap.c,v retrieving revision 1.163 diff -u -r1.163 ldap.c --- ext/ldap/ldap.c 6 Dec 2005 02:24:38 -0000 1.163 +++ ext/ldap/ldap.c 10 Dec 2005 14:45:08 -0000 @@ -191,13 +253,19 @@ { 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)--; } @@ -370,7 +513,13 @@ { 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, *walletpasswd; int walletlen, walletpasswdlen; @@ -406,21 +555,39 @@ 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() ius 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:%ld", host ? host : "", port ? port : LDAP_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); @@ -479,7 +646,21 @@ 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 { @@ -1030,7 +1211,6 @@ BerElement *ber; char *attribute; size_t attr_len; - char **ldap_value; char *dn; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) { @@ -1061,16 +1241,22 @@ attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber); while (attribute != NULL) { - ldap_value = ldap_get_values(ldap, ldap_result_entry, attribute); - num_values = ldap_count_values(ldap_value); + struct berval **ldap_value; + + /* ldap_get_values() is deprecated, because it cannot deal + * with non-null terminated string values; always use + * the *_len() variant instead, which __should__ be portable + * and is safe regardless of the actual data being returned. */ + ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute); + num_values = ldap_count_values_len(ldap_value); MAKE_STD_ZVAL(tmp2); array_init(tmp2); add_assoc_long(tmp2, "count", num_values); for (i = 0; i < num_values; i++) { - add_index_string(tmp2, i, ldap_value[i], 1); + add_index_stringl(tmp2, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1); } - ldap_value_free(ldap_value); + ldap_value_free_len(ldap_value); attr_len = strlen(attribute); zend_hash_update(Z_ARRVAL_P(tmp1), php_strtolower(attribute, attr_len), attr_len+1, (void *) &tmp2, sizeof(zval *), NULL); @@ -1177,7 +1363,6 @@ ldap_linkdata *ld; ldap_resultentry *resultentry; char *attribute; - char **ldap_value; int i, num_values, num_attrib; BerElement *ber; @@ -1193,16 +1378,18 @@ attribute = ldap_first_attribute(ld->link, resultentry->data, &ber); while (attribute != NULL) { - ldap_value = ldap_get_values(ld->link, resultentry->data, attribute); - num_values = ldap_count_values(ldap_value); + struct berval **ldap_value; + + ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute); + num_values = ldap_count_values_len(ldap_value); MAKE_STD_ZVAL(tmp); array_init(tmp); add_assoc_long(tmp, "count", num_values); for (i = 0; i < num_values; i++) { - add_index_string(tmp, i, ldap_value[i], 1); + add_index_stringl(tmp, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1); } - ldap_value_free(ldap_value); + ldap_value_free_len(ldap_value); zend_hash_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute)+1, (void *) &tmp, sizeof(zval *), NULL); add_index_string(return_value, num_attrib, attribute, 1); @@ -1231,7 +1418,7 @@ ldap_linkdata *ld; ldap_resultentry *resultentry; char *attribute; - char **ldap_value; + struct berval **ldap_value; int i, num_values; if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &attr) == FAILURE) { @@ -1244,21 +1431,21 @@ convert_to_string_ex(attr); attribute = Z_STRVAL_PP(attr); - if ((ldap_value = ldap_get_values(ld->link, resultentry->data, attribute)) == NULL) { + if ((ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute)) == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link))); RETURN_FALSE; } - num_values = ldap_count_values(ldap_value); + num_values = ldap_count_values_len(ldap_value); array_init(return_value); for (i = 0; i<num_values; i++) { - add_next_index_string(return_value, ldap_value[i], 1); + add_next_index_stringl(return_value, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1); } add_assoc_long(return_value, "count", num_values); - ldap_value_free(ldap_value); + ldap_value_free_len(ldap_value); } /* }}} */ @@ -1363,7 +1550,12 @@ 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 */ } /* }}} */
This patch provides basic support for raw and well-known standar track (or wannabe...) LDAP controls and extended operations to the LDAP extension of PHP. It is intended for PHP HEAD code as of December 2005, but it is known to apply without relevant issues to PHP 5 and 4. See discussion in <http://news.php.net/php.internals/20215>. Extensions: support for request, response of: - raw LDAP extended operations (RFC 2251) - LDAP WhoAmI exop (draft-zeilenga-ldap-authzid) - LDAP Password modify exop (RFC 3062) support for request encoding, response decoding of: - raw LDAP controls (RFC 2251) - manageDSAit control (RFC 3296) - pagedResults control (RFC 2696) - passwordPolicy control (draft-behera-ldap-password-policy; incomplete) - no-op control (draft-zeilenga-ldap-noop) - manageDIT control (no spec; OpenLDAP work in progress) - permissive modify control (MS Active Directory) - more to come... It is mainly intended for use with OpenLDAP 2.3 and above, but it __should__ be backward compatible at least with OpenLDAP 2.2. All requested features are detected at configure, so it __should__ not cause problem with any other LDAP API; simply, the extensions will not be available. Author: Pierangelo Masarati <[EMAIL PROTECTED]>, <[EMAIL PROTECTED]> This software is released under the terms of the PHP license for inclusion in PHP software. Index: ext/ldap/config.m4 =================================================================== RCS file: /repository/php-src/ext/ldap/config.m4,v retrieving revision 1.42 diff -u -r1.42 config.m4 --- ext/ldap/config.m4 3 Nov 2005 20:41:05 -0000 1.42 +++ ext/ldap/config.m4 10 Dec 2005 14:45:07 -0000 @@ -173,7 +173,8 @@ 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]) dnl dnl SASL check Index: ext/ldap/ldap.c =================================================================== RCS file: /repository/php-src/ext/ldap/ldap.c,v retrieving revision 1.163 diff -u -r1.163 ldap.c --- ext/ldap/ldap.c 6 Dec 2005 02:24:38 -0000 1.163 +++ ext/ldap/ldap.c 10 Dec 2005 14:45:08 -0000 @@ -80,11 +80,38 @@ ZEND_DECLARE_MODULE_GLOBALS(ldap) static - ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0) + 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(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(); @@ -144,15 +171,27 @@ 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 #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) @@ -163,6 +202,29 @@ 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, NULL) +#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} }; /* }}} */ @@ -215,6 +283,81 @@ efree(entry); } +static int _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; +} + +static int _parse_server_controls_resp(LDAPControl ***lserverctrlsp, zval **serverctrls) +{ + int num_serverctrls = 0; + + if (*lserverctrlsp != NULL) { + int error = 0; + LDAPControl **ctrlp = *lserverctrlsp; + + 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(*serverctrls, ctrlval); + + num_serverctrls++; + ctrlp++; + } + ldap_controls_free(*lserverctrlsp); + *lserverctrlsp = NULL; + + if (error) { + /* ... */ + return -1; + } + } + + return num_serverctrls; +} + /* {{{ PHP_INI_BEGIN */ PHP_INI_BEGIN() @@ -1929,18 +2121,19 @@ /* }}} */ #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; } @@ -1951,7 +2144,7 @@ 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)); @@ -1963,17 +2156,15 @@ /* 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); + _parse_server_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); - } + _parse_referrals_resp(&lreferrals, referrals); case 5: zval_dtor(*errmsg); if (lerrmsg == NULL) { @@ -1996,6 +2187,144 @@ /* }}} */ #endif +#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 */ +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 < 2 || 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, + myargcount > 2 ? &lauthzid : NULL ); + 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; + } + + /* Reverse -> fall through */ + switch (myargcount) { + case 3: + /* use arg #3 as the new passwd returned by the server */ + 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_entended_result() */ +#endif +#endif + /* {{{ proto resource ldap_first_reference(resource link, resource result) Return first reference */ PHP_FUNCTION(ldap_first_reference) @@ -2057,32 +2386,38 @@ 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); + _parse_server_controls_resp(&lserverctrls, serverctrls); + case 3: + zval_dtor(*referrals); + array_init(*referrals); + _parse_referrals_resp(&lreferrals, referrals); } + RETURN_TRUE; } /* }}} */ @@ -2297,6 +2632,547 @@ /* }}} */ #endif +#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 < 2 || 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; + } + + 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_entended_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_entended_operation_s() */ +#endif +#endif +/* {{{ 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); + } + } +} + +#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 < 1 || 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 */ + case 2: + 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; + BerElement *ber; + ber_tag_t tag; + int rc, i, 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; + } + + for (i = 0; lserverctrls[i] != NULL; i++) { + if (strcmp(lserverctrls[i]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { + break; + } + } + + if (lserverctrls[i] == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control response in result"); + RETURN_FALSE; + } + + ber = ber_init(&lserverctrls[i]->ldctl_value); + if (ber == NULL) { + 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) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response"); + RETURN_FALSE; + } + + if (lestimated < 0) { + 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) + Inject password policy control */ +PHP_FUNCTION(ldap_ctrl_ppolicy) +{ +} +/* }}} */ + +/* {{{ proto bool ldap_ctrl_ppolicy_resp(resource link, resource result, string cookie, int estimated) + Extract password policy control response */ +PHP_FUNCTION(ldap_ctrl_ppolicy_resp) +{ +} +/* }}} */ +#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 + + /* * Local variables: * tab-width: 4 Index: ext/ldap/php_ldap.h =================================================================== RCS file: /repository/php-src/ext/ldap/php_ldap.h,v retrieving revision 1.32 diff -u -r1.32 php_ldap.h --- ext/ldap/php_ldap.h 3 Aug 2005 14:07:23 -0000 1.32 +++ ext/ldap/php_ldap.h 10 Dec 2005 14:45:08 -0000 @@ -85,8 +85,18 @@ #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 +#endif #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) PHP_FUNCTION(ldap_set_rebind_proc); @@ -97,6 +107,119 @@ 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> */ +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> */ +PHP_FUNCTION(ldap_ctrl_assert); +#endif +#ifdef LDAP_CONTROL_PRE_READ +/* <draft-zeilenga-ldap-readentry> */ +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> */ +PHP_FUNCTION(ldap_ctrl_ppolicy); +PHP_FUNCTION(ldap_ctrl_ppolicy_resp); +#endif +#ifdef LDAP_CONTROL_NOOP +/* <draft-zeilenga-ldap-noop> */ +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> */ +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> */ +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> */ +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> */ +PHP_FUNCTION(ldap_ctrl_vlv); +PHP_FUNCTION(ldap_ctrl_vlv_resp); +#endif + + ZEND_BEGIN_MODULE_GLOBALS(ldap) long num_links; long max_links;
exops.php
Description: application/php
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php