diff --git a/CHANGELOG b/CHANGELOG
index af97bb420..99daf1241 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,8 @@
#Nmap Changelog ($Id$); -*-text-*-
+o [Ncat][GH#2087][GH#1927][GH#1928][GH#1974] It is now possible to override
+ the value of TLS SNI via --ssl-servername [Hank Leininger, nnposter]
+
o [GH#2104] Fixed parsing of TCP options which would hang (infinite loop) if an
option had an explicit length of 0. Affects Nmap 7.80 only.
[Daniel Miller, Imed Mnif]
diff --git a/ncat/docs/ncat.usage.txt b/ncat/docs/ncat.usage.txt
index d00aab367..f45de3eef 100644
--- a/ncat/docs/ncat.usage.txt
+++ b/ncat/docs/ncat.usage.txt
@@ -50,7 +50,8 @@ Options taking a time assume seconds. Append 'ms' for milliseconds,
--ssl-verify Verify trust and domain name of certificates
--ssl-trustfile PEM file containing trusted SSL certificates
--ssl-ciphers Cipherlist containing SSL ciphers to use
- --ssl-alpn ALPN protocol list to use.
+ --ssl-servername Request distinct server name (SNI)
+ --ssl-alpn ALPN protocol list to use
--version Display Ncat's version information and exit
See the ncat(1) manpage for full options, descriptions and usage examples
diff --git a/ncat/docs/ncat.xml b/ncat/docs/ncat.xml
index cfc0137f5..e6fd64bb2 100644
--- a/ncat/docs/ncat.xml
+++ b/ncat/docs/ncat.xml
@@ -411,6 +411,21 @@
+
+
+ (Request distinct server name)
+ (Ncat option)
+
+
+ In client mode, this option sets the TLS SNI (Server Name
+ Indication) extension, which tells the server the name of the
+ logical server Ncat is contacting. This is important when the
+ target server hosts multiple virtual servers at a single underlying
+ network address. If the option is not provided, the TLS SNI
+ extension will be populated with the target server hostname.
+
+
+
(Specify ALPN protocol list)
diff --git a/ncat/ncat_connect.c b/ncat/ncat_connect.c
index 4acb8ef8a..7a0848050 100644
--- a/ncat/ncat_connect.c
+++ b/ncat/ncat_connect.c
@@ -972,7 +972,7 @@ static nsock_iod new_iod(nsock_pool mypool) {
nsock_iod nsi = nsock_iod_new(mypool, NULL);
if (nsi == NULL)
bye("Failed to create nsock_iod.");
- if (nsock_iod_set_hostname(nsi, o.target) == -1)
+ if (nsock_iod_set_hostname(nsi, o.sslservername) == -1)
bye("Failed to set hostname on iod.");
switch (srcaddr.storage.ss_family) {
@@ -1128,7 +1128,8 @@ int ncat_connect(void)
/* Once the proxy negotiation is done, Nsock takes control of the
socket. */
cs.sock_nsi = nsock_iod_new2(mypool, connect_socket, NULL);
- nsock_iod_set_hostname(cs.sock_nsi, o.target);
+ if (nsock_iod_set_hostname(cs.sock_nsi, o.sslservername) == -1)
+ bye("Failed to set hostname on iod.");
if (o.ssl)
{
nsock_reconnect_ssl(mypool, cs.sock_nsi, connect_handler, o.conntimeout, NULL, NULL);
@@ -1267,7 +1268,7 @@ static void connect_handler(nsock_pool nsp, nsock_event evt, void *data)
if (nsock_iod_check_ssl(cs.sock_nsi)) {
/* Check the domain name. ssl_post_connect_check prints an
error message if appropriate. */
- if (!ssl_post_connect_check((SSL *)nsock_iod_get_ssl(cs.sock_nsi), o.target))
+ if (!ssl_post_connect_check((SSL *)nsock_iod_get_ssl(cs.sock_nsi), o.sslservername))
bye("Certificate verification error.");
}
#endif
diff --git a/ncat/ncat_core.c b/ncat/ncat_core.c
index 4c13bc539..450f62710 100644
--- a/ncat/ncat_core.c
+++ b/ncat/ncat_core.c
@@ -217,6 +217,7 @@ void options_init(void)
o.sslverify = 0;
o.ssltrustfile = NULL;
o.sslciphers = NULL;
+ o.sslservername = NULL;
o.sslalpn = NULL;
#endif
}
diff --git a/ncat/ncat_core.h b/ncat/ncat_core.h
index e421ed69f..ebf266f23 100644
--- a/ncat/ncat_core.h
+++ b/ncat/ncat_core.h
@@ -223,6 +223,7 @@ struct options {
int sslverify;
char *ssltrustfile;
char *sslciphers;
+ char* sslservername;
char *sslalpn;
int zerobyte;
};
diff --git a/ncat/ncat_main.c b/ncat/ncat_main.c
index d1fff7e7e..f36db49a9 100644
--- a/ncat/ncat_main.c
+++ b/ncat/ncat_main.c
@@ -358,6 +358,7 @@ int main(int argc, char *argv[])
{"ssl-verify", no_argument, NULL, 0},
{"ssl-trustfile", required_argument, NULL, 0},
{"ssl-ciphers", required_argument, NULL, 0},
+ {"ssl-servername", required_argument, NULL, 0},
{"ssl-alpn", required_argument, NULL, 0},
#else
{"ssl-cert", optional_argument, NULL, 0},
@@ -573,6 +574,9 @@ int main(int argc, char *argv[])
} else if (strcmp(long_options[option_index].name, "ssl-ciphers") == 0) {
o.ssl = 1;
o.sslciphers = Strdup(optarg);
+ } else if (strcmp(long_options[option_index].name, "ssl-servername") == 0) {
+ o.ssl = 1;
+ o.sslservername = Strdup(optarg);
#ifdef HAVE_ALPN_SUPPORT
} else if (strcmp(long_options[option_index].name, "ssl-alpn") == 0) {
o.ssl = 1;
@@ -594,6 +598,8 @@ int main(int argc, char *argv[])
bye("OpenSSL isn't compiled in. The --ssl-trustfile option cannot be chosen.");
} else if (strcmp(long_options[option_index].name, "ssl-ciphers") == 0) {
bye("OpenSSL isn't compiled in. The --ssl-ciphers option cannot be chosen.");
+ } else if (strcmp(long_options[option_index].name, "ssl-servername") == 0) {
+ bye("OpenSSL isn't compiled in. The --ssl-servername option cannot be chosen.");
} else if (strcmp(long_options[option_index].name, "ssl-alpn") == 0) {
bye("OpenSSL isn't compiled in. The --ssl-alpn option cannot be chosen.");
}
@@ -695,7 +701,8 @@ int main(int argc, char *argv[])
" --ssl-verify Verify trust and domain name of certificates\n"
" --ssl-trustfile PEM file containing trusted SSL certificates\n"
" --ssl-ciphers Cipherlist containing SSL ciphers to use\n"
-" --ssl-alpn ALPN protocol list to use.\n"
+" --ssl-servername Request distinct server name (SNI)\n"
+" --ssl-alpn ALPN protocol list to use\n"
#endif
" --version Display Ncat's version information and exit\n"
"\n"
@@ -943,6 +950,8 @@ int main(int argc, char *argv[])
&& (rc = resolve_multi(o.target, 0, targetaddrs, o.af)) != 0)
bye("Could not resolve hostname \"%s\": %s.", o.target, gai_strerror(rc));
+ if (!o.sslservername)
+ o.sslservername = o.target;
optind++;
} else {
if (!o.listen)