Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ PHP 8.5 UPGRADE NOTES
1. Backward Incompatible Changes
========================================

- LDAP:
. ldap_get_option() and ldap_set_option() now throw a ValueError when
passing an invalid option.

- SPL:
. ArrayObject no longer accepts enums, as modifying the $name or $value
properties can break engine assumptions.
Expand Down
215 changes: 113 additions & 102 deletions ext/ldap/ldap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2101,7 +2101,6 @@ PHP_FUNCTION(ldap_explode_dn)
{
zend_long with_attrib;
char *dn, **ldap_value;
int i, count;
size_t dn_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "pl", &dn, &dn_len, &with_attrib) != SUCCESS) {
Expand All @@ -2113,16 +2112,12 @@ PHP_FUNCTION(ldap_explode_dn)
RETURN_FALSE;
}

i=0;
while (ldap_value[i] != NULL) i++;
count = i;

array_init(return_value);

add_assoc_long(return_value, "count", count);
for (i = 0; i<count; i++) {
int i;
for (i = 0; ldap_value[i] != NULL; i++) {
add_index_string(return_value, i, ldap_value[i]);
}
add_assoc_long(return_value, "count", i);

ldap_memvfree((void **)ldap_value);
}
Expand Down Expand Up @@ -3009,7 +3004,8 @@ PHP_FUNCTION(ldap_get_option)
case LDAP_OPT_API_FEATURE_INFO:
*/
default:
RETURN_FALSE;
zend_argument_value_error(2, "must be a valid LDAP option");
RETURN_THROWS();
}
RETURN_TRUE;
}
Expand Down Expand Up @@ -3063,14 +3059,18 @@ PHP_FUNCTION(ldap_set_option)
case LDAP_OPT_X_KEEPALIVE_INTERVAL:
#endif
{
int val;
bool failed = false;
zend_long lval = zval_try_get_long(newval, &failed);
if (failed) {
zend_argument_type_error(3, "must be of type int for the given option, %s given", zend_zval_value_name(newval));
RETURN_THROWS();
}

convert_to_long(newval);
if (ZEND_LONG_EXCEEDS_INT(Z_LVAL_P(newval))) {
if (ZEND_LONG_EXCEEDS_INT(lval)) {
zend_argument_value_error(3, "is too large");
RETURN_THROWS();
}
val = (int)Z_LVAL_P(newval);
int val = (int)lval;
if (ldap_set_option(ldap, option, &val)) {
RETURN_FALSE;
}
Expand All @@ -3079,9 +3079,13 @@ PHP_FUNCTION(ldap_set_option)
case LDAP_OPT_NETWORK_TIMEOUT:
{
struct timeval timeout;

convert_to_long(newval);
timeout.tv_sec = Z_LVAL_P(newval);
bool failed = false;
zend_long lval = zval_try_get_long(newval, &failed);
if (failed) {
zend_argument_type_error(3, "must be of type int for the LDAP_OPT_NETWORK_TIMEOUT option, %s given", zend_zval_value_name(newval));
RETURN_THROWS();
}
timeout.tv_sec = lval;
timeout.tv_usec = 0;
if (ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
RETURN_FALSE;
Expand All @@ -3091,9 +3095,13 @@ PHP_FUNCTION(ldap_set_option)
case LDAP_X_OPT_CONNECT_TIMEOUT:
{
int timeout;

convert_to_long(newval);
timeout = 1000 * Z_LVAL_P(newval); /* Convert to milliseconds */
bool failed = false;
zend_long lval = zval_try_get_long(newval, &failed);
if (failed) {
zend_argument_type_error(3, "must be of type int for the LDAP_X_OPT_CONNECT_TIMEOUT option, %s given", zend_zval_value_name(newval));
RETURN_THROWS();
}
timeout = 1000 * lval; /* Convert to milliseconds */
if (ldap_set_option(ldap, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
RETURN_FALSE;
}
Expand All @@ -3104,8 +3112,13 @@ PHP_FUNCTION(ldap_set_option)
{
struct timeval timeout;

convert_to_long(newval);
timeout.tv_sec = Z_LVAL_P(newval);
bool failed = false;
zend_long lval = zval_try_get_long(newval, &failed);
if (failed) {
zend_argument_type_error(3, "must be of type int for the LDAP_OPT_TIMEOUT option, %s given", zend_zval_value_name(newval));
RETURN_THROWS();
}
timeout.tv_sec = lval;
timeout.tv_usec = 0;
if (ldap_set_option(ldap, LDAP_OPT_TIMEOUT, (void *) &timeout)) {
RETURN_FALSE;
Expand Down Expand Up @@ -3141,9 +3154,8 @@ PHP_FUNCTION(ldap_set_option)
case LDAP_OPT_MATCHED_DN:
#endif
{
zend_string *val;
val = zval_get_string(newval);
if (EG(exception)) {
zend_string *val = zval_try_get_string(newval);
if (val == NULL) {
RETURN_THROWS();
}
if (ldap_set_option(ldap, option, ZSTR_VAL(val))) {
Expand All @@ -3161,8 +3173,7 @@ PHP_FUNCTION(ldap_set_option)
case LDAP_OPT_X_SASL_NOCANON:
#endif
{
void *val;
val = zend_is_true(newval) ? LDAP_OPT_ON : LDAP_OPT_OFF;
void *val = zend_is_true(newval) ? LDAP_OPT_ON : LDAP_OPT_OFF;
if (ldap_set_option(ldap, option, val)) {
RETURN_FALSE;
}
Expand Down Expand Up @@ -3192,7 +3203,8 @@ PHP_FUNCTION(ldap_set_option)
}
} break;
default:
RETURN_FALSE;
zend_argument_value_error(2, "must be a valid LDAP option");
RETURN_THROWS();
}
RETURN_TRUE;
}
Expand All @@ -3202,15 +3214,15 @@ PHP_FUNCTION(ldap_set_option)
/* {{{ Extract information from result */
PHP_FUNCTION(ldap_parse_result)
{
zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals, *serverctrls;
zval *link, *result, *errcode, *matcheddn = NULL, *errmsg = NULL, *referrals = NULL, *serverctrls = NULL;
ldap_linkdata *ld;
ldap_resultdata *ldap_result;
LDAPControl **lserverctrls = NULL;
char **lreferrals, **refp;
char *lmatcheddn, *lerrmsg;
int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
int rc, lerrcode;

if (zend_parse_parameters(myargcount, "OOz|zzzz", &link, ldap_link_ce, &result, ldap_result_ce, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOz|zzzz", &link, ldap_link_ce, &result, ldap_result_ce, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) {
RETURN_THROWS();
}

Expand All @@ -3221,10 +3233,10 @@ PHP_FUNCTION(ldap_parse_result)
VERIFY_LDAP_RESULT_OPEN(ldap_result);

rc = ldap_parse_result(ld->link, ldap_result->result, &lerrcode,
myargcount > 3 ? &lmatcheddn : NULL,
myargcount > 4 ? &lerrmsg : NULL,
myargcount > 5 ? &lreferrals : NULL,
myargcount > 6 ? &lserverctrls : NULL,
matcheddn ? &lmatcheddn : NULL,
errmsg ? &lerrmsg : NULL,
referrals ? &lreferrals : NULL,
serverctrls ? &lserverctrls : NULL,
0);
if (rc != LDAP_SUCCESS) {
php_error_docref(NULL, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
Expand All @@ -3233,41 +3245,40 @@ PHP_FUNCTION(ldap_parse_result)

ZEND_TRY_ASSIGN_REF_LONG(errcode, lerrcode);

/* Reverse -> fall through */
switch (myargcount) {
case 7:
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
ZEND_FALLTHROUGH;
case 6:
referrals = zend_try_array_init(referrals);
if (!referrals) {
RETURN_THROWS();
}
if (lreferrals != NULL) {
refp = lreferrals;
while (*refp) {
add_next_index_string(referrals, *refp);
refp++;
}
ldap_memvfree((void**)lreferrals);
}
ZEND_FALLTHROUGH;
case 5:
if (lerrmsg == NULL) {
ZEND_TRY_ASSIGN_REF_EMPTY_STRING(errmsg);
} else {
ZEND_TRY_ASSIGN_REF_STRING(errmsg, lerrmsg);
ldap_memfree(lerrmsg);
}
ZEND_FALLTHROUGH;
case 4:
if (lmatcheddn == NULL) {
ZEND_TRY_ASSIGN_REF_EMPTY_STRING(matcheddn);
} else {
ZEND_TRY_ASSIGN_REF_STRING(matcheddn, lmatcheddn);
ldap_memfree(lmatcheddn);
if (serverctrls) {
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
}
if (referrals) {
referrals = zend_try_array_init(referrals);
if (!referrals) {
RETURN_THROWS();
}
if (lreferrals != NULL) {
refp = lreferrals;
while (*refp) {
add_next_index_string(referrals, *refp);
refp++;
}
ldap_memvfree((void**)lreferrals);
}
}
if (errmsg) {
if (lerrmsg == NULL) {
ZEND_TRY_ASSIGN_REF_EMPTY_STRING(errmsg);
} else {
ZEND_TRY_ASSIGN_REF_STRING(errmsg, lerrmsg);
ldap_memfree(lerrmsg);
}
}
if (matcheddn) {
if (lmatcheddn == NULL) {
ZEND_TRY_ASSIGN_REF_EMPTY_STRING(matcheddn);
} else {
ZEND_TRY_ASSIGN_REF_STRING(matcheddn, lmatcheddn);
ldap_memfree(lmatcheddn);
}
}

RETURN_TRUE;
}
/* }}} */
Expand All @@ -3278,14 +3289,14 @@ PHP_FUNCTION(ldap_parse_result)
/* {{{ Extract information from extended operation result */
PHP_FUNCTION(ldap_parse_exop)
{
zval *link, *result, *retdata, *retoid;
zval *link, *result, *retdata = NULL, *retoid = NULL;
ldap_linkdata *ld;
ldap_resultdata *ldap_result;
char *lretoid;
struct berval *lretdata;
int rc, myargcount = ZEND_NUM_ARGS();
int rc;

if (zend_parse_parameters(myargcount, "OO|zz", &link, ldap_link_ce, &result, ldap_result_ce, &retdata, &retoid) != SUCCESS) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO|zz", &link, ldap_link_ce, &result, ldap_result_ce, &retdata, &retoid) != SUCCESS) {
RETURN_THROWS();
}

Expand All @@ -3296,34 +3307,34 @@ PHP_FUNCTION(ldap_parse_exop)
VERIFY_LDAP_RESULT_OPEN(ldap_result);

rc = ldap_parse_extended_result(ld->link, ldap_result->result,
myargcount > 3 ? &lretoid: NULL,
myargcount > 2 ? &lretdata: NULL,
retoid ? &lretoid: NULL,
retdata ? &lretdata: NULL,
0);
if (rc != LDAP_SUCCESS) {
php_error_docref(NULL, E_WARNING, "Unable to parse extended operation result: %s", ldap_err2string(rc));
RETURN_FALSE;
}

/* Reverse -> fall through */
switch (myargcount) {
case 4:
if (lretoid == NULL) {
ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retoid);
} else {
ZEND_TRY_ASSIGN_REF_STRING(retoid, lretoid);
ldap_memfree(lretoid);
}
ZEND_FALLTHROUGH;
case 3:
/* use arg #3 as the data returned by the server */
if (lretdata == NULL) {
ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retdata);
} else {
ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
ldap_memfree(lretdata->bv_val);
ldap_memfree(lretdata);
}
if (retoid) {
if (lretoid == NULL) {
ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retoid);
} else {
ZEND_TRY_ASSIGN_REF_STRING(retoid, lretoid);
ldap_memfree(lretoid);
}
}

if (retdata) {
/* use arg #3 as the data returned by the server */
if (lretdata == NULL) {
ZEND_TRY_ASSIGN_REF_EMPTY_STRING(retdata);
} else {
ZEND_TRY_ASSIGN_REF_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
ldap_memfree(lretdata->bv_val);
ldap_memfree(lretdata);
}
}

RETURN_TRUE;
}
/* }}} */
Expand Down Expand Up @@ -3907,30 +3918,30 @@ PHP_FUNCTION(ldap_exop_sync)
/* {{{ Passwd modify extended operation */
PHP_FUNCTION(ldap_exop_passwd)
{
zval *link, *serverctrls;
zval *link, *serverctrls = NULL;
struct berval luser = { 0L, NULL };
struct berval loldpw = { 0L, NULL };
struct berval lnewpw = { 0L, NULL };
struct berval lgenpasswd = { 0L, NULL };
LDAPControl *ctrl, **lserverctrls = NULL, *requestctrls[2] = { NULL, NULL };
LDAPMessage* ldap_res = NULL;
ldap_linkdata *ld;
int rc, myargcount = ZEND_NUM_ARGS(), msgid, err;
int rc, msgid, err;
char* errmsg = NULL;

if (zend_parse_parameters(myargcount, "O|sssz/", &link, ldap_link_ce, &luser.bv_val, &luser.bv_len, &loldpw.bv_val, &loldpw.bv_len, &lnewpw.bv_val, &lnewpw.bv_len, &serverctrls) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|sssz/", &link, ldap_link_ce, &luser.bv_val, &luser.bv_len, &loldpw.bv_val, &loldpw.bv_len, &lnewpw.bv_val, &lnewpw.bv_len, &serverctrls) == FAILURE) {
RETURN_THROWS();
}

ld = Z_LDAP_LINK_P(link);
VERIFY_LDAP_LINK_CONNECTED(ld);

switch (myargcount) {
case 5:
/* ldap_create_passwordpolicy_control() allocates ctrl */
if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) {
requestctrls[0] = ctrl;
}
if (serverctrls) {
/* ldap_create_passwordpolicy_control() allocates ctrl */
if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) {
requestctrls[0] = ctrl;
}
// TODO Should this warn?
}

/* asynchronous call to get result and controls */
Expand Down Expand Up @@ -3965,14 +3976,14 @@ PHP_FUNCTION(ldap_exop_passwd)
goto cleanup;
}

rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 0);
rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (serverctrls ? &lserverctrls : NULL), 0);
if( rc != LDAP_SUCCESS ) {
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
RETVAL_FALSE;
goto cleanup;
}

if (myargcount > 4) {
if (serverctrls) {
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
}

Expand Down
Loading