Index: ext/ldap/ldap.c =================================================================== RCS file: /repository/php-src/ext/ldap/ldap.c,v retrieving revision 1.162 diff -u -r1.162 ldap.c --- ext/ldap/ldap.c 22 Aug 2005 12:22:08 -0000 1.162 +++ ext/ldap/ldap.c 10 Nov 2005 17:25:16 -0000 @@ -80,13 +80,22 @@ ZEND_DECLARE_MODULE_GLOBALS(ldap) static - ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0) + ZEND_BEGIN_ARG_INFO(arg3to4of4_force_ref, 0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(0) + ZEND_ARG_PASS_INFO(1) + ZEND_ARG_PASS_INFO(1) + ZEND_END_ARG_INFO(); + +static + ZEND_BEGIN_ARG_INFO(arg3to7of7_force_ref, 0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(1) ZEND_ARG_PASS_INFO(1) ZEND_ARG_PASS_INFO(1) ZEND_ARG_PASS_INFO(1) + ZEND_ARG_PASS_INFO(1) ZEND_END_ARG_INFO(); static int le_link, le_result, le_result_entry, le_ber_entry; @@ -144,10 +153,10 @@ PHP_FE(ldap_first_reference, NULL) PHP_FE(ldap_next_reference, NULL) #ifdef HAVE_LDAP_PARSE_REFERENCE - PHP_FE(ldap_parse_reference, third_arg_force_ref) + PHP_FE(ldap_parse_reference, arg3to4of4_force_ref) #endif #ifdef HAVE_LDAP_PARSE_RESULT - PHP_FE(ldap_parse_result, arg3to6of6_force_ref) + PHP_FE(ldap_parse_result, arg3to7of7_force_ref) #endif #ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, NULL) @@ -191,7 +211,9 @@ { ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr; - ldap_unbind_s(ld->link); + /* ldap_unbind_s() is deprecated; + * the distinction between ldap_unbind() and ldap_unbind_s() is moot */ + ldap_unbind_ext(ld->link, NULL, NULL); #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) if (ld->rebindproc != NULL) { zval_dtor(ld->rebindproc); @@ -215,6 +237,103 @@ efree(entry); } +static int _parse_referrals_resp(char ***lreferralsp, zval **referrals) +{ + int num_referrals = 0; + + if (*lreferralsp != NULL) { + char **refp = *lreferralsp; + + while (*refp) { + add_next_index_string(*referrals, *refp, 1); + refp++; + num_referrals++; + } +#ifdef LDAP_API_FEATURE_X_OPENLDAP + ber_memvfree((void **)*lreferralsp); +#else + ldap_value_free(*lreferralsp); +#endif + *lreferralsp = NULL; + } + +#if ando_0 + /* It has been suggested by Jani Taskinen to avoid the "count" entry; + * it was added for consistency with entry data, where attributes and + * attribute values have one. + */ + add_assoc_long(*referrals, "count", num_referrals); +#endif + + return num_referrals; +} + +static int _parse_server_controls_resp(LDAPControl ***lserverctrlsp, zval **serverctrls) +{ + int num_serverctrls = 0; + + if (*lserverctrlsp != NULL) { + int error = 0; + LDAPControl **ctrlp = *lserverctrlsp; + + while (*ctrlp) { + zval *ctrlval = NULL; + + if ( (*ctrlp)->ldctl_oid == NULL ) { + error = 1; + break; + } + + MAKE_STD_ZVAL(ctrlval); + array_init(ctrlval); + + add_assoc_string(ctrlval, "oid", (*ctrlp)->ldctl_oid, 1); + if ( (*ctrlp)->ldctl_value.bv_len ) { + add_assoc_stringl(ctrlval, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len, 1); + } +#if ando_0 + /* As per : + * + * 4.1.11 + + The criticality field only has meaning in controls attached to + request messages (except UnbindRequest). For controls attached to + response messages and the UnbindRequest, the criticality field SHOULD + be FALSE, and MUST be ignored by the receiving protocol peer. + + */ + if ((*ctrlp)->ldctl_iscritical) { + add_assoc_bool(ctrlval, "iscritical", (*ctrlp)->ldctl_iscritical); + } +#endif + + add_next_index_zval(*serverctrls, ctrlval); + + num_serverctrls++; + ctrlp++; + } + ldap_controls_free(*lserverctrlsp); + *lserverctrlsp = NULL; + + if (error) { + /* ... */ + return -1; + } + } + +#if ando_0 + /* It has been suggested by Jani Taskinen to avoid the "count" entry; + * it was added for consistency with entry data, where attributes and + * attribute values have one. + */ + if (num_serverctrls != -1) { + add_assoc_long(*serverctrls, "count", num_serverctrls); + } +#endif + + return num_serverctrls; +} + /* {{{ PHP_INI_BEGIN */ PHP_INI_BEGIN() @@ -370,7 +489,11 @@ { char *host = NULL; int hostlen; +#ifdef LDAP_API_FEATURE_X_OPENLDAP + long port = LDAP_PORT; +#else long port = 389; /* Default port */ +#endif #ifdef HAVE_ORALDAP char *wallet, *walletpasswd; int walletlen, walletpasswdlen; @@ -406,17 +529,33 @@ ld = ecalloc(1, sizeof(ldap_linkdata)); #ifdef LDAP_API_FEATURE_X_OPENLDAP - if (host != NULL && strchr(host, '/')) { - int rc; + /* OpenLDAP provides a specific call to detect valid LDAP URIs */ + { + int rc; + char *url = host; + + if (!ldap_is_ldap_url(url)) { + int urllen = hostlen + sizeof( "ldap://:65535" ); + + if (port < 0 || port > 65535) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid port number: %ld", port); + RETURN_FALSE; + } + + url = emalloc(urllen); + snprintf( url, urllen, "ldap://%s:%ld", host ? host : "", port ? port : LDAP_PORT ); + } - rc = ldap_initialize(&ldap, host); + rc = ldap_initialize(&ldap, url); if (rc != LDAP_SUCCESS) { efree(ld); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc)); RETURN_FALSE; } - } else { - ldap = ldap_init(host, port); + + if (url != host) { + efree(url); + } } #else ldap = ldap_open(host, port); @@ -479,7 +618,21 @@ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); - if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) { +#ifdef LDAP_API_FEATURE_X_OPENLDAP + { + struct berval cred; + + /* ldap_bind_s() is deprecated; use ldap_sasl_bind_s() instead */ + cred.bv_val = ldap_bind_pw; + cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; + rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, + NULL, NULL, /* no controls right now */ + NULL); /* we don't care about the server's credentials */ + } +#else + rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE); +#endif + if ( rc != LDAP_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); RETURN_FALSE; } else { @@ -1363,7 +1518,11 @@ add_index_string(return_value, i, ldap_value[i], 1); } +#ifdef LDAP_API_FEATURE_X_OPENLDAP + ber_memvfree((void **)ldap_value); +#else ldap_value_free(ldap_value); +#endif } /* }}} */ @@ -1933,14 +2092,15 @@ Extract information from result */ PHP_FUNCTION(ldap_parse_result) { - zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals; + zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals, **serverctrls; ldap_linkdata *ld; LDAPMessage *ldap_result; - char **lreferrals, **refp; + LDAPControl **lserverctrls; + char **lreferrals; char *lmatcheddn, *lerrmsg; int rc, lerrcode, myargcount = ZEND_NUM_ARGS(); - if (myargcount < 3 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals) == FAILURE) { + if (myargcount < 3 || myargcount > 7 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) == FAILURE) { WRONG_PARAM_COUNT; } @@ -1951,7 +2111,7 @@ myargcount > 3 ? &lmatcheddn : NULL, myargcount > 4 ? &lerrmsg : NULL, myargcount > 5 ? &lreferrals : NULL, - NULL /* &serverctrls */, + myargcount > 6 ? &lserverctrls : NULL, 0); if (rc != LDAP_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc)); @@ -1963,17 +2123,15 @@ /* Reverse -> fall through */ switch (myargcount) { + case 7: + /* use arg #7 as the array of controls returned by the server */ + zval_dtor(*serverctrls); + array_init(*serverctrls); + _parse_server_controls_resp(&lserverctrls, serverctrls); case 6: zval_dtor(*referrals); array_init(*referrals); - if (lreferrals != NULL) { - refp = lreferrals; - while (*refp) { - add_next_index_string(*referrals, *refp, 1); - refp++; - } - ldap_value_free(lreferrals); - } + _parse_referrals_resp(&lreferrals, referrals); case 5: zval_dtor(*errmsg); if (lerrmsg == NULL) { @@ -2057,32 +2215,38 @@ Extract information from reference entry */ PHP_FUNCTION(ldap_parse_reference) { - zval **link, **result_entry, **referrals; + zval **link, **result_entry, **referrals, **serverctrls; ldap_linkdata *ld; ldap_resultentry *resultentry; - char **lreferrals, **refp; + char **lreferrals; + LDAPControl **lserverctrls; + int myargcount = ZEND_NUM_ARGS(); - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &referrals) == FAILURE) { + if (myargcount < 3 || myargcount > 4 || zend_get_parameters_ex(4, &link, &result_entry, &referrals, &serverctrls) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry); - if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) { + if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, &lserverctrls, 0) != LDAP_SUCCESS) { RETURN_FALSE; } - zval_dtor(*referrals); - array_init(*referrals); - if (lreferrals != NULL) { - refp = lreferrals; - while (*refp) { - add_next_index_string(*referrals, *refp, 1); - refp++; - } - ldap_value_free(lreferrals); + + /* Reverse -> fall through */ + switch (myargcount) { + case 4: + /* use arg #4 as the array of controls returned by the server */ + zval_dtor(*serverctrls); + array_init(*serverctrls); + _parse_server_controls_resp(&lserverctrls, serverctrls); + case 3: + zval_dtor(*referrals); + array_init(*referrals); + _parse_referrals_resp(&lreferrals, referrals); } + RETURN_TRUE; } /* }}} */