[PATCH 1/8] wldap32: Add support for ldap_bind_s(LDAP_AUTH_NEGOTIATE). (resend)

Dmitry Timoshkov dmitry at baikal.ru
Fri Mar 20 02:21:21 CDT 2020


Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 configure.ac                   |   1 +
 dlls/wldap32/bind.c            | 121 +++++++++++++++++++++++++++++----
 dlls/wldap32/winldap_private.h |   2 +
 dlls/wldap32/wldap32.h         |  16 +++++
 include/config.h.in            |   3 +
 5 files changed, 128 insertions(+), 15 deletions(-)

diff --git a/configure.ac b/configure.ac
index 7096e2fb66..83e659742b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -487,6 +487,7 @@ AC_CHECK_HEADERS(\
 	port.h \
 	pthread.h \
 	pwd.h \
+	sasl/sasl.h \
 	sched.h \
 	scsi/scsi.h \
 	scsi/scsi_ioctl.h \
diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c
index 27fb286f50..76d76323b2 100644
--- a/dlls/wldap32/bind.c
+++ b/dlls/wldap32/bind.c
@@ -25,10 +25,14 @@
 #ifdef HAVE_LDAP_H
 #include <ldap.h>
 #endif
+#ifdef HAVE_SASL_SASL_H
+#include <sasl/sasl.h>
+#endif
 
 #include "windef.h"
 #include "winbase.h"
 #include "winnls.h"
+#include "rpc.h"
 
 #include "winldap_private.h"
 #include "wldap32.h"
@@ -156,20 +160,68 @@ ULONG CDECL ldap_bind_sA( WLDAP32_LDAP *ld, PCHAR dn, PCHAR cred, ULONG method )
         if (!dnW) goto exit;
     }
     if (cred) {
-        credW = strAtoW( cred );
-        if (!credW) goto exit;
+        if (method == LDAP_AUTH_SIMPLE)
+        {
+            credW = strAtoW( cred );
+            if (!credW) goto exit;
+        }
+        else
+            credW = (WCHAR *)cred /* SEC_WINNT_AUTH_IDENTITY_A */;
     }
 
     ret = ldap_bind_sW( ld, dnW, credW, method );
 
 exit:
     strfreeW( dnW );
-    strfreeW( credW );
+    if (credW != (WCHAR *)cred) strfreeW( credW );
 
 #endif
     return ret;
 }
 
+#ifdef HAVE_SASL_SASL_H
+
+static int sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *interact )
+{
+    SEC_WINNT_AUTH_IDENTITY_W *id = defaults;
+    sasl_interact_t *sasl = interact;
+
+    TRACE( "%p,%08x,%p,%p\n", ld, flags, defaults, interact );
+
+    while (sasl->id != SASL_CB_LIST_END)
+    {
+        if (sasl->id == SASL_CB_GETREALM)
+        {
+            sasl->result = id->Domain;
+            sasl->len = id->DomainLength;
+        }
+        else if (sasl->id == SASL_CB_AUTHNAME)
+        {
+            sasl->result = id->User;
+            sasl->len = id->UserLength;
+        }
+        else if (sasl->id == SASL_CB_PASS)
+        {
+            sasl->result = id->Password;
+            sasl->len = id->PasswordLength;
+        }
+
+        sasl++;
+    }
+
+    return LDAP_SUCCESS;
+}
+
+#else
+
+static int sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *interact )
+{
+    FIXME( "%p,%08x,%p,%p: stub\n", ld, flags, defaults, interact );
+    return LDAP_SUCCESS;
+}
+
+#endif /* HAVE_SASL_SASL_H */
+
 /***********************************************************************
  *      ldap_bind_sW     (WLDAP32.@)
  *
@@ -197,21 +249,60 @@ ULONG CDECL ldap_bind_sW( WLDAP32_LDAP *ld, PWCHAR dn, PWCHAR cred, ULONG method
     TRACE( "(%p, %s, %p, 0x%08x)\n", ld, debugstr_w(dn), cred, method );
 
     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
-    if (method != LDAP_AUTH_SIMPLE) return WLDAP32_LDAP_PARAM_ERROR;
 
-    if (dn) {
-        dnU = strWtoU( dn );
-        if (!dnU) goto exit;
+    if (method == LDAP_AUTH_SIMPLE)
+    {
+        if (dn)
+        {
+            dnU = strWtoU( dn );
+            if (!dnU) goto exit;
+        }
+        if (cred)
+        {
+            credU = strWtoU( cred );
+            if (!credU) goto exit;
+
+            pwd.bv_len = strlen( credU );
+            pwd.bv_val = credU;
+        }
+
+        ret = map_error( ldap_sasl_bind_s( ld, dnU, LDAP_SASL_SIMPLE, &pwd, NULL, NULL, NULL ));
     }
-    if (cred) {
-        credU = strWtoU( cred );
-        if (!credU) goto exit;
-
-        pwd.bv_len = strlen( credU );
-        pwd.bv_val = credU;
+    else if (method == WLDAP32_LDAP_AUTH_NEGOTIATE)
+    {
+        SEC_WINNT_AUTH_IDENTITY_A idU;
+
+        memset( &idU, 0, sizeof(idU) );
+
+        if (cred)
+        {
+            SEC_WINNT_AUTH_IDENTITY_W *id = (SEC_WINNT_AUTH_IDENTITY_W *)cred;
+
+            if (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
+            {
+                FIXME( "ANSI credentials not supported\n" );
+                return WLDAP32_LDAP_PARAM_ERROR;
+            }
+
+            idU.Domain = (unsigned char *)strnWtoU( id->Domain, id->DomainLength, &idU.DomainLength );
+            idU.User = (unsigned char *)strnWtoU( id->User, id->UserLength, &idU.UserLength );
+            idU.Password = (unsigned char *)strnWtoU( id->Password, id->PasswordLength, &idU.PasswordLength );
+        }
+
+        ret = map_error( ldap_sasl_interactive_bind_s( ld,
+                             NULL /* server will ignore DN anyway */,
+                             NULL /* query supportedSASLMechanisms */,
+                             NULL, NULL, LDAP_SASL_QUIET, sasl_interact, &idU ));
+
+        strfreeU( (char *)idU.Domain );
+        strfreeU( (char *)idU.User );
+        strfreeU( (char *)idU.Password );
+    }
+    else
+    {
+        FIXME( "method %#x not supported\n", method );
+        return WLDAP32_LDAP_PARAM_ERROR;
     }
