Jacek Caban : secur32: Added support for grbitEnabledProtocols in schan_AcquireClientCredentials.
Alexandre Julliard
julliard at winehq.org
Wed Mar 27 15:40:06 CDT 2013
Module: wine
Branch: master
Commit: 0f2e0365ea1f5c6baba4cfd9c0ff69defe66d7ea
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0f2e0365ea1f5c6baba4cfd9c0ff69defe66d7ea
Author: Jacek Caban <jacek at codeweavers.com>
Date: Wed Mar 27 12:22:23 2013 +0100
secur32: Added support for grbitEnabledProtocols in schan_AcquireClientCredentials.
---
dlls/secur32/schannel.c | 169 ++++++++++++++++++++++++++++++++++++-------
dlls/secur32/secur32_priv.h | 1 +
2 files changed, 145 insertions(+), 25 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index 387eaad..87bb942 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -25,10 +25,13 @@
#include "windef.h"
#include "winbase.h"
+#include "winreg.h"
#include "winnls.h"
#include "sspi.h"
#include "schannel.h"
#include "secur32_priv.h"
+
+#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
@@ -62,6 +65,12 @@ static struct schan_handle *schan_free_handles;
static SIZE_T schan_handle_table_size;
static SIZE_T schan_handle_count;
+/* Protocols enabled, only those may be used for the connection. */
+static DWORD config_enabled_protocols;
+
+/* Protocols disabled by default. They are enabled for using, but disabled when caller asks for default settings. */
+static DWORD config_default_disabled_protocols;
+
static ULONG_PTR schan_alloc_handle(void *object, enum schan_handle_type type)
{
struct schan_handle *handle;
@@ -141,11 +150,110 @@ static void *schan_get_object(ULONG_PTR handle_idx, enum schan_handle_type type)
return handle->object;
}
+static void read_config(void)
+{
+ DWORD enabled = 0, default_disabled = 0;
+ HKEY protocols_key, key;
+ WCHAR subkey_name[64];
+ unsigned i;
+ DWORD res;
+
+ static BOOL config_read = FALSE;
+
+ static const WCHAR protocol_config_key_name[] = {
+ 'S','Y','S','T','E','M','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'C','o','n','t','r','o','l','\\',
+ 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s','\\',
+ 'S','C','H','A','N','N','E','L','\\',
+ 'P','r','o','t','o','c','o','l','s',0 };
+
+ static const WCHAR clientW[] = {'\\','C','l','i','e','n','t',0};
+ static const WCHAR enabledW[] = {'e','n','a','b','l','e','d',0};
+ static const WCHAR disabledbydefaultW[] = {'D','i','s','a','b','l','e','d','B','y','D','e','f','a','u','l','t',0};
+
+ static const struct {
+ WCHAR key_name[20];
+ DWORD prot_client_flag;
+ BOOL enabled; /* If no config is present, enable the protocol */
+ BOOL disabled_by_default; /* Disable if caller asks for default protocol set */
+ } protocol_config_keys[] = {
+ {{'S','S','L',' ','2','.','0',0}, SP_PROT_SSL2_CLIENT, TRUE, TRUE},
+ {{'S','S','L',' ','3','.','0',0}, SP_PROT_SSL3_CLIENT, TRUE, FALSE},
+ {{'T','L','S',' ','1','.','0',0}, SP_PROT_TLS1_0_CLIENT, TRUE, FALSE},
+ {{'T','L','S',' ','1','.','1',0}, SP_PROT_TLS1_1_CLIENT, TRUE, FALSE /* NOTE: not enabled by default on Windows */ },
+ {{'T','L','S',' ','1','.','2',0}, SP_PROT_TLS1_2_CLIENT, TRUE, FALSE /* NOTE: not enabled by default on Windows */ }
+ };
+
+ /* No need for thread safety */
+ if(config_read)
+ return;
+
+ res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, protocol_config_key_name, 0, KEY_READ, &protocols_key);
+ if(res == ERROR_SUCCESS) {
+ DWORD type, size, value;
+
+ for(i=0; i < sizeof(protocol_config_keys)/sizeof(*protocol_config_keys); i++) {
+ strcpyW(subkey_name, protocol_config_keys[i].key_name);
+ strcatW(subkey_name, clientW);
+ res = RegOpenKeyExW(protocols_key, subkey_name, 0, KEY_READ, &key);
+ if(res != ERROR_SUCCESS) {
+ if(protocol_config_keys[i].enabled)
+ enabled |= protocol_config_keys[i].prot_client_flag;
+ if(protocol_config_keys[i].disabled_by_default)
+ default_disabled |= protocol_config_keys[i].prot_client_flag;
+ continue;
+ }
+
+ size = sizeof(value);
+ res = RegQueryValueExW(key, enabledW, NULL, &type, (BYTE*)&value, &size);
+ if(res == ERROR_SUCCESS) {
+ if(type == REG_DWORD && value)
+ enabled |= protocol_config_keys[i].prot_client_flag;
+ }else if(protocol_config_keys[i].enabled) {
+ enabled |= protocol_config_keys[i].prot_client_flag;
+ }
+
+ size = sizeof(value);
+ res = RegQueryValueExW(key, disabledbydefaultW, NULL, &type, (BYTE*)&value, &size);
+ if(res == ERROR_SUCCESS) {
+ if(type != REG_DWORD || value)
+ default_disabled |= protocol_config_keys[i].prot_client_flag;
+ }else if(protocol_config_keys[i].disabled_by_default) {
+ default_disabled |= protocol_config_keys[i].prot_client_flag;
+ }
+
+ RegCloseKey(key);
+ }
+ }else {
+ /* No config, enable all known protocols. */
+ for(i=0; i < sizeof(protocol_config_keys)/sizeof(*protocol_config_keys); i++) {
+ if(protocol_config_keys[i].enabled)
+ enabled |= protocol_config_keys[i].prot_client_flag;
+ if(protocol_config_keys[i].disabled_by_default)
+ default_disabled |= protocol_config_keys[i].prot_client_flag;
+ }
+ }
+
+ RegCloseKey(protocols_key);
+
+ config_enabled_protocols = enabled;
+ config_default_disabled_protocols = default_disabled;
+ config_read = TRUE;
+
+ TRACE("enabled %x, disabled by default %x\n", config_enabled_protocols, config_default_disabled_protocols);
+}
+
static SECURITY_STATUS schan_QueryCredentialsAttributes(
PCredHandle phCredential, ULONG ulAttribute, VOID *pBuffer)
{
+ struct schan_credentials *cred;
SECURITY_STATUS ret;
+ cred = schan_get_object(phCredential->dwLower, SCHAN_HANDLE_CRED);
+ if(!cred)
+ return SEC_E_INVALID_HANDLE;
+
switch (ulAttribute)
{
case SECPKG_ATTR_SUPPORTED_ALGS:
@@ -285,6 +393,8 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan
PCredHandle phCredential, PTimeStamp ptsExpiry)
{
struct schan_credentials *creds;
+ unsigned enabled_protocols;
+ ULONG_PTR handle;
SECURITY_STATUS st = SEC_E_OK;
TRACE("schanCred %p, phCredential %p, ptsExpiry %p\n", schanCred, phCredential, ptsExpiry);
@@ -292,40 +402,49 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan
if (schanCred)
{
st = schan_CheckCreds(schanCred);
- if (st == SEC_E_NO_CREDENTIALS)
- st = SEC_E_OK;
+ if (st != SEC_E_OK && st != SEC_E_NO_CREDENTIALS)
+ return st;
+
+ st = SEC_E_OK;
+ }
+
+ read_config();
+ if(schanCred && schanCred->grbitEnabledProtocols)
+ enabled_protocols = schanCred->grbitEnabledProtocols & config_enabled_protocols;
+ else
+ enabled_protocols = config_enabled_protocols & ~config_default_disabled_protocols;
+ if(!enabled_protocols) {
+ ERR("Could not find matching protocol\n");
+ return SEC_E_NO_AUTHENTICATING_AUTHORITY;
}
/* For now, the only thing I'm interested in is the direction of the
* connection, so just store it.
*/
- if (st == SEC_E_OK)
- {
- ULONG_PTR handle;
+ creds = HeapAlloc(GetProcessHeap(), 0, sizeof(*creds));
+ if (!creds) return SEC_E_INSUFFICIENT_MEMORY;
- creds = HeapAlloc(GetProcessHeap(), 0, sizeof(*creds));
- if (!creds) return SEC_E_INSUFFICIENT_MEMORY;
-
- handle = schan_alloc_handle(creds, SCHAN_HANDLE_CRED);
- if (handle == SCHAN_INVALID_HANDLE) goto fail;
+ handle = schan_alloc_handle(creds, SCHAN_HANDLE_CRED);
+ if (handle == SCHAN_INVALID_HANDLE) goto fail;
- creds->credential_use = SECPKG_CRED_OUTBOUND;
- if (!schan_imp_allocate_certificate_credentials(creds))
- {
- schan_free_handle(handle, SCHAN_HANDLE_CRED);
- goto fail;
- }
+ creds->credential_use = SECPKG_CRED_OUTBOUND;
+ if (!schan_imp_allocate_certificate_credentials(creds))
+ {
+ schan_free_handle(handle, SCHAN_HANDLE_CRED);
+ goto fail;
+ }
- phCredential->dwLower = handle;
- phCredential->dwUpper = 0;
+ creds->enabled_protocols = enabled_protocols;
+ phCredential->dwLower = handle;
+ phCredential->dwUpper = 0;
- /* Outbound credentials have no expiry */
- if (ptsExpiry)
- {
- ptsExpiry->LowPart = 0;
- ptsExpiry->HighPart = 0;
- }
+ /* Outbound credentials have no expiry */
+ if (ptsExpiry)
+ {
+ ptsExpiry->LowPart = 0;
+ ptsExpiry->HighPart = 0;
}
+
return st;
fail:
@@ -348,7 +467,7 @@ static SECURITY_STATUS schan_AcquireServerCredentials(const SCHANNEL_CRED *schan
ULONG_PTR handle;
struct schan_credentials *creds;
- creds = HeapAlloc(GetProcessHeap(), 0, sizeof(*creds));
+ creds = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*creds));
if (!creds) return SEC_E_INSUFFICIENT_MEMORY;
creds->credential_use = SECPKG_CRED_INBOUND;
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h
index bc4b74b..5b2ac89 100644
--- a/dlls/secur32/secur32_priv.h
+++ b/dlls/secur32/secur32_priv.h
@@ -214,6 +214,7 @@ typedef struct schan_credentials
{
ULONG credential_use;
void *credentials;
+ DWORD enabled_protocols;
} schan_credentials;
struct schan_transport;
More information about the wine-cvs
mailing list