[PATCH] secur32/schannel: diabled TLS1.1/1.2 by Default

Hiroshi Miura miurahr at linux.com
Sun Sep 9 10:14:51 CDT 2012


   -Set TLS1.1/1.2 disabled by Default that is
    same as Windows 7 default.

    See registry entry for schannel and control
    enable/disable tls versions.

    It also see grbitEnabledProtocols defined in
    credentials that take precedence over registry.

   -Control a behavoir of unsafe renegotiation
    thru registry key MS10-049 shows.
     ie. 'AllowInsecureRenegoClients'

Signed-off-by: Hiroshi Miura <miurahr at linux.com>
---
 dlls/secur32/schannel_gnutls.c |  137 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 135 insertions(+), 2 deletions(-)

diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c
index 16ce0de..9ebc754 100644
--- a/dlls/secur32/schannel_gnutls.c
+++ b/dlls/secur32/schannel_gnutls.c
@@ -34,6 +34,7 @@
 #include "secur32_priv.h"
 #include "wine/debug.h"
 #include "wine/library.h"
+#include "winreg.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
 
@@ -60,6 +61,8 @@ MAKE_FUNCPTR(gnutls_kx_get);
 MAKE_FUNCPTR(gnutls_mac_get);
 MAKE_FUNCPTR(gnutls_mac_get_key_size);
 MAKE_FUNCPTR(gnutls_perror);
+MAKE_FUNCPTR(gnutls_priority_init);
+MAKE_FUNCPTR(gnutls_priority_set);
 MAKE_FUNCPTR(gnutls_protocol_get_version);
 MAKE_FUNCPTR(gnutls_set_default_priority);
 MAKE_FUNCPTR(gnutls_record_get_max_size);
@@ -106,10 +109,116 @@ static ssize_t schan_push_adapter(gnutls_transport_ptr_t transport,
     return buff_len;
 }
 
