Damjan Jovanovic : secur32: Implement the SECPKG_ATTR_UNIQUE_BINDINGS context attribute.

Alexandre Julliard julliard at winehq.org
Thu Jan 28 15:41:41 CST 2021


Module: wine
Branch: master
Commit: de9238962c237f0d4463199a0a1f9f6b6835aed5
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=de9238962c237f0d4463199a0a1f9f6b6835aed5

Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date:   Thu Jan 28 19:02:39 2021 +0200

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 at gmail.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

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




More information about the wine-cvs mailing list