Skip to content

Commit

Permalink
MFH: Fixing #48441 (ldap_search() with sizelimit/timelimit/deref opti…
Browse files Browse the repository at this point in the history
…ons makes those options persistent)
  • Loading branch information
patrickallaert committed Jun 15, 2009
1 parent 08c7d57 commit 13594f8
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 3 deletions.
17 changes: 14 additions & 3 deletions ext/ldap/ldap.c
Expand Up @@ -641,31 +641,37 @@ PHP_FUNCTION(ldap_unbind)

/* {{{ php_set_opts
*/
static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref)
static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, int *old_sizelimit, int *old_timelimit, int *old_deref)
{
/* sizelimit */
if (sizelimit > -1) {
#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_sizelimit);
ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit);
#else
*old_sizelimit = ldap->ld_sizelimit;
ldap->ld_sizelimit = sizelimit;
#endif
}

/* timelimit */
if (timelimit > -1) {
#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_timelimit);
ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit);
#else
*old_timelimit = ldap->ld_timelimit;
ldap->ld_timelimit = timelimit;
#endif
}

/* deref */
if (deref > -1) {
#if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_deref);
ldap_set_option(ldap, LDAP_OPT_DEREF, &deref);
#else
*old_deref = ldap->ld_deref;
ldap->ld_deref = deref;
#endif
}
Expand All @@ -686,6 +692,9 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
int ldap_sizelimit = -1;
int ldap_timelimit = -1;
int ldap_deref = -1;
int old_ldap_sizelimit = -1;
int old_ldap_timelimit = -1;
int old_ldap_deref = -1;
int num_attribs = 0;
int i, errno;
int myargcount = ZEND_NUM_ARGS();
Expand Down Expand Up @@ -820,7 +829,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
ldap_filter = Z_STRVAL_PP(entry);
}

php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref);
php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);

/* Run the actual search */
rcs[i] = ldap_search(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly);
Expand Down Expand Up @@ -862,7 +871,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
goto cleanup;
}

php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref);
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_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, &ldap_res);
Expand Down Expand Up @@ -893,6 +902,8 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
}

cleanup:
// Restoring previous options
php_set_opts(ld->link, old_ldap_sizelimit, old_ldap_timelimit, old_ldap_deref, &ldap_sizelimit, &ldap_timelimit, &ldap_deref);
if (ldap_attrs != NULL) {
efree(ldap_attrs);
}
Expand Down
169 changes: 169 additions & 0 deletions ext/ldap/tests/bug48441.phpt
@@ -0,0 +1,169 @@
--TEST--
ldap_search() bug 48441 - options persists after specifying them in ldap_search
--CREDITS--
Patrick Allaert <patrickallaert@php.net>
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifbindfailure.inc');
?>
--FILE--
<?php
include "connect.inc";

$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
insert_dummy_data($link);

$dn = "dc=my-domain,dc=com";
$filter = "(objectclass=person)";

var_dump(
$result = ldap_search($link, $dn, $filter, array('sn')),
ldap_get_entries($link, $result)
);
var_dump(
$result = ldap_search($link, $dn, $filter, array('sn'), 1, 1, 1, LDAP_DEREF_ALWAYS),
ldap_get_entries($link, $result)
);
var_dump(
$result = ldap_search($link, $dn, $filter, array('sn')),
ldap_get_entries($link, $result)
);
?>
===DONE===
--CLEAN--
<?php
include "connect.inc";

$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
remove_dummy_data($link);
?>
--EXPECTF--
resource(%d) of type (ldap result)
array(4) {
["count"]=>
int(3)
[0]=>
array(4) {
["sn"]=>
array(2) {
["count"]=>
int(1)
[0]=>
string(7) "testSN1"
}
[0]=>
string(2) "sn"
["count"]=>
int(1)
["dn"]=>
string(28) "cn=userA,dc=my-domain,dc=com"
}
[1]=>
array(4) {
["sn"]=>
array(2) {
["count"]=>
int(1)
[0]=>
string(7) "testSN2"
}
[0]=>
string(2) "sn"
["count"]=>
int(1)
["dn"]=>
string(28) "cn=userB,dc=my-domain,dc=com"
}
[2]=>
array(4) {
["sn"]=>
array(2) {
["count"]=>
int(1)
[0]=>
string(7) "testSN3"
}
[0]=>
string(2) "sn"
["count"]=>
int(1)
["dn"]=>
string(37) "cn=userC,cn=userB,dc=my-domain,dc=com"
}
}

