From de9238962c237f0d4463199a0a1f9f6b6835aed5 Mon Sep 17 00:00:00 2001 From: Damjan Jovanovic Date: Thu, 28 Jan 2021 19:02:39 +0200 Subject: [PATCH] secur32: Implement the SECPKG_ATTR_UNIQUE_BINDINGS context attribute. .NET's System.Data.SqlClient needs this to connect to MSSQL Server. Signed-off-by: Damjan Jovanovic Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/secur32/schannel.c | 7 +++++++ dlls/secur32/schannel_gnutls.c | 37 ++++++++++++++++++++++++++++++++++ dlls/secur32/schannel_macosx.c | 7 +++++++ dlls/secur32/secur32_priv.h | 2 ++ dlls/secur32/tests/schannel.c | 26 ++++++++++++++++++++++++ 5 files changed, 79 insertions(+) diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index e76a3e46c34..2d135a85227 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -1115,6 +1115,11 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( memcpy(p, hash, hash_size); return SEC_E_OK; } + case SECPKG_ATTR_UNIQUE_BINDINGS: + { + SecPkgContext_Bindings *bindings = buffer; + return schan_imp_get_unique_channel_binding(ctx->session, bindings); + } case SECPKG_ATTR_APPLICATION_PROTOCOL: { SecPkgContext_ApplicationProtocol *protocol = buffer; @@ -1154,6 +1159,8 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesA( return schan_QueryContextAttributesW(context_handle, attribute, buffer); case SECPKG_ATTR_ENDPOINT_BINDINGS: return schan_QueryContextAttributesW(context_handle, attribute, buffer); + case SECPKG_ATTR_UNIQUE_BINDINGS: + return schan_QueryContextAttributesW(context_handle, attribute, buffer); case SECPKG_ATTR_APPLICATION_PROTOCOL: return schan_QueryContextAttributesW(context_handle, attribute, buffer); diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 784c1ffe6e8..e342df3874d 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -95,6 +95,7 @@ MAKE_FUNCPTR(gnutls_record_get_max_size); MAKE_FUNCPTR(gnutls_record_recv); MAKE_FUNCPTR(gnutls_record_send); MAKE_FUNCPTR(gnutls_server_name_set); +MAKE_FUNCPTR(gnutls_session_channel_binding); MAKE_FUNCPTR(gnutls_transport_get_ptr); MAKE_FUNCPTR(gnutls_transport_set_errno); MAKE_FUNCPTR(gnutls_transport_set_ptr); @@ -507,6 +508,41 @@ SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session, return SEC_E_OK; } +SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session, + SecPkgContext_Bindings *bindings) +{ + static const char prefix[] = "tls-unique:"; + gnutls_datum_t datum; + int rc; + SECURITY_STATUS ret; + char *p; + gnutls_session_t s = (gnutls_session_t)session; + + rc = pgnutls_session_channel_binding(s, GNUTLS_CB_TLS_UNIQUE, &datum); + if (rc) + { + pgnutls_perror(rc); + return SEC_E_INTERNAL_ERROR; + } + + bindings->BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + sizeof(prefix)-1 + datum.size; + bindings->Bindings = heap_alloc_zero(bindings->BindingsLength); + if (!bindings->Bindings) + ret = SEC_E_INSUFFICIENT_MEMORY; + else + { + bindings->Bindings->cbApplicationDataLength = sizeof(prefix)-1 + datum.size; + bindings->Bindings->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS); + p = (char*)(bindings->Bindings+1); + memcpy(p, prefix, sizeof(prefix)-1); + p += sizeof(prefix)-1; + memcpy(p, datum.data, datum.size); + ret = SEC_E_OK; + } + free(datum.data); + return ret; +} + ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session) { gnutls_session_t s = (gnutls_session_t)session; @@ -1032,6 +1068,7 @@ BOOL schan_imp_init(void) LOAD_FUNCPTR(gnutls_record_recv); LOAD_FUNCPTR(gnutls_record_send); LOAD_FUNCPTR(gnutls_server_name_set) + LOAD_FUNCPTR(gnutls_session_channel_binding) LOAD_FUNCPTR(gnutls_transport_get_ptr) LOAD_FUNCPTR(gnutls_transport_set_errno) LOAD_FUNCPTR(gnutls_transport_set_ptr) diff --git a/dlls/secur32/schannel_macosx.c b/dlls/secur32/schannel_macosx.c index d725c9d22c2..6e6296722cc 100644 --- a/dlls/secur32/schannel_macosx.c +++ b/dlls/secur32/schannel_macosx.c @@ -1039,6 +1039,13 @@ SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session, return SEC_E_OK; } +SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session, + SecPkgContext_Bindings *bindings) +{ + FIXME("SECPKG_ATTR_UNIQUE_BINDINGS is unsupported on MacOS\n"); + return SEC_E_UNSUPPORTED_FUNCTION; +} + #ifndef HAVE_SSLCOPYPEERCERTIFICATES static void schan_imp_cf_release(const void *arg, void *ctx) { diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index c34d1d32566..ce8d55d1eb6 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -237,6 +237,8 @@ extern unsigned int schan_imp_get_max_message_size(schan_imp_session session) DE extern ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session) DECLSPEC_HIDDEN; extern SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session, SecPkgContext_ConnectionInfo *info) DECLSPEC_HIDDEN; +extern SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session, + SecPkgContext_Bindings *bindings) DECLSPEC_HIDDEN; extern SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE, PCCERT_CONTEXT *cert) DECLSPEC_HIDDEN; extern SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer, diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c index 30022437bc0..99adf0bbc19 100644 --- a/dlls/secur32/tests/schannel.c +++ b/dlls/secur32/tests/schannel.c @@ -925,6 +925,32 @@ todo_wine win_skip("SECPKG_ATTR_ENDPOINT_BINDINGS not supported\n"); } + status = pQueryContextAttributesA(&context, SECPKG_ATTR_UNIQUE_BINDINGS, &bindings); + ok(status == SEC_E_OK || broken(status == SEC_E_UNSUPPORTED_FUNCTION), + "QueryContextAttributesW(SECPKG_ATTR_UNIQUE_BINDINGS) failed: %08x\n", status); + if(status == SEC_E_OK) { + const char *p; + static const char prefix[] = "tls-unique:"; + + ok(bindings.BindingsLength > sizeof(*bindings.Bindings) + sizeof(prefix)-1, + "bindings.BindingsLength = %u\n", bindings.BindingsLength); + ok(!bindings.Bindings->dwInitiatorAddrType, "dwInitiatorAddrType = %x\n", bindings.Bindings->dwInitiatorAddrType); + ok(!bindings.Bindings->cbInitiatorLength, "cbInitiatorLength = %x\n", bindings.Bindings->cbInitiatorLength); + ok(!bindings.Bindings->dwInitiatorOffset, "dwInitiatorOffset = %x\n", bindings.Bindings->dwInitiatorOffset); + ok(!bindings.Bindings->dwAcceptorAddrType, "dwAcceptorAddrType = %x\n", bindings.Bindings->dwAcceptorAddrType); + ok(!bindings.Bindings->cbAcceptorLength, "cbAcceptorLength = %x\n", bindings.Bindings->cbAcceptorLength); + ok(!bindings.Bindings->dwAcceptorOffset, "dwAcceptorOffset = %x\n", bindings.Bindings->dwAcceptorOffset); + ok(sizeof(*bindings.Bindings) + bindings.Bindings->cbApplicationDataLength == bindings.BindingsLength, + "cbApplicationDataLength = %x\n", bindings.Bindings->cbApplicationDataLength); + ok(bindings.Bindings->dwApplicationDataOffset == sizeof(*bindings.Bindings), + "dwApplicationDataOffset = %x\n", bindings.Bindings->dwApplicationDataOffset); + p = (const char*)(bindings.Bindings+1); + ok(!memcmp(p, prefix, sizeof(prefix)-1), "wrong prefix\n"); + FreeContextBuffer(bindings.Bindings); + } else { + win_skip("SECPKG_ATTR_UNIQUE_BINDINGS not supported\n"); + } + CertFreeCertificateContext(cert); }