[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
test program for ldap_int_sasl_init issue
- To: openldap-technical@openldap.org
- Subject: test program for ldap_int_sasl_init issue
- From: Ryan Tandy <ryan@nardis.ca>
- Date: Wed, 26 Apr 2017 21:44:04 -0700
- Content-disposition: inline
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nardis.ca; s=google; h=date:from:to:subject:message-id:mail-followup-to:mime-version :content-disposition:user-agent; bh=FZhqdCVvsD0swWwj9kNrnepnw/xTElmU5itjWjQQ/LQ=; b=gSqQI2RLCxcV960cJJLpJBR/FsTCjAassxb993Q4aLXvooPX48z2nzz2eFLvgFiB1L H4ICwjRg8fiP53uk6SMfXnhUsNkoR7PMC18/ymiwUqyEIOxO1RJfAxE+Oge5L/qYUleA RmPBoQWevWxFfNXhKF5Y5OTBGYE6JWhhh+tl0=
- Mail-followup-to: openldap-technical@openldap.org
- User-agent: Mutt/1.5.23 (2014-03-12)
I'm looking into a Debian bug report: https://bugs.debian.org/860947
ldap_int_sasl_init says:
/* XXX not threadsafe */
static int sasl_initialized = 0;
I'm not yet sure whether it's the cause of that report, but it does seem
to be problematic. I'm seeing spurious "no such mechanism" results
and/or crashes in mutiple environments performing SASL binds in
parallel:
- slapd with multiple syncrepl clients all using SASL binds,
- the ldclt tool from the 389-ds project, and
- the test program I'm about to describe below.
I wrote a test program for this issue, and I'd like to ask the list to
check the code before I submit an ITS, in case I've made a mistake that
renders my test invalid.
gcc -g sasltest.c -pthread -llber -lldap -lsasl2 -DSASL
As I understand it, -lldap_r should not be needed here since each thread
creates its own LDAP instance. (It doesn't seem to change the results,
anyway.)
Built without -DSASL, it uses simple binds, and appears to work fine,
but again, I'm not confident my code is correct.
Thanks!
Ryan
#include <assert.h>
#include <ldap.h>
#include <pthread.h>
#ifdef SASL
#include <sasl/sasl.h>
#endif
#include <stdio.h>
#define THREADS 10
#define BINDS 5
#define URI "ldap://"
#define BINDDN "cn=admin,dc=example,dc=com"
#define USER "admin"
#define PASS "admin"
static void check(int rc) {
if (rc == LDAP_SUCCESS) {
return;
}
char *err = ldap_err2string(rc);
fprintf(stderr, "rc = %d (%s)\n", rc, err);
}
#ifdef SASL
static int sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in) {
sasl_interact_t *interact = in;
while (interact->id != SASL_CB_LIST_END) {
switch (interact->id) {
case SASL_CB_AUTHNAME:
interact->result = USER;
interact->len = strlen(USER);
break;
case SASL_CB_USER:
interact->result = "";
interact->len = 0;
break;
case SASL_CB_PASS:
interact->result = PASS;
interact->len = strlen(PASS);
break;
default:
assert(0);
}
interact++;
}
return 0;
}
#endif
static void *bind_thread(void *unused) {
LDAP *ld;
int rc;
int i;
int version = 3;
rc = ldap_initialize(&ld, URI);
check(rc); assert(rc == LDAP_SUCCESS);
rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
check(rc); assert(rc == LDAP_SUCCESS);
for (i = 0; i < BINDS; i++) {
#ifdef SASL
rc = ldap_sasl_interactive_bind_s(ld, NULL, "DIGEST-MD5", NULL, NULL, LDAP_SASL_QUIET, sasl_interact, NULL);
#else
rc = ldap_sasl_bind_s(ld, BINDDN, LDAP_SASL_SIMPLE, ber_bvstr(PASS), NULL, NULL, NULL);
#endif
check(rc); assert(rc == LDAP_SUCCESS);
}
rc = ldap_unbind_ext_s(ld, NULL, NULL);
check(rc); assert(rc == LDAP_SUCCESS);
return NULL;
}
int main (int argc, char *argv[]) {
pthread_t threads[THREADS];
int rc;
int i;
int debug;
/* give libldap a chance to do global init */
ldap_get_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
for (i = 0; i < THREADS; i++) {
rc = pthread_create(&threads[i], NULL, bind_thread, NULL);
assert(!rc);
}
for (i = 0; i < THREADS; i++) {
rc = pthread_join(threads[i], NULL);
assert (!rc);
}
pthread_exit(NULL);
return 0;
}