[PATCH] secur32: Add support for SCH_CREDENTIALS.

Hans Leidekker hans at codeweavers.com
Wed May 25 05:09:01 CDT 2022


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/secur32/schannel.c       | 104 +++++++++++++++++++++++++---------
 dlls/secur32/tests/schannel.c |  11 +++-
 include/schannel.h            |  49 ++++++++++++++++
 3 files changed, 137 insertions(+), 27 deletions(-)

diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index c7d62c47758..bbbac37c6bb 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -31,6 +31,7 @@
 #include "winnls.h"
 #include "lmcons.h"
 #include "sspi.h"
+#define SCHANNEL_USE_BLACKLISTS
 #include "schannel.h"
 
 #include "wine/unixlib.h"
@@ -333,46 +334,74 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryCredentialsAttributesW(
     return ret;
 }
 
-static SECURITY_STATUS get_cert(const SCHANNEL_CRED *cred, CERT_CONTEXT const **cert)
+static SECURITY_STATUS get_cert(const void *credentials, CERT_CONTEXT const **cert)
 {
     SECURITY_STATUS status;
-    DWORD i;
-
-    TRACE("dwVersion = %lu\n", cred->dwVersion);
-    TRACE("cCreds = %lu\n", cred->cCreds);
-    TRACE("paCred = %p\n", cred->paCred);
-    TRACE("hRootStore = %p\n", cred->hRootStore);
-    TRACE("cMappers = %lu\n", cred->cMappers);
-    TRACE("cSupportedAlgs = %lu:\n", cred->cSupportedAlgs);
-    for (i = 0; i < cred->cSupportedAlgs; i++) TRACE("%08x\n", cred->palgSupportedAlgs[i]);
-    TRACE("grbitEnabledProtocols = %08lx\n", cred->grbitEnabledProtocols);
-    TRACE("dwMinimumCipherStrength = %lu\n", cred->dwMinimumCipherStrength);
-    TRACE("dwMaximumCipherStrength = %lu\n", cred->dwMaximumCipherStrength);
-    TRACE("dwSessionLifespan = %lu\n", cred->dwSessionLifespan);
-    TRACE("dwFlags = %08lx\n", cred->dwFlags);
-    TRACE("dwCredFormat = %lu\n", cred->dwCredFormat);
+    const SCHANNEL_CRED *cred_old;
+    const SCH_CREDENTIALS *cred = credentials;
+    PCCERT_CONTEXT *cert_list;
+    DWORD i, cert_count;
 
     switch (cred->dwVersion)
     {
     case SCH_CRED_V3:
     case SCHANNEL_CRED_VERSION:
+        cred_old = credentials;
+        TRACE("dwVersion = %lu\n", cred_old->dwVersion);
+        TRACE("cCreds = %lu\n", cred_old->cCreds);
+        TRACE("paCred = %p\n", cred_old->paCred);
+        TRACE("hRootStore = %p\n", cred_old->hRootStore);
+        TRACE("cMappers = %lu\n", cred_old->cMappers);
+        TRACE("cSupportedAlgs = %lu:\n", cred_old->cSupportedAlgs);
+        for (i = 0; i < cred_old->cSupportedAlgs; i++) TRACE("%08x\n", cred_old->palgSupportedAlgs[i]);
+        TRACE("grbitEnabledProtocols = %08lx\n", cred_old->grbitEnabledProtocols);
+        TRACE("dwMinimumCipherStrength = %lu\n", cred_old->dwMinimumCipherStrength);
+        TRACE("dwMaximumCipherStrength = %lu\n", cred_old->dwMaximumCipherStrength);
+        TRACE("dwSessionLifespan = %lu\n", cred_old->dwSessionLifespan);
+        TRACE("dwFlags = %08lx\n", cred_old->dwFlags);
+        TRACE("dwCredFormat = %lu\n", cred_old->dwCredFormat);
+        cert_list = cred_old->paCred;
+        cert_count = cred_old->cCreds;
         break;
+
+    case SCH_CREDENTIALS_VERSION:
+        TRACE("dwVersion = %lu\n", cred->dwVersion);
+        TRACE("dwCredFormat = %lu\n", cred->dwCredFormat);
+        TRACE("cCreds = %lu\n", cred->cCreds);
+        TRACE("paCred = %p\n", cred->paCred);
+        TRACE("hRootStore = %p\n", cred->hRootStore);
+        TRACE("cMappers = %lu\n", cred->cMappers);
+        TRACE("dwSessionLifespan = %lu\n", cred->dwSessionLifespan);
+        TRACE("dwFlags = %08lx\n", cred->dwFlags);
+        TRACE("cTlsParameters = %lu:\n", cred->cTlsParameters);
+        for (i = 0; i < cred->cTlsParameters; i++)
+        {
+            TRACE(" cAlpnIds %lu\n", cred->pTlsParameters[i].cAlpnIds);
+            TRACE(" grbitDisabledProtocols %08lx\n", cred->pTlsParameters[i].grbitDisabledProtocols);
+            TRACE(" cDisabledCrypto %lu\n", cred->pTlsParameters[i].cDisabledCrypto);
+            TRACE(" dwFlags %08lx\n", cred->pTlsParameters[i].dwFlags);
+        }
+        cert_list = cred->paCred;
+        cert_count = cred->cCreds;
+        break;
+
     default:
+        FIXME("unhandled version %lu\n", cred->dwVersion);
         return SEC_E_INTERNAL_ERROR;
     }
 
-    if (!cred->cCreds) status = SEC_E_NO_CREDENTIALS;
-    else if (cred->cCreds > 1) status = SEC_E_UNKNOWN_CREDENTIALS;
+    if (!cert_count) status = SEC_E_NO_CREDENTIALS;
+    else if (cert_count > 1) status = SEC_E_UNKNOWN_CREDENTIALS;
     else
     {
         DWORD spec;
         HCRYPTPROV prov;
         BOOL free;
 
-        if (CryptAcquireCertificatePrivateKey(cred->paCred[0], CRYPT_ACQUIRE_CACHE_FLAG, NULL, &prov, &spec, &free))
+        if (CryptAcquireCertificatePrivateKey(cert_list[0], CRYPT_ACQUIRE_CACHE_FLAG, NULL, &prov, &spec, &free))
         {
             if (free) CryptReleaseContext(prov, 0);
-            *cert = cred->paCred[0];
+            *cert = cert_list[0];
             status = SEC_E_OK;
         }
         else status = SEC_E_UNKNOWN_CREDENTIALS;
@@ -381,6 +410,28 @@ static SECURITY_STATUS get_cert(const SCHANNEL_CRED *cred, CERT_CONTEXT const **
     return status;
 }
 
+static DWORD get_enabled_protocols(const void *credentials)
+{
+    const SCHANNEL_CRED *cred_old;
+    const SCH_CREDENTIALS *cred = credentials;
+
+    switch (cred->dwVersion)
+    {
+    case SCH_CRED_V3:
+    case SCHANNEL_CRED_VERSION:
+        cred_old = credentials;
+        return cred_old->grbitEnabledProtocols;
+
+    case SCH_CREDENTIALS_VERSION:
+        if (cred->cTlsParameters) FIXME("handle TLS parameters\n");
+        return 0;
+
+    default:
+        FIXME("unhandled version %lu\n", cred->dwVersion);
+        return 0;
+    }
+}
+
 static WCHAR *get_key_container_path(const CERT_CONTEXT *ctx)
 {
     CERT_KEY_CONTEXT keyctx;
@@ -486,11 +537,11 @@ static BYTE *get_key_blob(const CERT_CONTEXT *ctx, DWORD *size)
     return ret;
 }
 
-static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schanCred,
+static SECURITY_STATUS schan_AcquireClientCredentials(const void *schanCred,
  PCredHandle phCredential, PTimeStamp ptsExpiry)
 {
     struct schan_credentials *creds;
-    unsigned enabled_protocols;
+    DWORD enabled_protocols, cred_enabled_protocols;
     ULONG_PTR handle;
     SECURITY_STATUS status = SEC_E_OK;
     const CERT_CONTEXT *cert = NULL;
@@ -509,15 +560,16 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan
         if (status != SEC_E_OK && status != SEC_E_NO_CREDENTIALS)
             return status;
 
-        if ((schanCred->grbitEnabledProtocols & tls_protocols) &&
-            (schanCred->grbitEnabledProtocols & dtls_protocols)) return SEC_E_ALGORITHM_MISMATCH;
+        cred_enabled_protocols = get_enabled_protocols(schanCred);
+        if ((cred_enabled_protocols & tls_protocols) &&
+            (cred_enabled_protocols & dtls_protocols)) return SEC_E_ALGORITHM_MISMATCH;
 
         status = SEC_E_OK;
     }
 
     read_config();
-    if(schanCred && schanCred->grbitEnabledProtocols)
-        enabled_protocols = schanCred->grbitEnabledProtocols & config_enabled_protocols;
+    if(schanCred && cred_enabled_protocols)
+        enabled_protocols = cred_enabled_protocols & config_enabled_protocols;
     else
         enabled_protocols = config_enabled_protocols & ~config_default_disabled_protocols;
     if(!enabled_protocols) {
diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c
index 1cf751a3198..2bf0336f3f5 100644
--- a/dlls/secur32/tests/schannel.c
+++ b/dlls/secur32/tests/schannel.c
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #define SECURITY_WIN32
 #include <security.h>
+#define SCHANNEL_USE_BLACKLISTS
 #include <schannel.h>
 
 #include "wine/test.h"
@@ -272,6 +273,7 @@ static void testAcquireSecurityContext(void)
     SecPkgCredentials_NamesA names;
     TimeStamp exp;
     SCHANNEL_CRED schanCred;
+    SCH_CREDENTIALS schCred;
     PCCERT_CONTEXT certs[2];
     HCRYPTPROV csp;
     WCHAR ms_def_prov_w[MAX_PATH];
@@ -279,7 +281,6 @@ static void testAcquireSecurityContext(void)
     HCRYPTKEY key;
     CRYPT_KEY_PROV_INFO keyProvInfo;
 
-
     if (SUCCEEDED(EnumerateSecurityPackagesA(&i, &package_info)))
     {
         while(i--)
@@ -545,6 +546,14 @@ static void testAcquireSecurityContext(void)
         CryptDestroyKey(key);
     }
 
+    memset(&schCred, 0, sizeof(schCred));
+    schCred.dwVersion = SCH_CREDENTIALS_VERSION;
+    st = AcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
+     NULL, &schCred, NULL, NULL, &cred, NULL);
+    ok(st == SEC_E_OK || broken(st == SEC_E_UNKNOWN_CREDENTIALS) /* <= win10v1570 */,
+       "AcquireCredentialsHandleA failed: %08lx\n", st);
+    FreeCredentialsHandle(&cred);
+
     CryptReleaseContext(csp, 0);
     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
 
diff --git a/include/schannel.h b/include/schannel.h
index b60fdf7ad47..556ec1882c9 100644
--- a/include/schannel.h
+++ b/include/schannel.h
@@ -80,6 +80,7 @@ static const WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l',0 };
 #define SCH_CRED_VERSION      2
 #define SCH_CRED_V3           3
 #define SCHANNEL_CRED_VERSION 4
+#define SCH_CREDENTIALS_VERSION 5
 
 #define SCHANNEL_RENEGOTIATE 0
 #define SCHANNEL_SHUTDOWN    1
@@ -216,6 +217,54 @@ typedef struct _SCHANNEL_CRED
     DWORD dwCredFormat;
 } SCHANNEL_CRED, *PSCHANNEL_CRED;
 
+#ifdef SCHANNEL_USE_BLACKLISTS
+
+typedef enum _eTlsAlgorithmUsage
+{
+    TlsParametersCngAlgUsageKeyExchange,
+    TlsParametersCngAlgUsageSignature,
+    TlsParametersCngAlgUsageCipher,
+    TlsParametersCngAlgUsageDigest,
+    TlsParametersCngAlgUsageCertSig,
+} eTlsAlgorithmUsage;
+
+typedef struct _CRYPTO_SETTINGS
+{
+    eTlsAlgorithmUsage eAlgorithmUsage;
+    UNICODE_STRING     strCngAlgId;
+    DWORD              cChainingModes;
+    PUNICODE_STRING    rgstrChainingModes;
+    DWORD              dwMinBitLength;
+    DWORD              dwMaxBitLength;
+} CRYPTO_SETTINGS, *PCRYPTO_SETTINGS;
+
+typedef struct _TLS_PARAMETERS
+{
+    DWORD            cAlpnIds;
+    PUNICODE_STRING  rgstrAlpnIds;
+    DWORD            grbitDisabledProtocols;
+    DWORD            cDisabledCrypto;
+    PCRYPTO_SETTINGS pDisabledCrypto;
+    DWORD            dwFlags;
+} TLS_PARAMETERS, *PTLS_PARAMETERS;
+
+typedef struct _SCH_CREDENTIALS
+{
+    DWORD             dwVersion;
+    DWORD             dwCredFormat;
+    DWORD             cCreds;
+    PCCERT_CONTEXT   *paCred;
+    HCERTSTORE        hRootStore;
+    DWORD             cMappers;
+    struct _HMAPPER **aphMappers;
+    DWORD             dwSessionLifespan;
+    DWORD             dwFlags;
+    DWORD             cTlsParameters;
+    PTLS_PARAMETERS   pTlsParameters;
+} SCH_CREDENTIALS, *PSCH_CREDENTIALS;
+
+#endif
+
 typedef struct _SecPkgCred_SupportedAlgs
 {
     DWORD cSupportedAlgs;
-- 
2.30.2




More information about the wine-devel mailing list