Signed-off-by: Hans Leidekker hans@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;