wldap32: Add support for ldap_bind_s(LDAP_AUTH_NEGOTIATE).

Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Dmitry Timoshkov 2020-03-23 21:14:15 +08:00 committed by Alexandre Julliard
parent 3d37d45ed0
commit 364ac6787a
6 changed files with 154 additions and 14 deletions

1
configure vendored
View File

@ -7427,6 +7427,7 @@ for ac_header in \
port.h \
pthread.h \
pwd.h \
sasl/sasl.h \
sched.h \
scsi/scsi.h \
scsi/scsi_ioctl.h \

View File

@ -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 \

View File

@ -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,67 @@ 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_LDAP_H
static int sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *interact )
{
#ifdef HAVE_SASL_SASL_H
SEC_WINNT_AUTH_IDENTITY_A *id = defaults;
sasl_interact_t *sasl = interact;
TRACE( "%p,%08x,%p,%p\n", ld, flags, defaults, interact );
while (sasl->id != SASL_CB_LIST_END)
{
TRACE("sasl->id = %04lx\n", sasl->id);
if (sasl->id == SASL_CB_GETREALM)
{
sasl->result = id->Domain;
sasl->len = id->DomainLength;
}
else if (sasl->id == SASL_CB_USER)
{
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
FIXME( "%p,%08x,%p,%p: stub\n", ld, flags, defaults, interact );
return LDAP_SUCCESS;
#endif /* HAVE_SASL_SASL_H */
}
#endif /* HAVE_LDAP_H */
/***********************************************************************
* ldap_bind_sW (WLDAP32.@)
*
@ -197,21 +248,71 @@ 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;
else if (method == WLDAP32_LDAP_AUTH_NEGOTIATE)
{
SEC_WINNT_AUTH_IDENTITY_A idU;
SEC_WINNT_AUTH_IDENTITY_W idW;
SEC_WINNT_AUTH_IDENTITY_W *id = (SEC_WINNT_AUTH_IDENTITY_W *)cred;
pwd.bv_len = strlen( credU );
pwd.bv_val = credU;
memset( &idU, 0, sizeof(idU) );
if (id)
{
if (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
idW.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
idW.Domain = (unsigned short *)strnAtoW( (char *)id->Domain, id->DomainLength, &idW.DomainLength );
idW.User = (unsigned short *)strnAtoW( (char *)id->User, id->UserLength, &idW.UserLength );
idW.Password = (unsigned short *)strnAtoW( (char *)id->Password, id->PasswordLength, &idW.PasswordLength );
id = &idW;
}
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 ));
if (id && (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI))
{
strfreeW( (WCHAR *)idW.Domain );
strfreeW( (WCHAR *)idW.User );
strfreeW( (WCHAR *)idW.Password );
}
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 );

View File

@ -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

View File

@ -93,6 +93,38 @@ static inline LPWSTR strUtoW( char *str )
return ret;
}
static inline LPWSTR strnAtoW( LPCSTR str, DWORD inlen, DWORD *outlen )
{
LPWSTR ret = NULL;
*outlen = 0;
if (str)
{
DWORD len = MultiByteToWideChar( CP_ACP, 0, str, inlen, NULL, 0 );
if ((ret = heap_alloc( len * sizeof(WCHAR) )))
{
MultiByteToWideChar( CP_ACP, 0, str, inlen, ret, len );
*outlen = len;
}
}
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 );

View File

@ -779,6 +779,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