emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] gnutls: Add SNI support


From: Toke Høiland-Jørgensen
Subject: [PATCH] gnutls: Add SNI support
Date: Mon, 24 Nov 2014 13:17:22 +0100

Currently, Emacs does not support Server Name Identification. This means
that servers that host multiple SSL sites on the same IP will send the
wrong certificate to Emacs. In addition, some servers refuse connections
entirely if the SNI extension is not included in the client handshake.

This patch adds what I think is the required call into GnuTLS to add the
hostname information on the handshake. Unfortunately I have been unable
to actually test the patch, since I can't get the git trunk to compile.
However, I thought I'd post it anyway to maybe get someone else to have
a look.

Oh, and there's a bit of a hack in trying to detect whether the hostname
is an IPv4 or IPv6 literal (in which case the hostname shouldn't be
included in the handshake). Not sure if omitting that check entirely
will work, or if there's a better way to detect this case.

-Toke



diff --git a/src/gnutls.c b/src/gnutls.c
index 22e3aec..e8a6966 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -187,6 +187,9 @@ DEF_GNUTLS_FN (int, gnutls_x509_crt_get_key_id,
 DEF_GNUTLS_FN (const char*, gnutls_sec_param_get_name, (gnutls_sec_param_t));
 DEF_GNUTLS_FN (const char*, gnutls_sign_algorithm_get_name,
               (gnutls_sign_algorithm_t));
+DEF_GNUTLS_FN (int, gnutls_server_name_set, (gnutls_session_t,
+                                            gnutls_server_name_type_t,
+                                            const void *, size_t));
 
 static bool
 init_gnutls_functions (void)
@@ -263,6 +266,7 @@ init_gnutls_functions (void)
   LOAD_GNUTLS_FN (library, gnutls_x509_crt_get_key_id);
   LOAD_GNUTLS_FN (library, gnutls_sec_param_get_name);
   LOAD_GNUTLS_FN (library, gnutls_sign_algorithm_get_name);
+  LOAD_GNUTLS_FN (library, gnutls_server_name_set);
 
   max_log_level = global_gnutls_log_level;
 
@@ -335,6 +339,7 @@ init_gnutls_functions (void)
 #define fn_gnutls_x509_crt_get_key_id           gnutls_x509_crt_get_key_id
 #define fn_gnutls_sec_param_get_name            gnutls_sec_param_get_name
 #define fn_gnutls_sign_algorithm_get_name       gnutls_sign_algorithm_get_name
+#define fn_gnutls_server_name_set              gnutls_server_name_set
 
 #endif /* !WINDOWSNT */
 
@@ -1137,6 +1142,7 @@ one trustfile (usually a CA bundle).  */)
   char const *priority_string_ptr = "NORMAL"; /* default priority string.  */
   unsigned int peer_verification;
   char *c_hostname;
+  char *c; bool send_hostname = 0;
 
   /* Placeholders for the property list elements.  */
   Lisp_Object priority_string;
@@ -1375,6 +1381,22 @@ one trustfile (usually a CA bundle).  */)
   if (ret < GNUTLS_E_SUCCESS)
     return gnutls_make_error (ret);
 
+  /* Quick and dirty test of the hostname; shouldn't be an IP. If it
+     contains letters, we assume it's a hostname, unless it contains a
+     : in which case we assume it's a literal IPv6 address. */
+  for(c = c_hostname; c; c++) {
+    if(c >= 'a') send_hostname = 1;
+    if(c == ':') {send_hostname = 0; break;}
+  }
+
+  if(send_hostname) {
+    GNUTLS_LOG (1, max_log_level, "setting TLS hostname");
+    ret = fn_gnutls_server_name_set(state, GNUTLS_NAME_DNS, c_hostname, 
strlen(c_hostname));
+    if (ret < GNUTLS_E_SUCCESS)
+      return gnutls_make_error (ret);
+  }
+
+
   GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
   ret = emacs_gnutls_handshake (XPROCESS (proc));
   if (ret < GNUTLS_E_SUCCESS)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]