[PATCH v2 7/7] wldap32: supply SASL credentials in a mechanism-specific form
Damjan Jovanovic
damjan.jov at gmail.com
Sat Feb 13 04:45:30 CST 2021
So far it appears that SASL mechanisms require credentials supplied
to them in a mechanism-specific form.
OpenLDAP's ldap_sasl_interactive_bind() passes the caller-supplied
rmech to ldap_int_sasl_bind() in libraries/libldap/cyrus.c.
There, it is populated from the chosen authentication mechanism
(mech) returned by sasl_client_start(), before calling the interact()
callback. By providing rmech to our sasl_interact() callback, it can
know which SASL mechanism it is supplying credentials for, and can
supply them in a mechanism-specific form.
Hans reported GSSAPI and GSS-SPNEGO want an empty AUTH_CB_USER.
I verified DIGEST-MD5 wants AUTH_CB_AUTHNAME and doesn't mind if
AUTH_CB_USER is supplied. Dmitry reported that for his mechanism
(some variation of Kerberos?) AUTH_CB_AUTHNAME is used for initial
tickets but AUTH_CB_USER is mandatory thereafter. This patch should
hopefully make all those mechanisms happy.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50572
Signed-off-by: Damjan Jovanovic <damjan.jov at gmail.com>
---
dlls/wldap32/bind.c | 65 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 58 insertions(+), 7 deletions(-)
-------------- next part --------------
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))
{
More information about the wine-devel
mailing list