Jacek Caban : secur32: Added support for SECPKG_ATTR_ENDPOINT_BINDINGS in schannel.

Alexandre Julliard julliard at winehq.org
Thu Mar 2 16:09:55 CST 2017


Module: wine
Branch: master
Commit: 0706ba1114dc5c6a24d1ae21334bc88415c0d359
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0706ba1114dc5c6a24d1ae21334bc88415c0d359

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Mar  2 13:45:53 2017 +0100

secur32: Added support for SECPKG_ATTR_ENDPOINT_BINDINGS in schannel.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/secur32/schannel.c       | 78 +++++++++++++++++++++++++++++++++++--------
 dlls/secur32/tests/schannel.c | 42 +++++++++++++++++++++++
 2 files changed, 107 insertions(+), 13 deletions(-)

diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index 71f219c..6914837 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -23,6 +23,7 @@
 #include <stdarg.h>
 #include <errno.h>
 
+#define NONAMELESSUNION
 #include "windef.h"
 #include "winbase.h"
 #include "winreg.h"
@@ -961,6 +962,23 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextA(
     return ret;
 }
 
+static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx)
+{
+    HCERTSTORE cert_store;
+    SECURITY_STATUS status;
+
+    if(ctx->cert)
+        return SEC_E_OK;
+
+    cert_store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
+    if(!cert_store)
+        return GetLastError();
+
+    status = schan_imp_get_session_peer_certificate(ctx->session, cert_store, &ctx->cert);
+    CertCloseStore(cert_store, 0);
+    return status;
+}
+
 static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
         PCtxtHandle context_handle, ULONG attribute, PVOID buffer)
 {
@@ -1001,20 +1019,11 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
         case SECPKG_ATTR_REMOTE_CERT_CONTEXT:
         {
             PCCERT_CONTEXT *cert = buffer;
+            SECURITY_STATUS status;
 
-            if (!ctx->cert) {
-                HCERTSTORE cert_store;
-                SECURITY_STATUS status;
-
-                cert_store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
-                if(!cert_store)
-                    return GetLastError();
-
-                status = schan_imp_get_session_peer_certificate(ctx->session, cert_store, &ctx->cert);
-                CertCloseStore(cert_store, 0);
-                if(status != SEC_E_OK)
-                    return status;
-            }
+            status = ensure_remote_cert(ctx);
+            if(status != SEC_E_OK)
+                return status;
 
             *cert = CertDuplicateCertificateContext(ctx->cert);
             return SEC_E_OK;
@@ -1024,6 +1033,47 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
             SecPkgContext_ConnectionInfo *info = buffer;
             return schan_imp_get_connection_info(ctx->session, info);
         }
+        case SECPKG_ATTR_ENDPOINT_BINDINGS:
+        {
+            SecPkgContext_Bindings *bindings = buffer;
+            CCRYPT_OID_INFO *info;
+            ALG_ID hash_alg = CALG_SHA_256;
+            BYTE hash[1024];
+            DWORD hash_size;
+            SECURITY_STATUS status;
+            char *p;
+            BOOL r;
+
+            static const char prefix[] = "tls-server-end-point:";
+
+            status = ensure_remote_cert(ctx);
+            if(status != SEC_E_OK)
+                return status;
+
+            /* RFC 5929 */
+            info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, ctx->cert->pCertInfo->SignatureAlgorithm.pszObjId, 0);
+            if(info && info->u.Algid != CALG_SHA1 && info->u.Algid != CALG_MD5)
+                hash_alg = info->u.Algid;
+
+            hash_size = sizeof(hash);
+            r = CryptHashCertificate(0, hash_alg, 0, ctx->cert->pbCertEncoded, ctx->cert->cbCertEncoded, hash, &hash_size);
+            if(!r)
+                return GetLastError();
+
+            bindings->BindingsLength = sizeof(*bindings->Bindings) + sizeof(prefix)-1 + hash_size;
+            bindings->Bindings = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bindings->BindingsLength);
+            if(!bindings->Bindings)
+                return SEC_E_INSUFFICIENT_MEMORY;
+
+            bindings->Bindings->cbApplicationDataLength = sizeof(prefix)-1 + hash_size;
+            bindings->Bindings->dwApplicationDataOffset = sizeof(*bindings->Bindings);
+
+            p = (char*)(bindings->Bindings+1);
+            memcpy(p, prefix, sizeof(prefix)-1);
+            p += sizeof(prefix)-1;
+            memcpy(p, hash, hash_size);
+            return SEC_E_OK;
+        }
 
         default:
             FIXME("Unhandled attribute %#x\n", attribute);
@@ -1045,6 +1095,8 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesA(
             return schan_QueryContextAttributesW(context_handle, attribute, buffer);
         case SECPKG_ATTR_CONNECTION_INFO:
             return schan_QueryContextAttributesW(context_handle, attribute, buffer);
+        case SECPKG_ATTR_ENDPOINT_BINDINGS:
+            return schan_QueryContextAttributesW(context_handle, attribute, buffer);
 
         default:
             FIXME("Unhandled attribute %#x\n", attribute);
diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c
index a858488..b52510d 100644
--- a/dlls/secur32/tests/schannel.c
+++ b/dlls/secur32/tests/schannel.c
@@ -870,7 +870,49 @@ todo_wine
     status = pQueryContextAttributesA(&context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
     ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed: %08x\n", status);
     if(status == SEC_E_OK) {
+        SecPkgContext_Bindings bindings = {0xdeadbeef, (void*)0xdeadbeef};
+
         test_remote_cert(cert);
+
+        status = pQueryContextAttributesA(&context, SECPKG_ATTR_ENDPOINT_BINDINGS, &bindings);
+        ok(status == SEC_E_OK || broken(status == SEC_E_UNSUPPORTED_FUNCTION),
+           "QueryContextAttributesW(SECPKG_ATTR_ENDPOINT_BINDINGS) failed: %08x\n", status);
+        if(status == SEC_E_OK) {
+            static const char prefix[] = "tls-server-end-point:";
+            const char *p;
+            BYTE hash[64];
+            DWORD hash_size;
+
+            ok(bindings.BindingsLength == sizeof(*bindings.Bindings) + sizeof(prefix)-1 + 32 /* hash size */,
+               "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), "missing prefix\n");
+            p += sizeof(prefix)-1;
+
+            hash_size = sizeof(hash);
+            ret = CryptHashCertificate(0, CALG_SHA_256, 0, cert->pbCertEncoded, cert->cbCertEncoded, hash, &hash_size);
+            if(ret) {
+                ok(hash_size == 32, "hash_size = %u\n", hash_size);
+                ok(!memcmp(hash, p, hash_size), "unexpected hash part\n");
+            }else {
+                win_skip("SHA 256 hash not supported.\n");
+            }
+
+            FreeContextBuffer(bindings.Bindings);
+        }else {
+            win_skip("SECPKG_ATTR_ENDPOINT_BINDINGS not supported\n");
+        }
+
         CertFreeCertificateContext(cert);
     }
 




More information about the wine-cvs mailing list