aboutsummaryrefslogtreecommitdiffstats
path: root/community/claws-mail/sni.patch
blob: 14621ba76ec3e8e86692527cba89f419cec11351 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
--- a/src/common/ssl.c	
+++ a/src/common/ssl.c	
@@ -410,6 +410,17 @@ gboolean ssl_init_socket(SockInfo *sockinfo)
 
 	gnutls_record_disable_padding(session);
 
+	/* If we have a host name, rather than a numerical IP address, tell
+	 * gnutls to send it in the server name identification extension field,
+	 * to give the server a chance to select the correct certificate in the
+	 * virtual hosting case where multiple domain names are hosted on the
+	 * same IP address. */
+	if (NULL != sockinfo->canonical_name && !is_numeric_host_address(sockinfo->canonical_name)) {
+		r = gnutls_server_name_set(session, GNUTLS_NAME_DNS, sockinfo->canonical_name, strlen(sockinfo->canonical_name));
+		debug_print("Set GnuTLS session server name indication to %s, status = %d\n",
+			    sockinfo->canonical_name, r);
+	}
+
 	gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
 
 	if (claws_ssl_get_cert_file()) {
--- a/src/common/utils.c	
+++ a/src/common/utils.c	
@@ -1924,6 +1924,29 @@ const gchar *get_domain_name(void)
 #endif
 }
 
+/* Tells whether the given host address string is a valid representation of a
+ * numerical IP (v4 or, if supported, v6) address.
+ */
+gboolean is_numeric_host_address(const gchar *hostaddress)
+{
+	struct addrinfo hints, *res;
+	int err;
+
+	/* See what getaddrinfo makes of the string when told that it is a
+	 * numeric IP address representation. */
+	memset(&hints, 0, sizeof(struct addrinfo));
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = 0;
+	hints.ai_flags = AI_NUMERICHOST;
+	hints.ai_protocol = 0;
+
+	err = getaddrinfo(hostaddress, NULL, &hints, &res);
+	if (0 == err) {
+		freeaddrinfo(res);
+	}
+	return (0 == err);
+}
+
 off_t get_file_size(const gchar *file)
 {
 #ifdef G_OS_WIN32
--- a/src/common/utils.h	
+++ a/src/common/utils.h	
@@ -396,6 +396,7 @@ const gchar *get_tmp_dir		(void);
 const gchar *get_locale_dir		(void);
 gchar *get_tmp_file			(void);
 const gchar *get_domain_name		(void);
+gboolean is_numeric_host_address	(const gchar *hostaddress);
 const gchar *get_desktop_file(void);
 #ifdef G_OS_WIN32
 const gchar *w32_get_themes_dir    (void);
--- a/src/etpan/etpan-ssl.c	
+++ a/src/etpan/etpan-ssl.c	
@@ -171,6 +171,19 @@ void etpan_connect_ssl_context_cb(struct mailstream_ssl_context * ssl_context, v
 		gnutls_x509_crt_deinit(x509);
 		gnutls_x509_privkey_deinit(pkey);
 	}
+
+	/* If we have a host name, rather than a numerical IP address, tell
+	 * gnutls to send it in the server name identification extension field,
+	 * to give the server a chance to select the correct certificate in the
+	 * virtual hosting case where multiple domain names are hosted on the
+	 * same IP address. */
+	if (!is_numeric_host_address(account->recv_server)) {
+		int r;
+
+		r = mailstream_ssl_set_server_name(ssl_context, account->recv_server);
+		debug_print("Set libetpan SSL mail stream server name indication to %s, status = %d\n",
+			    account->recv_server, r);
+	}
 }
 
 #endif /* USE_GNUTLS */