I am currently using Mac OS X 10.6.2 and am attempting to use the ldap_sasl_interactive_bind_s API to do a digest-md5 authentication against Active Directory (2008, though I don't think it matters what flavor of AD is used). The bind works fine the first time. However, if I unbind and attempt to rebind as the same user, it fails with ldap_sasl_interactive_bind_s: Invalid credentials (49). If I bind with a different user, then unbind, and bind as the original user, it works. I created a simple program that illustrates the issue. When run, it binds correctly, unbinds, and then fails on the second bind:
trying ldap_sasl_interactive_bind_s callback callback done ldap_sasl_interactive_bind_s Done Unbinding Unbound. ldap_sasl_interactive_bind_s callback callback done ldap_sasl_interactive_bind_s: Invalid credentials (49) additional info: 80090308: LdapErr: DSID-0C0904D1, comment: AcceptSecurityContext error, data 57, v1772
Any idea why it is not possible to use the same credentials twice?
Here is the test program. I tried reinitializing the sasl library with sasl_done and sasl_client_init, but that doesn't seem to make a difference.
#include <ldap.h> #include <sasl/sasl.h> #include <stdio.h>
typedef struct sasl_defaults { char *mech; char *realm; char *authcid; char *passwd; char *authzid; } sasl_defaults;
int callback(LDAP *ld, unsigned flags, void* defaults, void *interact ) { printf("callback\n"); sasl_interact_t *in_out=(sasl_interact_t *)interact; sasl_defaults *in_defaults=(sasl_defaults *)defaults;
while (in_out->id !=SASL_CB_LIST_END) {
switch (in_out->id) { case SASL_CB_USER: in_out->result=in_defaults->authcid; in_out->len=strlen(in_defaults->authcid); break; case SASL_CB_AUTHNAME: in_out->result=in_defaults->authcid; in_out->len=strlen(in_defaults->authcid); break; case SASL_CB_PASS: in_out->result=in_defaults->passwd; in_out->len=strlen(in_defaults->passwd); break; case SASL_CB_GETREALM: in_out->result=""; in_out->len=strlen(""); break;
}
in_out++; } printf("callback done\n"); return 0; }
int main (int argv, char ** argc) {
printf("trying\n"); for (;;) { LDAP *ld;
ldap_initialize(&ld, "ldap://dc.ad.domain.com:389");
ldap_set_option(ld,LDAP_OPT_REFERRALS,LDAP_OPT_OFF);
int version=3; ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); int timelimit=5; if (ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS ) { printf("err\n"); return -1; }
sasl_defaults defaults; defaults.mech = "DIGEST-MD5"; defaults.passwd="password"; defaults.authcid="user"; defaults.realm="realm.com"; defaults.authzid="user";
printf("ldap_sasl_interactive_bind_s\n"); int rc=ldap_sasl_interactive_bind_s( ld, NULL,defaults.mech, NULL, NULL, LDAP_SASL_QUIET, callback, &defaults );
if( rc != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); ldap_unbind(ld); return -1; } printf("ldap_sasl_interactive_bind_s Done\n");
printf("Unbinding\n"); ldap_unbind(ld); printf("Unbound.\n"); sleep(5);
} }