ctxt_handle is moved to the top of struct tlsw_session so that it can be easily retrieved via LDAP_OPT_X_TLS_SSL_CTX.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54727
-- v4: wldap32: Implement setting LDAP_OPT_SERVER_CERTIFICATE and add tests.
From: Alex Henrie alexhenrie24@gmail.com
--- dlls/wldap32/init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/wldap32/init.c b/dlls/wldap32/init.c index b8010a2da12..78891d9be61 100644 --- a/dlls/wldap32/init.c +++ b/dlls/wldap32/init.c @@ -251,7 +251,11 @@ ULONG CDECL WLDAP32_ldap_connect( LDAP *ld, struct l_timeval *timeout ) TRACE( "(%p, %p)\n", ld, timeout );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; - return WLDAP32_LDAP_SUCCESS; /* FIXME: do something, e.g. ping the host */ + + if (timeout && (timeout->tv_sec || timeout->tv_usec)) + FIXME( "ignoring timeout\n" ); + + return map_error( ldap_connect( CTX(ld) ) ); }
/***********************************************************************
From: Alex Henrie alexhenrie24@gmail.com
ctxt_handle is moved to the top of struct tlsw_session so that it can be easily retrieved via LDAP_OPT_X_TLS_SSL_CTX.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54727 --- dlls/wldap32/Makefile.in | 2 +- dlls/wldap32/add.c | 8 +++++-- dlls/wldap32/bind.c | 22 +++++++++++++------ dlls/wldap32/compare.c | 8 +++++-- dlls/wldap32/control.c | 2 ++ dlls/wldap32/delete.c | 8 +++++-- dlls/wldap32/extended.c | 8 +++++-- dlls/wldap32/init.c | 34 ++++++++++++++++++++++++++++- dlls/wldap32/modify.c | 8 +++++-- dlls/wldap32/modrdn.c | 14 ++++++------ dlls/wldap32/option.c | 7 ++++-- dlls/wldap32/rename.c | 8 +++++-- dlls/wldap32/search.c | 16 ++++++++------ dlls/wldap32/tests/Makefile.in | 2 +- dlls/wldap32/tests/parse.c | 39 ++++++++++++++++++++++++++++++++++ dlls/wldap32/winldap_private.h | 16 ++++++++++++-- include/winldap.h | 2 ++ libs/ldap/libldap/tls_w.c | 2 +- 18 files changed, 166 insertions(+), 40 deletions(-)
diff --git a/dlls/wldap32/Makefile.in b/dlls/wldap32/Makefile.in index ed8630e47af..903f6f67666 100644 --- a/dlls/wldap32/Makefile.in +++ b/dlls/wldap32/Makefile.in @@ -1,6 +1,6 @@ MODULE = wldap32.dll IMPORTLIB = wldap32 -IMPORTS = $(LDAP_PE_LIBS) secur32 ws2_32 user32 +IMPORTS = $(LDAP_PE_LIBS) crypt32 secur32 ws2_32 user32 EXTRAINCL = $(LDAP_PE_CFLAGS)
C_SRCS = \ diff --git a/dlls/wldap32/add.c b/dlls/wldap32/add.c index 4509910abc5..1ff46935641 100644 --- a/dlls/wldap32/add.c +++ b/dlls/wldap32/add.c @@ -102,7 +102,7 @@ exit: ULONG CDECL ldap_add_extW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL; LDAPMod **attrsU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; @@ -110,7 +110,9 @@ ULONG CDECL ldap_add_extW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW * TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), attrs, serverctrls, clientctrls, message );
if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = dn ? strWtoU( dn ) : strdup( "" ))) goto exit; if (attrs && !(attrsU = modarrayWtoU( attrs ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; @@ -164,7 +166,7 @@ exit: ULONG CDECL ldap_add_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL; LDAPMod **attrsU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; @@ -172,7 +174,9 @@ ULONG CDECL ldap_add_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **attrs, LDAPControlW TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), attrs, serverctrls, clientctrls );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = dn ? strWtoU( dn ) : strdup(""))) goto exit; if (attrs && !(attrsU = modarrayWtoU( attrs ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c index 5441aeba6c7..55422c82474 100644 --- a/dlls/wldap32/bind.c +++ b/dlls/wldap32/bind.c @@ -58,7 +58,7 @@ exit: */ ULONG CDECL ldap_bindW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL, *credU = NULL; struct berval pwd = { 0, NULL }; int msg; @@ -67,7 +67,9 @@ ULONG CDECL ldap_bindW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method )
if (!ld) return ~0u; if (method != WLDAP32_LDAP_AUTH_SIMPLE) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (dn && !(dnU = strWtoU( dn ))) goto exit; if (cred) { @@ -171,14 +173,16 @@ static int interact_callback( LDAP *ld, unsigned flags, void *defaults, void *sa */ ULONG CDECL ldap_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *cred, ULONG method ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL, *credU = NULL; struct berval pwd = { 0, NULL };
TRACE( "(%p, %s, %p, %#lx)\n", ld, debugstr_w(dn), cred, method );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (method == WLDAP32_LDAP_AUTH_SIMPLE) { if (dn && !(dnU = strWtoU( dn ))) goto exit; @@ -260,7 +264,7 @@ exit: ULONG CDECL ldap_sasl_bindW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, const BERVAL *cred, LDAPControlW **serverctrls, LDAPControlW **clientctrls, int *message ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU, *mechanismU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; struct berval credU; @@ -269,7 +273,9 @@ ULONG CDECL ldap_sasl_bindW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, debugstr_w(mechanism), cred, serverctrls, clientctrls, message );
if (!ld || !dn || !mechanism || !cred || !message) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = strWtoU( dn ))) goto exit; if (!(mechanismU = strWtoU( mechanism ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; @@ -325,7 +331,7 @@ exit: ULONG CDECL ldap_sasl_bind_sW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism, const BERVAL *cred, LDAPControlW **serverctrls, LDAPControlW **clientctrls, BERVAL **serverdata ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU, *mechanismU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; struct berval *dataU, credU; @@ -334,7 +340,9 @@ ULONG CDECL ldap_sasl_bind_sW( LDAP *ld, const PWCHAR dn, const PWCHAR mechanism debugstr_w(mechanism), cred, serverctrls, clientctrls, serverdata );
if (!ld || !dn || !mechanism || !cred || !serverdata) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = strWtoU( dn ))) goto exit; if (!(mechanismU = strWtoU( mechanism ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; @@ -395,7 +403,7 @@ ULONG CDECL ldap_simple_bindW( LDAP *ld, WCHAR *dn, WCHAR *passwd )
TRACE( "(%p, %s, %p)\n", ld, debugstr_w(dn), passwd );
- if (!ld) return ~0u; + if (!ld || WLDAP32_ldap_connect( ld, NULL ) != WLDAP32_LDAP_SUCCESS) return ~0u;
if (dn && !(dnU = strWtoU( dn ))) goto exit; if (passwd) @@ -445,14 +453,16 @@ exit: */ ULONG CDECL ldap_simple_bind_sW( LDAP *ld, WCHAR *dn, WCHAR *passwd ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL, *passwdU = NULL; struct berval pwd = { 0, NULL };
TRACE( "(%p, %s, %p)\n", ld, debugstr_w(dn), passwd );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (dn && !(dnU = strWtoU( dn ))) goto exit; if (passwd) { diff --git a/dlls/wldap32/compare.c b/dlls/wldap32/compare.c index cc51c64ebeb..b4265185538 100644 --- a/dlls/wldap32/compare.c +++ b/dlls/wldap32/compare.c @@ -106,7 +106,7 @@ exit: ULONG CDECL ldap_compare_extW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct WLDAP32_berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL, *attrU = NULL, *valueU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; struct berval *dataU = NULL, val = { 0, NULL }; @@ -116,7 +116,9 @@ ULONG CDECL ldap_compare_extW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, s
if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR; if (!attr) return WLDAP32_LDAP_NO_MEMORY; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = dn ? strWtoU( dn ) : strdup( "" ))) goto exit; if (!(attrU = strWtoU( attr ))) goto exit; if (!data) @@ -187,7 +189,7 @@ exit: ULONG CDECL ldap_compare_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value, struct WLDAP32_berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL, *attrU = NULL, *valueU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; struct berval *dataU = NULL, val = { 0, NULL }; @@ -197,7 +199,9 @@ ULONG CDECL ldap_compare_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *attr, WCHAR *value,
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; if (!attr) return LDAP_UNDEFINED_TYPE; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = dn ? strWtoU( dn ) : strdup( "" ))) goto exit; if (!(attrU = strWtoU( attr ))) goto exit; if (!data) diff --git a/dlls/wldap32/control.c b/dlls/wldap32/control.c index 131ea4dad64..de65194e0cc 100644 --- a/dlls/wldap32/control.c +++ b/dlls/wldap32/control.c @@ -108,6 +108,7 @@ ULONG CDECL ldap_create_sort_controlW( LDAP *ld, LDAPSortKeyW **sortkey, UCHAR c TRACE( "(%p, %p, 0x%02x, %p)\n", ld, sortkey, critical, control );
if (!ld || !sortkey || !control) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
if (!(sortkeyU = sortkeyarrayWtoU( sortkey ))) return WLDAP32_LDAP_NO_MEMORY;
@@ -160,6 +161,7 @@ INT CDECL ldap_create_vlv_controlW( LDAP *ld, WLDAP32_LDAPVLVInfo *info, UCHAR c TRACE( "(%p, %p, 0x%02x, %p)\n", ld, info, critical, control );
if (!ld || !control) return ~0u; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
if (info && !(infoU = vlvinfoWtoU( info ))) return WLDAP32_LDAP_NO_MEMORY;
diff --git a/dlls/wldap32/delete.c b/dlls/wldap32/delete.c index 8539b7266eb..4155ca7e934 100644 --- a/dlls/wldap32/delete.c +++ b/dlls/wldap32/delete.c @@ -93,14 +93,16 @@ exit: ULONG CDECL ldap_delete_extW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), serverctrls, clientctrls, message );
if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = dn ? strWtoU( dn ) : strdup( "" ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; @@ -147,14 +149,16 @@ exit: */ ULONG CDECL ldap_delete_ext_sW( LDAP *ld, WCHAR *dn, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
TRACE( "(%p, %s, %p, %p)\n", ld, debugstr_w(dn), serverctrls, clientctrls );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = dn ? strWtoU( dn ) : strdup( "" ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit; diff --git a/dlls/wldap32/extended.c b/dlls/wldap32/extended.c index b168615c0fc..ce4773e6961 100644 --- a/dlls/wldap32/extended.c +++ b/dlls/wldap32/extended.c @@ -72,7 +72,7 @@ exit: ULONG CDECL ldap_extended_operationW( LDAP *ld, WCHAR *oid, struct WLDAP32_berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *oidU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; struct berval *dataU = NULL; @@ -80,7 +80,9 @@ ULONG CDECL ldap_extended_operationW( LDAP *ld, WCHAR *oid, struct WLDAP32_berva TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_w(oid), data, serverctrls, clientctrls, message );
if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (oid && !(oidU = strWtoU( oid ))) goto exit; if (data && !(dataU = bervalWtoU( data ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; @@ -138,7 +140,7 @@ exit: ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct WLDAP32_berval *data, LDAPControlW **serverctrls, LDAPControlW **clientctrls, WCHAR **retoid, struct WLDAP32_berval **retdata ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *oidU = NULL, *retoidU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; struct berval *retdataU, *dataU = NULL; @@ -146,7 +148,9 @@ ULONG CDECL ldap_extended_operation_sW( LDAP *ld, WCHAR *oid, struct WLDAP32_ber TRACE( "(%p, %s, %p, %p, %p, %p, %p)\n", ld, debugstr_w(oid), data, serverctrls, clientctrls, retoid, retdata );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (oid && !(oidU = strWtoU( oid ))) goto exit; if (data && !(dataU = bervalWtoU( data ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; diff --git a/dlls/wldap32/init.c b/dlls/wldap32/init.c index 78891d9be61..e68782add8d 100644 --- a/dlls/wldap32/init.c +++ b/dlls/wldap32/init.c @@ -24,6 +24,8 @@ #include "winbase.h" #include "winnls.h" #include "winternl.h" +#include "schannel.h" +#include "sspi.h"
#include "wine/debug.h" #include "winldap_private.h" @@ -248,6 +250,9 @@ exit: */ ULONG CDECL WLDAP32_ldap_connect( LDAP *ld, struct l_timeval *timeout ) { + VERIFYSERVERCERT *cert_callback = CERT_CALLBACK(ld); + int ret; + TRACE( "(%p, %p)\n", ld, timeout );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; @@ -255,7 +260,32 @@ ULONG CDECL WLDAP32_ldap_connect( LDAP *ld, struct l_timeval *timeout ) if (timeout && (timeout->tv_sec || timeout->tv_usec)) FIXME( "ignoring timeout\n" );
- return map_error( ldap_connect( CTX(ld) ) ); + if ((ret = ldap_connect( CTX(ld) ))) + return map_error( ret ); + + if (cert_callback) + { + CtxtHandle *tls_context; + const CERT_CONTEXT *cert; + + if ((ret = ldap_get_option( CTX(ld), LDAP_OPT_X_TLS_SSL_CTX, &tls_context ))) + return map_error( ret ); + + if (QueryContextAttributesA( tls_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &cert ) != SEC_E_OK) + return WLDAP32_LDAP_SERVER_DOWN; + + if (cert_callback( ld, &cert )) + { + TRACE( "accepted\n" ); + } + else + { + WARN( "rejected\n" ); + return WLDAP32_LDAP_SERVER_DOWN; + } + } + + return WLDAP32_LDAP_SUCCESS; }
/*********************************************************************** @@ -427,6 +457,8 @@ ULONG CDECL ldap_start_tls_sW( LDAP *ld, ULONG *retval, LDAPMessage **result, LD else { ret = map_error( ldap_start_tls_s( CTX(ld), serverctrlsU, clientctrlsU ) ); + if (!ret && WLDAP32_ldap_connect( ld, NULL ) != WLDAP32_LDAP_SUCCESS) + ret = WLDAP32_LDAP_LOCAL_ERROR; }
exit: diff --git a/dlls/wldap32/modify.c b/dlls/wldap32/modify.c index 2dea3279151..6daa0d7b0f7 100644 --- a/dlls/wldap32/modify.c +++ b/dlls/wldap32/modify.c @@ -102,7 +102,7 @@ exit: ULONG CDECL ldap_modify_extW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL; LDAPMod **modsU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; @@ -110,7 +110,9 @@ ULONG CDECL ldap_modify_extW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW TRACE( "(%p, %s, %p, %p, %p, %p)\n", ld, debugstr_w(dn), mods, serverctrls, clientctrls, message );
if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = dn ? strWtoU( dn ) : strdup( "" ))) goto exit; if (mods && !(modsU = modarrayWtoU( mods ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; @@ -164,7 +166,7 @@ exit: ULONG CDECL ldap_modify_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL; LDAPMod **modsU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; @@ -172,7 +174,9 @@ ULONG CDECL ldap_modify_ext_sW( LDAP *ld, WCHAR *dn, LDAPModW **mods, LDAPContro TRACE( "(%p, %s, %p, %p, %p)\n", ld, debugstr_w(dn), mods, serverctrls, clientctrls );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (!(dnU = dn ? strWtoU( dn ) : strdup( "" ))) goto exit; if (mods && !(modsU = modarrayWtoU( mods ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; diff --git a/dlls/wldap32/modrdn.c b/dlls/wldap32/modrdn.c index 4acf16eb5e4..e61ab48200c 100644 --- a/dlls/wldap32/modrdn.c +++ b/dlls/wldap32/modrdn.c @@ -88,23 +88,21 @@ exit: */ ULONG CDECL ldap_modrdn2W( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret = ~0u; char *dnU = NULL, *newdnU = NULL; int msg;
TRACE( "(%p, %s, %p, 0x%02x)\n", ld, debugstr_w(dn), newdn, delete );
if (!ld || !newdn) return ~0u; + if (WLDAP32_ldap_connect( ld, NULL ) != WLDAP32_LDAP_SUCCESS) return ~0u;
- if (dn && !(dnU = strWtoU( dn ))) return WLDAP32_LDAP_NO_MEMORY; + if (dn && !(dnU = strWtoU( dn ))) return ~0u;
if ((newdnU = strWtoU( newdn ))) { - ret = ldap_rename( CTX(ld), dnU, newdnU, NULL, delete, NULL, NULL, &msg ); - if (ret == WLDAP32_LDAP_SUCCESS) + if (ldap_rename( CTX(ld), dnU, newdnU, NULL, delete, NULL, NULL, &msg ) == LDAP_SUCCESS) ret = msg; - else - ret = ~0u; free( newdnU ); } free( dnU ); @@ -139,15 +137,17 @@ exit: */ ULONG CDECL ldap_modrdn2_sW( LDAP *ld, WCHAR *dn, WCHAR *newdn, int delete ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL, *newdnU = NULL;
TRACE( "(%p, %s, %p, 0x%02x)\n", ld, debugstr_w(dn), newdn, delete );
if (!ld || !newdn) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
if (dn && !(dnU = strWtoU( dn ))) return WLDAP32_LDAP_NO_MEMORY;
+ ret = WLDAP32_LDAP_NO_MEMORY; if ((newdnU = strWtoU( newdn ))) { ret = map_error( ldap_rename_s( CTX(ld), dnU, newdnU, NULL, delete, NULL, NULL ) ); diff --git a/dlls/wldap32/option.c b/dlls/wldap32/option.c index 2a2b7e9a517..38398c6d46c 100644 --- a/dlls/wldap32/option.c +++ b/dlls/wldap32/option.c @@ -291,6 +291,7 @@ ULONG CDECL ldap_set_optionA( LDAP *ld, int option, void *value ) case WLDAP32_LDAP_OPT_PROTOCOL_VERSION: case WLDAP32_LDAP_OPT_REFERRALS: case WLDAP32_LDAP_OPT_REFERRAL_HOP_LIMIT: + case WLDAP32_LDAP_OPT_SERVER_CERTIFICATE: case WLDAP32_LDAP_OPT_SIZELIMIT: case WLDAP32_LDAP_OPT_SSL: case WLDAP32_LDAP_OPT_TIMELIMIT: @@ -330,7 +331,6 @@ ULONG CDECL ldap_set_optionA( LDAP *ld, int option, void *value ) case WLDAP32_LDAP_OPT_SASL_METHOD: case WLDAP32_LDAP_OPT_SECURITY_CONTEXT: case WLDAP32_LDAP_OPT_SEND_TIMEOUT: - case WLDAP32_LDAP_OPT_SERVER_CERTIFICATE: case WLDAP32_LDAP_OPT_SERVER_ERROR: case WLDAP32_LDAP_OPT_SERVER_EXT_ERROR: case WLDAP32_LDAP_OPT_SIGN: @@ -443,6 +443,10 @@ ULONG CDECL ldap_set_optionW( LDAP *ld, int option, void *value ) FIXME( "ignoring referral hop limit\n" ); return WLDAP32_LDAP_SUCCESS;
+ case WLDAP32_LDAP_OPT_SERVER_CERTIFICATE: + CERT_CALLBACK(ld) = value; + return WLDAP32_LDAP_SUCCESS; + case WLDAP32_LDAP_OPT_DEREF: case WLDAP32_LDAP_OPT_DESC: case WLDAP32_LDAP_OPT_ERROR_NUMBER: @@ -515,7 +519,6 @@ ULONG CDECL ldap_set_optionW( LDAP *ld, int option, void *value ) case WLDAP32_LDAP_OPT_SASL_METHOD: case WLDAP32_LDAP_OPT_SECURITY_CONTEXT: case WLDAP32_LDAP_OPT_SEND_TIMEOUT: - case WLDAP32_LDAP_OPT_SERVER_CERTIFICATE: case WLDAP32_LDAP_OPT_SERVER_ERROR: case WLDAP32_LDAP_OPT_SERVER_EXT_ERROR: case WLDAP32_LDAP_OPT_SIGN: diff --git a/dlls/wldap32/rename.c b/dlls/wldap32/rename.c index f2b224b3d0f..b8d4a50a3af 100644 --- a/dlls/wldap32/rename.c +++ b/dlls/wldap32/rename.c @@ -66,7 +66,7 @@ exit: ULONG CDECL ldap_rename_extW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newparent, int delete, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG *message ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *dnU = NULL, *newrdnU = NULL, *newparentU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
@@ -74,7 +74,9 @@ ULONG CDECL ldap_rename_extW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newpare delete, serverctrls, clientctrls, message );
if (!ld || !message) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (dn && !(dnU = strWtoU( dn ))) goto exit; if (newrdn && !(newrdnU = strWtoU( newrdn ))) goto exit; if (newparent && !(newparentU = strWtoU( newparent ))) goto exit; @@ -132,7 +134,7 @@ exit: ULONG CDECL ldap_rename_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newparent, int delete, LDAPControlW **serverctrls, LDAPControlW **clientctrls ) { - ULONG ret = WLDAP32_LDAP_PARAM_ERROR; + ULONG ret; char *dnU = NULL, *newrdnU = NULL, *newparentU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL;
@@ -140,7 +142,9 @@ ULONG CDECL ldap_rename_ext_sW( LDAP *ld, WCHAR *dn, WCHAR *newrdn, WCHAR *newpa delete, serverctrls, clientctrls );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, NULL ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (dn && !(dnU = strWtoU( dn ))) goto exit; if (newrdn && !(newrdnU = strWtoU( newrdn ))) goto exit; if (newparent && !(newparentU = strWtoU( newparent ))) goto exit; diff --git a/dlls/wldap32/search.c b/dlls/wldap32/search.c index 18a079dd5bc..03fe41b3794 100644 --- a/dlls/wldap32/search.c +++ b/dlls/wldap32/search.c @@ -109,25 +109,25 @@ ULONG CDECL ldap_search_extW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filter, LDAPControlW **serverctrls, LDAPControlW **clientctrls, ULONG timelimit, ULONG sizelimit, ULONG *message ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *baseU = NULL, *filterU = NULL, **attrsU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; - struct timeval timevalU; + struct l_timeval timevalW = { timelimit, 0 }; + struct timeval timevalU = { timelimit, 0 };
TRACE( "(%p, %s, %#lx, %s, %p, %#lx, %p, %p, %#lx, %#lx, %p)\n", ld, debugstr_w(base), scope, debugstr_w(filter), attrs, attrsonly, serverctrls, clientctrls, timelimit, sizelimit, message );
- if (!ld) return ~0u; + if (!ld) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, &timevalW ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (base && !(baseU = strWtoU( base ))) goto exit; if (filter && !(filterU = strWtoU( filter ))) goto exit; if (attrs && !(attrsU = strarrayWtoU( attrs ))) goto exit; if (serverctrls && !(serverctrlsU = controlarrayWtoU( serverctrls ))) goto exit; if (clientctrls && !(clientctrlsU = controlarrayWtoU( clientctrls ))) goto exit;
- timevalU.tv_sec = timelimit; - timevalU.tv_usec = 0; - ret = map_error( ldap_search_ext( CTX(ld), baseU, scope, filterU, attrsU, attrsonly, serverctrlsU, clientctrlsU, timelimit ? &timevalU : NULL, sizelimit, (int *)message ) ); exit: @@ -180,7 +180,7 @@ ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filte LDAPControlW **serverctrls, LDAPControlW **clientctrls, struct l_timeval *timeout, ULONG sizelimit, LDAPMessage **res ) { - ULONG ret = WLDAP32_LDAP_NO_MEMORY; + ULONG ret; char *baseU = NULL, *filterU = NULL, **attrsU = NULL; LDAPControl **serverctrlsU = NULL, **clientctrlsU = NULL; struct timeval timevalU; @@ -190,7 +190,9 @@ ULONG CDECL ldap_search_ext_sW( LDAP *ld, WCHAR *base, ULONG scope, WCHAR *filte debugstr_w(filter), attrs, attrsonly, serverctrls, clientctrls, timeout, sizelimit, res );
if (!ld || !res) return WLDAP32_LDAP_PARAM_ERROR; + if ((ret = WLDAP32_ldap_connect( ld, timeout ))) return ret;
+ ret = WLDAP32_LDAP_NO_MEMORY; if (base && !(baseU = strWtoU( base ))) goto exit; if (filter && !(filterU = strWtoU( filter ))) goto exit; if (attrs && !(attrsU = strarrayWtoU( attrs ))) goto exit; diff --git a/dlls/wldap32/tests/Makefile.in b/dlls/wldap32/tests/Makefile.in index 05fe5b9af6d..0911147a784 100644 --- a/dlls/wldap32/tests/Makefile.in +++ b/dlls/wldap32/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = wldap32.dll -IMPORTS = wldap32 +IMPORTS = crypt32 wldap32
C_SRCS = \ ber.c \ diff --git a/dlls/wldap32/tests/parse.c b/dlls/wldap32/tests/parse.c index 8cd313cd6ca..031b8bcb22a 100644 --- a/dlls/wldap32/tests/parse.c +++ b/dlls/wldap32/tests/parse.c @@ -544,6 +544,44 @@ static void test_opt_ssl(void) ldap_unbind( ld ); }
+static BOOLEAN CDECL verify_certificate( LDAP *ld, const CERT_CONTEXT **cert ) +{ + CertFreeCertificateContext(*cert); + return FALSE; +} + +static void test_opt_server_certificate(void) +{ + LDAP *ld; + ULONG ret, version = LDAP_VERSION3; + + ld = ldap_initA( (char *)"db.debian.org", 636 ); + ok( ld != NULL, "ldap_init failed\n" ); + ret = ldap_set_optionA( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + ok( !ret, "ldap_set_optionA should succeed, got %#lx\n", ret ); + ret = ldap_set_optionA( ld, LDAP_OPT_SSL, LDAP_OPT_ON ); + ok( !ret, "ldap_set_optionA should succeed, got %#lx\n", ret ); + ret = ldap_set_optionA( ld, LDAP_OPT_SERVER_CERTIFICATE, &verify_certificate ); + ok( !ret, "ldap_set_optionA should succeed, got %#lx\n", ret ); + ret = ldap_connect( ld, NULL ); + ok( ret == LDAP_SERVER_DOWN, "ldap_connect should fail, got %#lx\n", ret ); + ret = ldap_simple_bindA( ld, NULL, NULL ); + ok( ret == (ULONG)-1, "ldap_simple_bindA should fail, got %#lx\n", ret ); + ret = ldap_simple_bind_sA( ld, NULL, NULL ); + ok( ret == LDAP_SERVER_DOWN, "ldap_simple_bind_sA should fail, got %#lx\n", ret ); + ldap_unbind( ld ); + + ld = ldap_initA( (char *)"db.debian.org", 389 ); + ok( ld != NULL, "ldap_init failed\n" ); + ret = ldap_set_optionA( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + ok( !ret, "ldap_set_optionA should succeed, got %#lx\n", ret ); + ret = ldap_set_optionA( ld, LDAP_OPT_SERVER_CERTIFICATE, &verify_certificate ); + ok( !ret, "ldap_set_optionA should succeed, got %#lx\n", ret ); + ret = ldap_start_tls_sA( ld, NULL, NULL, NULL, NULL ); + ok( ret == LDAP_LOCAL_ERROR, "ldap_start_tls_sA should fail, got %#lx\n", ret ); + ldap_unbind( ld ); +} + START_TEST (parse) { LDAP *ld; @@ -552,6 +590,7 @@ START_TEST (parse) test_ldap_server_control(); test_ldap_bind_sA(); test_opt_ssl(); + test_opt_server_certificate();
ld = ldap_initA( (char *)"db.debian.org", 389 ); ok( ld != NULL, "ldap_init failed\n" ); diff --git a/dlls/wldap32/winldap_private.h b/dlls/wldap32/winldap_private.h index 7adf77f151e..249af99e51e 100644 --- a/dlls/wldap32/winldap_private.h +++ b/dlls/wldap32/winldap_private.h @@ -21,6 +21,7 @@ #include <assert.h> #include <stdlib.h> #include "winternl.h" +#include "wincrypt.h" #include "winnls.h"
#define LDAP_NEEDS_PROTOTYPES @@ -362,8 +363,18 @@ typedef struct ldapsearch struct WLDAP32_berval *cookie; } LDAPSearch;
-#define CTX(ld) (*(LDAP **)ld->Reserved3) -#define SERVER_CTRLS(ld) (*(struct berval ***)(ld->Reserved3 + sizeof(LDAP *))) +typedef BOOLEAN (CDECL VERIFYSERVERCERT)(LDAP*,const CERT_CONTEXT**); + +struct private_data +{ + LDAP *ctx; + struct berval **server_ctrls; + VERIFYSERVERCERT *cert_callback; +}; + +#define CTX(ld) (((struct private_data *)ld->Reserved3)->ctx) +#define SERVER_CTRLS(ld) (((struct private_data *)ld->Reserved3)->server_ctrls) +#define CERT_CALLBACK(ld) (((struct private_data *)ld->Reserved3)->cert_callback) #define MSG(entry) (entry->Request) #define BER(ber) ((BerElement *)((ber)->opaque))
@@ -423,6 +434,7 @@ ULONG CDECL ldap_compare_ext_sW( LDAP *, WCHAR *, WCHAR *, WCHAR *, struct WLDAP LDAPControlW ** ); ULONG CDECL ldap_compare_sA( LDAP *, char *, char *, char * ); ULONG CDECL ldap_compare_sW( LDAP *, WCHAR *, WCHAR *, WCHAR * ); +ULONG CDECL WLDAP32_ldap_connect( LDAP *, struct l_timeval * ); ULONG CDECL ldap_create_sort_controlA( LDAP *, LDAPSortKeyA **, UCHAR, LDAPControlA ** ); ULONG CDECL ldap_create_sort_controlW( LDAP *, LDAPSortKeyW **, UCHAR, LDAPControlW ** ); int CDECL ldap_create_vlv_controlA( LDAP *, WLDAP32_LDAPVLVInfo *, UCHAR, LDAPControlA ** ); diff --git a/include/winldap.h b/include/winldap.h index 825d3f63b1e..9e91d0e653a 100644 --- a/include/winldap.h +++ b/include/winldap.h @@ -391,6 +391,8 @@ typedef struct ldap_apifeature_infoW
DECL_WINELIB_TYPE_AW(LDAPAPIFeatureInfo)
+typedef BOOLEAN (CDECL VERIFYSERVERCERT)(LDAP*,const CERT_CONTEXT**); +
#ifdef __cplusplus extern "C" { diff --git a/libs/ldap/libldap/tls_w.c b/libs/ldap/libldap/tls_w.c index bc64b9f62e5..c798d4249c0 100644 --- a/libs/ldap/libldap/tls_w.c +++ b/libs/ldap/libldap/tls_w.c @@ -46,8 +46,8 @@ typedef struct tlsw_ctx { } tlsw_ctx;
typedef struct tlsw_session { + CtxtHandle ctxt_handle; /* ctxt_handle must be the first field */ CredHandle cred_handle; - CtxtHandle ctxt_handle; Sockbuf_IO_Desc *sbiod; struct berval peer_der_dn; } tlsw_session;
Thank you for the careful review. I wish I had caught those mistakes before resubmitting last night. It should all be fixed now.