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 <damjan.jov@gmail.com>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Damjan Jovanovic 2021-01-28 19:02:39 +02:00 committed by Alexandre Julliard
parent faa9f5be59
commit de9238962c
5 changed files with 79 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}