Warning: ldap_search(): Partial search results returned: Sizelimit exceeded in %s on line %d
resource(%d) of type (ldap result)
array(2) {
["count"]=>
int(1)
[0]=>
array(4) {
["sn"]=>
array(1) {
["count"]=>
int(0)
}
[0]=>
string(2) "sn"
["count"]=>
int(1)
["dn"]=>
string(28) "cn=userA,dc=my-domain,dc=com"
}
}
resource(%d) of type (ldap result)
array(4) {
["count"]=>
int(3)
[0]=>
array(4) {
["sn"]=>
array(2) {
["count"]=>
int(1)
[0]=>
string(7) "testSN1"
}
[0]=>
string(2) "sn"
["count"]=>
int(1)
["dn"]=>
string(28) "cn=userA,dc=my-domain,dc=com"
}
[1]=>
array(4) {
["sn"]=>
array(2) {
["count"]=>
int(1)
[0]=>
string(7) "testSN2"
}
[0]=>
string(2) "sn"
["count"]=>
int(1)
["dn"]=>
string(28) "cn=userB,dc=my-domain,dc=com"
}
[2]=>
array(4) {
["sn"]=>
array(2) {
["count"]=>
int(1)
[0]=>
string(7) "testSN3"
}
[0]=>
string(2) "sn"
["count"]=>
int(1)
["dn"]=>
string(37) "cn=userC,cn=userB,dc=my-domain,dc=com"
}
}
===DONE===
61 changes: 61 additions & 0 deletions ext/ldap/tests/connect.inc
@@ -0,0 +1,61 @@
<?php

/*
Default values are "localhost", "root", database "test" and empty password.
Change the LDAP_TEST_* environment values if you want to use another configuration.
*/

$host = getenv("LDAP_TEST_HOST") ? getenv("LDAP_TEST_HOST") : "localhost";
$port = getenv("LDAP_TEST_PORT") ? getenv("LDAP_TEST_PORT") : 389;
$user = getenv("LDAP_TEST_USER") ? getenv("LDAP_TEST_USER") : "cn=Manager,dc=my-domain,dc=com";
$sasl_user = getenv("LDAP_TEST_SASL_USER") ? getenv("LDAP_TEST_SASL_USER") : "Manager";
$passwd = getenv("LDAP_TEST_PASSWD") ? getenv("LDAP_TEST_PASSWD") : "secret";
$protocol_version = getenv("LDAP_TEST_OPT_PROTOCOL_VERSION") ? getenv("LDAP_TEST_OPT_PROTOCOL_VERSION") : 3;
$skip_on_bind_failure = getenv("LDAP_TEST_SKIP_BIND_FAILURE") ? getenv("LDAP_TEST_SKIP_BIND_FAILURE") : true;

function ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version) {
$link = ldap_connect($host, $port);
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, $protocol_version);
ldap_bind($link, $user, $passwd);
return $link;
}

function insert_dummy_data($link) {
ldap_add($link, "dc=my-domain,dc=com", array(
"objectClass" => array(
"top",
"dcObject",
"organization"),
"dc" => "my-domain",
"o" => "my-domain",
));
ldap_add($link, "cn=userA,dc=my-domain,dc=com", array(
"objectclass" => "person",
"cn" => "userA",
"sn" => "testSN1",
"userPassword" => "oops",
"telephoneNumber" => "xx-xx-xx-xx-xx",
"description" => "user A",
));
ldap_add($link, "cn=userB,dc=my-domain,dc=com", array(
"objectclass" => "person",
"cn" => "userB",
"sn" => "testSN2",
"userPassword" => "oopsIDitItAgain",
"description" => "user B",
));
ldap_add($link, "cn=userC,cn=userB,dc=my-domain,dc=com", array(
"objectclass" => "person",
"cn" => "userC",
"sn" => "testSN3",
"userPassword" => "0r1g1na1 passw0rd",
));
}

function remove_dummy_data($link) {
ldap_delete($link, "cn=userC,cn=userB,dc=my-domain,dc=com");
ldap_delete($link, "cn=userA,dc=my-domain,dc=com");
ldap_delete($link, "cn=userB,dc=my-domain,dc=com");
ldap_delete($link, "dc=my-domain,dc=com");
}
?>
13 changes: 13 additions & 0 deletions ext/ldap/tests/skipifbindfailure.inc
@@ -0,0 +1,13 @@
<?php
require_once 'connect.inc';

if ($skip_on_bind_failure) {

$link = ldap_connect($host, $port);
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, $protocol_version);
if (!@ldap_bind($link, $user, $passwd))
die(sprintf("skip Can't bind to LDAP Server - [%d] %s", ldap_errno($link), ldap_error($link)));

ldap_unbind($link);
}
?>

0 comments on commit 13594f8

Please sign in to comment.