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 */
|