mirror of
https://github.com/nmap/nmap.git
synced 2025-12-20 14:39:02 +00:00
Add DTLS and ALPN support to Ncat. Closes #446
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [Ncat][GH#446] Added Datagram TLS (DTLS) support to Ncat in connect (client)
|
||||
mode with --udp --ssl. Also added Application Layer Protocol Negotiation
|
||||
(ALPN) support with the --ssl-alpn option. [denandz, Daniel Miller]
|
||||
|
||||
o Updated the default ciphers list for Ncat and the secure ciphers list for
|
||||
Nsock to use "!aNULL:!eNULL" instead of "!ADH". With the addition of ECDH
|
||||
ciphersuites, anonymous ECDH suites were being allowed. [Daniel Miller]
|
||||
|
||||
@@ -314,6 +314,8 @@
|
||||
particularly handy for talking to SSL enabled HTTP servers, etc.</para>
|
||||
<para>In server mode, this option listens for incoming SSL connections,
|
||||
rather than plain untunneled traffic.</para>
|
||||
<para>In UDP connect mode, this option enables Datagram TLS (DTLS).
|
||||
This is not supported in server mode.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -395,6 +397,20 @@
|
||||
<literal>ALL:!aNULL:!eNULL:!LOW:!EXP:!MD5:@STRENGTH</literal></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--ssl-alpn <replaceable>ALPN list</replaceable></option> (Specify ALPN protocol list)
|
||||
<indexterm><primary><option>--ssl-alpn</option> (Ncat option)</primary></indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>This option allows you to specify a comma-separated list of
|
||||
protocols to send via the Application-Layer Protocol Negotiation
|
||||
(ALPN) TLS extension. Not supported by all versions of OpenSSL.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsect1>
|
||||
|
||||
@@ -308,8 +308,8 @@ Content-Type: text/html; charset=UTF-8
|
||||
with only one client, and the
|
||||
<option>--keep-open</option><indexterm><primary><option>--keep-open</option> (Ncat option)</primary><secondary>not supported with UDP</secondary></indexterm>
|
||||
option doesn't work, the reason for this being that UDP has no notion
|
||||
of a connection. UDP may not be combined with
|
||||
SSL.<indexterm><primary>SSL</primary><secondary>not supported with UDP</secondary></indexterm>
|
||||
of a connection. UDP may be secured by a form of SSL called Datagram TLS (DTLS)<indexterm><primary>DTLS</primary><secondary>Datagram TLS</secondary></indexterm>.
|
||||
This is currently only supported in connect (client) mode.<indexterm><primary>SSL</primary><secondary>not supported with UDP in server mode</secondary></indexterm>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
||||
@@ -256,6 +256,30 @@ static void set_ssl_ctx_options(SSL_CTX *ctx)
|
||||
if (!SSL_CTX_set_cipher_list(ctx, o.sslciphers))
|
||||
bye("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL));
|
||||
}
|
||||
|
||||
#ifdef HAVE_ALPN_SUPPORT
|
||||
|
||||
if (o.sslalpn) {
|
||||
size_t alpn_len;
|
||||
unsigned char *alpn = next_protos_parse(&alpn_len, o.sslalpn);
|
||||
|
||||
if (alpn == NULL)
|
||||
bye("Could not parse ALPN string");
|
||||
|
||||
if (o.debug)
|
||||
logdebug("Using ALPN String %s\n", o.sslalpn);
|
||||
|
||||
/* SSL_CTX_set_alpn_protos returns 0 on success */
|
||||
if (SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len) != 0){
|
||||
free(alpn);
|
||||
bye("SSL_CTX_set_alpn_protos: %s.", ERR_error_string(ERR_get_error(), NULL));
|
||||
}
|
||||
|
||||
free(alpn);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -878,6 +902,51 @@ static int do_proxy_socks5(void)
|
||||
return(sd);
|
||||
}
|
||||
|
||||
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)
|
||||
bye("Failed to set hostname on iod.");
|
||||
|
||||
switch (srcaddr.storage.ss_family) {
|
||||
case AF_UNSPEC:
|
||||
break;
|
||||
case AF_INET:
|
||||
nsock_iod_set_localaddr(nsi, &srcaddr.storage,
|
||||
sizeof(srcaddr.in));
|
||||
break;
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
nsock_iod_set_localaddr(nsi, &srcaddr.storage,
|
||||
sizeof(srcaddr.in6));
|
||||
break;
|
||||
#endif
|
||||
#if HAVE_SYS_UN_H
|
||||
case AF_UNIX:
|
||||
nsock_iod_set_localaddr(nsi, &srcaddr.storage,
|
||||
SUN_LEN((struct sockaddr_un *)&srcaddr.storage));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
nsock_iod_set_localaddr(nsi, &srcaddr.storage,
|
||||
sizeof(srcaddr.storage));
|
||||
break;
|
||||
}
|
||||
|
||||
if (o.numsrcrtes) {
|
||||
unsigned char *ipopts = NULL;
|
||||
size_t ipoptslen = 0;
|
||||
|
||||
if (o.af != AF_INET)
|
||||
bye("Sorry, -g can only currently be used with IPv4.");
|
||||
ipopts = buildsrcrte(targetaddrs->addr.in.sin_addr, o.srcrtes, o.numsrcrtes, o.srcrteptr, &ipoptslen);
|
||||
|
||||
nsock_iod_set_ipoptions(nsi, ipopts, ipoptslen);
|
||||
free(ipopts); /* Nsock has its own copy */
|
||||
}
|
||||
return nsi;
|
||||
}
|
||||
|
||||
int ncat_connect(void)
|
||||
{
|
||||
@@ -908,18 +977,15 @@ int ncat_connect(void)
|
||||
nsock_pool_set_broadcast(mypool, 1);
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
set_ssl_ctx_options((SSL_CTX *) nsock_pool_ssl_init(mypool, 0));
|
||||
#ifdef HAVE_DTLS_CLIENT_METHOD
|
||||
if(o.proto == IPPROTO_UDP)
|
||||
set_ssl_ctx_options((SSL_CTX *) nsock_pool_dtls_init(mypool, 0));
|
||||
else
|
||||
#endif
|
||||
set_ssl_ctx_options((SSL_CTX *) nsock_pool_ssl_init(mypool, 0));
|
||||
#endif
|
||||
|
||||
if (!o.proxytype) {
|
||||
/* A non-proxy connection. Create an iod for a new socket. */
|
||||
cs.sock_nsi = nsock_iod_new(mypool, NULL);
|
||||
if (cs.sock_nsi == NULL)
|
||||
bye("Failed to create nsock_iod.");
|
||||
|
||||
if (nsock_iod_set_hostname(cs.sock_nsi, o.target) == -1)
|
||||
bye("Failed to set hostname on iod.");
|
||||
|
||||
#if HAVE_SYS_UN_H
|
||||
/* For DGRAM UNIX socket we have to use source socket */
|
||||
if (o.af == AF_UNIX && o.proto == IPPROTO_UDP)
|
||||
@@ -945,50 +1011,13 @@ int ncat_connect(void)
|
||||
strncpy(srcaddr.un.sun_path, tmp_name, sizeof(srcaddr.un.sun_path));
|
||||
free (tmp_name);
|
||||
}
|
||||
nsock_iod_set_localaddr(cs.sock_nsi, &srcaddr.storage,
|
||||
SUN_LEN((struct sockaddr_un *)&srcaddr.storage));
|
||||
|
||||
if (o.verbose)
|
||||
loguser("[%s] used as source DGRAM Unix domain socket.\n", srcaddr.un.sun_path);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
switch (srcaddr.storage.ss_family) {
|
||||
case AF_UNSPEC:
|
||||
break;
|
||||
case AF_INET:
|
||||
nsock_iod_set_localaddr(cs.sock_nsi, &srcaddr.storage,
|
||||
sizeof(srcaddr.in));
|
||||
break;
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
nsock_iod_set_localaddr(cs.sock_nsi, &srcaddr.storage,
|
||||
sizeof(srcaddr.in6));
|
||||
break;
|
||||
#endif
|
||||
#if HAVE_SYS_UN_H
|
||||
case AF_UNIX:
|
||||
nsock_iod_set_localaddr(cs.sock_nsi, &srcaddr.storage,
|
||||
SUN_LEN((struct sockaddr_un *)&srcaddr.storage));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
nsock_iod_set_localaddr(cs.sock_nsi, &srcaddr.storage,
|
||||
sizeof(srcaddr.storage));
|
||||
break;
|
||||
}
|
||||
|
||||
if (o.numsrcrtes) {
|
||||
unsigned char *ipopts = NULL;
|
||||
size_t ipoptslen = 0;
|
||||
|
||||
if (o.af != AF_INET)
|
||||
bye("Sorry, -g can only currently be used with IPv4.");
|
||||
ipopts = buildsrcrte(targetaddrs->addr.in.sin_addr, o.srcrtes, o.numsrcrtes, o.srcrteptr, &ipoptslen);
|
||||
|
||||
nsock_iod_set_ipoptions(cs.sock_nsi, ipopts, ipoptslen);
|
||||
free(ipopts); /* Nsock has its own copy */
|
||||
}
|
||||
/* A non-proxy connection. Create an iod for a new socket. */
|
||||
cs.sock_nsi = new_iod(mypool);
|
||||
|
||||
#if HAVE_SYS_UN_H
|
||||
if (o.af == AF_UNIX) {
|
||||
@@ -1068,35 +1097,27 @@ int ncat_connect(void)
|
||||
|
||||
static void try_nsock_connect(nsock_pool nsp, struct sockaddr_list *conn_addr)
|
||||
{
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (o.ssl) {
|
||||
nsock_connect_ssl(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
o.proto, inet_port(&conn_addr->addr),
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (o.proto == IPPROTO_UDP) {
|
||||
nsock_connect_udp(nsp, cs.sock_nsi, connect_handler, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
inet_port(&conn_addr->addr));
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
else if (o.proto == IPPROTO_SCTP && o.ssl) {
|
||||
nsock_connect_ssl(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
IPPROTO_SCTP, inet_port(&conn_addr->addr),
|
||||
NULL);
|
||||
}
|
||||
#endif
|
||||
else if (o.proto == IPPROTO_SCTP) {
|
||||
nsock_connect_sctp(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
inet_port(&conn_addr->addr));
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
else if (o.ssl) {
|
||||
nsock_connect_ssl(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
IPPROTO_TCP, inet_port(&conn_addr->addr),
|
||||
NULL);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
nsock_connect_tcp(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
@@ -1132,6 +1153,13 @@ static void connect_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
loguser("Connection to %s failed: %s.\n", inet_socktop(&peer), socket_strerror(errcode));
|
||||
loguser("Trying next address...\n");
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
/* If it's an SSL reconnect, clear out any old session info */
|
||||
if (nsock_iod_check_ssl(cs.sock_nsi)) {
|
||||
nsock_iod_delete(cs.sock_nsi, NSOCK_PENDING_NOTIFY);
|
||||
cs.sock_nsi = new_iod(nsp);
|
||||
}
|
||||
#endif
|
||||
try_nsock_connect(nsp, next_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -215,6 +215,7 @@ void options_init(void)
|
||||
o.sslverify = 0;
|
||||
o.ssltrustfile = NULL;
|
||||
o.sslciphers = NULL;
|
||||
o.sslalpn = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -218,6 +218,7 @@ struct options {
|
||||
int sslverify;
|
||||
char *ssltrustfile;
|
||||
char *sslciphers;
|
||||
char *sslalpn;
|
||||
int zerobyte;
|
||||
};
|
||||
|
||||
|
||||
@@ -264,6 +264,8 @@ static int ncat_listen_stream(int proto)
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (o.ssl)
|
||||
if (o.sslalpn)
|
||||
bye("ALPN is not supported in listen mode\n");
|
||||
setup_ssl_listen();
|
||||
#endif
|
||||
|
||||
@@ -712,6 +714,11 @@ static int ncat_listen_dgram(int proto)
|
||||
struct timeval *tvp = NULL;
|
||||
unsigned int num_sockets;
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
if(o.ssl)
|
||||
bye("DTLS is not supported in listen mode\n");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_LISTEN_ADDRS; i++) {
|
||||
sockfd[i].fd = -1;
|
||||
sockfd[i].addr.storage.ss_family = AF_UNSPEC;
|
||||
|
||||
@@ -320,12 +320,14 @@ 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-alpn", required_argument, NULL, 0},
|
||||
#else
|
||||
{"ssl-cert", optional_argument, NULL, 0},
|
||||
{"ssl-key", optional_argument, NULL, 0},
|
||||
{"ssl-verify", no_argument, NULL, 0},
|
||||
{"ssl-trustfile", optional_argument, NULL, 0},
|
||||
{"ssl-ciphers", optional_argument, NULL, 0},
|
||||
{"ssl-alpn", optional_argument, NULL, 0},
|
||||
#endif
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
@@ -536,7 +538,16 @@ int main(int argc, char *argv[])
|
||||
} else if (strcmp(long_options[option_index].name, "ssl-ciphers") == 0) {
|
||||
o.ssl = 1;
|
||||
o.sslciphers = Strdup(optarg);
|
||||
#ifdef HAVE_ALPN_SUPPORT
|
||||
} else if (strcmp(long_options[option_index].name, "ssl-alpn") == 0) {
|
||||
o.ssl = 1;
|
||||
o.sslalpn = Strdup(optarg);
|
||||
}
|
||||
#else
|
||||
} else if (strcmp(long_options[option_index].name, "ssl-alpn") == 0) {
|
||||
bye("OpenSSL does not have ALPN support compiled in. The --ssl-alpn option cannot be chosen.");
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
else if (strcmp(long_options[option_index].name, "ssl-cert") == 0) {
|
||||
bye("OpenSSL isn't compiled in. The --ssl-cert option cannot be chosen.");
|
||||
@@ -548,6 +559,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-alpn") == 0) {
|
||||
bye("OpenSSL isn't compiled in. The --ssl-alpn option cannot be chosen.");
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LUA
|
||||
@@ -637,6 +650,7 @@ 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"
|
||||
#endif
|
||||
" --version Display Ncat's version information and exit\n"
|
||||
"\n"
|
||||
@@ -903,9 +917,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (o.proto == IPPROTO_UDP) {
|
||||
/* Don't allow a false sense of security if someone tries SSL over UDP. */
|
||||
|
||||
#ifndef HAVE_DTLS_CLIENT_METHOD
|
||||
if (o.ssl)
|
||||
bye("UDP mode does not support SSL.");
|
||||
bye("OpenSSL does not have DTLS support compiled in.");
|
||||
#endif
|
||||
if (o.keepopen && o.cmdexec == NULL)
|
||||
bye("UDP mode does not support the -k or --keep-open options, except with --exec or --sh-exec.");
|
||||
if (o.broker)
|
||||
|
||||
36
ncat/util.c
36
ncat/util.c
@@ -750,3 +750,39 @@ int fix_line_endings(char *src, int *len, char **dst, int *state)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* next_protos_parse parses a comma separated list of strings into a string
|
||||
* in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
|
||||
* outlen: (output) set to the length of the resulting buffer on success.
|
||||
* err: NULL on failure
|
||||
* in: a NULL terminated string like "abc,def,ghi"
|
||||
*
|
||||
* returns: a malloc'd buffer or NULL on failure.
|
||||
*/
|
||||
unsigned char *next_protos_parse(size_t *outlen, const char *in)
|
||||
{
|
||||
size_t len;
|
||||
unsigned char *out;
|
||||
size_t i, start = 0;
|
||||
|
||||
len = strlen(in);
|
||||
if (len >= 65535)
|
||||
return NULL;
|
||||
|
||||
out = safe_malloc(strlen(in) + 1);
|
||||
for (i = 0; i <= len; ++i) {
|
||||
if (i == len || in[i] == ',') {
|
||||
if (i - start > 255) {
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
out[start] = i - start;
|
||||
start = i + 1;
|
||||
} else
|
||||
out[i + 1] = in[i];
|
||||
}
|
||||
|
||||
*outlen = len + 1;
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -230,4 +230,6 @@ struct fdinfo *get_fdinfo(const fd_list_t *, int);
|
||||
|
||||
int fix_line_endings(char *src, int *len, char **dst, int *state);
|
||||
|
||||
unsigned char *next_protos_parse(size_t *outlen, const char *in);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -248,6 +248,13 @@ void nsock_pool_set_device(nsock_pool nsp, const char *device);
|
||||
#define NSOCK_SSL_MAX_SPEED (1 << 0)
|
||||
nsock_ssl_ctx nsock_pool_ssl_init(nsock_pool ms_pool, int flags);
|
||||
|
||||
/* Initializes an Nsock pool to create a DTLS connect. This sets and internal
|
||||
* SSL_CTX, which is like a template that sets options for all connections that
|
||||
* are made from it. Returns the SSL_CTX so tyou can set your own options.
|
||||
*
|
||||
* Functionally similar to nsock_pool_ssl_init, just for the DTLS */
|
||||
nsock_ssl_ctx nsock_pool_dtls_init(nsock_pool ms_pool, int flags);
|
||||
|
||||
/* Enforce use of a given IO engine.
|
||||
* The engine parameter is a zero-terminated string that will be
|
||||
* strup()'ed by the library. No validity check is performed by this function,
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
|
||||
#undef HAVE_OPENSSL
|
||||
#undef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
||||
#undef HAVE_DTLS_CLIENT_METHOD
|
||||
#undef HAVE_ALPN_SUPPORT
|
||||
|
||||
#undef HAVE_EPOLL
|
||||
#undef HAVE_POLL
|
||||
|
||||
60
nsock/src/configure
vendored
60
nsock/src/configure
vendored
@@ -664,6 +664,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -738,6 +739,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE}'
|
||||
@@ -990,6 +992,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1127,7 +1138,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1280,6 +1291,7 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -4908,6 +4920,52 @@ if ac_fn_c_try_link "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }; $as_echo "#define HAVE_SSL_SET_TLSEXT_HOST_NAME 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DTLS_client_method" >&5
|
||||
$as_echo_n "checking for DTLS_client_method... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <openssl/ssl.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
DTLS_client_method()
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }; $as_echo "#define HAVE_DTLS_CLIENT_METHOD 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_set_alpn_protos" >&5
|
||||
$as_echo_n "checking for SSL_set_alpn_protos... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <openssl/ssl.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
SSL_set_alpn_protos(NULL, NULL, 0)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }; $as_echo "#define HAVE_ALPN_SUPPORT 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
@@ -263,6 +263,14 @@ if test "$use_openssl" = "yes"; then
|
||||
AC_TRY_LINK([#include <openssl/ssl.h>], [SSL_set_tlsext_host_name(NULL, NULL)],
|
||||
[AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_SSL_SET_TLSEXT_HOST_NAME)],
|
||||
[AC_MSG_RESULT([no])])
|
||||
AC_MSG_CHECKING([for DTLS_client_method])
|
||||
AC_TRY_LINK([#include <openssl/ssl.h>], [DTLS_client_method()],
|
||||
[AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_DTLS_CLIENT_METHOD)],
|
||||
[AC_MSG_RESULT([no])])
|
||||
AC_MSG_CHECKING([for SSL_set_alpn_protos])
|
||||
AC_TRY_LINK([#include <openssl/ssl.h>], [SSL_set_alpn_protos(NULL, NULL, 0)],
|
||||
[AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_ALPN_SUPPORT)],
|
||||
[AC_MSG_RESULT([no])])
|
||||
LIBS="$LIBS_TMP"
|
||||
|
||||
fi
|
||||
|
||||
@@ -184,8 +184,8 @@ int nsock_setup_udp(nsock_pool nsp, nsock_iod ms_iod, int af) {
|
||||
return nsi->sd;
|
||||
}
|
||||
|
||||
/* This does the actual logistics of requesting a TCP connection. It is shared
|
||||
* by nsock_connect_tcp and nsock_connect_ssl */
|
||||
/* This does the actual logistics of requesting a connection. It is shared
|
||||
* by nsock_connect_tcp and nsock_connect_ssl, among others */
|
||||
void nsock_connect_internal(struct npool *ms, struct nevent *nse, int type, int proto, struct sockaddr_storage *ss, size_t sslen,
|
||||
unsigned short port) {
|
||||
|
||||
@@ -256,7 +256,7 @@ void nsock_connect_internal(struct npool *ms, struct nevent *nse, int type, int
|
||||
if (ms->engine->io_operations->iod_connect(ms, iod->sd, (struct sockaddr *)ss, sslen) == -1) {
|
||||
int err = socket_errno();
|
||||
|
||||
if (proto == IPPROTO_UDP || (err != EINPROGRESS && err != EAGAIN)) {
|
||||
if ((proto == IPPROTO_UDP) || (err != EINPROGRESS && err != EAGAIN)) {
|
||||
nse->event_done = 1;
|
||||
nse->status = NSE_STATUS_ERROR;
|
||||
nse->errnum = err;
|
||||
@@ -376,7 +376,7 @@ nsock_event_id nsock_connect_sctp(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_han
|
||||
return nse->id;
|
||||
}
|
||||
|
||||
/* Request an SSL over TCP/SCTP connection to another system (by IP address).
|
||||
/* Request an SSL over TCP/SCTP/UDP connection to another system (by IP address).
|
||||
* The in_addr is normal network byte order, but the port number should be given
|
||||
* in HOST BYTE ORDER. This function will call back only after it has made the
|
||||
* connection AND done the initial SSL negotiation. From that point on, you use
|
||||
@@ -397,7 +397,12 @@ nsock_event_id nsock_connect_ssl(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handl
|
||||
struct nevent *nse;
|
||||
|
||||
if (!ms->sslctx)
|
||||
nsock_pool_ssl_init(ms, 0);
|
||||
{
|
||||
if (proto == IPPROTO_UDP)
|
||||
nsock_pool_dtls_init(ms, 0);
|
||||
else
|
||||
nsock_pool_ssl_init(ms, 0);
|
||||
}
|
||||
|
||||
assert(nsi->state == NSIOD_STATE_INITIAL || nsi->state == NSIOD_STATE_UNKNOWN);
|
||||
|
||||
@@ -405,14 +410,22 @@ nsock_event_id nsock_connect_ssl(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handl
|
||||
assert(nse);
|
||||
|
||||
/* Set our SSL_SESSION so we can benefit from session-id reuse. */
|
||||
nsi_set_ssl_session(nsi, (SSL_SESSION *)ssl_session);
|
||||
/* but not with DTLS; save space in ClientHello message */
|
||||
if (proto != IPPROTO_UDP)
|
||||
nsi_set_ssl_session(nsi, (SSL_SESSION *)ssl_session);
|
||||
|
||||
nsock_log_info("SSL connection requested to %s:%hu/%s (IOD #%li) EID %li",
|
||||
if (proto == IPPROTO_UDP)
|
||||
nsock_log_info("DTLS connection requested to %s:%hu/udp (IOD #%li) EID %li",
|
||||
|
||||
inet_ntop_ez(ss, sslen), port, nsi->id, nse->id);
|
||||
else
|
||||
nsock_log_info("SSL connection requested to %s:%hu/%s (IOD #%li) EID %li",
|
||||
inet_ntop_ez(ss, sslen), port, (proto == IPPROTO_TCP ? "tcp" : "sctp"),
|
||||
nsi->id, nse->id);
|
||||
|
||||
/* Do the actual connect() */
|
||||
nsock_connect_internal(ms, nse, SOCK_STREAM, proto, ss, sslen, port);
|
||||
nsock_connect_internal(ms, nse, (proto == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM), proto, ss, sslen, port);
|
||||
|
||||
nsock_pool_add_event(ms, nse);
|
||||
|
||||
return nse->id;
|
||||
|
||||
@@ -377,7 +377,9 @@ void handle_connect_result(struct npool *ms, struct nevent *nse, enum nse_status
|
||||
}
|
||||
|
||||
#if HAVE_SSL_SET_TLSEXT_HOST_NAME
|
||||
if (iod->hostname != NULL) {
|
||||
/* Avoid sending SNI extension with DTLS because many servers don't allow
|
||||
* fragmented ClientHello messages. */
|
||||
if (iod->hostname != NULL && iod->lastproto != IPPROTO_UDP) {
|
||||
if (SSL_set_tlsext_host_name(iod->ssl, iod->hostname) != 1)
|
||||
fatal("SSL_set_tlsext_host_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
|
||||
}
|
||||
|
||||
@@ -80,8 +80,7 @@
|
||||
|
||||
extern struct timeval nsock_tod;
|
||||
|
||||
/* Create an SSL_CTX and do initialization that is common to all init modes. */
|
||||
static SSL_CTX *ssl_init_common() {
|
||||
static SSL_CTX *ssl_init_helper(const SSL_METHOD *method) {
|
||||
SSL_CTX *ctx;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
|
||||
@@ -89,7 +88,7 @@ static SSL_CTX *ssl_init_common() {
|
||||
SSL_library_init();
|
||||
#endif
|
||||
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
ctx = SSL_CTX_new(method);
|
||||
if (!ctx) {
|
||||
fatal("OpenSSL failed to create a new SSL_CTX: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
@@ -105,18 +104,19 @@ static SSL_CTX *ssl_init_common() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/* Create an SSL_CTX and do initialization that is common to all init modes. */
|
||||
static SSL_CTX *ssl_init_common() {
|
||||
return ssl_init_helper(SSLv23_client_method());
|
||||
}
|
||||
|
||||
/* Initializes an Nsock pool to create SSL connections. This sets an internal
|
||||
* SSL_CTX, which is like a template that sets options for all connections that
|
||||
* are made from it. The connections made from this context will use only secure
|
||||
* ciphers but no server certificate verification is done. Returns the SSL_CTX
|
||||
* so you can set your own options. */
|
||||
nsock_ssl_ctx nsock_pool_ssl_init(nsock_pool ms_pool, int flags) {
|
||||
struct npool *ms = (struct npool *)ms_pool;
|
||||
static nsock_ssl_ctx nsock_pool_ssl_init_helper(struct npool *ms, int flags) {
|
||||
char rndbuf[128];
|
||||
|
||||
if (ms->sslctx == NULL)
|
||||
ms->sslctx = ssl_init_common();
|
||||
|
||||
/* Get_random_bytes may or may not provide high-quality randomness. Add it to
|
||||
* the entropy pool without increasing the entropy estimate (third argument of
|
||||
* RAND_add is 0). We rely on OpenSSL's entropy gathering, called implicitly
|
||||
@@ -146,6 +146,49 @@ nsock_ssl_ctx nsock_pool_ssl_init(nsock_pool ms_pool, int flags) {
|
||||
return ms->sslctx;
|
||||
}
|
||||
|
||||
nsock_ssl_ctx nsock_pool_ssl_init(nsock_pool ms_pool, int flags) {
|
||||
struct npool *ms = (struct npool *)ms_pool;
|
||||
|
||||
if (ms->sslctx == NULL)
|
||||
ms->sslctx = ssl_init_common();
|
||||
return nsock_pool_ssl_init_helper(ms, flags);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DTLS_CLIENT_METHOD
|
||||
|
||||
/* Create an SSL_CTX and do initialisation, creating a DTLS client */
|
||||
static SSL_CTX *dtls_init_common() {
|
||||
return ssl_init_helper(DTLS_client_method());
|
||||
}
|
||||
|
||||
/* Initializes an Nsock pool to create DTLS connections. Very much similar to
|
||||
* nsock_pool_ssl_init, just with DTLS. */
|
||||
nsock_ssl_ctx nsock_pool_dtls_init(nsock_pool ms_pool, int flags) {
|
||||
SSL_CTX *dtls_ctx = NULL;
|
||||
struct npool *ms = (struct npool *)ms_pool;
|
||||
|
||||
if (ms->sslctx == NULL)
|
||||
ms->sslctx = dtls_init_common();
|
||||
dtls_ctx = (SSL_CTX *) nsock_pool_ssl_init_helper(ms, flags);
|
||||
|
||||
/* Don't add padding or the ClientHello will fragment and not connect properly. */
|
||||
SSL_CTX_clear_options(dtls_ctx, SSL_OP_TLSEXT_PADDING);
|
||||
|
||||
if (!SSL_CTX_set_cipher_list(dtls_ctx, "DEFAULT"))
|
||||
fatal("Unable to set OpenSSL cipher list: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
return dtls_ctx;
|
||||
}
|
||||
|
||||
#else /* OpenSSL Version does not support DTLS */
|
||||
|
||||
nsock_ssl_ctx nsock_pool_dtls_init(nsock_pool ms_pool, int flags) {
|
||||
fatal("%s called with no OpenSSL DTLS support", __func__);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Check server certificate verification, after a connection is established. We
|
||||
* check first that a certificate was even offered, then call
|
||||
* SSL_get_verify_result to get the overall status of verification. (Just
|
||||
@@ -180,6 +223,10 @@ nsock_ssl_ctx nsock_pool_ssl_init(nsock_pool ms_pool, int flags) {
|
||||
fatal("%s called with no OpenSSL support", __func__);
|
||||
}
|
||||
|
||||
nsock_ssl_ctx nsock_pool_dtls_init(nsock_pool ms_pool, int flags) {
|
||||
fatal("%s called with no OpenSSL support", __func__);
|
||||
}
|
||||
|
||||
int nsi_ssl_post_connect_verify(const nsock_iod nsockiod) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user