From 5ccb31e49ee117808bed4775dc40521f418b783b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 20 Jul 2017 12:17:59 +0200 Subject: [PATCH 01/31] Added controls support to ldap_parse_result and ldap_exop_passwd Known controls are parsed to and from associative arrays. Only ppolicy and paged results are implemented for now. --- ext/ldap/config.m4 | 2 +- ext/ldap/config.w32 | 2 +- ext/ldap/ldap.c | 360 +++++++++++++----- ext/ldap/tests/ldap_exop_passwd.phpt | 5 +- ext/ldap/tests/ldap_exop_passwd_error.phpt | 7 +- ext/ldap/tests/ldap_get_option_controls.phpt | 58 ++- ext/ldap/tests/ldap_get_option_variation.phpt | 8 +- .../tests/ldap_parse_result_controls.phpt | 45 +++ ext/ldap/tests/ldap_set_option_variation.phpt | 8 +- 9 files changed, 391 insertions(+), 104 deletions(-) create mode 100644 ext/ldap/tests/ldap_parse_result_controls.phpt diff --git a/ext/ldap/config.m4 b/ext/ldap/config.m4 index f77ff5a4c55a6..59af4211f19aa 100644 --- a/ext/ldap/config.m4 +++ b/ext/ldap/config.m4 @@ -204,7 +204,7 @@ if test "$PHP_LDAP" != "no"; then 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 ldap_control_find ldap_parse_extended_result ldap_extended_operation ldap_extended_operation_s ldap_passwd_s ldap_whoami_s ldap_refresh_s]) + AC_CHECK_FUNCS([ldap_parse_result ldap_parse_reference ldap_start_tls_s ldap_control_find ldap_parse_extended_result ldap_extended_operation ldap_extended_operation_s ldap_passwd ldap_whoami_s ldap_refresh_s]) dnl dnl SASL check diff --git a/ext/ldap/config.w32 b/ext/ldap/config.w32 index 626375502ea90..a608ff7132969 100644 --- a/ext/ldap/config.w32 +++ b/ext/ldap/config.w32 @@ -23,7 +23,7 @@ if (PHP_LDAP != "no") { AC_DEFINE('HAVE_LDAP_CONTROL_FIND', 1); AC_DEFINE('HAVE_LDAP_PARSE_EXTENDED_RESULT', 1); AC_DEFINE('HAVE_LDAP_EXTENDED_OPERATION_S', 1); - AC_DEFINE('HAVE_LDAP_PASSWD_S', 1); + AC_DEFINE('HAVE_LDAP_PASSWD', 1); AC_DEFINE('HAVE_LDAP_WHOAMI_S', 1); AC_DEFINE('HAVE_LDAP_REFRESH_S', 1); AC_DEFINE('HAVE_LDAP_EXTENDED_OPERATION', 1); diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 9740bad9f1912..a1843eeec9642 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -19,6 +19,7 @@ | Jani Taskinen | | Stig Venaas | | Doug Goldstein | + | Côme Chilliet | | PHP 4.0 updates: Zeev Suraski | +----------------------------------------------------------------------+ */ @@ -135,6 +136,196 @@ static void _free_ldap_result_entry(zend_resource *rsrc) /* {{{ */ } /* }}} */ +/* {{{ Parse controls from and to arrays */ +static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array) +{ + array_init(array); + + add_assoc_string(array, "oid", ctrl->ldctl_oid); + add_assoc_bool(array, "iscritical", (ctrl->ldctl_iscritical != 0)); + + // If it is a known oid, parse to values + if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) { + int expire = 0, grace = 0, rc; + LDAPPasswordPolicyError pperr; + zval value; + + rc = ldap_parse_passwordpolicy_control(ld, ctrl, &expire, &grace, &pperr); + if ( rc == LDAP_SUCCESS ) { + array_init(&value); + add_assoc_long(&value, "expire", expire); + add_assoc_long(&value, "grace", grace); + + if ( pperr != PP_noError ) { + add_assoc_long(&value, "error", pperr); + } + add_assoc_zval(array, "value", &value); + } else { + add_assoc_null(array, "value"); + } + } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { + int lestimated, rc; + struct berval lcookie; + zval value; + + if (ctrl->ldctl_value.bv_len) { + rc = ldap_parse_pageresponse_control(ld, ctrl, &lestimated, &lcookie); + } else { + /* ldap_parse_pageresponse_control will crash if value is empty */ + rc = -1; + } + if ( rc == LDAP_SUCCESS ) { + array_init(&value); + add_assoc_long(&value, "size", lestimated); + add_assoc_stringl(&value, "cookie", lcookie.bv_val, lcookie.bv_len); + add_assoc_zval(array, "value", &value); + } else { + add_assoc_null(array, "value"); + } + } else { + if (ctrl->ldctl_value.bv_len) { + add_assoc_stringl(array, "value", ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len); + } else { + add_assoc_null(array, "value"); + } + } +} + +static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* array) +{ + zval* val; + char * control_oid = NULL; + int control_iscritical = 0, rc; + + if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "oid", sizeof("oid") - 1)) == NULL) { + php_error_docref(NULL, E_WARNING, "Control must have an oid key"); + return -1; + } + convert_to_string_ex(val); + control_oid = Z_STRVAL_P(val); + + if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "iscritical", sizeof("iscritical") - 1)) != NULL) { + convert_to_boolean_ex(val); + control_iscritical = (Z_TYPE_P(val) == IS_TRUE); + } else { + control_iscritical = 0; + } + + struct berval *control_value = NULL; + + if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "value", sizeof("value") - 1)) != NULL) { + if (Z_TYPE_P(val) != IS_ARRAY) { + convert_to_string_ex(val); + control_value = ber_memalloc(sizeof * control_value); + if (control_value != NULL) { + control_value->bv_val = Z_STRVAL_P(val); + control_value->bv_len = Z_STRLEN_P(val); + } + } else if (strcmp(control_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { + zval* tmp; + int pagesize = 1; + struct berval *cookie = NULL; + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) { + convert_to_long_ex(tmp); + pagesize = Z_LVAL_P(tmp); + } + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "cookie", sizeof("cookie") - 1)) != NULL) { + convert_to_string_ex(tmp); + cookie = ber_memalloc(sizeof * cookie); + if (cookie != NULL) { + cookie->bv_val = Z_STRVAL_P(tmp); + cookie->bv_len = Z_STRLEN_P(tmp); + } + } + control_value = ber_memalloc(sizeof * control_value); + if (control_value != NULL) { + rc = ldap_create_page_control_value(ld, pagesize, cookie, control_value); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc); + control_value = NULL; + } + } + } else { + php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", control_oid); + } + } + + rc = ldap_control_create(control_oid, control_iscritical, control_value, 1, ctrl); + + if (control_value != NULL) { + ber_memfree(control_value); + control_value = NULL; + } + + if (rc == LDAP_SUCCESS) { + return LDAP_SUCCESS; + } + + // Failed + *ctrl = NULL; + return -1; +} + +static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* array) +{ + zval tmp1; + LDAPControl **ctrlp; + + array_init(array); + if (ctrls == NULL) { + return; + } + ctrlp = ctrls; + while (*ctrlp != NULL) { + _php_ldap_control_to_array(ld, *ctrlp, &tmp1); + add_next_index_zval(array, &tmp1); + ctrlp++; + } + ldap_controls_free(ctrls); +} + +static LDAPControl** _php_ldap_controls_from_array(LDAP *ld, zval* array) +{ + int ncontrols; + LDAPControl** ctrlp, **ctrls = NULL; + zval* ctrlarray; + int error = 0; + + ncontrols = zend_hash_num_elements(Z_ARRVAL_P(array)); + ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0); + *ctrls = NULL; + ctrlp = ctrls; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), ctrlarray) { + if (Z_TYPE_P(ctrlarray) != IS_ARRAY) { + php_error_docref(NULL, E_WARNING, "The array value must contain only arrays, where each array is a control"); + error = 1; + break; + } + + if (_php_ldap_control_from_array(ld, ctrlp, ctrlarray) == LDAP_SUCCESS) { + ++ctrlp; + } else { + error = 1; + break; + } + + *ctrlp = NULL; + } ZEND_HASH_FOREACH_END(); + + if (error) { + ctrlp = ctrls; + while (*ctrlp) { + ldap_control_free(*ctrlp); + ctrlp++; + } + efree(ctrls); + ctrls = NULL; + } + + return ctrls; +} +/* }}} */ + /* {{{ PHP_INI_BEGIN */ PHP_INI_BEGIN() @@ -2346,9 +2537,7 @@ PHP_FUNCTION(ldap_get_option) case LDAP_OPT_SERVER_CONTROLS: case LDAP_OPT_CLIENT_CONTROLS: { - zval tmp1; - int num_entries; - LDAPControl **ctrls = NULL, **ctrlp; + LDAPControl **ctrls = NULL; if (ldap_get_option(ld->link, option, &ctrls) || ctrls == NULL) { if (ctrls) { @@ -2356,24 +2545,7 @@ PHP_FUNCTION(ldap_get_option) } RETURN_FALSE; } - - zval_ptr_dtor(retval); - array_init(retval); - num_entries = 0; - ctrlp = ctrls; - while (*ctrlp != NULL) - { - array_init(&tmp1); - add_assoc_string(&tmp1, "oid", (*ctrlp)->ldctl_oid); - add_assoc_bool(&tmp1, "iscritical", ((*ctrlp)->ldctl_iscritical != 0)); - if ((*ctrlp)->ldctl_value.bv_len) { - add_assoc_stringl(&tmp1, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len); - } - zend_hash_index_update(Z_ARRVAL_P(retval), num_entries, &tmp1); - num_entries++; - ctrlp++; - } - ldap_controls_free(ctrls); + _php_ldap_controls_to_array(ld->link, ctrls, retval); } break; /* options not implemented case LDAP_OPT_API_INFO: @@ -2539,62 +2711,29 @@ PHP_FUNCTION(ldap_set_option) case LDAP_OPT_SERVER_CONTROLS: case LDAP_OPT_CLIENT_CONTROLS: { - LDAPControl *ctrl, **ctrls, **ctrlp; - zval *ctrlval, *val; - int ncontrols; - char error=0; + LDAPControl **ctrls, **ctrlp; + int rc; if (Z_TYPE_P(newval) != IS_ARRAY) { php_error_docref(NULL, E_WARNING, "Expected array value for this option"); RETURN_FALSE; } - ncontrols = zend_hash_num_elements(Z_ARRVAL_P(newval)); - ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0); - *ctrls = NULL; - ctrlp = ctrls; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(newval), ctrlval) { - if (Z_TYPE_P(ctrlval) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "The array value must contain only arrays, where each array is a control"); - error = 1; - break; - } - if ((val = zend_hash_str_find(Z_ARRVAL_P(ctrlval), "oid", sizeof("oid") - 1)) == NULL) { - php_error_docref(NULL, E_WARNING, "Control must have an oid key"); - error = 1; - break; - } - ctrl = *ctrlp = emalloc(sizeof(**ctrlp)); - convert_to_string_ex(val); - ctrl->ldctl_oid = Z_STRVAL_P(val); - if ((val = zend_hash_str_find(Z_ARRVAL_P(ctrlval), "value", sizeof("value") - 1)) != NULL) { - convert_to_string_ex(val); - ctrl->ldctl_value.bv_val = Z_STRVAL_P(val); - ctrl->ldctl_value.bv_len = Z_STRLEN_P(val); - } else { - ctrl->ldctl_value.bv_val = NULL; - ctrl->ldctl_value.bv_len = 0; - } - if ((val = zend_hash_str_find(Z_ARRVAL_P(ctrlval), "iscritical", sizeof("iscritical") - 1)) != NULL) { - convert_to_boolean_ex(val); - ctrl->ldctl_iscritical = Z_TYPE_P(val) == IS_TRUE; - } else { - ctrl->ldctl_iscritical = 0; - } - ++ctrlp; - *ctrlp = NULL; - } ZEND_HASH_FOREACH_END(); - if (!error) { - error = ldap_set_option(ldap, option, ctrls); - } - ctrlp = ctrls; - while (*ctrlp) { - efree(*ctrlp); - ctrlp++; - } - efree(ctrls); - if (error) { + ctrls = _php_ldap_controls_from_array(ldap, newval); + + if (ctrls == NULL) { RETURN_FALSE; + } else { + rc = ldap_set_option(ldap, option, ctrls); + ctrlp = ctrls; + while (*ctrlp) { + ldap_control_free(*ctrlp); + ctrlp++; + } + efree(ctrls); + if (rc != LDAP_SUCCESS) { + RETURN_FALSE; + } } } break; default: @@ -2609,14 +2748,16 @@ PHP_FUNCTION(ldap_set_option) Extract information from result */ PHP_FUNCTION(ldap_parse_result) { - zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals; + zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals, *serverctrls; + zval ctrl, php_ber; ldap_linkdata *ld; LDAPMessage *ldap_result; + LDAPControl **lserverctrls = NULL, **ctrlp = NULL; char **lreferrals, **refp; char *lmatcheddn, *lerrmsg; - int rc, lerrcode, myargcount = ZEND_NUM_ARGS(); + int rc, lerrcode, myargcount = ZEND_NUM_ARGS(), ber_decode_error_count = -1; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrz/|z/z/z/", &link, &result, &errcode, &matcheddn, &errmsg, &referrals) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrz/|z/z/z/z/", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) { return; } @@ -2632,7 +2773,7 @@ PHP_FUNCTION(ldap_parse_result) 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, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc)); @@ -2644,6 +2785,8 @@ PHP_FUNCTION(ldap_parse_result) /* Reverse -> fall through */ switch (myargcount) { + case 7: + _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls); case 6: zval_ptr_dtor(referrals); array_init(referrals); @@ -3410,17 +3553,21 @@ PHP_FUNCTION(ldap_exop) /* }}} */ #endif -#ifdef HAVE_LDAP_PASSWD_S -/* {{{ proto bool|string ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw ]]]) +#ifdef HAVE_LDAP_PASSWD +/* {{{ proto bool|string ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw [, array ctrls]]]]) Passwd modify extended operation */ PHP_FUNCTION(ldap_exop_passwd) { - zval *link, *user, *newpw, *oldpw; + zval *link, *user, *newpw, *oldpw, *serverctrls; struct berval luser, loldpw, lnewpw, lgenpasswd; + LDAPControl **lserverctrls = NULL, **requestctrls = NULL; + LDAPControl *ctrl, **ctrlp; + LDAPMessage* ldap_res; ldap_linkdata *ld; - int rc, myargcount = ZEND_NUM_ARGS(); + int rc, myargcount = ZEND_NUM_ARGS(), msgid, err; + char* errmsg; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|zzz", &link, &user, &oldpw, &newpw) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|zzzz/", &link, &user, &oldpw, &newpw, &serverctrls) == FAILURE) { WRONG_PARAM_COUNT; } @@ -3433,6 +3580,17 @@ PHP_FUNCTION(ldap_exop_passwd) lnewpw.bv_len = 0; switch (myargcount) { + case 5: + requestctrls = safe_emalloc(2, sizeof(*requestctrls), 0); + *requestctrls = NULL; + ctrlp = requestctrls; + + if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) { + *ctrlp = ctrl; + ++ctrlp; + } + + *ctrlp = NULL; case 4: convert_to_string_ex(newpw); lnewpw.bv_val = Z_STRVAL_P(newpw); @@ -3449,24 +3607,52 @@ PHP_FUNCTION(ldap_exop_passwd) luser.bv_len = Z_STRLEN_P(user); } - /* synchronous call */ - rc = ldap_passwd_s(ld->link, &luser, + /* asynchronous call to get result and controls */ + rc = ldap_passwd(ld->link, &luser, loldpw.bv_len > 0 ? &loldpw : NULL, lnewpw.bv_len > 0 ? &lnewpw : NULL, - &lgenpasswd, NULL, NULL); + requestctrls, + NULL, &msgid); if (rc != LDAP_SUCCESS ) { php_error_docref(NULL, 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 < 0) || !ldap_res) { + rc = _get_lderrno(ld->link); + php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); + RETURN_FALSE; + } + + rc = ldap_parse_passwd(ld->link, ldap_res, &lgenpasswd); + if( rc != LDAP_SUCCESS ) { + php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); + ldap_msgfree(ldap_res); + RETURN_FALSE; + } + + rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 1); + if( rc != LDAP_SUCCESS ) { + php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); + RETURN_FALSE; + } + if (lnewpw.bv_len == 0) { if (lgenpasswd.bv_len == 0) { RETVAL_EMPTY_STRING(); } else { RETVAL_STRINGL(lgenpasswd.bv_val, lgenpasswd.bv_len); } + } else if (err == LDAP_SUCCESS) { + RETVAL_TRUE; } else { - RETURN_TRUE; + php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", errmsg, err); + RETVAL_FALSE; + } + + if (myargcount > 4) { + _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls); } ldap_memfree(lgenpasswd.bv_val); @@ -3799,6 +3985,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_parse_result, 0, 0, 3) ZEND_ARG_INFO(1, matcheddn) ZEND_ARG_INFO(1, errmsg) ZEND_ARG_INFO(1, referrals) + ZEND_ARG_INFO(1, serverctrls) ZEND_END_ARG_INFO() #endif #endif @@ -3837,12 +4024,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop, 0, 0, 2) ZEND_END_ARG_INFO() #endif -#ifdef HAVE_LDAP_PASSWD_S -ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_passwd, 0, 0, 4) +#ifdef HAVE_LDAP_PASSWD +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_passwd, 0, 0, 1) ZEND_ARG_INFO(0, link) ZEND_ARG_INFO(0, user) ZEND_ARG_INFO(0, oldpw) ZEND_ARG_INFO(0, newpw) + ZEND_ARG_INFO(1, serverctrls) ZEND_END_ARG_INFO() #endif @@ -3935,7 +4123,7 @@ const zend_function_entry ldap_functions[] = { #ifdef HAVE_LDAP_EXTENDED_OPERATION_S PHP_FE(ldap_exop, arginfo_ldap_exop) #endif -#ifdef HAVE_LDAP_PASSWD_S +#ifdef HAVE_LDAP_PASSWD PHP_FE(ldap_exop_passwd, arginfo_ldap_exop_passwd) #endif #ifdef HAVE_LDAP_WHOAMI_S diff --git a/ext/ldap/tests/ldap_exop_passwd.phpt b/ext/ldap/tests/ldap_exop_passwd.phpt index 2f0d4cb599723..e50b30760ce5e 100644 --- a/ext/ldap/tests/ldap_exop_passwd.phpt +++ b/ext/ldap/tests/ldap_exop_passwd.phpt @@ -16,7 +16,8 @@ insert_dummy_data($link, $base); // and optionally returns the NEW password if none was passed. // ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw [, string newpasswd ]]]]) var_dump( - $genpw = ldap_exop_passwd($link, "cn=userA,$base", "oops", ""), + $genpw = ldap_exop_passwd($link, "cn=userA,$base", "oops", "", $ctrls), + $ctrls, $genpw = ldap_exop_passwd($link, "cn=userA,$base"), test_bind($host, $port, "cn=userA,$base", $genpw, $protocol_version), ldap_exop_passwd($link, "cn=userA,$base", $genpw, "newPassword"), @@ -34,6 +35,8 @@ remove_dummy_data($link, $base); ?> --EXPECTF-- string(%d) "%s" +array(0) { +} string(%d) "%s" bool(true) bool(true) diff --git a/ext/ldap/tests/ldap_exop_passwd_error.phpt b/ext/ldap/tests/ldap_exop_passwd_error.phpt index d858bd4bdcdd4..bfb0cbcae23d8 100644 --- a/ext/ldap/tests/ldap_exop_passwd_error.phpt +++ b/ext/ldap/tests/ldap_exop_passwd_error.phpt @@ -12,7 +12,8 @@ require "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); insert_dummy_data($link, $base); -var_dump(ldap_exop_passwd($link, "cn=userA,$base", "wrongPassword", "newPassword")); +var_dump(ldap_exop_passwd($link, "cn=userA,$base", "wrongPassword", "newPassword", $ctrls)); +var_dump($ctrls); var_dump(ldap_error($link)); var_dump(ldap_errno($link)); var_dump(test_bind($host, $port, "cn=userA,$base", "newPassword", $protocol_version)); @@ -27,8 +28,10 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); remove_dummy_data($link, $base); ?> --EXPECTF-- -Warning: ldap_exop_passwd(): Passwd modify extended operation failed: Server is unwilling to perform (53) in %s on line %d +Warning: ldap_exop_passwd(): Passwd modify extended operation failed: %s (53) in %s on line %d bool(false) +array(0) { +} string(30) "Server is unwilling to perform" int(53) diff --git a/ext/ldap/tests/ldap_get_option_controls.phpt b/ext/ldap/tests/ldap_get_option_controls.phpt index 3b55685d5e8f2..ea42532d4bf4e 100644 --- a/ext/ldap/tests/ldap_get_option_controls.phpt +++ b/ext/ldap/tests/ldap_get_option_controls.phpt @@ -30,7 +30,17 @@ $controls_set = array( array( 'oid' => LDAP_CONTROL_PAGEDRESULTS, 'iscritical' => TRUE, - 'value' => build_ctrl_paged_value(1, '') + 'value' => build_ctrl_paged_value(1, 'opaque') + ) +); +$controls_set2 = array( + array( + 'oid' => LDAP_CONTROL_PAGEDRESULTS, + 'iscritical' => TRUE, + 'value' => array( + 'size' => 1, + 'cookie' => '', + ) ) ); var_dump( @@ -38,10 +48,10 @@ var_dump( ldap_get_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_get), ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_set), ldap_get_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_get), - count($controls_get), - $controls_get[0]['oid'], - $controls_get[0]['iscritical'], - bin2hex($controls_get[0]['value']), + $controls_get, + ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_set2), + ldap_get_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_get), + $controls_get, $result = ldap_search($link, $base, "(objectClass=person)", array('cn')), ldap_get_entries($link, $result)['count'], ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array()), @@ -57,14 +67,44 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); remove_dummy_data($link, $base); ?> --EXPECTF-- -string(14) "30050201010400" +string(26) "300b02010104066f7061717565" bool(false) bool(true) bool(true) -int(1) -string(22) "1.2.840.113556.1.4.319" +array(1) { + [0]=> + array(3) { + ["oid"]=> + string(22) "1.2.840.113556.1.4.319" + ["iscritical"]=> + bool(true) + ["value"]=> + array(2) { + ["size"]=> + int(1) + ["cookie"]=> + string(6) "opaque" + } + } +} bool(true) -string(14) "30050201010400" +bool(true) +array(1) { + [0]=> + array(3) { + ["oid"]=> + string(22) "1.2.840.113556.1.4.319" + ["iscritical"]=> + bool(true) + ["value"]=> + array(2) { + ["size"]=> + int(1) + ["cookie"]=> + string(0) "" + } + } +} resource(%d) of type (ldap result) int(1) bool(true) diff --git a/ext/ldap/tests/ldap_get_option_variation.phpt b/ext/ldap/tests/ldap_get_option_variation.phpt index 759936ec629b6..d980350eb642b 100644 --- a/ext/ldap/tests/ldap_get_option_variation.phpt +++ b/ext/ldap/tests/ldap_get_option_variation.phpt @@ -67,11 +67,13 @@ int(0) bool(true) array(2) { [0]=> - array(2) { + array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" ["iscritical"]=> bool(true) + ["value"]=> + NULL } [1]=> array(3) { @@ -86,11 +88,13 @@ array(2) { bool(true) array(2) { [0]=> - array(2) { + array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" ["iscritical"]=> bool(true) + ["value"]=> + NULL } [1]=> array(3) { diff --git a/ext/ldap/tests/ldap_parse_result_controls.phpt b/ext/ldap/tests/ldap_parse_result_controls.phpt new file mode 100644 index 0000000000000..ef1dca8ebf2a1 --- /dev/null +++ b/ext/ldap/tests/ldap_parse_result_controls.phpt @@ -0,0 +1,45 @@ +--TEST-- +ldap_parse_result() - Test the parsing of controls from result object +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + +--FILE-- + +===DONE=== +--CLEAN-- + +--EXPECTF-- +bool(true) +resource(%d) of type (ldap result) +bool(true) +string(22) "1.2.840.113556.1.4.319" +bool(false) +int(%d) +string(%d) "%s" +int(1) +===DONE=== diff --git a/ext/ldap/tests/ldap_set_option_variation.phpt b/ext/ldap/tests/ldap_set_option_variation.phpt index bb8a3f1051899..b496bb1311fc3 100644 --- a/ext/ldap/tests/ldap_set_option_variation.phpt +++ b/ext/ldap/tests/ldap_set_option_variation.phpt @@ -78,11 +78,13 @@ bool(false) bool(true) array(2) { [0]=> - array(2) { + array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" ["iscritical"]=> bool(true) + ["value"]=> + NULL } [1]=> array(3) { @@ -97,11 +99,13 @@ array(2) { bool(true) array(2) { [0]=> - array(2) { + array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" ["iscritical"]=> bool(true) + ["value"]=> + NULL } [1]=> array(3) { From 8de071e0f76784ef2fd18fb1d270c30b08274be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Wed, 26 Jul 2017 16:41:44 +0200 Subject: [PATCH 02/31] Added controls support to ldap_search, ldap_list and ldap_read. --- ext/ldap/ldap.c | 88 ++++++++++++++--- ext/ldap/tests/ldap_list_error.phpt | 4 +- ext/ldap/tests/ldap_read_error.phpt | 4 +- .../ldap_search_paged_result_controls.phpt | 97 +++++++++++++++++++ 4 files changed, 174 insertions(+), 19 deletions(-) create mode 100644 ext/ldap/tests/ldap_search_paged_result_controls.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index a1843eeec9642..82ac0720b0dc9 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -324,6 +324,21 @@ static LDAPControl** _php_ldap_controls_from_array(LDAP *ld, zval* array) return ctrls; } + +static void _php_ldap_controls_free (LDAPControl*** ctrls) +{ + LDAPControl **ctrlp; + + if (*ctrls) { + ctrlp = *ctrls; + while (*ctrlp) { + ldap_control_free(*ctrlp); + ctrlp++; + } + efree(*ctrls); + *ctrls = NULL; + } +} /* }}} */ /* {{{ PHP_INI_BEGIN @@ -1018,22 +1033,25 @@ static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, in */ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) { - zval *link, *base_dn, *filter, *attrs = NULL, *attr; + zval *link, *base_dn, *filter, *attrs = NULL, *attr, *serverctrls, *clientctrls; zend_long attrsonly, sizelimit, timelimit, deref; char *ldap_base_dn = NULL, *ldap_filter = NULL, **ldap_attrs = NULL; ldap_linkdata *ld = NULL; LDAPMessage *ldap_res; + LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1; int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1; int num_attribs = 0, ret = 1, i, errno, argcount = ZEND_NUM_ARGS(); - if (zend_parse_parameters(argcount, "zzz|allll", &link, &base_dn, &filter, &attrs, &attrsonly, - &sizelimit, &timelimit, &deref) == FAILURE) { + if (zend_parse_parameters(argcount, "zzz|allllzz", &link, &base_dn, &filter, &attrs, &attrsonly, + &sizelimit, &timelimit, &deref, &serverctrls, &clientctrls) == FAILURE) { return; } /* Reverse -> fall through */ switch (argcount) { + case 10: + case 9: case 8: ldap_deref = deref; case 7: @@ -1136,10 +1154,28 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ldap_filter = Z_STRVAL_P(entry); } + if (argcount > 8) { + // We have to parse controls again for each link as they use it + _php_ldap_controls_free(&lserverctrls); + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + rcs[i] = -1; + continue; + } + if (argcount > 9) { + _php_ldap_controls_free(&lclientctrls); + lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); + if (lclientctrls == NULL) { + rcs[i] = -1; + continue; + } + } + } + php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref); /* Run the actual search */ - ldap_search_ext(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, NULL, NULL, NULL, ldap_sizelimit, &rcs[i]); + ldap_search_ext(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, lserverctrls, lclientctrls, NULL, ldap_sizelimit, &rcs[i]); lds[i] = ld; zend_hash_move_forward(Z_ARRVAL_P(link)); } @@ -1177,10 +1213,25 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) goto cleanup; } + if (argcount > 8) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + ret = 0; + goto cleanup; + } + if (argcount > 9) { + lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); + if (lclientctrls == NULL) { + ret = 0; + goto cleanup; + } + } + } + php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref); /* Run the actual search */ - errno = ldap_search_ext_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, NULL, NULL, NULL, ldap_sizelimit, &ldap_res); + errno = ldap_search_ext_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, lserverctrls, lclientctrls, NULL, ldap_sizelimit, &ldap_res); if (errno != LDAP_SUCCESS && errno != LDAP_SIZELIMIT_EXCEEDED @@ -1218,10 +1269,16 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) if (!ret) { RETVAL_BOOL(ret); } + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + if (lclientctrls) { + _php_ldap_controls_free(&lclientctrls); + } } /* }}} */ -/* {{{ proto resource ldap_read(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]]) +/* {{{ proto resource ldap_read(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols [, array clientcontrols]]]]]]]) Read an entry */ PHP_FUNCTION(ldap_read) { @@ -1229,7 +1286,7 @@ PHP_FUNCTION(ldap_read) } /* }}} */ -/* {{{ proto resource ldap_list(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]]) +/* {{{ proto resource ldap_list(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols [, array clientcontrols]]]]]]]) Single-level search */ PHP_FUNCTION(ldap_list) { @@ -1237,7 +1294,7 @@ PHP_FUNCTION(ldap_list) } /* }}} */ -/* {{{ proto resource ldap_search(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]]) +/* {{{ proto resource ldap_search(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols [, array clientcontrols]]]]]]]) Search LDAP tree under base_dn */ PHP_FUNCTION(ldap_search) { @@ -2711,7 +2768,7 @@ PHP_FUNCTION(ldap_set_option) case LDAP_OPT_SERVER_CONTROLS: case LDAP_OPT_CLIENT_CONTROLS: { - LDAPControl **ctrls, **ctrlp; + LDAPControl **ctrls; int rc; if (Z_TYPE_P(newval) != IS_ARRAY) { @@ -2725,12 +2782,7 @@ PHP_FUNCTION(ldap_set_option) RETURN_FALSE; } else { rc = ldap_set_option(ldap, option, ctrls); - ctrlp = ctrls; - while (*ctrlp) { - ldap_control_free(*ctrlp); - ctrlp++; - } - efree(ctrls); + _php_ldap_controls_free(&ctrls); if (rc != LDAP_SUCCESS) { RETURN_FALSE; } @@ -3778,6 +3830,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3) ZEND_ARG_INFO(0, sizelimit) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) @@ -3789,6 +3843,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) ZEND_ARG_INFO(0, sizelimit) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3) @@ -3800,6 +3856,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3) ZEND_ARG_INFO(0, sizelimit) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_count_entries, 0, 0, 2) diff --git a/ext/ldap/tests/ldap_list_error.phpt b/ext/ldap/tests/ldap_list_error.phpt index 51bcaa583f195..801d2464f13e5 100644 --- a/ext/ldap/tests/ldap_list_error.phpt +++ b/ext/ldap/tests/ldap_list_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_list($link)); var_dump(ldap_list($link, $link)); // Too many parameters -var_dump(ldap_list($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0 , "Additional data")); +var_dump(ldap_list($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0, [], [], "Additional data")); ?> ===DONE=== --EXPECTF-- @@ -30,6 +30,6 @@ NULL Warning: ldap_list() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_list() expects at most 8 parameters, 9 given in %s on line %d +Warning: ldap_list() expects at most 10 parameters, 11 given in %s on line %d NULL ===DONE=== diff --git a/ext/ldap/tests/ldap_read_error.phpt b/ext/ldap/tests/ldap_read_error.phpt index 7d57172e0d637..c1e15a6aed774 100644 --- a/ext/ldap/tests/ldap_read_error.phpt +++ b/ext/ldap/tests/ldap_read_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_read($link)); var_dump(ldap_read($link, $link)); // Too many parameters -var_dump(ldap_read($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0 , "Additional data")); +var_dump(ldap_read($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0, [], [], "Additional data")); ?> ===DONE=== --EXPECTF-- @@ -30,6 +30,6 @@ NULL Warning: ldap_read() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_read() expects at most 8 parameters, 9 given in %s on line %d +Warning: ldap_read() expects at most 10 parameters, 11 given in %s on line %d NULL ===DONE=== diff --git a/ext/ldap/tests/ldap_search_paged_result_controls.phpt b/ext/ldap/tests/ldap_search_paged_result_controls.phpt new file mode 100644 index 0000000000000..e75f408e9a851 --- /dev/null +++ b/ext/ldap/tests/ldap_search_paged_result_controls.phpt @@ -0,0 +1,97 @@ +--TEST-- +ldap_search() test with paged result controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + +--FILE-- + LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => 2]]]), + ldap_get_entries($link, $result), + ldap_parse_result($link, $result, $errcode , $matcheddn , $errmsg , $referrals, $controls), + $result = ldap_search($link, $dn, $filter, array('cn'), 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => 20, 'cookie' => $controls[0]['value']['cookie']]]]), + ldap_get_entries($link, $result) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +array(3) { + ["count"]=> + int(2) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userA" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userA,%s" + } + [1]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userB" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userB,%s" + } +} +bool(true) +resource(%d) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userC" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userC,cn=userB,%s" + } +} +===DONE=== From 5691d8bf49e8e6609c4b8187dce419dd7bc92e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Wed, 6 Sep 2017 16:39:21 +0200 Subject: [PATCH 03/31] Added controls support to ldap_exop --- ext/ldap/ldap.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 82ac0720b0dc9..ba125f0cddc84 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -3525,16 +3525,17 @@ PHP_FUNCTION(ldap_control_paged_result_response) Extended operation */ PHP_FUNCTION(ldap_exop) { - zval *servercontrols; + zval *serverctrls = NULL; zval *link, *retdata = NULL, *retoid = NULL; char *lretoid = NULL; zend_string *reqoid, *reqdata = NULL; struct berval lreqdata, *lretdata = NULL; ldap_linkdata *ld; LDAPMessage *ldap_res; + LDAPControl **lserverctrls = NULL; int rc, msgid; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rS|S!zz/z/", &link, &reqoid, &reqdata, &servercontrols, &retdata, &retoid) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rS|S!a!z/z/", &link, &reqoid, &reqdata, &serverctrls, &retdata, &retoid) != SUCCESS) { return; } @@ -3549,17 +3550,26 @@ PHP_FUNCTION(ldap_exop) lreqdata.bv_len = 0; } + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + if (retdata) { /* synchronous call */ rc = ldap_extended_operation_s(ld->link, ZSTR_VAL(reqoid), lreqdata.bv_len > 0 ? &lreqdata: NULL, - NULL, + lserverctrls, NULL, retoid ? &lretoid : NULL, &lretdata ); if (rc != LDAP_SUCCESS ) { php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc); - RETURN_FALSE; + RETVAL_FALSE; + goto cleanup; } if (retoid) { @@ -3581,26 +3591,36 @@ PHP_FUNCTION(ldap_exop) ZVAL_EMPTY_STRING(retdata); } - RETURN_TRUE; + RETVAL_TRUE; + goto cleanup; } /* asynchronous call */ rc = ldap_extended_operation(ld->link, ZSTR_VAL(reqoid), lreqdata.bv_len > 0 ? &lreqdata: NULL, - NULL, NULL, &msgid); + lserverctrls, + NULL, + &msgid); if (rc != LDAP_SUCCESS ) { php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc); - RETURN_FALSE; + RETVAL_FALSE; + goto cleanup; } rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); if (rc == -1) { php_error_docref(NULL, E_WARNING, "Extended operation %s failed", ZSTR_VAL(reqoid)); - RETURN_FALSE; + RETVAL_FALSE; + goto cleanup; } /* return a PHP control object */ RETVAL_RES(zend_register_resource(ldap_res, le_result)); + + cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } } /* }}} */ #endif @@ -3699,7 +3719,7 @@ PHP_FUNCTION(ldap_exop_passwd) } else if (err == LDAP_SUCCESS) { RETVAL_TRUE; } else { - php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", errmsg, err); + php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", (errmsg ? errmsg : ldap_err2string(err)), err); RETVAL_FALSE; } From 02bd89a5520ca58c24a774a1768199cc43280171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Wed, 26 Jul 2017 11:51:29 +0200 Subject: [PATCH 04/31] Added support for assert control value encoding --- ext/ldap/ldap.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index ba125f0cddc84..642301839f32e 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -245,6 +245,21 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra control_value = NULL; } } + } else if (strcmp(control_oid, LDAP_CONTROL_ASSERT) == 0) { + zval* tmp; + char* assert; + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) != NULL) { + convert_to_string_ex(tmp); + assert = Z_STRVAL_P(tmp); + control_value = ber_memalloc(sizeof * control_value); + if (control_value != NULL) { + rc = ldap_create_assertion_control_value(ld, assert, control_value); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc); + control_value = NULL; + } + } + } } else { php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", control_oid); } From 6d3a914641a084f32276b9f7ccf567f32a1ef142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Wed, 6 Sep 2017 17:54:12 +0200 Subject: [PATCH 05/31] Added a test for PROXY_AUTHZ control on ldap_exop --- ext/ldap/tests/ldap_exop.phpt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/ldap/tests/ldap_exop.phpt b/ext/ldap/tests/ldap_exop.phpt index 48038cf230241..a26c01974029c 100644 --- a/ext/ldap/tests/ldap_exop.phpt +++ b/ext/ldap/tests/ldap_exop.phpt @@ -42,6 +42,8 @@ var_dump( ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, NULL, $retdata, $retoid), $retdata, $retoid, + ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, [['oid' => LDAP_CONTROL_PROXY_AUTHZ, 'value' => "dn:cn=userA,$base"]], [], $retdata), + $retdata, $r = ldap_exop($link, LDAP_EXOP_WHO_AM_I), ldap_parse_exop($link, $r, $retdata2), $retdata2, @@ -66,6 +68,8 @@ remove_dummy_data($link, $base); bool(true) string(%d) "dn:%s" string(0) "" +bool(true) +string(%d) "dn:cn=user%s" resource(%d) of type (ldap result) bool(true) string(%d) "dn:%s" From 79cfa55caeef1c89564dc0481bbbfe45f3e0d8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 09:33:01 +0200 Subject: [PATCH 06/31] Added a test for assertion control --- ext/ldap/tests/ldap_controls.phpt | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 ext/ldap/tests/ldap_controls.phpt diff --git a/ext/ldap/tests/ldap_controls.phpt b/ext/ldap/tests/ldap_controls.phpt new file mode 100644 index 0000000000000..3838da4ac85c2 --- /dev/null +++ b/ext/ldap/tests/ldap_controls.phpt @@ -0,0 +1,58 @@ +--TEST-- +Test the use of controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + +--FILE-- + LDAP_CONTROL_ASSERT, 'value' => ['filter' => '(objectClass=organization)']]]), + ldap_get_entries($link, $result), + $result = ldap_search($link, "o=test,$base", "objectClass=*", array('o'), 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_ASSERT, 'value' => ['filter' => '(objectClass=organizationalUnit)']]]) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +Warning: ldap_search(): Search: Assertion Failed in %s on line %d +resource(%d) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["o"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(4) "test" + } + [0]=> + string(1) "o" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "o=test,%s" + } +} +bool(false) +===DONE=== From 5ee0fc9b56eb0c210020d1f0a56af16fb2e1f546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 11:04:52 +0200 Subject: [PATCH 07/31] Added support for controls in ldap_add, ldap_modify, ldap_mod_* Also added workaround for a bug in ldap_create_assertion_control_value Made sure failed control creation aborts the operation And added test for assertion control on ldap_modify --- ext/ldap/ldap.c | 54 ++++++++++++++++++++++++---- ext/ldap/tests/ldap_controls.phpt | 58 +++++++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 9 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 642301839f32e..892dfa24e4c08 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -195,7 +195,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra { zval* val; char * control_oid = NULL; - int control_iscritical = 0, rc; + int control_iscritical = 0, rc = LDAP_SUCCESS; if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "oid", sizeof("oid") - 1)) == NULL) { php_error_docref(NULL, E_WARNING, "Control must have an oid key"); @@ -253,6 +253,10 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra assert = Z_STRVAL_P(tmp); control_value = ber_memalloc(sizeof * control_value); if (control_value != NULL) { + // ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves + // See http://www.openldap.org/its/index.cgi/Incoming?id=8674 + int success = LDAP_SUCCESS; + ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success); rc = ldap_create_assertion_control_value(ld, assert, control_value); if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc); @@ -262,10 +266,13 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra } } else { php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", control_oid); + rc = -1; } } - rc = ldap_control_create(control_oid, control_iscritical, control_value, 1, ctrl); + if (rc == LDAP_SUCCESS) { + rc = ldap_control_create(control_oid, control_iscritical, control_value, 1, ctrl); + } if (control_value != NULL) { ber_memfree(control_value); @@ -1800,10 +1807,12 @@ PHP_FUNCTION(ldap_dn2ufn) */ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) { + zval *serverctrls = NULL, *clientctrls = NULL; zval *link, *entry, *value, *ivalue; ldap_linkdata *ld; char *dn; LDAPMod **ldap_mods; + LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; int i, j, num_attribs, num_values; size_t dn_len; int *num_berval; @@ -1811,7 +1820,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) zend_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_parse_parameters(ZEND_NUM_ARGS(), "rsa/", &link, &dn, &dn_len, &entry) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|aa", &link, &dn, &dn_len, &entry, &serverctrls, &clientctrls) != SUCCESS) { return; } @@ -1879,7 +1888,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) num_berval[i] = j; num_attribs = i + 1; RETVAL_FALSE; - goto errexit; + goto cleanup; } convert_to_string_ex(ivalue); ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval)); @@ -1892,20 +1901,35 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) } ldap_mods[num_attribs] = NULL; + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + if (clientctrls) { + lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); + if (lclientctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + /* check flag to see if do_mod was called to perform full add , gerrit thomson */ if (is_full_add == 1) { - if ((i = ldap_add_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { + if ((i = ldap_add_ext_s(ld->link, dn, ldap_mods, lserverctrls, lclientctrls)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Add: %s", ldap_err2string(i)); RETVAL_FALSE; } else RETVAL_TRUE; } else { - if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { + if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, lclientctrls)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Modify: %s", ldap_err2string(i)); RETVAL_FALSE; } else RETVAL_TRUE; } -errexit: +cleanup: for (i = 0; i < num_attribs; i++) { efree(ldap_mods[i]->mod_type); for (j = 0; j < num_berval[i]; j++) { @@ -1916,6 +1940,12 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) } efree(num_berval); efree(ldap_mods); + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + if (lclientctrls) { + _php_ldap_controls_free(&lclientctrls); + } return; } @@ -3960,6 +3990,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete, 0, 0, 2) @@ -3971,6 +4003,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify_batch, 0, 0, 3) @@ -3983,18 +4017,24 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_err2str, 0, 0, 1) diff --git a/ext/ldap/tests/ldap_controls.phpt b/ext/ldap/tests/ldap_controls.phpt index 3838da4ac85c2..bb0226be6a37e 100644 --- a/ext/ldap/tests/ldap_controls.phpt +++ b/ext/ldap/tests/ldap_controls.phpt @@ -17,10 +17,18 @@ insert_dummy_data($link, $base); /* Test assertion control */ var_dump( $result = ldap_search($link, "o=test,$base", "objectClass=*", array('o'), 0, 0, 0, LDAP_DEREF_NEVER, - [['oid' => LDAP_CONTROL_ASSERT, 'value' => ['filter' => '(objectClass=organization)']]]), + [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(objectClass=organization)']]]), ldap_get_entries($link, $result), $result = ldap_search($link, "o=test,$base", "objectClass=*", array('o'), 0, 0, 0, LDAP_DEREF_NEVER, - [['oid' => LDAP_CONTROL_ASSERT, 'value' => ['filter' => '(objectClass=organizationalUnit)']]]) + [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(objectClass=organizationalUnit)']]]), + ldap_modify($link, "o=test,$base", ['description' => 'desc'], + [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(!(description=*))']]]), + $result = ldap_read($link, "o=test,$base", "objectClass=*", array('description')), + ldap_get_entries($link, $result), + ldap_modify($link, "o=test,$base", ['description' => 'desc2'], + [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(!(description=*))']]]), + $result = ldap_read($link, "o=test,$base", "objectClass=*", array('description')), + ldap_get_entries($link, $result) ); ?> ===DONE=== @@ -33,6 +41,8 @@ remove_dummy_data($link, $base); ?> --EXPECTF-- Warning: ldap_search(): Search: Assertion Failed in %s on line %d + +Warning: ldap_modify(): Modify: Assertion Failed in %s on line %d resource(%d) of type (ldap result) array(2) { ["count"]=> @@ -55,4 +65,48 @@ array(2) { } } bool(false) +bool(true) +resource(%d) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["description"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(4) "desc" + } + [0]=> + string(11) "description" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "o=test,%s" + } +} +bool(false) +resource(%d) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["description"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(4) "desc" + } + [0]=> + string(11) "description" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "o=test,%s" + } +} ===DONE=== From 93fbbbf5a6162411a03794b9621236bc04920dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 11:21:47 +0200 Subject: [PATCH 08/31] Added controls support to ldap_delete --- ext/ldap/ldap.c | 39 +++++++++++++++++++++++++++---- ext/ldap/tests/ldap_controls.phpt | 10 +++++++- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 892dfa24e4c08..2bff9febcde6c 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -1986,17 +1986,19 @@ PHP_FUNCTION(ldap_mod_del) } /* }}} */ -/* {{{ proto bool ldap_delete(resource link, string dn) +/* {{{ proto bool ldap_delete(resource link, string dn [, array servercontrols [, array clientcontrols]]) Delete an entry from a directory */ PHP_FUNCTION(ldap_delete) { + zval *serverctrls = NULL, *clientctrls = NULL; zval *link; ldap_linkdata *ld; + LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; char *dn; int rc; size_t dn_len; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &link, &dn, &dn_len) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|aa", &link, &dn, &dn_len, &serverctrls, &clientctrls) != SUCCESS) { return; } @@ -2004,12 +2006,37 @@ PHP_FUNCTION(ldap_delete) RETURN_FALSE; } - if ((rc = ldap_delete_ext_s(ld->link, dn, NULL, NULL)) != LDAP_SUCCESS) { + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + if (clientctrls) { + lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); + if (lclientctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + + if ((rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, lclientctrls)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Delete: %s", ldap_err2string(rc)); - RETURN_FALSE; + RETVAL_FALSE; + } else { + RETVAL_TRUE; } - RETURN_TRUE; +cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + if (lclientctrls) { + _php_ldap_controls_free(&lclientctrls); + } + + return; } /* }}} */ @@ -3997,6 +4024,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete, 0, 0, 2) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3) diff --git a/ext/ldap/tests/ldap_controls.phpt b/ext/ldap/tests/ldap_controls.phpt index bb0226be6a37e..85a0b8cba3585 100644 --- a/ext/ldap/tests/ldap_controls.phpt +++ b/ext/ldap/tests/ldap_controls.phpt @@ -28,7 +28,10 @@ var_dump( ldap_modify($link, "o=test,$base", ['description' => 'desc2'], [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(!(description=*))']]]), $result = ldap_read($link, "o=test,$base", "objectClass=*", array('description')), - ldap_get_entries($link, $result) + ldap_get_entries($link, $result), + ldap_delete($link, "o=test,$base", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), + ldap_errno($link), + ldap_error($link) ); ?> ===DONE=== @@ -43,6 +46,8 @@ remove_dummy_data($link, $base); Warning: ldap_search(): Search: Assertion Failed in %s on line %d Warning: ldap_modify(): Modify: Assertion Failed in %s on line %d + +Warning: ldap_delete(): Delete: Assertion Failed in %s on line %d resource(%d) of type (ldap result) array(2) { ["count"]=> @@ -109,4 +114,7 @@ array(2) { string(%d) "o=test,%s" } } +bool(false) +int(122) +string(16) "Assertion Failed" ===DONE=== From c8572da1830cd4ed277b4337ccb3cae418b0d51c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 11:36:02 +0200 Subject: [PATCH 09/31] Fixed wrong argument number error tests --- ext/ldap/tests/ldap_add_error.phpt | 10 +++++----- ext/ldap/tests/ldap_delete_error.phpt | 8 ++++---- ext/ldap/tests/ldap_mod_add_error.phpt | 10 +++++----- ext/ldap/tests/ldap_mod_del_error.phpt | 10 +++++----- ext/ldap/tests/ldap_mod_replace_error.phpt | 10 +++++----- ext/ldap/tests/ldap_modify_error.phpt | 10 +++++----- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/ext/ldap/tests/ldap_add_error.phpt b/ext/ldap/tests/ldap_add_error.phpt index a53277da80908..6ae61348cc65c 100644 --- a/ext/ldap/tests/ldap_add_error.phpt +++ b/ext/ldap/tests/ldap_add_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_add($link)); var_dump(ldap_add($link, "$base")); // Too many parameters -var_dump(ldap_add($link, "$base", array(), "Additional data")); +var_dump(ldap_add($link, "$base", array(), [], [], "Additional data")); var_dump(ldap_add($link, "$base", array())); @@ -97,16 +97,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_add() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_add() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_add() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_add() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_add() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_add() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_add() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_add() expects at most 5 parameters, 6 given in %s on line %d NULL Warning: ldap_add(): Add: Protocol error in %s on line %d diff --git a/ext/ldap/tests/ldap_delete_error.phpt b/ext/ldap/tests/ldap_delete_error.phpt index 1d160f1074f61..1fce39b94ac04 100644 --- a/ext/ldap/tests/ldap_delete_error.phpt +++ b/ext/ldap/tests/ldap_delete_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_delete()); var_dump(ldap_delete($link)); // Too many parameters -var_dump(ldap_delete($link, "$base", "Additional data")); +var_dump(ldap_delete($link, "$base", [], [], "Additional data")); // Invalid DN var_dump( @@ -41,13 +41,13 @@ require "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ?> --EXPECTF-- -Warning: ldap_delete() expects exactly 2 parameters, 0 given in %s on line %d +Warning: ldap_delete() expects at least 2 parameters, 0 given in %s on line %d NULL -Warning: ldap_delete() expects exactly 2 parameters, 1 given in %s on line %d +Warning: ldap_delete() expects at least 2 parameters, 1 given in %s on line %d NULL -Warning: ldap_delete() expects exactly 2 parameters, 3 given in %s on line %d +Warning: ldap_delete() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_delete(): Delete: Invalid DN syntax in %s on line %d diff --git a/ext/ldap/tests/ldap_mod_add_error.phpt b/ext/ldap/tests/ldap_mod_add_error.phpt index c04e2cbd3d2ce..d026a7d0c011e 100644 --- a/ext/ldap/tests/ldap_mod_add_error.phpt +++ b/ext/ldap/tests/ldap_mod_add_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_add($link)); var_dump(ldap_mod_add($link, "$base")); // Too many parameters -var_dump(ldap_mod_add($link, "$base", array(), "Additional data")); +var_dump(ldap_mod_add($link, "$base", array(), [], [], "Additional data")); // DN not found var_dump(ldap_mod_add($link, "dc=my-domain,$base", array())); @@ -57,16 +57,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_mod_add() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_mod_add() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_mod_add() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_mod_add() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_mod_add() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_mod_add() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_add() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_mod_add() expects at most 5 parameters, 6 given in %s on line %d NULL Warning: ldap_mod_add(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_mod_del_error.phpt b/ext/ldap/tests/ldap_mod_del_error.phpt index 679adb6e6e17c..a9d62bfb8ec6f 100644 --- a/ext/ldap/tests/ldap_mod_del_error.phpt +++ b/ext/ldap/tests/ldap_mod_del_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_del($link)); var_dump(ldap_mod_del($link, "$base")); // Too many parameters -var_dump(ldap_mod_del($link, "$base", array(), "Additional data")); +var_dump(ldap_mod_del($link, "$base", array(), [], [], "Additional data")); // DN not found var_dump(ldap_mod_del($link, "dc=my-domain,$base", array())); @@ -39,16 +39,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_mod_del() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_mod_del() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_mod_del() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_mod_del() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_mod_del() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_mod_del() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_del() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_mod_del() expects at most 5 parameters, 6 given in %s on line %d NULL Warning: ldap_mod_del(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_mod_replace_error.phpt b/ext/ldap/tests/ldap_mod_replace_error.phpt index f796568d0762d..2617da02466ca 100644 --- a/ext/ldap/tests/ldap_mod_replace_error.phpt +++ b/ext/ldap/tests/ldap_mod_replace_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_replace($link)); var_dump(ldap_mod_replace($link, "$base")); // Too many parameters -var_dump(ldap_mod_replace($link, "$base", array(), "Additional data")); +var_dump(ldap_mod_replace($link, "$base", array(), [], [], "Additional data")); // DN not found var_dump(ldap_mod_replace($link, "dc=my-domain,$base", array())); @@ -37,16 +37,16 @@ require "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ?> --EXPECTF-- -Warning: ldap_mod_replace() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_mod_replace() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_mod_replace() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_mod_replace() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_mod_replace() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_mod_replace() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_replace() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_mod_replace() expects at most 5 parameters, 6 given in %s on line %d NULL Warning: ldap_mod_replace(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_modify_error.phpt b/ext/ldap/tests/ldap_modify_error.phpt index 0ca2ea49dc04c..68f12b73a4f7b 100644 --- a/ext/ldap/tests/ldap_modify_error.phpt +++ b/ext/ldap/tests/ldap_modify_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_modify($link)); var_dump(ldap_modify($link, "$base")); // Too many parameters -var_dump(ldap_modify($link, "$base", array(), "Additional data")); +var_dump(ldap_modify($link, "$base", array(), [], [], "Additional data")); // DN not found var_dump(ldap_modify($link, "cn=not-found,$base", array())); @@ -57,16 +57,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_modify() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_modify() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_modify() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_modify() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_modify() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_modify() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_modify() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_modify() expects at most 5 parameters, 6 given in %s on line %d NULL Warning: ldap_modify(): Modify: No such object in %s on line %d From 59f32408f880ac0a24c3bd4ad368a5d9704f5032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 11:36:20 +0200 Subject: [PATCH 10/31] Using new control syntax for MANAGEDSAIT control when deleting references --- ext/ldap/tests/ldap_first_reference_basic.phpt | 3 +-- ext/ldap/tests/ldap_next_reference_basic.phpt | 5 ++--- ext/ldap/tests/ldap_parse_result_basic.phpt | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/ext/ldap/tests/ldap_first_reference_basic.phpt b/ext/ldap/tests/ldap_first_reference_basic.phpt index 312a81cc8072f..9c83c9127d357 100644 --- a/ext/ldap/tests/ldap_first_reference_basic.phpt +++ b/ext/ldap/tests/ldap_first_reference_basic.phpt @@ -30,8 +30,7 @@ include "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); // Referral can only be removed with Manage DSA IT Control -ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array(array("oid" => LDAP_CONTROL_MANAGEDSAIT))); -ldap_delete($link, "cn=userref,$base"); +ldap_delete($link, "cn=userref,$base", [['oid' => LDAP_CONTROL_MANAGEDSAIT, 'iscritical' => TRUE]]); remove_dummy_data($link, $base); ?> --EXPECTF-- diff --git a/ext/ldap/tests/ldap_next_reference_basic.phpt b/ext/ldap/tests/ldap_next_reference_basic.phpt index d92f69de0a0be..2476e02c5776c 100644 --- a/ext/ldap/tests/ldap_next_reference_basic.phpt +++ b/ext/ldap/tests/ldap_next_reference_basic.phpt @@ -35,9 +35,8 @@ include "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); // Referral can only be removed with Manage DSA IT Control -ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array(array("oid" => LDAP_CONTROL_MANAGEDSAIT))); -ldap_delete($link, "cn=userref,$base"); -ldap_delete($link, "cn=userref2,$base"); +ldap_delete($link, "cn=userref,$base", [['oid' => LDAP_CONTROL_MANAGEDSAIT, 'iscritical' => TRUE]]); +ldap_delete($link, "cn=userref2,$base", [['oid' => LDAP_CONTROL_MANAGEDSAIT, 'iscritical' => TRUE]]); remove_dummy_data($link, $base); ?> --EXPECTF-- diff --git a/ext/ldap/tests/ldap_parse_result_basic.phpt b/ext/ldap/tests/ldap_parse_result_basic.phpt index a4c03ee19772a..e2a975d5b198c 100644 --- a/ext/ldap/tests/ldap_parse_result_basic.phpt +++ b/ext/ldap/tests/ldap_parse_result_basic.phpt @@ -31,8 +31,7 @@ include "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); // Referral can only be removed with Manage DSA IT Control -ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array(array("oid" => LDAP_CONTROL_MANAGEDSAIT))); -ldap_delete($link, "cn=userref,$base"); +ldap_delete($link, "cn=userref,$base", [['oid' => LDAP_CONTROL_MANAGEDSAIT, 'iscritical' => TRUE]]); remove_dummy_data($link, $base); ?> --EXPECTF-- From 437c75abcbfb209d4f91b2c36a6bfd77afb16d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 11:39:46 +0200 Subject: [PATCH 11/31] Fixed prototypes in comments --- ext/ldap/ldap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 2bff9febcde6c..d4118ac5f3ed0 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -1951,7 +1951,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) } /* }}} */ -/* {{{ proto bool ldap_add(resource link, string dn, array entry) +/* {{{ proto bool ldap_add(resource link, string dn, array entry [, array servercontrols [, array clientcontrols]]) Add entries to LDAP directory */ PHP_FUNCTION(ldap_add) { @@ -1962,7 +1962,7 @@ PHP_FUNCTION(ldap_add) /* three functions for attribute base modifications, gerrit Thomson */ -/* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry) +/* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry [, array servercontrols [, array clientcontrols]]) Replace attribute values with new ones */ PHP_FUNCTION(ldap_mod_replace) { @@ -1970,7 +1970,7 @@ PHP_FUNCTION(ldap_mod_replace) } /* }}} */ -/* {{{ proto bool ldap_mod_add(resource link, string dn, array entry) +/* {{{ proto bool ldap_mod_add(resource link, string dn, array entry [, array servercontrols [, array clientcontrols]]) Add attribute values to current */ PHP_FUNCTION(ldap_mod_add) { @@ -1978,7 +1978,7 @@ PHP_FUNCTION(ldap_mod_add) } /* }}} */ -/* {{{ proto bool ldap_mod_del(resource link, string dn, array entry) +/* {{{ proto bool ldap_mod_del(resource link, string dn, array entry [, array servercontrols [, array clientcontrols]]) Delete attribute values */ PHP_FUNCTION(ldap_mod_del) { From 82cc72a3ba3c7a0fcdaa174ef94bf8ec22dcaa08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 11:57:13 +0200 Subject: [PATCH 12/31] Added controls support to ldap_rename --- ext/ldap/ldap.c | 44 ++++++++++++++++++++++++--- ext/ldap/tests/ldap_controls.phpt | 4 ++- ext/ldap/tests/ldap_rename_error.phpt | 2 +- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index d4118ac5f3ed0..7b954e80381b0 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -3112,18 +3112,20 @@ PHP_FUNCTION(ldap_parse_reference) /* }}} */ #endif -/* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn) +/* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols [, array clientcontrols]]) Modify the name of an entry */ PHP_FUNCTION(ldap_rename) { + zval *serverctrls = NULL, *clientctrls = NULL; zval *link; ldap_linkdata *ld; + LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; int rc; char *dn, *newrdn, *newparent; size_t dn_len, newrdn_len, newparent_len; zend_bool deleteoldrdn; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsssb", &link, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsssb|aa", &link, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn, &serverctrls, &clientctrls) != SUCCESS) { return; } @@ -3136,20 +3138,50 @@ PHP_FUNCTION(ldap_rename) } #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP - rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, NULL, NULL); + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + if (clientctrls) { + lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); + if (lclientctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + + rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, lclientctrls); #else if (newparent_len != 0) { php_error_docref(NULL, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN"); RETURN_FALSE; } + if (serverctrls || clientctrls) { + php_error_docref(NULL, E_WARNING, "You are using old LDAP API, controls are not supported"); + RETURN_FALSE; + } /* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */ rc = ldap_modrdn2_s(ld->link, dn, newrdn, deleteoldrdn); #endif if (rc == LDAP_SUCCESS) { - RETURN_TRUE; + RETVAL_TRUE; + } else { + RETVAL_FALSE; } - RETURN_FALSE; + +cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + if (lclientctrls) { + _php_ldap_controls_free(&lclientctrls); + } + + return; } /* }}} */ @@ -4106,6 +4138,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename, 0, 0, 5) ZEND_ARG_INFO(0, newrdn) ZEND_ARG_INFO(0, newparent) ZEND_ARG_INFO(0, deleteoldrdn) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_option, 0, 0, 3) diff --git a/ext/ldap/tests/ldap_controls.phpt b/ext/ldap/tests/ldap_controls.phpt index 85a0b8cba3585..51187bdcfb0de 100644 --- a/ext/ldap/tests/ldap_controls.phpt +++ b/ext/ldap/tests/ldap_controls.phpt @@ -31,7 +31,8 @@ var_dump( ldap_get_entries($link, $result), ldap_delete($link, "o=test,$base", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), ldap_errno($link), - ldap_error($link) + ldap_error($link), + ldap_rename($link, "o=test,$base", "o=test2", "", TRUE, [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]) ); ?> ===DONE=== @@ -117,4 +118,5 @@ array(2) { bool(false) int(122) string(16) "Assertion Failed" +bool(false) ===DONE=== diff --git a/ext/ldap/tests/ldap_rename_error.phpt b/ext/ldap/tests/ldap_rename_error.phpt index 111717f0b013e..8a580e5c3486e 100644 --- a/ext/ldap/tests/ldap_rename_error.phpt +++ b/ext/ldap/tests/ldap_rename_error.phpt @@ -15,7 +15,7 @@ var_dump(ldap_rename($link, "cn=userNotFound,$base", "cn=userZ", "$base", true)) ?> ===DONE=== --EXPECTF-- -Warning: ldap_rename() expects exactly 5 parameters, 1 given in %s on line %d +Warning: ldap_rename() expects at least 5 parameters, 1 given in %s on line %d NULL bool(false) ===DONE=== From 2b52cb74da92a2cc9b355a4b422168a1069ab321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 12:19:36 +0200 Subject: [PATCH 13/31] Added controls support to ldap_compare Note: for functions like ldap_compare, ldap_delete, ldap_modify, a way to get the result object back will need to be added so that controls returned by the server may be analyzed. --- ext/ldap/ldap.c | 42 ++++++++++++++++++++++---- ext/ldap/tests/ldap_compare_error.phpt | 10 +++--- ext/ldap/tests/ldap_controls.phpt | 10 +++++- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 7b954e80381b0..9c0d598d7826b 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2445,14 +2445,16 @@ PHP_FUNCTION(ldap_error) Determine if an entry has a specific value for one of its attributes */ PHP_FUNCTION(ldap_compare) { + zval *serverctrls = NULL, *clientctrls = NULL; zval *link; char *dn, *attr, *value; size_t dn_len, attr_len, value_len; ldap_linkdata *ld; + LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; int errno; struct berval lvalue; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsss", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsss|aa", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &serverctrls, &clientctrls) != SUCCESS) { return; } @@ -2460,23 +2462,49 @@ PHP_FUNCTION(ldap_compare) RETURN_FALSE; } + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + if (clientctrls) { + lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); + if (lclientctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + lvalue.bv_val = value; lvalue.bv_len = value_len; - errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, NULL, NULL); + errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, lserverctrls, lclientctrls); switch (errno) { case LDAP_COMPARE_TRUE: - RETURN_TRUE; + RETVAL_TRUE; break; case LDAP_COMPARE_FALSE: - RETURN_FALSE; + RETVAL_FALSE; break; + + default: + php_error_docref(NULL, E_WARNING, "Compare: %s", ldap_err2string(errno)); + RETVAL_LONG(-1); + } + +cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + if (lclientctrls) { + _php_ldap_controls_free(&lclientctrls); } - php_error_docref(NULL, E_WARNING, "Compare: %s", ldap_err2string(errno)); - RETURN_LONG(-1); + return; } /* }}} */ @@ -4107,6 +4135,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_compare, 0, 0, 4) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, attribute) ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sort, 0, 0, 3) diff --git a/ext/ldap/tests/ldap_compare_error.phpt b/ext/ldap/tests/ldap_compare_error.phpt index 07393f6de657c..b1d4514eb11b4 100644 --- a/ext/ldap/tests/ldap_compare_error.phpt +++ b/ext/ldap/tests/ldap_compare_error.phpt @@ -19,7 +19,7 @@ var_dump(ldap_compare($link, $link)); var_dump(ldap_compare($link, $link, $link)); // Too many parameters -var_dump(ldap_compare($link, $link, $link, $link, "Additional data")); +var_dump(ldap_compare($link, $link, $link, $link, [], [], "Additional data")); var_dump( ldap_compare($link, "cn=userNotAvailable,$base", "sn", "testSN1"), @@ -36,16 +36,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); remove_dummy_data($link, $base); ?> --EXPECTF-- -Warning: ldap_compare() expects exactly 4 parameters, 1 given in %s on line %d +Warning: ldap_compare() expects at least 4 parameters, 1 given in %s on line %d NULL -Warning: ldap_compare() expects exactly 4 parameters, 2 given in %s on line %d +Warning: ldap_compare() expects at least 4 parameters, 2 given in %s on line %d NULL -Warning: ldap_compare() expects exactly 4 parameters, 3 given in %s on line %d +Warning: ldap_compare() expects at least 4 parameters, 3 given in %s on line %d NULL -Warning: ldap_compare() expects exactly 4 parameters, 5 given in %s on line %d +Warning: ldap_compare() expects at most 6 parameters, 7 given in %s on line %d NULL Warning: ldap_compare(): Compare: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_controls.phpt b/ext/ldap/tests/ldap_controls.phpt index 51187bdcfb0de..b5fd6ac4401f4 100644 --- a/ext/ldap/tests/ldap_controls.phpt +++ b/ext/ldap/tests/ldap_controls.phpt @@ -32,7 +32,10 @@ var_dump( ldap_delete($link, "o=test,$base", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), ldap_errno($link), ldap_error($link), - ldap_rename($link, "o=test,$base", "o=test2", "", TRUE, [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]) + ldap_rename($link, "o=test,$base", "o=test2", "", TRUE, [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), + ldap_compare($link, "o=test,$base", "o", "test"), + ldap_compare($link, "o=test,$base", "o", "test", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), + ldap_compare($link, "o=test,$base", "o", "test", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc)']]]) ); ?> ===DONE=== @@ -49,6 +52,8 @@ Warning: ldap_search(): Search: Assertion Failed in %s on line %d Warning: ldap_modify(): Modify: Assertion Failed in %s on line %d Warning: ldap_delete(): Delete: Assertion Failed in %s on line %d + +Warning: ldap_compare(): Compare: Assertion Failed in %s on line %d resource(%d) of type (ldap result) array(2) { ["count"]=> @@ -119,4 +124,7 @@ bool(false) int(122) string(16) "Assertion Failed" bool(false) +bool(true) +int(-1) +bool(true) ===DONE=== From 81b27abac01e8241467d608b38ac17f3d1161e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 14:42:34 +0200 Subject: [PATCH 14/31] Added support for controls in ldap_modify_batch --- ext/ldap/ldap.c | 32 +++++++++++++++++++-- ext/ldap/tests/ldap_modify_batch_error.phpt | 10 +++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 9c0d598d7826b..3b5bac8513aab 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2083,10 +2083,11 @@ static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out) } /* }}} */ -/* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs) +/* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs [, array servercontrols [, array clientcontrols]]) Perform multiple modifications as part of one operation */ PHP_FUNCTION(ldap_modify_batch) { + zval *serverctrls = NULL, *clientctrls = NULL; ldap_linkdata *ld; zval *link, *mods, *mod, *modinfo, *modval; zval *attrib, *modtype, *vals; @@ -2096,6 +2097,7 @@ PHP_FUNCTION(ldap_modify_batch) int i, j, k; int num_mods, num_modprops, num_modvals; LDAPMod **ldap_mods; + LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; uint32_t oper; /* @@ -2122,7 +2124,7 @@ PHP_FUNCTION(ldap_modify_batch) ); */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/", &link, &dn, &dn_len, &mods) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|aa", &link, &dn, &dn_len, &mods, &serverctrls, &clientctrls) != SUCCESS) { return; } @@ -2350,8 +2352,23 @@ PHP_FUNCTION(ldap_modify_batch) /* NULL-terminate modifications */ ldap_mods[num_mods] = NULL; + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + if (clientctrls) { + lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); + if (lclientctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + /* perform (finally) */ - if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { + if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, lclientctrls)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Batch Modify: %s", ldap_err2string(i)); RETVAL_FALSE; } else RETVAL_TRUE; @@ -2382,6 +2399,13 @@ PHP_FUNCTION(ldap_modify_batch) /* the modifications array */ efree(ldap_mods); + + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + if (lclientctrls) { + _php_ldap_controls_free(&lclientctrls); + } } } /* }}} */ @@ -4100,6 +4124,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify_batch, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_ARRAY_INFO(0, modifications_info, 0) + ZEND_ARG_INFO(0, servercontrols) + ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3) diff --git a/ext/ldap/tests/ldap_modify_batch_error.phpt b/ext/ldap/tests/ldap_modify_batch_error.phpt index 2d72d491f8f31..3a1030f91758d 100644 --- a/ext/ldap/tests/ldap_modify_batch_error.phpt +++ b/ext/ldap/tests/ldap_modify_batch_error.phpt @@ -26,7 +26,7 @@ var_dump(ldap_modify_batch($link)); var_dump(ldap_modify_batch($link, "$base")); // Too many parameters -var_dump(ldap_modify_batch($link, "$base", $addGivenName, "Invalid additional parameter")); +var_dump(ldap_modify_batch($link, "$base", $addGivenName, [], [], "Invalid additional parameter")); // DN not found var_dump(ldap_modify_batch($link, "cn=not-found,$base", $addGivenName)); @@ -78,16 +78,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_modify_batch() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_modify_batch() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_modify_batch() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_modify_batch() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_modify_batch() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_modify_batch() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_modify_batch() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_modify_batch() expects at most 5 parameters, 6 given in %s on line %d NULL Warning: ldap_modify_batch(): Batch Modify: No such object in %s on line %d From d377edb884949fd7e32b5d9e62772321b550a08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 16:47:59 +0200 Subject: [PATCH 15/31] Fixed ldap_exop test since rebase remove client controls --- ext/ldap/tests/ldap_exop.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ldap/tests/ldap_exop.phpt b/ext/ldap/tests/ldap_exop.phpt index a26c01974029c..f5543c0e4edb2 100644 --- a/ext/ldap/tests/ldap_exop.phpt +++ b/ext/ldap/tests/ldap_exop.phpt @@ -42,7 +42,7 @@ var_dump( ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, NULL, $retdata, $retoid), $retdata, $retoid, - ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, [['oid' => LDAP_CONTROL_PROXY_AUTHZ, 'value' => "dn:cn=userA,$base"]], [], $retdata), + ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, [['oid' => LDAP_CONTROL_PROXY_AUTHZ, 'value' => "dn:cn=userA,$base"]], $retdata), $retdata, $r = ldap_exop($link, LDAP_EXOP_WHO_AM_I), ldap_parse_exop($link, $r, $retdata2), From b5ca0c1c78f05f1ad1332265ee6dabfc083c6d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 7 Sep 2017 17:03:45 +0200 Subject: [PATCH 16/31] Removed client controls alltogether Client controls are ldap client lib specific and all the one I could find are ignoring client controls anyway. --- ext/ldap/ldap.c | 157 +++++--------------- ext/ldap/tests/ldap_add_error.phpt | 4 +- ext/ldap/tests/ldap_compare_error.phpt | 4 +- ext/ldap/tests/ldap_delete_error.phpt | 4 +- ext/ldap/tests/ldap_list_error.phpt | 4 +- ext/ldap/tests/ldap_mod_add_error.phpt | 4 +- ext/ldap/tests/ldap_mod_del_error.phpt | 4 +- ext/ldap/tests/ldap_mod_replace_error.phpt | 4 +- ext/ldap/tests/ldap_modify_batch_error.phpt | 4 +- ext/ldap/tests/ldap_modify_error.phpt | 4 +- ext/ldap/tests/ldap_read_error.phpt | 4 +- 11 files changed, 58 insertions(+), 139 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 3b5bac8513aab..60cfc8be9cd65 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -1055,24 +1055,23 @@ static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, in */ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) { - zval *link, *base_dn, *filter, *attrs = NULL, *attr, *serverctrls, *clientctrls; + zval *link, *base_dn, *filter, *attrs = NULL, *attr, *serverctrls = NULL; zend_long attrsonly, sizelimit, timelimit, deref; char *ldap_base_dn = NULL, *ldap_filter = NULL, **ldap_attrs = NULL; ldap_linkdata *ld = NULL; LDAPMessage *ldap_res; - LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; + LDAPControl **lserverctrls = NULL; int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1; int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1; int num_attribs = 0, ret = 1, i, errno, argcount = ZEND_NUM_ARGS(); - if (zend_parse_parameters(argcount, "zzz|allllzz", &link, &base_dn, &filter, &attrs, &attrsonly, - &sizelimit, &timelimit, &deref, &serverctrls, &clientctrls) == FAILURE) { + if (zend_parse_parameters(argcount, "zzz|alllla", &link, &base_dn, &filter, &attrs, &attrsonly, + &sizelimit, &timelimit, &deref, &serverctrls) == FAILURE) { return; } /* Reverse -> fall through */ switch (argcount) { - case 10: case 9: case 8: ldap_deref = deref; @@ -1184,20 +1183,12 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) rcs[i] = -1; continue; } - if (argcount > 9) { - _php_ldap_controls_free(&lclientctrls); - lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); - if (lclientctrls == NULL) { - rcs[i] = -1; - continue; - } - } } php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref); /* Run the actual search */ - ldap_search_ext(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, lserverctrls, lclientctrls, NULL, ldap_sizelimit, &rcs[i]); + ldap_search_ext(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &rcs[i]); lds[i] = ld; zend_hash_move_forward(Z_ARRVAL_P(link)); } @@ -1241,19 +1232,12 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ret = 0; goto cleanup; } - if (argcount > 9) { - lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); - if (lclientctrls == NULL) { - ret = 0; - goto cleanup; - } - } } php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref); /* Run the actual search */ - errno = ldap_search_ext_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, lserverctrls, lclientctrls, NULL, ldap_sizelimit, &ldap_res); + errno = ldap_search_ext_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &ldap_res); if (errno != LDAP_SUCCESS && errno != LDAP_SIZELIMIT_EXCEEDED @@ -1294,13 +1278,10 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) if (lserverctrls) { _php_ldap_controls_free(&lserverctrls); } - if (lclientctrls) { - _php_ldap_controls_free(&lclientctrls); - } } /* }}} */ -/* {{{ proto resource ldap_read(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols [, array clientcontrols]]]]]]]) +/* {{{ proto resource ldap_read(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]]) Read an entry */ PHP_FUNCTION(ldap_read) { @@ -1308,7 +1289,7 @@ PHP_FUNCTION(ldap_read) } /* }}} */ -/* {{{ proto resource ldap_list(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols [, array clientcontrols]]]]]]]) +/* {{{ proto resource ldap_list(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]]) Single-level search */ PHP_FUNCTION(ldap_list) { @@ -1316,7 +1297,7 @@ PHP_FUNCTION(ldap_list) } /* }}} */ -/* {{{ proto resource ldap_search(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols [, array clientcontrols]]]]]]]) +/* {{{ proto resource ldap_search(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]]) Search LDAP tree under base_dn */ PHP_FUNCTION(ldap_search) { @@ -1807,12 +1788,12 @@ PHP_FUNCTION(ldap_dn2ufn) */ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) { - zval *serverctrls = NULL, *clientctrls = NULL; + zval *serverctrls = NULL; zval *link, *entry, *value, *ivalue; ldap_linkdata *ld; char *dn; LDAPMod **ldap_mods; - LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; + LDAPControl **lserverctrls = NULL; int i, j, num_attribs, num_values; size_t dn_len; int *num_berval; @@ -1820,7 +1801,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) zend_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_parse_parameters(ZEND_NUM_ARGS(), "rsa/|aa", &link, &dn, &dn_len, &entry, &serverctrls, &clientctrls) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|a", &link, &dn, &dn_len, &entry, &serverctrls) != SUCCESS) { return; } @@ -1908,22 +1889,15 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) goto cleanup; } } - if (clientctrls) { - lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); - if (lclientctrls == NULL) { - RETVAL_FALSE; - goto cleanup; - } - } /* check flag to see if do_mod was called to perform full add , gerrit thomson */ if (is_full_add == 1) { - if ((i = ldap_add_ext_s(ld->link, dn, ldap_mods, lserverctrls, lclientctrls)) != LDAP_SUCCESS) { + if ((i = ldap_add_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Add: %s", ldap_err2string(i)); RETVAL_FALSE; } else RETVAL_TRUE; } else { - if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, lclientctrls)) != LDAP_SUCCESS) { + if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Modify: %s", ldap_err2string(i)); RETVAL_FALSE; } else RETVAL_TRUE; @@ -1943,15 +1917,12 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) if (lserverctrls) { _php_ldap_controls_free(&lserverctrls); } - if (lclientctrls) { - _php_ldap_controls_free(&lclientctrls); - } return; } /* }}} */ -/* {{{ proto bool ldap_add(resource link, string dn, array entry [, array servercontrols [, array clientcontrols]]) +/* {{{ proto bool ldap_add(resource link, string dn, array entry [, array servercontrols]) Add entries to LDAP directory */ PHP_FUNCTION(ldap_add) { @@ -1962,7 +1933,7 @@ PHP_FUNCTION(ldap_add) /* three functions for attribute base modifications, gerrit Thomson */ -/* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry [, array servercontrols [, array clientcontrols]]) +/* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry [, array servercontrols]) Replace attribute values with new ones */ PHP_FUNCTION(ldap_mod_replace) { @@ -1970,7 +1941,7 @@ PHP_FUNCTION(ldap_mod_replace) } /* }}} */ -/* {{{ proto bool ldap_mod_add(resource link, string dn, array entry [, array servercontrols [, array clientcontrols]]) +/* {{{ proto bool ldap_mod_add(resource link, string dn, array entry [, array servercontrols]) Add attribute values to current */ PHP_FUNCTION(ldap_mod_add) { @@ -1978,7 +1949,7 @@ PHP_FUNCTION(ldap_mod_add) } /* }}} */ -/* {{{ proto bool ldap_mod_del(resource link, string dn, array entry [, array servercontrols [, array clientcontrols]]) +/* {{{ proto bool ldap_mod_del(resource link, string dn, array entry [, array servercontrols]) Delete attribute values */ PHP_FUNCTION(ldap_mod_del) { @@ -1986,19 +1957,19 @@ PHP_FUNCTION(ldap_mod_del) } /* }}} */ -/* {{{ proto bool ldap_delete(resource link, string dn [, array servercontrols [, array clientcontrols]]) +/* {{{ proto bool ldap_delete(resource link, string dn [, array servercontrols]) Delete an entry from a directory */ PHP_FUNCTION(ldap_delete) { - zval *serverctrls = NULL, *clientctrls = NULL; + zval *serverctrls = NULL; zval *link; ldap_linkdata *ld; - LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; + LDAPControl **lserverctrls = NULL; char *dn; int rc; size_t dn_len; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|aa", &link, &dn, &dn_len, &serverctrls, &clientctrls) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|a", &link, &dn, &dn_len, &serverctrls) != SUCCESS) { return; } @@ -2013,15 +1984,8 @@ PHP_FUNCTION(ldap_delete) goto cleanup; } } - if (clientctrls) { - lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); - if (lclientctrls == NULL) { - RETVAL_FALSE; - goto cleanup; - } - } - if ((rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, lclientctrls)) != LDAP_SUCCESS) { + if ((rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, NULL)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Delete: %s", ldap_err2string(rc)); RETVAL_FALSE; } else { @@ -2032,9 +1996,6 @@ PHP_FUNCTION(ldap_delete) if (lserverctrls) { _php_ldap_controls_free(&lserverctrls); } - if (lclientctrls) { - _php_ldap_controls_free(&lclientctrls); - } return; } @@ -2083,11 +2044,11 @@ static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out) } /* }}} */ -/* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs [, array servercontrols [, array clientcontrols]]) +/* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs [, array servercontrols]) Perform multiple modifications as part of one operation */ PHP_FUNCTION(ldap_modify_batch) { - zval *serverctrls = NULL, *clientctrls = NULL; + zval *serverctrls = NULL; ldap_linkdata *ld; zval *link, *mods, *mod, *modinfo, *modval; zval *attrib, *modtype, *vals; @@ -2097,7 +2058,7 @@ PHP_FUNCTION(ldap_modify_batch) int i, j, k; int num_mods, num_modprops, num_modvals; LDAPMod **ldap_mods; - LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; + LDAPControl **lserverctrls = NULL; uint32_t oper; /* @@ -2124,7 +2085,7 @@ PHP_FUNCTION(ldap_modify_batch) ); */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|aa", &link, &dn, &dn_len, &mods, &serverctrls, &clientctrls) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|a", &link, &dn, &dn_len, &mods, &serverctrls) != SUCCESS) { return; } @@ -2359,16 +2320,9 @@ PHP_FUNCTION(ldap_modify_batch) goto cleanup; } } - if (clientctrls) { - lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); - if (lclientctrls == NULL) { - RETVAL_FALSE; - goto cleanup; - } - } /* perform (finally) */ - if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, lclientctrls)) != LDAP_SUCCESS) { + if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Batch Modify: %s", ldap_err2string(i)); RETVAL_FALSE; } else RETVAL_TRUE; @@ -2403,9 +2357,6 @@ PHP_FUNCTION(ldap_modify_batch) if (lserverctrls) { _php_ldap_controls_free(&lserverctrls); } - if (lclientctrls) { - _php_ldap_controls_free(&lclientctrls); - } } } /* }}} */ @@ -2469,16 +2420,16 @@ PHP_FUNCTION(ldap_error) Determine if an entry has a specific value for one of its attributes */ PHP_FUNCTION(ldap_compare) { - zval *serverctrls = NULL, *clientctrls = NULL; + zval *serverctrls = NULL; zval *link; char *dn, *attr, *value; size_t dn_len, attr_len, value_len; ldap_linkdata *ld; - LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; + LDAPControl **lserverctrls = NULL; int errno; struct berval lvalue; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsss|aa", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &serverctrls, &clientctrls) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsss|a", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &serverctrls) != SUCCESS) { return; } @@ -2493,18 +2444,11 @@ PHP_FUNCTION(ldap_compare) goto cleanup; } } - if (clientctrls) { - lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); - if (lclientctrls == NULL) { - RETVAL_FALSE; - goto cleanup; - } - } lvalue.bv_val = value; lvalue.bv_len = value_len; - errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, lserverctrls, lclientctrls); + errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, lserverctrls, NULL); switch (errno) { case LDAP_COMPARE_TRUE: @@ -2524,9 +2468,6 @@ PHP_FUNCTION(ldap_compare) if (lserverctrls) { _php_ldap_controls_free(&lserverctrls); } - if (lclientctrls) { - _php_ldap_controls_free(&lclientctrls); - } return; } @@ -3164,20 +3105,20 @@ PHP_FUNCTION(ldap_parse_reference) /* }}} */ #endif -/* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols [, array clientcontrols]]) +/* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols]) Modify the name of an entry */ PHP_FUNCTION(ldap_rename) { - zval *serverctrls = NULL, *clientctrls = NULL; + zval *serverctrls = NULL; zval *link; ldap_linkdata *ld; - LDAPControl **lserverctrls = NULL, **lclientctrls = NULL; + LDAPControl **lserverctrls = NULL; int rc; char *dn, *newrdn, *newparent; size_t dn_len, newrdn_len, newparent_len; zend_bool deleteoldrdn; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsssb|aa", &link, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn, &serverctrls, &clientctrls) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsssb|a", &link, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn, &serverctrls) != SUCCESS) { return; } @@ -3197,21 +3138,14 @@ PHP_FUNCTION(ldap_rename) goto cleanup; } } - if (clientctrls) { - lclientctrls = _php_ldap_controls_from_array(ld->link, clientctrls); - if (lclientctrls == NULL) { - RETVAL_FALSE; - goto cleanup; - } - } - rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, lclientctrls); + rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL); #else if (newparent_len != 0) { php_error_docref(NULL, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN"); RETURN_FALSE; } - if (serverctrls || clientctrls) { + if (serverctrls) { php_error_docref(NULL, E_WARNING, "You are using old LDAP API, controls are not supported"); RETURN_FALSE; } @@ -3229,9 +3163,6 @@ PHP_FUNCTION(ldap_rename) if (lserverctrls) { _php_ldap_controls_free(&lserverctrls); } - if (lclientctrls) { - _php_ldap_controls_free(&lclientctrls); - } return; } @@ -4007,7 +3938,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) @@ -4020,7 +3950,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3) @@ -4033,7 +3962,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_count_entries, 0, 0, 2) @@ -4102,14 +4030,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add, 0, 0, 3) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete, 0, 0, 2) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3) @@ -4117,7 +4043,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify_batch, 0, 0, 3) @@ -4125,7 +4050,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify_batch, 0, 0, 3) ZEND_ARG_INFO(0, dn) ZEND_ARG_ARRAY_INFO(0, modifications_info, 0) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3) @@ -4133,7 +4057,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace, 0, 0, 3) @@ -4141,7 +4064,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace, 0, 0, 3) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del, 0, 0, 3) @@ -4149,7 +4071,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del, 0, 0, 3) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_err2str, 0, 0, 1) @@ -4162,7 +4083,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_compare, 0, 0, 4) ZEND_ARG_INFO(0, attribute) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sort, 0, 0, 3) @@ -4195,7 +4115,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename, 0, 0, 5) ZEND_ARG_INFO(0, newparent) ZEND_ARG_INFO(0, deleteoldrdn) ZEND_ARG_INFO(0, servercontrols) - ZEND_ARG_INFO(0, clientcontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_option, 0, 0, 3) diff --git a/ext/ldap/tests/ldap_add_error.phpt b/ext/ldap/tests/ldap_add_error.phpt index 6ae61348cc65c..533496a4b2d71 100644 --- a/ext/ldap/tests/ldap_add_error.phpt +++ b/ext/ldap/tests/ldap_add_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_add($link)); var_dump(ldap_add($link, "$base")); // Too many parameters -var_dump(ldap_add($link, "$base", array(), [], [], "Additional data")); +var_dump(ldap_add($link, "$base", array(), [], "Additional data")); var_dump(ldap_add($link, "$base", array())); @@ -106,7 +106,7 @@ NULL Warning: ldap_add() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_add() expects at most 5 parameters, 6 given in %s on line %d +Warning: ldap_add() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_add(): Add: Protocol error in %s on line %d diff --git a/ext/ldap/tests/ldap_compare_error.phpt b/ext/ldap/tests/ldap_compare_error.phpt index b1d4514eb11b4..120dfab0595f0 100644 --- a/ext/ldap/tests/ldap_compare_error.phpt +++ b/ext/ldap/tests/ldap_compare_error.phpt @@ -19,7 +19,7 @@ var_dump(ldap_compare($link, $link)); var_dump(ldap_compare($link, $link, $link)); // Too many parameters -var_dump(ldap_compare($link, $link, $link, $link, [], [], "Additional data")); +var_dump(ldap_compare($link, $link, $link, $link, [], "Additional data")); var_dump( ldap_compare($link, "cn=userNotAvailable,$base", "sn", "testSN1"), @@ -45,7 +45,7 @@ NULL Warning: ldap_compare() expects at least 4 parameters, 3 given in %s on line %d NULL -Warning: ldap_compare() expects at most 6 parameters, 7 given in %s on line %d +Warning: ldap_compare() expects at most 5 parameters, 6 given in %s on line %d NULL Warning: ldap_compare(): Compare: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_delete_error.phpt b/ext/ldap/tests/ldap_delete_error.phpt index 1fce39b94ac04..a34d7b39fe5e7 100644 --- a/ext/ldap/tests/ldap_delete_error.phpt +++ b/ext/ldap/tests/ldap_delete_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_delete()); var_dump(ldap_delete($link)); // Too many parameters -var_dump(ldap_delete($link, "$base", [], [], "Additional data")); +var_dump(ldap_delete($link, "$base", [], "Additional data")); // Invalid DN var_dump( @@ -47,7 +47,7 @@ NULL Warning: ldap_delete() expects at least 2 parameters, 1 given in %s on line %d NULL -Warning: ldap_delete() expects at most 4 parameters, 5 given in %s on line %d +Warning: ldap_delete() expects at most 3 parameters, 4 given in %s on line %d NULL Warning: ldap_delete(): Delete: Invalid DN syntax in %s on line %d diff --git a/ext/ldap/tests/ldap_list_error.phpt b/ext/ldap/tests/ldap_list_error.phpt index 801d2464f13e5..817622e7252e4 100644 --- a/ext/ldap/tests/ldap_list_error.phpt +++ b/ext/ldap/tests/ldap_list_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_list($link)); var_dump(ldap_list($link, $link)); // Too many parameters -var_dump(ldap_list($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0, [], [], "Additional data")); +var_dump(ldap_list($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0, [], "Additional data")); ?> ===DONE=== --EXPECTF-- @@ -30,6 +30,6 @@ NULL Warning: ldap_list() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_list() expects at most 10 parameters, 11 given in %s on line %d +Warning: ldap_list() expects at most 9 parameters, 10 given in %s on line %d NULL ===DONE=== diff --git a/ext/ldap/tests/ldap_mod_add_error.phpt b/ext/ldap/tests/ldap_mod_add_error.phpt index d026a7d0c011e..4bfbaa5551ef7 100644 --- a/ext/ldap/tests/ldap_mod_add_error.phpt +++ b/ext/ldap/tests/ldap_mod_add_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_add($link)); var_dump(ldap_mod_add($link, "$base")); // Too many parameters -var_dump(ldap_mod_add($link, "$base", array(), [], [], "Additional data")); +var_dump(ldap_mod_add($link, "$base", array(), [], "Additional data")); // DN not found var_dump(ldap_mod_add($link, "dc=my-domain,$base", array())); @@ -66,7 +66,7 @@ NULL Warning: ldap_mod_add() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_add() expects at most 5 parameters, 6 given in %s on line %d +Warning: ldap_mod_add() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_mod_add(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_mod_del_error.phpt b/ext/ldap/tests/ldap_mod_del_error.phpt index a9d62bfb8ec6f..129d6472c12ef 100644 --- a/ext/ldap/tests/ldap_mod_del_error.phpt +++ b/ext/ldap/tests/ldap_mod_del_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_del($link)); var_dump(ldap_mod_del($link, "$base")); // Too many parameters -var_dump(ldap_mod_del($link, "$base", array(), [], [], "Additional data")); +var_dump(ldap_mod_del($link, "$base", array(), [], "Additional data")); // DN not found var_dump(ldap_mod_del($link, "dc=my-domain,$base", array())); @@ -48,7 +48,7 @@ NULL Warning: ldap_mod_del() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_del() expects at most 5 parameters, 6 given in %s on line %d +Warning: ldap_mod_del() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_mod_del(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_mod_replace_error.phpt b/ext/ldap/tests/ldap_mod_replace_error.phpt index 2617da02466ca..4f435b13d2add 100644 --- a/ext/ldap/tests/ldap_mod_replace_error.phpt +++ b/ext/ldap/tests/ldap_mod_replace_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_replace($link)); var_dump(ldap_mod_replace($link, "$base")); // Too many parameters -var_dump(ldap_mod_replace($link, "$base", array(), [], [], "Additional data")); +var_dump(ldap_mod_replace($link, "$base", array(), [], "Additional data")); // DN not found var_dump(ldap_mod_replace($link, "dc=my-domain,$base", array())); @@ -46,7 +46,7 @@ NULL Warning: ldap_mod_replace() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_replace() expects at most 5 parameters, 6 given in %s on line %d +Warning: ldap_mod_replace() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_mod_replace(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_modify_batch_error.phpt b/ext/ldap/tests/ldap_modify_batch_error.phpt index 3a1030f91758d..a2d9ef9debe49 100644 --- a/ext/ldap/tests/ldap_modify_batch_error.phpt +++ b/ext/ldap/tests/ldap_modify_batch_error.phpt @@ -26,7 +26,7 @@ var_dump(ldap_modify_batch($link)); var_dump(ldap_modify_batch($link, "$base")); // Too many parameters -var_dump(ldap_modify_batch($link, "$base", $addGivenName, [], [], "Invalid additional parameter")); +var_dump(ldap_modify_batch($link, "$base", $addGivenName, [], "Invalid additional parameter")); // DN not found var_dump(ldap_modify_batch($link, "cn=not-found,$base", $addGivenName)); @@ -87,7 +87,7 @@ NULL Warning: ldap_modify_batch() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_modify_batch() expects at most 5 parameters, 6 given in %s on line %d +Warning: ldap_modify_batch() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_modify_batch(): Batch Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_modify_error.phpt b/ext/ldap/tests/ldap_modify_error.phpt index 68f12b73a4f7b..31069bb98c962 100644 --- a/ext/ldap/tests/ldap_modify_error.phpt +++ b/ext/ldap/tests/ldap_modify_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_modify($link)); var_dump(ldap_modify($link, "$base")); // Too many parameters -var_dump(ldap_modify($link, "$base", array(), [], [], "Additional data")); +var_dump(ldap_modify($link, "$base", array(), [], "Additional data")); // DN not found var_dump(ldap_modify($link, "cn=not-found,$base", array())); @@ -66,7 +66,7 @@ NULL Warning: ldap_modify() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_modify() expects at most 5 parameters, 6 given in %s on line %d +Warning: ldap_modify() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_modify(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_read_error.phpt b/ext/ldap/tests/ldap_read_error.phpt index c1e15a6aed774..08f6280490606 100644 --- a/ext/ldap/tests/ldap_read_error.phpt +++ b/ext/ldap/tests/ldap_read_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_read($link)); var_dump(ldap_read($link, $link)); // Too many parameters -var_dump(ldap_read($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0, [], [], "Additional data")); +var_dump(ldap_read($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0, [], "Additional data")); ?> ===DONE=== --EXPECTF-- @@ -30,6 +30,6 @@ NULL Warning: ldap_read() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_read() expects at most 10 parameters, 11 given in %s on line %d +Warning: ldap_read() expects at most 9 parameters, 10 given in %s on line %d NULL ===DONE=== From 3a1ba93066c5c136a962152b2c37da5c61659be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 11 Sep 2017 11:37:55 +0200 Subject: [PATCH 17/31] Added support and test for LDAP_CONTROL_VALUESRETURNFILTER --- ext/ldap/ldap.c | 26 ++++++++++++++++++++++++++ ext/ldap/tests/connect.inc | 8 ++++++++ ext/ldap/tests/ldap_controls.phpt | 29 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 60cfc8be9cd65..776475a53b1c5 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -264,6 +264,32 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra } } } + } else if (strcmp(control_oid, LDAP_CONTROL_VALUESRETURNFILTER) == 0) { + zval* tmp; + char* filter; + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Filter missing from control value array"); + } else { + BerElement *vrber = NULL; + control_value = ber_memalloc(sizeof * control_value); + if ((vrber = ber_alloc_t(LBER_USE_DER)) == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + convert_to_string_ex(tmp); + if (ldap_put_vrFilter(vrber, Z_STRVAL_P(tmp)) == -1) { + ber_free(vrber, 1); + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to create control value: Bad ValuesReturnFilter: %s", Z_STRVAL_P(tmp)); + } else { + if (ber_flatten2(vrber, control_value, 0) == -1) { + rc = -1; + } + ber_free(vrber, 1); + } + } + } } else { php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", control_oid); rc = -1; diff --git a/ext/ldap/tests/connect.inc b/ext/ldap/tests/connect.inc index 1c2205056eb38..b6366c02ac788 100644 --- a/ext/ldap/tests/connect.inc +++ b/ext/ldap/tests/connect.inc @@ -69,6 +69,13 @@ function insert_dummy_data($link, $base) { "sn" => "testSN3", "userPassword" => "0r1g1na1 passw0rd", )); + ldap_add($link, "o=test2,$base", array( + "objectClass" => array( + "top", + "organization"), + "o" => "test2", + "l" => array("here", "there", "Antarctica"), + )); } function remove_dummy_data($link, $base) { @@ -76,5 +83,6 @@ function remove_dummy_data($link, $base) { ldap_delete($link, "cn=userA,$base"); ldap_delete($link, "cn=userB,$base"); ldap_delete($link, "o=test,$base"); + ldap_delete($link, "o=test2,$base"); } ?> diff --git a/ext/ldap/tests/ldap_controls.phpt b/ext/ldap/tests/ldap_controls.phpt index b5fd6ac4401f4..02f65b549ed52 100644 --- a/ext/ldap/tests/ldap_controls.phpt +++ b/ext/ldap/tests/ldap_controls.phpt @@ -37,6 +37,15 @@ var_dump( ldap_compare($link, "o=test,$base", "o", "test", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), ldap_compare($link, "o=test,$base", "o", "test", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc)']]]) ); + +/* Test valuesreturnfilter control */ +var_dump( + $result = ldap_read($link, "o=test2,$base", "objectClass=*", ["l"]), + ldap_get_entries($link, $result)[0]['l'], + $result = ldap_read($link, "o=test2,$base", "objectClass=*", ["l"], 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_VALUESRETURNFILTER, 'iscritical' => TRUE, 'value' => ['filter' => '(l=*here)']]]), + ldap_get_entries($link, $result)[0]['l'] +); ?> ===DONE=== --CLEAN-- @@ -127,4 +136,24 @@ bool(false) bool(true) int(-1) bool(true) +resource(%d) of type (ldap result) +array(4) { + ["count"]=> + int(3) + [0]=> + string(4) "here" + [1]=> + string(5) "there" + [2]=> + string(10) "Antarctica" +} +resource(%d) of type (ldap result) +array(3) { + ["count"]=> + int(2) + [0]=> + string(4) "here" + [1]=> + string(5) "there" +} ===DONE=== From 9275e05d8efc8672073adba472ef528be6708130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 11 Sep 2017 11:46:47 +0200 Subject: [PATCH 18/31] Improved a bit error handling to avoid passing commands with incomplete controls --- ext/ldap/ldap.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 776475a53b1c5..612b29d0f3220 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -217,7 +217,10 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra if (Z_TYPE_P(val) != IS_ARRAY) { convert_to_string_ex(val); control_value = ber_memalloc(sizeof * control_value); - if (control_value != NULL) { + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { control_value->bv_val = Z_STRVAL_P(val); control_value->bv_len = Z_STRLEN_P(val); } @@ -238,21 +241,29 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra } } control_value = ber_memalloc(sizeof * control_value); - if (control_value != NULL) { + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { rc = ldap_create_page_control_value(ld, pagesize, cookie, control_value); if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc); - control_value = NULL; } } } else if (strcmp(control_oid, LDAP_CONTROL_ASSERT) == 0) { zval* tmp; char* assert; - if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) != NULL) { + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Filter missing from assert control value array"); + } else { convert_to_string_ex(tmp); assert = Z_STRVAL_P(tmp); control_value = ber_memalloc(sizeof * control_value); - if (control_value != NULL) { + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { // ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves // See http://www.openldap.org/its/index.cgi/Incoming?id=8674 int success = LDAP_SUCCESS; @@ -260,7 +271,6 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra rc = ldap_create_assertion_control_value(ld, assert, control_value); if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc); - control_value = NULL; } } } From b36342453beb119ee134b21c3ded6313b0236516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 11 Sep 2017 15:38:32 +0200 Subject: [PATCH 19/31] Added ldap_bind_ext to pass controls and get result object ldap_bind_ext allows to pass controls and get result object from bind operation Also added a test for it, pretty basic as tests cannot depend upon ppolicy overlay --- ext/ldap/ldap.c | 85 +++++++++++++++++++++++++++++++ ext/ldap/tests/ldap_bind_ext.phpt | 68 +++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 ext/ldap/tests/ldap_bind_ext.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 612b29d0f3220..8962d421bf5a7 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -901,6 +901,83 @@ PHP_FUNCTION(ldap_bind) } /* }}} */ +/* {{{ proto resource ldap_bind_ext(resource link [, string dn [, string password [, serverctrls]]]) + Bind to LDAP directory */ +PHP_FUNCTION(ldap_bind_ext) +{ + zval *serverctrls = NULL; + zval *link; + char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL; + size_t ldap_bind_dnlen, ldap_bind_pwlen; + ldap_linkdata *ld; + LDAPControl **lserverctrls = NULL; + LDAPMessage *ldap_res; + int rc; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ssa", &link, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen, &serverctrls) != SUCCESS) { + RETURN_FALSE; + } + + if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) { + RETURN_FALSE; + } + + if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) { + _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS); + php_error_docref(NULL, E_WARNING, "DN contains a null byte"); + RETURN_FALSE; + } + + if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) { + _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS); + php_error_docref(NULL, E_WARNING, "Password contains a null byte"); + RETURN_FALSE; + } + + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + + { + /* ldap_simple_bind() is deprecated, use ldap_sasl_bind() instead */ + struct berval cred; + int msgid; + + cred.bv_val = ldap_bind_pw; + cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; + /* asynchronous call */ + rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, + lserverctrls, NULL, &msgid); + if (rc != LDAP_SUCCESS ) { + php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s (%d)", ldap_err2string(rc), rc); + RETVAL_FALSE; + goto cleanup; + } + + rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (rc == -1) { + php_error_docref(NULL, E_WARNING, "Bind operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); + } + +cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + + return; +} +/* }}} */ + #ifdef HAVE_LDAP_SASL typedef struct { char *mech; @@ -3952,6 +4029,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind, 0, 0, 1) ZEND_ARG_INFO(0, bind_password) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind_ext, 0, 0, 1) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, bind_rdn) + ZEND_ARG_INFO(0, bind_password) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + #ifdef HAVE_LDAP_SASL ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sasl_bind, 0, 0, 1) ZEND_ARG_INFO(0, link) @@ -4275,6 +4359,7 @@ const zend_function_entry ldap_functions[] = { PHP_FE(ldap_connect, arginfo_ldap_connect) PHP_FALIAS(ldap_close, ldap_unbind, arginfo_ldap_resource) PHP_FE(ldap_bind, arginfo_ldap_bind) + PHP_FE(ldap_bind_ext, arginfo_ldap_bind_ext) #ifdef HAVE_LDAP_SASL PHP_FE(ldap_sasl_bind, arginfo_ldap_sasl_bind) #endif diff --git a/ext/ldap/tests/ldap_bind_ext.phpt b/ext/ldap/tests/ldap_bind_ext.phpt new file mode 100644 index 0000000000000..04134bf3487c6 --- /dev/null +++ b/ext/ldap/tests/ldap_bind_ext.phpt @@ -0,0 +1,68 @@ +--TEST-- +ldap_bind_ext() - Basic binding +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + +--FILE-- + LDAP_CONTROL_PASSWORDPOLICYREQUEST]]), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls +); + +/* Failures */ +var_dump( + $result = ldap_bind_ext($link, $user, "wrongPassword", [['oid' => LDAP_CONTROL_PASSWORDPOLICYREQUEST]]), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls, + $result = ldap_bind_ext($link, "unexistingProperty=weirdValue,$user", $passwd, [['oid' => LDAP_CONTROL_PASSWORDPOLICYREQUEST]]), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls +); +?> +===DONE=== +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(0) { +} +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(0) { +} +resource(%d) of type (ldap result) +bool(true) +int(49) +string(0) "" +array(0) { +} +resource(%d) of type (ldap result) +bool(true) +int(34) +string(10) "invalid DN" +array(0) { +} +===DONE=== From 32b51035bedda2786d80f170b3aad1b2bf0f329f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 12 Sep 2017 09:53:49 +0200 Subject: [PATCH 20/31] Added ldap_add_ext and preread/postread support and tests --- ext/ldap/ldap.c | 160 ++++++++++++++++++++++++++++--- ext/ldap/tests/ldap_add_ext.phpt | 95 ++++++++++++++++++ 2 files changed, 243 insertions(+), 12 deletions(-) create mode 100644 ext/ldap/tests/ldap_add_ext.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 8962d421bf5a7..00b6050d2775b 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -182,6 +182,45 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array) } else { add_assoc_null(array, "value"); } + } else if ((strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_POST_READ) == 0)) { + BerElement *ber; + struct berval bv; + + ber = ber_init(&ctrl->ldctl_value); + if (ber == NULL) { + add_assoc_null(array, "value"); + } else if (ber_scanf(ber, "{m{" /*}}*/, &bv) == LBER_ERROR) { + add_assoc_null(array, "value"); + } else { + zval value; + + array_init(&value); + add_assoc_stringl(&value, "dn", bv.bv_val, bv.bv_len); + + while (ber_scanf(ber, "{m" /*}*/, &bv) != LBER_ERROR) { + int i; + BerVarray vals = NULL; + zval tmp; + + if (ber_scanf(ber, "[W]", &vals) == LBER_ERROR || vals == NULL) + { + break; + } + + array_init(&tmp); + for (i = 0; vals[i].bv_val != NULL; i++) { + add_next_index_stringl(&tmp, vals[i].bv_val, vals[i].bv_len); + } + add_assoc_zval(&value, bv.bv_val, &tmp); + + ber_bvarray_free(vals); + } + add_assoc_zval(array, "value", &value); + } + + if (ber != NULL) { + ber_free(ber, 1); + } } else { if (ctrl->ldctl_value.bv_len) { add_assoc_stringl(array, "value", ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len); @@ -196,6 +235,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra zval* val; char * control_oid = NULL; int control_iscritical = 0, rc = LDAP_SUCCESS; + char** ldap_attrs = NULL; if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "oid", sizeof("oid") - 1)) == NULL) { php_error_docref(NULL, E_WARNING, "Control must have an oid key"); @@ -276,14 +316,13 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra } } else if (strcmp(control_oid, LDAP_CONTROL_VALUESRETURNFILTER) == 0) { zval* tmp; - char* filter; if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) { rc = -1; php_error_docref(NULL, E_WARNING, "Filter missing from control value array"); } else { - BerElement *vrber = NULL; + BerElement *vrber = ber_alloc_t(LBER_USE_DER); control_value = ber_memalloc(sizeof * control_value); - if ((vrber = ber_alloc_t(LBER_USE_DER)) == NULL) { + if ((control_value == NULL) || (vrber == NULL)) { rc = -1; php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); } else { @@ -300,6 +339,52 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra } } } + } else if ((strcmp(control_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(control_oid, LDAP_CONTROL_POST_READ) == 0)) { + zval* tmp; + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrs", sizeof("attrs") - 1)) == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Attributes list missing from control value array"); + } else { + BerElement *ber = ber_alloc_t(LBER_USE_DER); + + control_value = ber_memalloc(sizeof * control_value); + if ((control_value == NULL) || (ber == NULL)) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + int num_attribs, i; + zval* attr; + + num_attribs = zend_hash_num_elements(Z_ARRVAL_P(tmp)); + ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0); + + for (i = 0; ilink, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) { + if (ext) { + i = ldap_add_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid); + } else { + i = ldap_add_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL); + } + if (i != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Add: %s", ldap_err2string(i)); RETVAL_FALSE; + } else if (ext) { + i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (i == -1) { + php_error_docref(NULL, E_WARNING, "Add operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); } else RETVAL_TRUE; } else { - if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) { + if (ext) { + i = ldap_modify_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid); + } else { + i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL); + } + if (i != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Modify: %s", ldap_err2string(i)); RETVAL_FALSE; + } else if (ext) { + i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (i == -1) { + php_error_docref(NULL, E_WARNING, "Modify operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); } else RETVAL_TRUE; } @@ -2027,6 +2147,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) } efree(num_berval); efree(ldap_mods); + if (lserverctrls) { _php_ldap_controls_free(&lserverctrls); } @@ -2040,7 +2161,15 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) 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); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0); +} +/* }}} */ + +/* {{{ proto resource ldap_add_ext(resource link, string dn, array entry [, array servercontrols]) + Add entries to LDAP directory */ +PHP_FUNCTION(ldap_add_ext) +{ + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 1); } /* }}} */ @@ -2050,7 +2179,7 @@ PHP_FUNCTION(ldap_add) 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); } /* }}} */ @@ -2058,7 +2187,7 @@ PHP_FUNCTION(ldap_mod_replace) 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); } /* }}} */ @@ -2066,7 +2195,7 @@ PHP_FUNCTION(ldap_mod_add) 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); } /* }}} */ @@ -2979,7 +3108,6 @@ PHP_FUNCTION(ldap_set_option) PHP_FUNCTION(ldap_parse_result) { zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals, *serverctrls; - zval ctrl, php_ber; ldap_linkdata *ld; LDAPMessage *ldap_result; LDAPControl **lserverctrls = NULL, **ctrlp = NULL; @@ -4152,6 +4280,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add, 0, 0, 3) ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add_ext, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete, 0, 0, 2) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) @@ -4381,6 +4516,7 @@ const zend_function_entry ldap_functions[] = { PHP_FE(ldap_explode_dn, arginfo_ldap_explode_dn) PHP_FE(ldap_dn2ufn, arginfo_ldap_dn2ufn) PHP_FE(ldap_add, arginfo_ldap_add) + PHP_FE(ldap_add_ext, arginfo_ldap_add_ext) PHP_FE(ldap_delete, arginfo_ldap_delete) PHP_FE(ldap_modify_batch, arginfo_ldap_modify_batch) PHP_FALIAS(ldap_modify, ldap_mod_replace, arginfo_ldap_modify) diff --git a/ext/ldap/tests/ldap_add_ext.phpt b/ext/ldap/tests/ldap_add_ext.phpt new file mode 100644 index 0000000000000..aa08afd09489a --- /dev/null +++ b/ext/ldap/tests/ldap_add_ext.phpt @@ -0,0 +1,95 @@ +--TEST-- +ldap_add_ext() - Add operation with controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + +--FILE-- + array( + "top", + "organization"), + "o" => "test_ldap_add_ext", + ), [['oid' => LDAP_CONTROL_POST_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['o']]]]), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls, + ldap_get_entries( + $link, + ldap_search($link, "$base", "(o=test_ldap_add_ext)") + ) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(1) { + [0]=> + array(3) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["iscritical"]=> + bool(false) + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "o=test_ldap_add_ext,%s" + ["o"]=> + array(1) { + [0]=> + string(17) "test_ldap_add_ext" + } + } + } +} +array(2) { + ["count"]=> + int(1) + [0]=> + array(6) { + ["objectclass"]=> + array(3) { + ["count"]=> + int(2) + [0]=> + string(3) "top" + [1]=> + string(12) "organization" + } + [0]=> + string(11) "objectclass" + ["o"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(17) "test_ldap_add_ext" + } + [1]=> + string(1) "o" + ["count"]=> + int(2) + ["dn"]=> + string(%d) "o=test_ldap_add_ext,%s" + } +} +===DONE=== From 17e490a2e3389da09c4a656f571292f14ddefb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 12 Sep 2017 11:13:23 +0200 Subject: [PATCH 21/31] Added ldap_mod_*_ext methods for modification with controls --- ext/ldap/ldap.c | 48 +++++++++ ext/ldap/tests/ldap_mod_ext.phpt | 175 +++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 ext/ldap/tests/ldap_mod_ext.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 00b6050d2775b..666251fae1df2 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2183,6 +2183,14 @@ PHP_FUNCTION(ldap_mod_replace) } /* }}} */ +/* {{{ proto resource ldap_mod_replace_ext(resource link, string dn, array entry [, array servercontrols]) + 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 bool ldap_mod_add(resource link, string dn, array entry [, array servercontrols]) Add attribute values to current */ PHP_FUNCTION(ldap_mod_add) @@ -2191,6 +2199,14 @@ PHP_FUNCTION(ldap_mod_add) } /* }}} */ +/* {{{ proto resource ldap_mod_add(resource link, string dn, array entry [, array servercontrols]) + Add attribute values to current */ +PHP_FUNCTION(ldap_mod_add_ext) +{ + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1); +} +/* }}} */ + /* {{{ proto bool ldap_mod_del(resource link, string dn, array entry [, array servercontrols]) Delete attribute values */ PHP_FUNCTION(ldap_mod_del) @@ -2199,6 +2215,14 @@ PHP_FUNCTION(ldap_mod_del) } /* }}} */ +/* {{{ proto resource ldap_mod_del_ext(resource link, string dn, array entry [, array servercontrols]) + Delete attribute values */ +PHP_FUNCTION(ldap_mod_del_ext) +{ + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1); +} +/* }}} */ + /* {{{ proto bool ldap_delete(resource link, string dn [, array servercontrols]) Delete an entry from a directory */ PHP_FUNCTION(ldap_delete) @@ -4314,6 +4338,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3) ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add_ext, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) @@ -4321,6 +4352,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace, 0, 0, 3) ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace_ext, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) @@ -4328,6 +4366,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del, 0, 0, 3) ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del_ext, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_err2str, 0, 0, 1) ZEND_ARG_INFO(0, errno) ZEND_END_ARG_INFO() @@ -4523,8 +4568,11 @@ const zend_function_entry ldap_functions[] = { /* additional functions for attribute based modifications, Gerrit Thomson */ PHP_FE(ldap_mod_add, arginfo_ldap_mod_add) + PHP_FE(ldap_mod_add_ext, arginfo_ldap_mod_add_ext) PHP_FE(ldap_mod_replace, arginfo_ldap_mod_replace) + PHP_FE(ldap_mod_replace_ext, arginfo_ldap_mod_replace_ext) PHP_FE(ldap_mod_del, arginfo_ldap_mod_del) + PHP_FE(ldap_mod_del_ext, arginfo_ldap_mod_del_ext) /* end gjt mod */ PHP_FE(ldap_errno, arginfo_ldap_resource) diff --git a/ext/ldap/tests/ldap_mod_ext.phpt b/ext/ldap/tests/ldap_mod_ext.phpt new file mode 100644 index 0000000000000..3f161f3973b14 --- /dev/null +++ b/ext/ldap/tests/ldap_mod_ext.phpt @@ -0,0 +1,175 @@ +--TEST-- +ldap_mod_ext() - Modify operations with controls +--CREDITS-- +Patrick Allaert +# Belgian PHP Testfest 2009 +--SKIPIF-- + + +--FILE-- + "Domain description", +); + +var_dump( + $result = ldap_mod_add_ext($link, "o=test,$base", $entry, + [ + ['oid' => LDAP_CONTROL_PRE_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['description']]], + ['oid' => LDAP_CONTROL_POST_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['description']]], + ] + ), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls, + ldap_get_entries( + $link, + ldap_search($link, "o=test,$base", "(Description=Domain description)") + ), + $result = ldap_mod_del_ext($link, "o=test,$base", $entry, + [ + ['oid' => LDAP_CONTROL_PRE_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['description']]], + ['oid' => LDAP_CONTROL_POST_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['description']]], + ] + ), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls, + ldap_get_entries( + $link, + ldap_search($link, "o=test,$base", "(Description=Domain description)") + ) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(2) { + [0]=> + array(3) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["iscritical"]=> + bool(false) + ["value"]=> + array(1) { + ["dn"]=> + string(%d) "o=test,%s" + } + } + [1]=> + array(3) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["iscritical"]=> + bool(false) + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "o=test,%s" + ["description"]=> + array(1) { + [0]=> + string(18) "Domain description" + } + } + } +} +array(2) { + ["count"]=> + int(1) + [0]=> + array(8) { + ["objectclass"]=> + array(3) { + ["count"]=> + int(2) + [0]=> + string(3) "top" + [1]=> + string(12) "organization" + } + [0]=> + string(11) "objectclass" + ["o"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(4) "test" + } + [1]=> + string(1) "o" + ["description"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(18) "Domain description" + } + [2]=> + string(11) "description" + ["count"]=> + int(3) + ["dn"]=> + string(%d) "o=test,%s" + } +} +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(2) { + [0]=> + array(3) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["iscritical"]=> + bool(false) + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "o=test,%s" + ["description"]=> + array(1) { + [0]=> + string(18) "Domain description" + } + } + } + [1]=> + array(3) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["iscritical"]=> + bool(false) + ["value"]=> + array(1) { + ["dn"]=> + string(%d) "o=test,%s" + } + } +} +array(1) { + ["count"]=> + int(0) +} +===DONE=== From ead53aba542eb6c848bdd73cf5f57b871e703f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 12 Sep 2017 11:39:00 +0200 Subject: [PATCH 22/31] Added ldap_delete_ext and its test --- ext/ldap/ldap.c | 50 ++++++++++++++++++-- ext/ldap/tests/ldap_delete_ext.phpt | 72 +++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 ext/ldap/tests/ldap_delete_ext.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 666251fae1df2..046610c92b3bb 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2223,16 +2223,17 @@ PHP_FUNCTION(ldap_mod_del_ext) } /* }}} */ -/* {{{ proto bool ldap_delete(resource link, string dn [, array servercontrols]) - Delete an entry from a directory */ -PHP_FUNCTION(ldap_delete) +/* {{{ php_ldap_do_delete + */ +static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext) { zval *serverctrls = NULL; zval *link; ldap_linkdata *ld; LDAPControl **lserverctrls = NULL; + LDAPMessage *ldap_res; char *dn; - int rc; + int rc, msgid; size_t dn_len; if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|a", &link, &dn, &dn_len, &serverctrls) != SUCCESS) { @@ -2251,9 +2252,25 @@ PHP_FUNCTION(ldap_delete) } } - if ((rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, NULL)) != LDAP_SUCCESS) { + if (ext) { + rc = ldap_delete_ext(ld->link, dn, lserverctrls, NULL, &msgid); + } else { + rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, NULL); + } + if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Delete: %s", ldap_err2string(rc)); RETVAL_FALSE; + goto cleanup; + } else if (ext) { + rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (rc == -1) { + php_error_docref(NULL, E_WARNING, "Delete operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); } else { RETVAL_TRUE; } @@ -2267,6 +2284,22 @@ PHP_FUNCTION(ldap_delete) } /* }}} */ +/* {{{ proto bool ldap_delete(resource link, string dn [, array servercontrols]) + Delete an entry from a directory */ +PHP_FUNCTION(ldap_delete) +{ + php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto resource ldap_delete_ext(resource link, string dn [, array servercontrols]) + Delete an entry from a directory */ +PHP_FUNCTION(ldap_delete_ext) +{ + php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + /* {{{ _ldap_str_equal_to_const */ static size_t _ldap_str_equal_to_const(const char *str, size_t str_len, const char *cstr) @@ -4317,6 +4350,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete, 0, 0, 2) ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete_ext, 0, 0, 2) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) @@ -4563,6 +4602,7 @@ const zend_function_entry ldap_functions[] = { PHP_FE(ldap_add, arginfo_ldap_add) PHP_FE(ldap_add_ext, arginfo_ldap_add_ext) PHP_FE(ldap_delete, arginfo_ldap_delete) + PHP_FE(ldap_delete_ext, arginfo_ldap_delete_ext) PHP_FE(ldap_modify_batch, arginfo_ldap_modify_batch) PHP_FALIAS(ldap_modify, ldap_mod_replace, arginfo_ldap_modify) diff --git a/ext/ldap/tests/ldap_delete_ext.phpt b/ext/ldap/tests/ldap_delete_ext.phpt new file mode 100644 index 0000000000000..6f48cb2e5b3b4 --- /dev/null +++ b/ext/ldap/tests/ldap_delete_ext.phpt @@ -0,0 +1,72 @@ +--TEST-- +ldap_delete_ext() - Delete operation with controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + +--FILE-- + array( + "top", + "dcObject", + "organization"), + "dc" => "my-domain", + "o" => "my-domain", +)); + +var_dump( + $result = ldap_delete_ext($link, "dc=my-domain,$base", + [['oid' => LDAP_CONTROL_PRE_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['dc', 'o']]]] + ), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls, + @ldap_search($link, "dc=my-domain,$base", "(o=my-domain)") +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(1) { + [0]=> + array(3) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["iscritical"]=> + bool(false) + ["value"]=> + array(3) { + ["dn"]=> + string(%d) "dc=my-domain,%s" + ["dc"]=> + array(1) { + [0]=> + string(9) "my-domain" + } + ["o"]=> + array(1) { + [0]=> + string(9) "my-domain" + } + } + } +} +bool(false) +===DONE=== From d8a7214d8ce244b9e27650e147931ddb162b70c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 12 Sep 2017 11:40:56 +0200 Subject: [PATCH 23/31] Fixed ldap_parse_result comment --- ext/ldap/ldap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 046610c92b3bb..a491678d3263a 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -3160,7 +3160,7 @@ PHP_FUNCTION(ldap_set_option) /* }}} */ #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 &controls]]]]) Extract information from result */ PHP_FUNCTION(ldap_parse_result) { From 9c7666d93acfd8f767ab36911ca46aa529b9593d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 12 Sep 2017 12:04:17 +0200 Subject: [PATCH 24/31] Avoid returning iscritical field when parsing response controls As stated in RFC4511 Section 4.1.11, this field is always false in response controls and only makes sense in request controls --- ext/ldap/ldap.c | 17 ++++++++++------- ext/ldap/tests/ldap_add_ext.phpt | 4 +--- ext/ldap/tests/ldap_delete_ext.phpt | 4 +--- ext/ldap/tests/ldap_mod_ext.phpt | 16 ++++------------ ext/ldap/tests/ldap_parse_result_controls.phpt | 2 -- 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index a491678d3263a..bfa6af2588d3e 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -137,12 +137,15 @@ static void _free_ldap_result_entry(zend_resource *rsrc) /* {{{ */ /* }}} */ /* {{{ Parse controls from and to arrays */ -static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array) +static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, int request) { array_init(array); add_assoc_string(array, "oid", ctrl->ldctl_oid); - add_assoc_bool(array, "iscritical", (ctrl->ldctl_iscritical != 0)); + if (request) { + /* iscritical field only makes sense in request controls (which may be obtained by ldap_get_option) */ + add_assoc_bool(array, "iscritical", (ctrl->ldctl_iscritical != 0)); + } // If it is a known oid, parse to values if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) { @@ -413,7 +416,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra return -1; } -static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* array) +static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* array, int request) { zval tmp1; LDAPControl **ctrlp; @@ -424,7 +427,7 @@ static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* arr } ctrlp = ctrls; while (*ctrlp != NULL) { - _php_ldap_control_to_array(ld, *ctrlp, &tmp1); + _php_ldap_control_to_array(ld, *ctrlp, &tmp1, request); add_next_index_zval(array, &tmp1); ctrlp++; } @@ -2966,7 +2969,7 @@ PHP_FUNCTION(ldap_get_option) } RETURN_FALSE; } - _php_ldap_controls_to_array(ld->link, ctrls, retval); + _php_ldap_controls_to_array(ld->link, ctrls, retval, 1); } break; /* options not implemented case LDAP_OPT_API_INFO: @@ -3201,7 +3204,7 @@ PHP_FUNCTION(ldap_parse_result) /* Reverse -> fall through */ switch (myargcount) { case 7: - _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls); + _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0); case 6: zval_ptr_dtor(referrals); array_init(referrals); @@ -4109,7 +4112,7 @@ PHP_FUNCTION(ldap_exop_passwd) } if (myargcount > 4) { - _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls); + _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0); } ldap_memfree(lgenpasswd.bv_val); diff --git a/ext/ldap/tests/ldap_add_ext.phpt b/ext/ldap/tests/ldap_add_ext.phpt index aa08afd09489a..a7a13d0677dd5 100644 --- a/ext/ldap/tests/ldap_add_ext.phpt +++ b/ext/ldap/tests/ldap_add_ext.phpt @@ -44,11 +44,9 @@ int(0) string(0) "" array(1) { [0]=> - array(3) { + array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.2" - ["iscritical"]=> - bool(false) ["value"]=> array(2) { ["dn"]=> diff --git a/ext/ldap/tests/ldap_delete_ext.phpt b/ext/ldap/tests/ldap_delete_ext.phpt index 6f48cb2e5b3b4..f27523d38a81e 100644 --- a/ext/ldap/tests/ldap_delete_ext.phpt +++ b/ext/ldap/tests/ldap_delete_ext.phpt @@ -46,11 +46,9 @@ int(0) string(0) "" array(1) { [0]=> - array(3) { + array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.1" - ["iscritical"]=> - bool(false) ["value"]=> array(3) { ["dn"]=> diff --git a/ext/ldap/tests/ldap_mod_ext.phpt b/ext/ldap/tests/ldap_mod_ext.phpt index 3f161f3973b14..9c1cdf28de781 100644 --- a/ext/ldap/tests/ldap_mod_ext.phpt +++ b/ext/ldap/tests/ldap_mod_ext.phpt @@ -64,11 +64,9 @@ int(0) string(0) "" array(2) { [0]=> - array(3) { + array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.1" - ["iscritical"]=> - bool(false) ["value"]=> array(1) { ["dn"]=> @@ -76,11 +74,9 @@ array(2) { } } [1]=> - array(3) { + array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.2" - ["iscritical"]=> - bool(false) ["value"]=> array(2) { ["dn"]=> @@ -139,11 +135,9 @@ int(0) string(0) "" array(2) { [0]=> - array(3) { + array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.1" - ["iscritical"]=> - bool(false) ["value"]=> array(2) { ["dn"]=> @@ -156,11 +150,9 @@ array(2) { } } [1]=> - array(3) { + array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.2" - ["iscritical"]=> - bool(false) ["value"]=> array(1) { ["dn"]=> diff --git a/ext/ldap/tests/ldap_parse_result_controls.phpt b/ext/ldap/tests/ldap_parse_result_controls.phpt index ef1dca8ebf2a1..d652f9c915c3a 100644 --- a/ext/ldap/tests/ldap_parse_result_controls.phpt +++ b/ext/ldap/tests/ldap_parse_result_controls.phpt @@ -19,7 +19,6 @@ var_dump( $result = ldap_search($link, $dn, $filter, array('cn')), ldap_parse_result($link, $result, $errcode, $dn, $errmsg, $refs, $ctrls), $ctrls[0]['oid'], - $ctrls[0]['iscritical'], $ctrls[0]['value']['size'], bin2hex($ctrls[0]['value']['cookie']), ldap_get_entries($link, $result)['count'] @@ -38,7 +37,6 @@ bool(true) resource(%d) of type (ldap result) bool(true) string(22) "1.2.840.113556.1.4.319" -bool(false) int(%d) string(%d) "%s" int(1) From 679442b1d1ed3a13af3076d17337898bdcee36e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 12 Sep 2017 12:58:46 +0200 Subject: [PATCH 25/31] Indexing controls by OID when parsing them --- ext/ldap/ldap.c | 2 +- ext/ldap/tests/ldap_add_ext.phpt | 25 ++++++------- ext/ldap/tests/ldap_delete_ext.phpt | 37 +++++++++---------- ext/ldap/tests/ldap_get_option_controls.phpt | 4 +- ext/ldap/tests/ldap_get_option_variation.phpt | 8 ++-- ext/ldap/tests/ldap_mod_ext.phpt | 8 ++-- .../tests/ldap_parse_result_controls.phpt | 6 +-- .../ldap_search_paged_result_controls.phpt | 2 +- ext/ldap/tests/ldap_set_option_variation.phpt | 8 ++-- 9 files changed, 47 insertions(+), 53 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index bfa6af2588d3e..7afbe0940d6c4 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -428,7 +428,7 @@ static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* arr ctrlp = ctrls; while (*ctrlp != NULL) { _php_ldap_control_to_array(ld, *ctrlp, &tmp1, request); - add_next_index_zval(array, &tmp1); + add_assoc_zval(array, (*ctrlp)->ldctl_oid, &tmp1); ctrlp++; } ldap_controls_free(ctrls); diff --git a/ext/ldap/tests/ldap_add_ext.phpt b/ext/ldap/tests/ldap_add_ext.phpt index a7a13d0677dd5..89d39c9d17228 100644 --- a/ext/ldap/tests/ldap_add_ext.phpt +++ b/ext/ldap/tests/ldap_add_ext.phpt @@ -21,7 +21,7 @@ var_dump( ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), $errcode, $errmsg, - $ctrls, + $ctrls[LDAP_CONTROL_POST_READ], ldap_get_entries( $link, ldap_search($link, "$base", "(o=test_ldap_add_ext)") @@ -42,20 +42,17 @@ resource(%d) of type (ldap result) bool(true) int(0) string(0) "" -array(1) { - [0]=> +array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["value"]=> array(2) { - ["oid"]=> - string(14) "1.3.6.1.1.13.2" - ["value"]=> - array(2) { - ["dn"]=> - string(%d) "o=test_ldap_add_ext,%s" - ["o"]=> - array(1) { - [0]=> - string(17) "test_ldap_add_ext" - } + ["dn"]=> + string(%d) "o=test_ldap_add_ext,%s" + ["o"]=> + array(1) { + [0]=> + string(17) "test_ldap_add_ext" } } } diff --git a/ext/ldap/tests/ldap_delete_ext.phpt b/ext/ldap/tests/ldap_delete_ext.phpt index f27523d38a81e..f4e9937e03e4a 100644 --- a/ext/ldap/tests/ldap_delete_ext.phpt +++ b/ext/ldap/tests/ldap_delete_ext.phpt @@ -26,7 +26,7 @@ var_dump( ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), $errcode, $errmsg, - $ctrls, + $ctrls[LDAP_CONTROL_PRE_READ], @ldap_search($link, "dc=my-domain,$base", "(o=my-domain)") ); ?> @@ -44,25 +44,22 @@ resource(%d) of type (ldap result) bool(true) int(0) string(0) "" -array(1) { - [0]=> - array(2) { - ["oid"]=> - string(14) "1.3.6.1.1.13.1" - ["value"]=> - array(3) { - ["dn"]=> - string(%d) "dc=my-domain,%s" - ["dc"]=> - array(1) { - [0]=> - string(9) "my-domain" - } - ["o"]=> - array(1) { - [0]=> - string(9) "my-domain" - } +array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["value"]=> + array(3) { + ["dn"]=> + string(%d) "dc=my-domain,%s" + ["dc"]=> + array(1) { + [0]=> + string(9) "my-domain" + } + ["o"]=> + array(1) { + [0]=> + string(9) "my-domain" } } } diff --git a/ext/ldap/tests/ldap_get_option_controls.phpt b/ext/ldap/tests/ldap_get_option_controls.phpt index ea42532d4bf4e..abe35497d6e43 100644 --- a/ext/ldap/tests/ldap_get_option_controls.phpt +++ b/ext/ldap/tests/ldap_get_option_controls.phpt @@ -72,7 +72,7 @@ bool(false) bool(true) bool(true) array(1) { - [0]=> + ["1.2.840.113556.1.4.319"]=> array(3) { ["oid"]=> string(22) "1.2.840.113556.1.4.319" @@ -90,7 +90,7 @@ array(1) { bool(true) bool(true) array(1) { - [0]=> + ["1.2.840.113556.1.4.319"]=> array(3) { ["oid"]=> string(22) "1.2.840.113556.1.4.319" diff --git a/ext/ldap/tests/ldap_get_option_variation.phpt b/ext/ldap/tests/ldap_get_option_variation.phpt index d980350eb642b..a18318849fc05 100644 --- a/ext/ldap/tests/ldap_get_option_variation.phpt +++ b/ext/ldap/tests/ldap_get_option_variation.phpt @@ -66,7 +66,7 @@ bool(true) int(0) bool(true) array(2) { - [0]=> + ["1.2.752.58.10.1"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" @@ -75,7 +75,7 @@ array(2) { ["value"]=> NULL } - [1]=> + ["1.2.752.58.1.10"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.1.10" @@ -87,7 +87,7 @@ array(2) { } bool(true) array(2) { - [0]=> + ["1.2.752.58.10.1"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" @@ -96,7 +96,7 @@ array(2) { ["value"]=> NULL } - [1]=> + ["1.2.752.58.1.10"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.1.10" diff --git a/ext/ldap/tests/ldap_mod_ext.phpt b/ext/ldap/tests/ldap_mod_ext.phpt index 9c1cdf28de781..f97ce1412b0fd 100644 --- a/ext/ldap/tests/ldap_mod_ext.phpt +++ b/ext/ldap/tests/ldap_mod_ext.phpt @@ -63,7 +63,7 @@ bool(true) int(0) string(0) "" array(2) { - [0]=> + ["1.3.6.1.1.13.1"]=> array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.1" @@ -73,7 +73,7 @@ array(2) { string(%d) "o=test,%s" } } - [1]=> + ["1.3.6.1.1.13.2"]=> array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.2" @@ -134,7 +134,7 @@ bool(true) int(0) string(0) "" array(2) { - [0]=> + ["1.3.6.1.1.13.1"]=> array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.1" @@ -149,7 +149,7 @@ array(2) { } } } - [1]=> + ["1.3.6.1.1.13.2"]=> array(2) { ["oid"]=> string(14) "1.3.6.1.1.13.2" diff --git a/ext/ldap/tests/ldap_parse_result_controls.phpt b/ext/ldap/tests/ldap_parse_result_controls.phpt index d652f9c915c3a..326f164f1256d 100644 --- a/ext/ldap/tests/ldap_parse_result_controls.phpt +++ b/ext/ldap/tests/ldap_parse_result_controls.phpt @@ -18,9 +18,9 @@ var_dump( ldap_control_paged_result($link, 1), $result = ldap_search($link, $dn, $filter, array('cn')), ldap_parse_result($link, $result, $errcode, $dn, $errmsg, $refs, $ctrls), - $ctrls[0]['oid'], - $ctrls[0]['value']['size'], - bin2hex($ctrls[0]['value']['cookie']), + $ctrls[LDAP_CONTROL_PAGEDRESULTS]['oid'], + $ctrls[LDAP_CONTROL_PAGEDRESULTS]['value']['size'], + bin2hex($ctrls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']), ldap_get_entries($link, $result)['count'] ); ?> diff --git a/ext/ldap/tests/ldap_search_paged_result_controls.phpt b/ext/ldap/tests/ldap_search_paged_result_controls.phpt index e75f408e9a851..fb85bc6709bad 100644 --- a/ext/ldap/tests/ldap_search_paged_result_controls.phpt +++ b/ext/ldap/tests/ldap_search_paged_result_controls.phpt @@ -22,7 +22,7 @@ var_dump( ldap_get_entries($link, $result), ldap_parse_result($link, $result, $errcode , $matcheddn , $errmsg , $referrals, $controls), $result = ldap_search($link, $dn, $filter, array('cn'), 0, 0, 0, LDAP_DEREF_NEVER, - [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => 20, 'cookie' => $controls[0]['value']['cookie']]]]), + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => 20, 'cookie' => $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']]]]), ldap_get_entries($link, $result) ); ?> diff --git a/ext/ldap/tests/ldap_set_option_variation.phpt b/ext/ldap/tests/ldap_set_option_variation.phpt index b496bb1311fc3..4c0a138552526 100644 --- a/ext/ldap/tests/ldap_set_option_variation.phpt +++ b/ext/ldap/tests/ldap_set_option_variation.phpt @@ -77,7 +77,7 @@ bool(true) bool(false) bool(true) array(2) { - [0]=> + ["1.2.752.58.10.1"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" @@ -86,7 +86,7 @@ array(2) { ["value"]=> NULL } - [1]=> + ["1.2.752.58.1.10"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.1.10" @@ -98,7 +98,7 @@ array(2) { } bool(true) array(2) { - [0]=> + ["1.2.752.58.10.1"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" @@ -107,7 +107,7 @@ array(2) { ["value"]=> NULL } - [1]=> + ["1.2.752.58.1.10"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.1.10" From c112b53a6011aa96098f7e706a31ffe6753d7270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 12 Sep 2017 14:56:31 +0200 Subject: [PATCH 26/31] Added ldap_rename_ext and its test --- ext/ldap/ldap.c | 61 ++++++++++++++++++++--- ext/ldap/tests/ldap_rename_ext.phpt | 75 +++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 ext/ldap/tests/ldap_rename_ext.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 7afbe0940d6c4..f325a00ecf521 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -3406,15 +3406,16 @@ PHP_FUNCTION(ldap_parse_reference) /* }}} */ #endif -/* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols]) - Modify the name of an entry */ -PHP_FUNCTION(ldap_rename) +/* {{{ php_ldap_do_rename + */ +static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, int ext) { zval *serverctrls = NULL; zval *link; ldap_linkdata *ld; LDAPControl **lserverctrls = NULL; - int rc; + LDAPMessage *ldap_res; + int rc, msgid; char *dn, *newrdn, *newparent; size_t dn_len, newrdn_len, newparent_len; zend_bool deleteoldrdn; @@ -3440,7 +3441,11 @@ PHP_FUNCTION(ldap_rename) } } - rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL); + if (ext) { + rc = ldap_rename(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL, &msgid); + } else { + rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL); + } #else if (newparent_len != 0) { php_error_docref(NULL, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN"); @@ -3450,14 +3455,28 @@ PHP_FUNCTION(ldap_rename) php_error_docref(NULL, E_WARNING, "You are using old LDAP API, controls are not supported"); RETURN_FALSE; } + if (ext) { + php_error_docref(NULL, E_WARNING, "You are using old LDAP API, ldap_rename_ext is not supported"); + RETURN_FALSE; + } /* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */ rc = ldap_modrdn2_s(ld->link, dn, newrdn, deleteoldrdn); #endif - if (rc == LDAP_SUCCESS) { - RETVAL_TRUE; - } else { + if (rc != LDAP_SUCCESS) { RETVAL_FALSE; + } else if (ext) { + rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (rc == -1) { + php_error_docref(NULL, E_WARNING, "Rename operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); + } else { + RETVAL_TRUE; } cleanup: @@ -3469,6 +3488,22 @@ PHP_FUNCTION(ldap_rename) } /* }}} */ +/* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols]) + Modify the name of an entry */ +PHP_FUNCTION(ldap_rename) +{ + php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto resource ldap_rename_ext(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols]) + Modify the name of an entry */ +PHP_FUNCTION(ldap_rename_ext) +{ + php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + #ifdef HAVE_LDAP_START_TLS_S /* {{{ proto bool ldap_start_tls(resource link) Start TLS */ @@ -4459,6 +4494,15 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename, 0, 0, 5) ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename_ext, 0, 0, 5) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, newrdn) + ZEND_ARG_INFO(0, newparent) + ZEND_ARG_INFO(0, deleteoldrdn) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_option, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, option) @@ -4626,6 +4670,7 @@ const zend_function_entry ldap_functions[] = { #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP PHP_FE(ldap_rename, arginfo_ldap_rename) + PHP_FE(ldap_rename_ext, arginfo_ldap_rename_ext) PHP_FE(ldap_get_option, arginfo_ldap_get_option) PHP_FE(ldap_set_option, arginfo_ldap_set_option) PHP_FE(ldap_first_reference, arginfo_ldap_first_reference) diff --git a/ext/ldap/tests/ldap_rename_ext.phpt b/ext/ldap/tests/ldap_rename_ext.phpt new file mode 100644 index 0000000000000..1de7e45364ba5 --- /dev/null +++ b/ext/ldap/tests/ldap_rename_ext.phpt @@ -0,0 +1,75 @@ +--TEST-- +ldap_rename_ext() - Rename operation with controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + +--FILE-- + LDAP_CONTROL_PRE_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['cn']]], + ['oid' => LDAP_CONTROL_POST_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['cn']]] + ] + ), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls[LDAP_CONTROL_PRE_READ], + $ctrls[LDAP_CONTROL_POST_READ], + ldap_count_entries($link, ldap_search($link, "$base", "(cn=userA)", array("cn"))), + ldap_count_entries($link, ldap_search($link, "$base", "(cn=userZ)", array("cn"))) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "cn=userA,%s" + ["cn"]=> + array(1) { + [0]=> + string(5) "userA" + } + } +} +array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "cn=userZ,%s" + ["cn"]=> + array(1) { + [0]=> + string(5) "userZ" + } + } +} +int(0) +int(1) +===DONE=== From d76d57b887b4bbc594ecae0b88bf5227786d1b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 14 Sep 2017 10:03:04 +0200 Subject: [PATCH 27/31] Fixed ifdef for VLV controls (copy/paste error) --- ext/ldap/ldap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index f325a00ecf521..8e2bfaba314af 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -711,7 +711,7 @@ PHP_MINIT_FUNCTION(ldap) REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_TREE_DELETE", LDAP_CONTROL_X_TREE_DELETE, CONST_PERSISTENT | CONST_CS); REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_EXTENDED_DN", LDAP_CONTROL_X_EXTENDED_DN, CONST_PERSISTENT | CONST_CS); #endif -#ifdef LDAP_CONTROL_X_INCREMENTAL_VALUES +#ifdef LDAP_CONTROL_VLVREQUEST /* LDAP VLV */ REGISTER_STRING_CONSTANT("LDAP_CONTROL_VLVREQUEST", LDAP_CONTROL_VLVREQUEST, CONST_PERSISTENT | CONST_CS); REGISTER_STRING_CONSTANT("LDAP_CONTROL_VLVRESPONSE", LDAP_CONTROL_VLVRESPONSE, CONST_PERSISTENT | CONST_CS); From def30dbde2edfbba9111d171458103d82c4ecda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 14 Sep 2017 10:08:22 +0200 Subject: [PATCH 28/31] Avoid memory leak when creating paged control value --- ext/ldap/ldap.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 8e2bfaba314af..5f5c4ce6e102a 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -270,25 +270,22 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra } else if (strcmp(control_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { zval* tmp; int pagesize = 1; - struct berval *cookie = NULL; + struct berval cookie = { 0, NULL }; if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) { convert_to_long_ex(tmp); pagesize = Z_LVAL_P(tmp); } if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "cookie", sizeof("cookie") - 1)) != NULL) { convert_to_string_ex(tmp); - cookie = ber_memalloc(sizeof * cookie); - if (cookie != NULL) { - cookie->bv_val = Z_STRVAL_P(tmp); - cookie->bv_len = Z_STRLEN_P(tmp); - } + cookie.bv_val = Z_STRVAL_P(tmp); + cookie.bv_len = Z_STRLEN_P(tmp); } control_value = ber_memalloc(sizeof * control_value); if (control_value == NULL) { rc = -1; php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); } else { - rc = ldap_create_page_control_value(ld, pagesize, cookie, control_value); + rc = ldap_create_page_control_value(ld, pagesize, &cookie, control_value); if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc); } From 76e9de681ab651f300e5eeff47b5ea92e903a5cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 14 Sep 2017 14:03:15 +0200 Subject: [PATCH 29/31] Added skip when control are not supported by the test ldap server --- ext/ldap/tests/ldap_add_ext.phpt | 4 ++++ ext/ldap/tests/ldap_bind_ext.phpt | 4 ++++ ext/ldap/tests/ldap_controls.phpt | 3 +++ ext/ldap/tests/ldap_delete_ext.phpt | 4 ++++ ext/ldap/tests/ldap_mod_ext.phpt | 5 +++++ ext/ldap/tests/ldap_parse_result_controls.phpt | 4 ++++ ext/ldap/tests/ldap_rename_ext.phpt | 5 +++++ .../tests/ldap_search_paged_result_controls.phpt | 2 ++ ext/ldap/tests/skipifcontrol.inc | 13 +++++++++++++ 9 files changed, 44 insertions(+) create mode 100644 ext/ldap/tests/skipifcontrol.inc diff --git a/ext/ldap/tests/ldap_add_ext.phpt b/ext/ldap/tests/ldap_add_ext.phpt index 89d39c9d17228..12916d98c3ca4 100644 --- a/ext/ldap/tests/ldap_add_ext.phpt +++ b/ext/ldap/tests/ldap_add_ext.phpt @@ -5,6 +5,10 @@ Côme Chilliet --SKIPIF-- + --FILE-- --SKIPIF-- + --FILE-- --FILE-- --SKIPIF-- + --FILE-- --SKIPIF-- + --FILE-- --SKIPIF-- + --FILE-- --SKIPIF-- + --FILE-- --FILE-- From 6ac7d313c8e0c05001d01c12a47fdea676a3a2b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 14 Sep 2017 14:55:42 +0200 Subject: [PATCH 30/31] Added support for SORT controls On an openldap server you need the sssvlv overlay for these to work --- ext/ldap/ldap.c | 79 ++++++++++++ ext/ldap/tests/ldap_search_sort_controls.phpt | 117 ++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 ext/ldap/tests/ldap_search_sort_controls.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 5f5c4ce6e102a..dbe68a3d61555 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -224,6 +224,27 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, if (ber != NULL) { ber_free(ber, 1); } + } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_SORTRESPONSE) == 0) { + zval value; + int errcode, rc; + char* attribute; + + if (ctrl->ldctl_value.bv_len) { + rc = ldap_parse_sortresponse_control(ld, ctrl, &errcode, &attribute); + } else { + rc = -1; + } + if ( rc == LDAP_SUCCESS ) { + array_init(&value); + add_assoc_long(&value, "errcode", errcode); + if (attribute) { + add_assoc_string(&value, "attribute", attribute); + ldap_memfree(attribute); + } + add_assoc_zval(array, "value", &value); + } else { + add_assoc_null(array, "value"); + } } else { if (ctrl->ldctl_value.bv_len) { add_assoc_stringl(array, "value", ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len); @@ -239,6 +260,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra char * control_oid = NULL; int control_iscritical = 0, rc = LDAP_SUCCESS; char** ldap_attrs = NULL; + LDAPSortKey** sort_keys = NULL; if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "oid", sizeof("oid") - 1)) == NULL) { php_error_docref(NULL, E_WARNING, "Control must have an oid key"); @@ -385,6 +407,54 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra } } } + } else if (strcmp(control_oid, LDAP_CONTROL_SORTREQUEST) == 0) { + int num_keys, i; + zval *sortkey, *tmp; + + num_keys = zend_hash_num_elements(Z_ARRVAL_P(val)); + sort_keys = safe_emalloc((num_keys+1), sizeof(LDAPSortKey*), 0); + + for (i = 0; iattributeType = Z_STRVAL_P(tmp); + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "oid", sizeof("oid") - 1)) != NULL) { + convert_to_string_ex(tmp); + sort_keys[i]->orderingRule = Z_STRVAL_P(tmp); + } else { + sort_keys[i]->orderingRule = NULL; + } + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "reverse", sizeof("reverse") - 1)) != NULL) { + convert_to_boolean_ex(tmp); + sort_keys[i]->reverseOrder = (Z_TYPE_P(tmp) == IS_TRUE); + } else { + sort_keys[i]->reverseOrder = 0; + } + } + sort_keys[num_keys] = NULL; + control_value = ber_memalloc(sizeof * control_value); + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + rc = ldap_create_sort_control_value(ld, sort_keys, control_value); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc); + } + } } else { php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", control_oid); rc = -1; @@ -403,6 +473,15 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra if (ldap_attrs != NULL) { efree(ldap_attrs); } + if (sort_keys != NULL) { + LDAPSortKey** sortp = sort_keys; + while (*sortp) { + efree(*sortp); + sortp++; + } + efree(sort_keys); + sort_keys = NULL; + } if (rc == LDAP_SUCCESS) { return LDAP_SUCCESS; diff --git a/ext/ldap/tests/ldap_search_sort_controls.phpt b/ext/ldap/tests/ldap_search_sort_controls.phpt new file mode 100644 index 0000000000000..a9781b6029706 --- /dev/null +++ b/ext/ldap/tests/ldap_search_sort_controls.phpt @@ -0,0 +1,117 @@ +--TEST-- +ldap_search() test with sort controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + +--FILE-- + LDAP_CONTROL_SORTREQUEST, + 'iscritical' => TRUE, + 'value' => [ + ['attr' => 'cn', 'oid' => '2.5.13.3' /* caseIgnoreOrderingMatch */, 'reverse' => TRUE] + ] + ] + ] + ), + ldap_get_entries($link, $result), + ldap_parse_result($link, $result, $errcode , $matcheddn , $errmsg , $referrals, $controls), + $errcode, + $errmsg, + $controls +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +array(4) { + ["count"]=> + int(3) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userC" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userC,cn=userB,%s" + } + [1]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userB" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userB,%s" + } + [2]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userA" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userA,%s" + } +} +bool(true) +int(0) +string(0) "" +array(1) { + ["1.2.840.113556.1.4.474"]=> + array(2) { + ["oid"]=> + string(22) "1.2.840.113556.1.4.474" + ["value"]=> + array(1) { + ["errcode"]=> + int(0) + } + } +} +===DONE=== From 9a4f3505ff53a6d8773cb988f636ad9b579fd3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 14 Sep 2017 15:50:05 +0200 Subject: [PATCH 31/31] Added support for VLV controls request and response --- ext/ldap/ldap.c | 87 ++++++++++++++++ ext/ldap/tests/ldap_search_sort_controls.phpt | 98 ++++++++++++++++++- 2 files changed, 181 insertions(+), 4 deletions(-) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index dbe68a3d61555..1b19e0599a25f 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -245,6 +245,27 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, } else { add_assoc_null(array, "value"); } + } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_VLVRESPONSE) == 0) { + int target, count, errcode, rc; + struct berval *context; + zval value; + + if (ctrl->ldctl_value.bv_len) { + rc = ldap_parse_vlvresponse_control(ld, ctrl, &target, &count, &context, &errcode); + } else { + rc = -1; + } + if ( rc == LDAP_SUCCESS ) { + array_init(&value); + add_assoc_long(&value, "target", target); + add_assoc_long(&value, "count", count); + add_assoc_long(&value, "errcode", errcode); + add_assoc_stringl(&value, "context", context->bv_val, context->bv_len); + add_assoc_zval(array, "value", &value); + } else { + add_assoc_null(array, "value"); + } + ber_bvfree(context); } else { if (ctrl->ldctl_value.bv_len) { add_assoc_stringl(array, "value", ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len); @@ -455,6 +476,72 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc); } } + } else if (strcmp(control_oid, LDAP_CONTROL_VLVREQUEST) == 0) { + zval* tmp; + LDAPVLVInfo vlvInfo; + struct berval attrValue; + struct berval context; + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "before", sizeof("before") - 1)) != NULL) { + convert_to_long_ex(tmp); + vlvInfo.ldvlv_before_count = Z_LVAL_P(tmp); + } else { + rc = -1; + php_error_docref(NULL, E_WARNING, "Before key missing from array value for VLV control"); + goto failure; + } + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "after", sizeof("after") - 1)) != NULL) { + convert_to_long_ex(tmp); + vlvInfo.ldvlv_after_count = Z_LVAL_P(tmp); + } else { + rc = -1; + php_error_docref(NULL, E_WARNING, "After key missing from array value for VLV control"); + goto failure; + } + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrvalue", sizeof("attrvalue") - 1)) != NULL) { + convert_to_string_ex(tmp); + attrValue.bv_val = Z_STRVAL_P(tmp); + attrValue.bv_len = Z_STRLEN_P(tmp); + vlvInfo.ldvlv_attrvalue = &attrValue; + } else if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "offset", sizeof("offset") - 1)) != NULL) { + vlvInfo.ldvlv_attrvalue = NULL; + convert_to_long_ex(tmp); + vlvInfo.ldvlv_offset = Z_LVAL_P(tmp); + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "count", sizeof("count") - 1)) != NULL) { + convert_to_long_ex(tmp); + vlvInfo.ldvlv_count = Z_LVAL_P(tmp); + } else { + rc = -1; + php_error_docref(NULL, E_WARNING, "Count key missing from array value for VLV control"); + goto failure; + } + } else { + rc = -1; + php_error_docref(NULL, E_WARNING, "Missing either attrvalue or offset key from array value for VLV control"); + goto failure; + } + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "context", sizeof("context") - 1)) != NULL) { + convert_to_string_ex(tmp); + context.bv_val = Z_STRVAL_P(tmp); + context.bv_len = Z_STRLEN_P(tmp); + vlvInfo.ldvlv_context = &context; + } else { + vlvInfo.ldvlv_context = NULL; + } + + control_value = ber_memalloc(sizeof * control_value); + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + rc = ldap_create_vlv_control_value(ld, &vlvInfo, control_value); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc); + } + } } else { php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", control_oid); rc = -1; diff --git a/ext/ldap/tests/ldap_search_sort_controls.phpt b/ext/ldap/tests/ldap_search_sort_controls.phpt index a9781b6029706..16504a6997507 100644 --- a/ext/ldap/tests/ldap_search_sort_controls.phpt +++ b/ext/ldap/tests/ldap_search_sort_controls.phpt @@ -1,5 +1,5 @@ --TEST-- -ldap_search() test with sort controls +ldap_search() test with sort and VLV controls --CREDITS-- Côme Chilliet --SKIPIF-- @@ -8,6 +8,7 @@ require_once('skipif.inc'); require_once('skipifbindfailure.inc'); require_once('skipifcontrol.inc'); skipifunsupportedcontrol(LDAP_CONTROL_SORTREQUEST); +skipifunsupportedcontrol(LDAP_CONTROL_VLVREQUEST); ?> --FILE-- LDAP_CONTROL_SORTREQUEST, @@ -36,6 +36,39 @@ var_dump( $errmsg, $controls ); + +/* Then with VLV control */ +var_dump( + $result = ldap_search($link, $base, '(cn=*)', array('cn'), 0, 0, 0, LDAP_DEREF_NEVER, + [ + [ + 'oid' => LDAP_CONTROL_SORTREQUEST, + 'iscritical' => TRUE, + 'value' => [ + ['attr' => 'cn', 'oid' => '2.5.13.3' /* caseIgnoreOrderingMatch */, 'reverse' => TRUE] + ] + ], + [ + 'oid' => LDAP_CONTROL_VLVREQUEST, + 'iscritical' => TRUE, + 'value' => [ + 'before' => 0, // Return 0 entry before target + 'after' => 1, // Return 1 entry after target + 'offset' => 2, // Target entry is the second one + 'count' => 0, // We have no idea how many entries there are + ] + ] + ] + ), + ldap_get_entries($link, $result), + ldap_parse_result($link, $result, $errcode , $matcheddn , $errmsg , $referrals, $controls), + array_keys($controls), + $controls[LDAP_CONTROL_SORTRESPONSE], + $controls[LDAP_CONTROL_VLVRESPONSE]['value']['target'], + $controls[LDAP_CONTROL_VLVRESPONSE]['value']['count'], + $controls[LDAP_CONTROL_VLVRESPONSE]['value']['errcode'], + bin2hex($controls[LDAP_CONTROL_VLVRESPONSE]['value']['context']) +); ?> ===DONE=== --CLEAN-- @@ -114,4 +147,61 @@ array(1) { } } } +resource(%d) of type (ldap result) +array(3) { + ["count"]=> + int(2) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userB" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userB,%s" + } + [1]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userA" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userA,%s" + } +} +bool(true) +array(2) { + [0]=> + string(22) "1.2.840.113556.1.4.474" + [1]=> + string(24) "2.16.840.1.113730.3.4.10" +} +array(2) { + ["oid"]=> + string(22) "1.2.840.113556.1.4.474" + ["value"]=> + array(1) { + ["errcode"]=> + int(0) + } +} +int(2) +int(3) +int(0) +string(%d) "%s" ===DONE===