You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by mi...@apache.org on 2025/03/11 13:27:43 UTC
svn commit: r1924295 [3/3] - in /apr/apr/trunk: ./ build/ include/ include/private/ ldap/ misc/unix/ test/
Modified: apr/apr/trunk/test/testldap.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/test/testldap.c?rev=1924295&r1=1924294&r2=1924295&view=diff
==============================================================================
--- apr/apr/trunk/test/testldap.c (original)
+++ apr/apr/trunk/test/testldap.c Tue Mar 11 13:27:42 2025
@@ -210,70 +210,470 @@ typedef struct test_ldap_connection_t {
apr_pollfd_t socket_write;
apu_err_t err;
int must_bind;
+ const char *context;
+ const char *dn;
+ const char *rdn;
+ const char *newdn;
} test_ldap_connection_t;
+static apr_status_t test_ldap_vlv_result_cb(apr_ldap_t *ldap,
+ apr_status_t status,
+ apr_size_t nentries,
+ const char *matcheddn,
+ apr_hash_t *serverctrls,
+ void *ctx, apu_err_t *err)
+{
+ char errbuf[128];
+
+ apr_ldap_control_t *sort = apr_hash_get(serverctrls, APR_LDAP_CONTROL_SORT_RESPONSE_OID, APR_HASH_KEY_STRING);
+ apr_ldap_control_t *vlv = apr_hash_get(serverctrls, APR_LDAP_CONTROL_VLV_RESPONSE_OID, APR_HASH_KEY_STRING);
+
+ /*
+ * Step 30: vlv search result callback triggered, result is complete.
+ */
+
+ abts_log_message("vlv search matcheddn: \n", matcheddn);
+
+ if (sort) {
+ abts_log_message("apr_ldap_search() sort control response: %s\n", apr_strerror(sort->c.sortrs.result, errbuf, sizeof(errbuf)));
+ }
+
+ if (vlv) {
+ abts_log_message("apr_ldap_search() vlv control response: %s\n", apr_strerror(sort->c.vlvrs.result, errbuf, sizeof(errbuf)));
+ }
+
+ if (APR_SUCCESS == status) {
+ /* success */
+ }
+ if (APR_STATUS_IS_OPERATIONS_ERROR(status)) {
+ abts_log_message("apr_ldap_search() failed, most likely because the LDAP server does not have a VLV index configured: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+ else {
+ abts_log_message("apr_ldap_search() failed: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ return status;
+}
+
+static apr_status_t test_ldap_vlv_entry_cb(apr_ldap_t *ldap,
+ const char *dn,
+ apr_size_t eidx,
+ apr_ldap_search_entry_t *entry,
+ void *ctx, apu_err_t *err)
+{
+ test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
+
+ /*
+ * Step 29: search vlv entry callback triggered, start processing results.
+ */
+
+ if (entry && !entry->aidx && !entry->vidx) {
+ /* first attribute and first value and attr present? output dn */
+ abts_log_message("dn: %s", dn);
+ }
+
+ if (entry) {
+ abts_log_message("%s: %s", entry->attr, apr_buffer_pstrdup(test->pool, &entry->val));
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t test_ldap_delete_cb(apr_ldap_t *ldap,
+ apr_status_t status,
+ const char *matcheddn,
+ apr_ldap_control_t **serverctrls,
+ void *ctx, apu_err_t *err)
+{
+ char errbuf[128];
+ test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
+
+ /*
+ * Step 27: delete result callback triggered, next is vlv search.
+ */
+
+ abts_log_message("delete matcheddn: \n", matcheddn);
+
+ if (APR_SUCCESS == status) {
+
+ /*
+ * Step 28: we're writable, trigger a vlv search, then wait for readable.
+ */
+ apr_array_header_t *scontrols = apr_array_make(test->pool, 2, sizeof(apr_ldap_control_t));
+ apr_ldap_control_t *sort = apr_array_push(scontrols);
+ apr_ldap_control_t *vlv = apr_array_push(scontrols);
+ apr_ldap_control_sortkey_t *sortkey;
+
+ /* make a sort control */
+ sort->type = APR_LDAP_CONTROL_SORT_REQUEST;
+ sort->critical = 1;
+ sort->c.sortrq.keys = apr_array_make(test->pool, 1, sizeof(apr_ldap_control_sortkey_t));
+
+ /* sort by ou */
+ sortkey = apr_array_push(sort->c.sortrq.keys);
+ sortkey->attribute = "ou";
+ sortkey->order = "caseIgnoreOrderingMatch";
+ sortkey->direction = APR_LDAP_CONTROL_SORT_FORWARD;
+
+ /* make a vlv control */
+ vlv->type = APR_LDAP_CONTROL_VLV_REQUEST;
+ vlv->c.vlvrq.before = 1; /* we want the one before the second entry */
+ vlv->c.vlvrq.after = 1; /* we want one after the second entry */
+ vlv->c.vlvrq.offset = 2; /* we want the second entry */
+
+ status = apr_ldap_search(test->pool, test->ldap, test->context /* base dn */,
+ APR_LDAP_SCOPE_ONELEVEL, "(objectclass=*)" /* filter */,
+ NULL /* attrs */, APR_LDAP_OPT_ON /* attrsonly */,
+ scontrols /* serverctls */, NULL /* clientctls */,
+ apr_time_from_sec(5) /* timelimit */, 0 /* sizelimit */,
+ test_ldap_vlv_result_cb, test_ldap_vlv_entry_cb, test, &test->err);
+
+ ABTS_INT_EQUAL(test->tc, APR_WANT_READ, status);
+
+ switch (status) {
+ case APR_SUCCESS:
+ case APR_WANT_READ:
+ case APR_WANT_WRITE:
+ break;
+ default:
+ abts_log_message("apr_ldap_result: %s [%s]\n", test->err.reason,
+ apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ }
+ else {
+ abts_log_message("apr_ldap_delete() failed: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ ABTS_INT_EQUAL(test->tc, APR_SUCCESS, status);
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t test_ldap_rename_cb(apr_ldap_t *ldap,
+ apr_status_t status,
+ const char *matcheddn,
+ apr_ldap_control_t **serverctrls,
+ void *ctx, apu_err_t *err)
+{
+ char errbuf[128];
+ test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
+
+ /*
+ * Step 24: rename result callback triggered.
+ */
+
+ abts_log_message("rename matcheddn: \n", matcheddn);
+
+ if (APR_SUCCESS == status || APR_ALREADY_EXISTS == status) {
+
+ /*
+ * Step 25: success or object already exists, it is time to trigger the delete.
+ */
+
+ status = apr_ldap_delete(test->pool, test->ldap, test->newdn /* dn to delete */,
+ NULL /* serverctls */, NULL /* clientctls */,
+ apr_time_from_sec(5) /* timeout */,
+ test_ldap_delete_cb, test, &test->err);
+
+ ABTS_INT_EQUAL(test->tc, APR_WANT_READ, status);
+
+ switch (status) {
+ case APR_SUCCESS:
+ case APR_WANT_READ:
+ case APR_WANT_WRITE:
+ break;
+ default:
+ abts_log_message("apr_ldap_delete: %s [%s]\n", test->err.reason,
+ apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ }
+ else {
+ abts_log_message("apr_ldap_rename() failed: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ ABTS_INT_EQUAL(test->tc, APR_SUCCESS, status);
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t test_ldap_modify_cb(apr_ldap_t *ldap,
+ apr_status_t status,
+ const char *matcheddn,
+ apr_ldap_control_t **serverctrls,
+ void *ctx, apu_err_t *err)
+{
+ char errbuf[128];
+ test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
+
+ /*
+ * Step 21: modify result callback triggered, result is complete.
+ */
+
+ abts_log_message("modify matcheddn: \n", matcheddn);
+
+ if (APR_SUCCESS == status) {
+
+ /*
+ * Step 22: modify succeeded, it is time to trigger the rename.
+ */
+
+ test->rdn = "ou=Apache Portable Runtime Test Organizational Unit 2";
+ test->newdn = apr_pstrcat(test->pool, test->rdn , ",", test->context, NULL);
+
+ status = apr_ldap_rename(test->pool, test->ldap, test->dn /* dn to rename */,
+ test->rdn /* new rdn */, NULL, APR_LDAP_RENAME_DELETEOLDRDN,
+ NULL /* serverctls */, NULL /* clientctls */,
+ apr_time_from_sec(5) /* timeout */,
+ test_ldap_rename_cb, test, &test->err);
+
+ ABTS_INT_EQUAL(test->tc, APR_WANT_READ, status);
+
+ switch (status) {
+ case APR_SUCCESS:
+ case APR_WANT_READ:
+ case APR_WANT_WRITE:
+ break;
+ default:
+ abts_log_message("apr_ldap_rename: %s [%s]\n", test->err.reason,
+ apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ }
+ else {
+ abts_log_message("apr_ldap_modify() failed: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ ABTS_INT_EQUAL(test->tc, APR_SUCCESS, status);
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t test_ldap_add_cb(apr_ldap_t *ldap,
+ apr_status_t status,
+ const char *matcheddn,
+ apr_ldap_control_t **serverctrls,
+ void *ctx, apu_err_t *err)
+{
+ char errbuf[128];
+ test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
+
+ /*
+ * Step 18: add result callback triggered, next is modify.
+ */
+
+ abts_log_message("add matcheddn: \n", matcheddn);
+
+ if (APR_SUCCESS == status) {
+
+ apr_array_header_t *mods = apr_array_make(test->pool, 10, sizeof(apr_ldap_modify_t));
+ apr_ldap_modify_t *mod;
+ apr_buffer_t *val;
+
+ /* modify our newly added object */
+
+ /*
+ * Step 19: add successful, it is time to trigger the modify.
+ */
+
+ /* create objectclass */
+ mod = apr_array_push(mods);
+ mod->op = APR_LDAP_MOD_ADD;
+ mod->pair.attr = "objectclass";
+ mod->pair.vals = apr_array_make(test->pool, 1, sizeof(apr_buffer_t));
+
+ /* objectclass: extensibleObject */
+ val = apr_array_push(mod->pair.vals);
+ apr_buffer_str_set(val, "extensibleObject", APR_BUFFER_STRING);
+
+
+
+ status = apr_ldap_modify(test->pool, test->ldap, test->dn /* dn to modify */,
+ mods /* modifications */,
+ NULL /* serverctls */, NULL /* clientctls */,
+ apr_time_from_sec(5) /* timeout */,
+ test_ldap_modify_cb, test, &test->err);
+
+ ABTS_INT_EQUAL(test->tc, APR_WANT_READ, status);
+
+ switch (status) {
+ case APR_SUCCESS:
+ case APR_WANT_READ:
+ case APR_WANT_WRITE:
+ break;
+ default:
+ abts_log_message("apr_ldap_modify: %s [%s]\n", test->err.reason,
+ apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ }
+ else if (APR_ALREADY_EXISTS == status) {
+
+ /* previous run has left objects lying around, clean up */
+
+ /*
+ * Step 25: add said object already exists, it is time to trigger the delete.
+ */
+
+ status = apr_ldap_delete(test->pool, test->ldap, test->dn /* dn to delete */,
+ NULL /* serverctls */, NULL /* clientctls */,
+ apr_time_from_sec(5) /* timeout */,
+ test_ldap_delete_cb, test, &test->err);
+
+ ABTS_INT_EQUAL(test->tc, APR_WANT_READ, status);
+
+ switch (status) {
+ case APR_SUCCESS:
+ case APR_WANT_READ:
+ case APR_WANT_WRITE:
+ break;
+ default:
+ abts_log_message("apr_ldap_delete: %s [%s]\n", test->err.reason,
+ apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ }
+ else if (APR_INSUFFICIENT_ACCESS == status) {
+ abts_log_message("apr_ldap_add() was denied, skipping: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+ else {
+ abts_log_message("apr_ldap_add() failed: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ ABTS_INT_EQUAL(test->tc, APR_SUCCESS, status);
+ }
+
+ return APR_SUCCESS;
+}
+
static apr_status_t test_ldap_compare_cb(apr_ldap_t *ldap,
apr_status_t status,
const char *matcheddn,
apr_ldap_control_t **serverctrls,
void *ctx, apu_err_t *err)
{
+ char errbuf[128];
test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
/*
- * Step 13: compare result callback triggered, result is complete.
+ * Step 15: compare result callback triggered, next is add.
*/
abts_log_message("comparison matcheddn: \n", matcheddn);
ABTS_INT_EQUAL(test->tc, APR_COMPARE_TRUE, status);
+ abts_log_message("\n");
+
+ if (APR_COMPARE_TRUE != status) {
+ abts_log_message("apr_ldap_compare() failed: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+ else if (!test->context) {
+ abts_log_message("no namingContext in root DSE, we're done.\n");
+ }
+ else {
+
+ apr_array_header_t *adds = apr_array_make(test->pool, 10, sizeof(apr_ldap_pair_t));
+ apr_ldap_pair_t *pair;
+ apr_buffer_t *val;
+
+ /*
+ * Step 16: compare successful, it is time to trigger the add.
+ */
+
+ test->dn = apr_pstrcat(test->pool, "ou=Apache Portable Runtime Test Organizational Unit,", test->context, NULL);
+
+ /* create objectclass */
+ pair = apr_array_push(adds);
+ pair->attr = "objectclass";
+ pair->vals = apr_array_make(test->pool, 2, sizeof(apr_buffer_t));
+
+ /* objectclass: top */
+ val = apr_array_push(pair->vals);
+ apr_buffer_str_set(val, "top", APR_BUFFER_STRING);
+
+ /* objectclass: organizationalUnit */
+ val = apr_array_push(pair->vals);
+ apr_buffer_str_set(val, "organizationalUnit", APR_BUFFER_STRING);
+
+ /* create cn */
+ pair = apr_array_push(adds);
+ pair->attr = "ou";
+ pair->vals = apr_array_make(test->pool, 1, sizeof(apr_buffer_t));
+
+ /* cn: Apache Portable Runtime Test Organizational Unit */
+ val = apr_array_push(pair->vals);
+ apr_buffer_str_set(val, "Apache Portable Runtime Test Organizational Unit", APR_BUFFER_STRING);
+
+ /* create description */
+ pair = apr_array_push(adds);
+ pair->attr = "description";
+ pair->vals = apr_array_make(test->pool, 1, sizeof(apr_buffer_t));
+
+ /* description: If found, please delete. */
+ val = apr_array_push(pair->vals);
+ apr_buffer_str_set(val, "This object was created by a test case. If found, please delete.", APR_BUFFER_STRING);
+
+ status = apr_ldap_add(test->pool, test->ldap, test->dn /* dn to add */,
+ adds /* attribute-value pairs */,
+ NULL /* serverctls */, NULL /* clientctls */,
+ apr_time_from_sec(5) /* timeout */,
+ test_ldap_add_cb, test, &test->err);
+
+ ABTS_INT_EQUAL(test->tc, APR_WANT_READ, status);
+
+ switch (status) {
+ case APR_SUCCESS:
+ case APR_WANT_READ:
+ case APR_WANT_WRITE:
+ break;
+ default:
+ abts_log_message("apr_ldap_add: %s [%s]\n", test->err.reason,
+ apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ }
+
+
return APR_SUCCESS;
}
static apr_status_t test_ldap_search_entry_cb(apr_ldap_t *ldap,
const char *dn,
- int eidx,
- int nattrs,
- int aidx,
- const char *attr,
- int nvals,
- int vidx,
- apr_buffer_t *val,
- int binary,
+ apr_size_t eidx,
+ apr_ldap_search_entry_t *entry,
void *ctx, apu_err_t *err)
{
test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
/*
- * Step 8: search entry callback triggered, start processing results.
+ * Step 11: search entry callback triggered, start processing results.
*/
- if (!nattrs && !vidx && attr) {
+ if (entry && !entry->aidx && !entry->vidx) {
/* first attribute and first value and attr present? output dn */
abts_log_message("dn: %s", dn);
}
- if (val) {
- abts_log_message("%s: %s", attr, apr_buffer_pstrdup(test->pool, val));
+ if (entry) {
+ abts_log_message("%s: %s", entry->attr, apr_buffer_pstrdup(test->pool, &entry->val));
+
+ if (!strcmp(entry->attr, "namingContexts")) {
+ test->context = apr_buffer_pstrdup(test->pool, &entry->val);
+ }
}
return APR_SUCCESS;
}
-
static apr_status_t test_ldap_search_result_cb(apr_ldap_t *ldap,
apr_status_t status,
apr_size_t nentries,
const char *matcheddn,
- apr_ldap_control_t **serverctrls,
+ apr_hash_t *serverctrls,
void *ctx, apu_err_t *err)
{
char errbuf[128];
test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
/*
- * Step 9: search result callback triggered, finish up.
+ * Step 12: search result callback triggered, next is compare.
*/
abts_log_message("\n");
@@ -283,7 +683,7 @@ static apr_status_t test_ldap_search_res
if (APR_SUCCESS == status) {
/*
- * Step 10: search successful, it is time to trigger the compare.
+ * Step 13: search successful, it is time to trigger the compare.
*/
apr_buffer_t val;
@@ -319,32 +719,42 @@ static apr_status_t test_ldap_search_res
return status;
}
-static apr_status_t test_ldap_bind_cb(apr_ldap_t *ldap, apr_status_t status,
- const char *matcheddn,
- apr_ldap_control_t **serverctrls,
- void *ctx, apu_err_t *err)
+static apr_status_t test_ldap_whoami_cb(apr_ldap_t *ldap, apr_status_t status,
+ const char *roid,
+ apr_buffer_t *rdata,
+ void *ctx, apu_err_t *err)
{
char errbuf[128];
test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
if (APR_SUCCESS == status) {
+ abts_log_message("whoami: %s\n", apr_buffer_pstrdup(test->pool, rdata));
+
/*
- * Step 5: bind successful, it is time to trigger the search.
+ * Step 8: extended operation successful, it is time to trigger the search.
*/
-
const char *attrs[2];
+
+ apr_array_header_t *scontrols = apr_array_make(test->pool, 1, sizeof(apr_ldap_control_t));
+ apr_ldap_control_t *page = apr_array_push(scontrols);
+
+ /* make a page control */
+ page->type = APR_LDAP_CONTROL_PAGE_REQUEST;
+ page->critical = 0;
+ page->c.pagerq.size = 1; /* one entry per page */
+
attrs[0] = "+";
attrs[1] = NULL;
/*
- * Step 6: we're writable, trigger a search, then wait for readable.
+ * Step 9: we're writable, trigger a search, then wait for readable.
*/
status = apr_ldap_search(test->pool, test->ldap, "" /* root dn */,
APR_LDAP_SCOPE_BASE, "(objectclass=*)" /* filter */,
attrs /* attrs */, APR_LDAP_OPT_OFF /* attrsonly */,
- NULL /* serverctls */, NULL /* clientctls */,
+ scontrols /* serverctls */, NULL /* clientctls */,
apr_time_from_sec(5) /* timelimit */, 0 /* sizelimit */,
test_ldap_search_result_cb, test_ldap_search_entry_cb, test, &test->err);
@@ -362,6 +772,51 @@ static apr_status_t test_ldap_bind_cb(ap
}
else {
+ abts_log_message("apr_ldap_extended() failed: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ return status;
+}
+
+static apr_status_t test_ldap_bind_cb(apr_ldap_t *ldap, apr_status_t status,
+ const char *matcheddn,
+ apr_ldap_control_t **serverctrls,
+ void *ctx, apu_err_t *err)
+{
+ char errbuf[128];
+ test_ldap_connection_t *test = (test_ldap_connection_t *)ctx;
+
+ if (APR_SUCCESS == status) {
+
+ /*
+ * Step 5: bind successful, it is time to trigger the extended operation.
+ */
+
+ const char *whoami = "1.3.6.1.4.1.4203.1.11.3";
+
+ /*
+ * Step 6: we're writable, trigger an extended operation, then wait for readable.
+ */
+
+ status = apr_ldap_extended(test->pool, test->ldap, whoami, NULL,
+ NULL /* serverctls */, NULL /* clientctls */,
+ apr_time_from_sec(5), test_ldap_whoami_cb,
+ test, &test->err);
+
+ ABTS_INT_EQUAL(test->tc, APR_WANT_READ, status);
+
+ switch (status) {
+ case APR_SUCCESS:
+ case APR_WANT_READ:
+ case APR_WANT_WRITE:
+ break;
+ default:
+ abts_log_message("apr_ldap_result: %s [%s]\n", test->err.reason,
+ apr_strerror(status, errbuf, sizeof(errbuf)));
+ }
+
+ }
+ else {
abts_log_message("apr_ldap_bind() failed: %s\n", apr_strerror(status, errbuf, sizeof(errbuf)));
}
@@ -383,8 +838,6 @@ static apr_status_t test_ldap_initialise
status = apr_ldap_bind(test->pool, test->ldap, test->mech, test->interact, NULL,
apr_time_from_sec(0), test_ldap_bind_cb, test, &test->err);
- ABTS_INT_EQUAL(test->tc, APR_WANT_READ, status);
-
switch (status) {
case APR_SUCCESS:
case APR_WANT_READ:
@@ -444,11 +897,31 @@ static apr_status_t test_ldap_connection
*/
/*
- * Step 7: we're readable, fetch the search result, then trigger search callback.
+ * Step 7: we're readable, fetch the extended operation result, then trigger extended callback.
+ */
+
+ /*
+ * Step 10: we're readable, fetch the search result, then trigger search callback.
+ */
+
+ /*
+ * Step 14: we're readable, fetch the compare result, then trigger compare callback.
+ */
+
+ /*
+ * Step 17: we're readable, fetch the add result, then trigger add callback.
+ */
+
+ /*
+ * Step 20: we're readable, fetch the modify result, then trigger modify callback.
+ */
+
+ /*
+ * Step 23: we're readable, fetch the rename result, then trigger rename callback.
*/
/*
- * Step 12: we're readable, fetch the compare result, then trigger compare callback.
+ * Step 26: we're readable, fetch the delete result, then trigger delete callback.
*/
status = apr_ldap_result(test->pool, test->ldap, -1, &test->err);
@@ -486,7 +959,7 @@ static void test_ldap_connection(abts_ca
apu_err_t err;
test_ldap_connection_t test;
apr_ldap_opt_t opt;
- apr_status_t status;
+ apr_status_t status, want;
memset(&test, 0, sizeof(test_ldap_connection_t));
@@ -505,6 +978,9 @@ static void test_ldap_connection(abts_ca
* Step 1: call us back when we're writable.
*/
+ want = APR_WANT_WRITE;
+
+
/* set the initialise callback */
apr_ldap_prepare(pool, ldap, test_ldap_initialise_cb, &test);
@@ -514,6 +990,23 @@ static void test_ldap_connection(abts_ca
status = apr_ldap_connect(pool, ldap, apr_time_from_sec(5), &err);
+ if (APR_ENOTIMPL == status) {
+
+ /* macos is a pain - as of this writing their ancient openldap
+ * does not support ldap_connect. To work around this,
+ * synchronously fire off the first callback, which will force
+ * a connect, which will in turn avoid a bad descriptor on the
+ * socket below.
+ */
+
+ status = apr_ldap_process(pool, ldap, apr_time_from_sec(0), &err);
+
+ if (APR_WANT_READ == status) {
+ status = APR_SUCCESS;
+ want = APR_WANT_READ;
+ }
+ }
+
if (APR_SUCCESS != status) {
abts_log_message("%s - %s (%d)\n", err.reason, err.msg, err.rc);
return;
@@ -546,15 +1039,13 @@ static void test_ldap_connection(abts_ca
test.socket_write.desc.s = opt.socket;
test.socket_write.client_data = opt.socket;
- status = APR_WANT_WRITE;
-
do {
- if (APR_SUCCESS == status) {
+ if (APR_SUCCESS == want) {
abts_log_message("apr_pollcb_poll() complete\n");
break;
}
- else if (APR_WANT_READ == status) {
+ else if (APR_WANT_READ == want) {
/* wait for socket to be readable, then process another result */
status = apr_pollcb_add(test.poll, &test.socket_read);
@@ -564,7 +1055,7 @@ static void test_ldap_connection(abts_ca
}
}
- else if (APR_WANT_WRITE == status) {
+ else if (APR_WANT_WRITE == want) {
/* wait for socket to be writeable, then process result */
status = apr_pollcb_add(test.poll, &test.socket_write);
@@ -576,17 +1067,19 @@ static void test_ldap_connection(abts_ca
}
else {
abts_log_message("apr_ldap_process/apr_ldap_result: %s [%s]\n", test.err.reason,
- apr_strerror(status, errbuf, sizeof(errbuf)));
+ apr_strerror(want, errbuf, sizeof(errbuf)));
break;
}
- status = apr_pollcb_poll(test.poll, -1, test_ldap_connection_cb, &test);
+ want = apr_pollcb_poll(test.poll, -1, test_ldap_connection_cb, &test);
} while (1);
/*
- * Step 14: bind, search, compare, result is complete, event loop unwound.
+ * Step 31: bind, extended, search, compare, add, modify, rename, delete, search.
+ *
+ * result is complete, event loop unwound.
*/
return;
@@ -1106,8 +1599,6 @@ static void test_ldapi(abts_case *tc, vo
apr_pool_create(&pool, p);
- opt.tls = APR_LDAP_TLS_STARTTLS;
-
url = apr_psprintf(pool, "ldapi://%s", apr_pescape_urlencoded(pool, testldapi));
apr_ldap_initialise(pool, &ldap, &(err));