+#ifndef SSL_OP_NO_TLSv1_2
+#define SSL_OP_NO_TLSv1_2				0x08000000L
+#endif
+#ifndef SSL_OP_NO_TLSv1_1
+#define SSL_OP_NO_TLSv1_1				0x10000000L
+#endif
+#ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION	0x00040000L
+#endif
+
+static long schan_get_tls_option(void) { 
+    long tls_option=0;
+    DWORD type, val, size;
+    HKEY hkey,protocols,tls12_client,tls11_client;
+    LONG res;
+    const WCHAR Schannel[] = { /* SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCANNEL */
+              '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', 0};
+    const WCHAR Protocols[] = {'P','r','o','t','o','c','o','l','s',0};
+    const WCHAR AllowInsecureRenegoClients[] = {
+              'A','l','l','o','w','I','n','s','e','c','u','r','e','R','e','n','e','g','o',
+              'C','l','i','e','n','t','s', 0};
+#if 0
+    const WCHAR AllowInsecureRenegoServers[] = {
+              'A','l','l','o','w','I','n','s','e','c','u','r','e','R','e','n','e','g','o',
+              'S','e','r','v','e','r','s', 0};
+#endif
+    const WCHAR TLS12_Client[] = {'T','L','S',' ','1','.','2','\\','C','l','i','e','n','t',0};
+    const WCHAR TLS11_Client[] = {'T','L','S',' ','1','.','1','\\','C','l','i','e','n','t',0};
+    const WCHAR DisabledByDefault[] = {'D','i','s','a','b','l','e','d','B','y','D','e','f','a','u','l','t',0};
+
+    res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+          Schannel,
+          0, KEY_READ, &hkey);
+    if (res != ERROR_SUCCESS) {
+        tls_option |= SSL_OP_NO_TLSv1_2;
+        tls_option |= SSL_OP_NO_TLSv1_1;
+        goto end;
+    }
+
+    size = sizeof(DWORD);
+    if (RegQueryValueExW(hkey, AllowInsecureRenegoClients, NULL, &type,  (LPBYTE) &val, &size) == ERROR_SUCCESS 
+            && type == REG_DWORD) {
+        tls_option |= val?SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION:0;
+    } 
+    if (RegOpenKeyExW(hkey, Protocols, 0, KEY_READ, &protocols) == ERROR_SUCCESS) {
+        if (RegOpenKeyExW(protocols, TLS12_Client, 0, KEY_READ, &tls12_client) == ERROR_SUCCESS) {
+            size = sizeof(DWORD);
+            if (RegQueryValueExW(tls12_client, DisabledByDefault, NULL, &type,  (LPBYTE) &val, &size) || type != REG_DWORD) {
+                tls_option |= SSL_OP_NO_TLSv1_2;
+            } else {
+                tls_option |= val?SSL_OP_NO_TLSv1_2:0;
+            }
+            RegCloseKey(tls12_client);
+        } else {
+            tls_option |= SSL_OP_NO_TLSv1_2;
+        }
+        if (RegOpenKeyExW(protocols, TLS11_Client, 0, KEY_READ, &tls11_client) == ERROR_SUCCESS) {
+            size = sizeof(DWORD);
+            if (RegQueryValueExW(tls11_client, DisabledByDefault, NULL, &type,  (LPBYTE) &val, &size) || type != REG_DWORD) {
+                tls_option |= SSL_OP_NO_TLSv1_1;
+            } else {
+                tls_option |= val?SSL_OP_NO_TLSv1_1:0;
+            }
+            RegCloseKey(tls11_client);
+        } else {
+            tls_option |= SSL_OP_NO_TLSv1_1;
+        }
+        RegCloseKey(protocols);
+    }
+
+    RegCloseKey(hkey);
+end:
+    return tls_option;
+}
+
+static gnutls_priority_t gnutls_priorities[2][2][2];
+    /* fields: TLS1.1:TLS1.2:Unsafe renagotiation */
+
+static void schannel_gnutls_init_priorities (void)
+{
+    /* FIXME hardcoded "NORMAL" priority */
+    pgnutls_priority_init (&gnutls_priorities[FALSE][FALSE][FALSE],
+        "NORMAL:!VERS-TLS1.2:!VERS-TLS1.1", NULL);
+    pgnutls_priority_init (&gnutls_priorities[TRUE][FALSE][FALSE],
+        "NORMAL:!VERS-TLS1.2", NULL);
+    pgnutls_priority_init (&gnutls_priorities[FALSE][TRUE][FALSE],
+        "NORMAL:!VERS-TLS1.1", NULL);
+    pgnutls_priority_init (&gnutls_priorities[TRUE][TRUE][FALSE],
+        "NORMAL", NULL);
+
+    pgnutls_priority_init (&gnutls_priorities[FALSE][FALSE][TRUE],
+        "NORMAL:!VERS-TLS1.2:!VERS-TLS1.1:%UNSAFE_RENEGOTIATION", NULL);
+    pgnutls_priority_init (&gnutls_priorities[TRUE][FALSE][TRUE],
+        "NORMAL:!VERS-TLS1.2:%UNSAFE_RENEGOTIATION", NULL);
+    pgnutls_priority_init (&gnutls_priorities[FALSE][TRUE][TRUE],
+        "NORMAL:!VERS-TLS1.1:%UNSAFE_RENEGOTIATION", NULL);
+    pgnutls_priority_init (&gnutls_priorities[TRUE][TRUE][TRUE],
+        "NORMAL:%UNSAFE_RENEGOTIATION", NULL);
+}
+
 BOOL schan_imp_create_session(schan_imp_session *session, BOOL is_server,
                               schan_imp_certificate_credentials cred)
 {
     gnutls_session_t *s = (gnutls_session_t*)session;
+    long tls_option;
+    int enable_tls11, enable_tls12, unsafe_rehandshake;
 
     int err = pgnutls_init(s, is_server ? GNUTLS_SERVER : GNUTLS_CLIENT);
     if (err != GNUTLS_E_SUCCESS)
@@ -118,9 +227,30 @@ BOOL schan_imp_create_session(schan_imp_session *session, BOOL is_server,
         return FALSE;
     }
 
+    /* FIXME registory DisabledByDefault value does not take precedence
+       over the grbitEnabledProtocols of credential,
+       but 'Enabled' value should take precedence over it.(for ssl3.0) */
+    tls_option = schan_get_tls_option();
+    if ((int)cred & SP_PROT_TLS1_1_CLIENT) {
+        enable_tls11 = TRUE;
+    } else {
+        enable_tls11 = (tls_option & SSL_OP_NO_TLSv1_1)?FALSE:TRUE;
+    }
+    if ((int)cred & SP_PROT_TLS1_2_CLIENT) {
+        enable_tls12 = TRUE;
+    } else {
+        enable_tls12 = (tls_option & SSL_OP_NO_TLSv1_2)?FALSE:TRUE;
+    }
+    unsafe_rehandshake = (tls_option & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)?TRUE:FALSE;
+
     /* FIXME: We should be using the information from the credentials here. */
-    FIXME("Using hardcoded \"NORMAL\" priority\n");
-    err = pgnutls_set_default_priority(*s);
+    FIXME("Using hardcoded \"NORMAL\" priority with: TLS1.1:%s, TLS1.2:%s, UnsafeRenego:%s\n",
+                                 enable_tls11?"enabled":"disabled",
+                                 enable_tls12?"enabled":"disabled",
+                                 unsafe_rehandshake?"enabled":"disabled"
+                                 );
+    err = pgnutls_priority_set (*s, gnutls_priorities[enable_tls11][enable_tls12][unsafe_rehandshake]);
+
     if (err != GNUTLS_E_SUCCESS)
     {
         pgnutls_perror(err);
@@ -454,6 +584,8 @@ BOOL schan_imp_init(void)
     LOAD_FUNCPTR(gnutls_mac_get)
     LOAD_FUNCPTR(gnutls_mac_get_key_size)
     LOAD_FUNCPTR(gnutls_perror)
+    LOAD_FUNCPTR(gnutls_priority_init);
+    LOAD_FUNCPTR(gnutls_priority_set);
     LOAD_FUNCPTR(gnutls_protocol_get_version)
     LOAD_FUNCPTR(gnutls_set_default_priority)
     LOAD_FUNCPTR(gnutls_record_get_max_size);
@@ -472,6 +604,7 @@ BOOL schan_imp_init(void)
         pgnutls_perror(ret);
         goto fail;
     }
+    schannel_gnutls_init_priorities();
 
     if (TRACE_ON(secur32))
     {
-- 
1.7.9.5




More information about the wine-patches mailing list