diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c index 1498dc49fe6..826feca9bc8 100644 --- a/dlls/wldap32/bind.c +++ b/dlls/wldap32/bind.c @@ -181,28 +181,50 @@ exit: #ifdef HAVE_LDAP +struct bind_pvt { + SEC_WINNT_AUTH_IDENTITY_A *id; + const char *mech; +}; + static int sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *interact ) { #ifdef HAVE_SASL_SASL_H - SEC_WINNT_AUTH_IDENTITY_A *id = defaults; + struct bind_pvt *pvt = defaults; + SEC_WINNT_AUTH_IDENTITY_A *id = pvt->id; + const char *mech = pvt->mech; sasl_interact_t *sasl = interact; TRACE( "%p,%08x,%p,%p\n", ld, flags, defaults, interact ); + if (mech == NULL) + mech = "unknown/invalid"; + while (sasl->id != SASL_CB_LIST_END) { - TRACE("sasl->id = %04lx\n", sasl->id); + TRACE("mechanism %s, sasl->id = %04lx\n", debugstr_a(mech), sasl->id); if (sasl->id == SASL_CB_GETREALM) { sasl->result = id->Domain; sasl->len = id->DomainLength; } - else if (sasl->id == SASL_CB_USER) + else if (sasl->id == SASL_CB_AUTHNAME) { sasl->result = id->User; sasl->len = id->UserLength; } + else if (sasl->id == SASL_CB_USER) + { + if (!strcmp(mech, "GSSAPI")) + ; + else if (!strcmp(mech, "GSS-SPNEGO")) + ; + else + { + sasl->result = id->User; + sasl->len = id->UserLength; + } + } else if (sasl->id == SASL_CB_PASS) { sasl->result = id->Password; @@ -219,6 +241,38 @@ static int sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *intera #endif /* HAVE_SASL_SASL_H */ } +static int _sasl_bind_s( LDAP *ld, SEC_WINNT_AUTH_IDENTITY_A *idU ) +{ + struct bind_pvt pvt; + LDAPMessage *result = NULL; + + pvt.id = idU; + pvt.mech = NULL; + while (1) + { + int msgid; + int ret; + + ret = ldap_sasl_interactive_bind( ld, + NULL /* server will ignore DN anyway */, + NULL /* query supportedSASLMechanisms */, + NULL, NULL, LDAP_SASL_QUIET, sasl_interact, &pvt, + result, &pvt.mech, &msgid ); + ldap_msgfree( result ); + if (ret != LDAP_SASL_BIND_IN_PROGRESS) + return ret; + ret = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); + if ( ret == -1 || !result ) + { + int err; + ldap_get_option( ld, LDAP_OPT_RESULT_CODE, &err ); + return err; + } + else if ( ret == 0 ) + return LDAP_TIMELIMIT_EXCEEDED; + } +} + #endif /* HAVE_LDAP */ /*********************************************************************** @@ -292,10 +346,7 @@ ULONG CDECL ldap_bind_sW( WLDAP32_LDAP *ld, PWCHAR dn, PWCHAR cred, ULONG method idU.Password = (unsigned char *)strnWtoU( id->Password, id->PasswordLength, &idU.PasswordLength ); } - ret = map_error( ldap_sasl_interactive_bind_s( ld->ld, - NULL /* server will ignore DN anyway */, - NULL /* query supportedSASLMechanisms */, - NULL, NULL, LDAP_SASL_QUIET, sasl_interact, &idU )); + ret = map_error( _sasl_bind_s( ld->ld, &idU )); if (id && (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)) {