-
-    ret = map_error( ldap_sasl_bind_s( ld, dnU, LDAP_SASL_SIMPLE, &pwd, NULL, NULL, NULL ));
 
 exit:
     strfreeU( dnU );
diff --git a/dlls/wldap32/winldap_private.h b/dlls/wldap32/winldap_private.h
index 74223029b7..df257dafec 100644
--- a/dlls/wldap32/winldap_private.h
+++ b/dlls/wldap32/winldap_private.h
@@ -101,6 +101,8 @@ typedef struct berelement
 #define WLDAP32_LDAP_OPT_SECURITY_CONTEXT       0x99
 #define WLDAP32_LDAP_OPT_ROOTDSE_CACHE          0x9a
 
+#define WLDAP32_LDAP_AUTH_NEGOTIATE             0x486
+
 typedef struct ldap
 {
     struct
diff --git a/dlls/wldap32/wldap32.h b/dlls/wldap32/wldap32.h
index 1d4052002a..080765896c 100644
--- a/dlls/wldap32/wldap32.h
+++ b/dlls/wldap32/wldap32.h
@@ -93,6 +93,22 @@ static inline LPWSTR strUtoW( char *str )
     return ret;
 }
 
+static inline char *strnWtoU( LPCWSTR str, DWORD inlen, DWORD *outlen )
+{
+    LPSTR ret = NULL;
+    *outlen = 0;
+    if (str)
+    {
+        DWORD len = WideCharToMultiByte( CP_UTF8, 0, str, inlen, NULL, 0, NULL, NULL );
+        if ((ret = heap_alloc( len )))
+        {
+            WideCharToMultiByte( CP_UTF8, 0, str, inlen, ret, len, NULL, NULL );
+            *outlen = len;
+        }
+    }
+    return ret;
+}
+
 static inline void strfreeA( LPSTR str )
 {
     heap_free( str );
diff --git a/include/config.h.in b/include/config.h.in
index de434d6ed2..e48e398ca8 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -776,6 +776,9 @@
 /* Define to 1 if you have the `roundf' function. */
 #undef HAVE_ROUNDF
 
+/* Define to 1 if you have the <sasl/sasl.h> header file. */
+#undef HAVE_SASL_SASL_H
+
 /* Define to 1 if you have the <sched.h> header file. */
 #undef HAVE_SCHED_H
 
-- 
2.25.1




More information about the wine-devel mailing list