Package: socat
Version: 1.7.3.2-2
Severity: wishlist
Tags: upstream
socat does not support the TLS Server Name Indication extension. This
extension has become pretty widely deployed at this point, and socat’s
TLS support could be substantially more useful if it sent SNI.
A patch against 1.7.3.0 is available [1]; I’ve also attached it here for
convenience. I haven’t tested or reviewed it, though, so its inclusion
should not be treated as an endorsement. :)
[1]
https://github.com/moparisthebest/socat/commit/268432bf4220502535dbd373344b60b8fd10e3ce
>From 268432bf4220502535dbd373344b60b8fd10e3ce Mon Sep 17 00:00:00 2001
From: moparisthebest
Date: Fri, 17 Jul 2015 22:08:00 -0400
Subject: [PATCH 1/1] Add OpenSSL snihost option for TLS SNI extension
---
doc/socat.yo | 9 +++--
xio-openssl.c | 16 +++-
xio-openssl.h | 2 ++
xioopts.c | 2 ++
xioopts.h | 1 +
5 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/doc/socat.yo b/doc/socat.yo
index 65e9894..18269da 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -502,13 +502,15 @@ label(ADDRESS_OPENSSL_CONNECT)dit(bf(tt(OPENSSL::)))
link(openssl-commonname)(OPTION_OPENSSL_COMMONNAME) option.
Socat tries to match it against the certificates subject commonName,
and the certifications extension subjectAltName DNS names. Wildcards in the
- certificate are supported.nl()
+ certificate are supported. To specify the TLS SNI hostname to set use the
+ link(snihost)(OPTION_OPENSSL_SNIHOST) option.nl()
Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(OPENSSL)(GROUP_OPENSSL),link(RETRY)(GROUP_RETRY) nl()
Useful options:
link(cipher)(OPTION_OPENSSL_CIPHERLIST),
link(method)(OPTION_OPENSSL_METHOD),
link(verify)(OPTION_OPENSSL_VERIFY),
- link(commonname)(OPTION_OPENSSL_COMMONNAME)
+ link(commonname)(OPTION_OPENSSL_COMMONNAME),
+ link(snihost)(OPTION_OPENSSL_SNIHOST),
link(cafile)(OPTION_OPENSSL_CAFILE),
link(capath)(OPTION_OPENSSL_CAPATH),
link(certificate)(OPTION_OPENSSL_CERTIFICATE),
@@ -2700,6 +2702,9 @@ label(OPTION_OPENSSL_COMMONNAME)dit(bf(tt(commonname=)))
certificates commonname. This option has only meaning when option
link(verify)(OPTION_OPENSSL_VERIFY) is not disabled and the choosen cipher
provides a peer certificate.
+label(OPTION_OPENSSL_SNIHOST)dit(bf(tt(snihost=)))
+ Specify the SNI hostname for the TLS request. The server can use this TLS
+ extension to choose which certificate to send.
label(OPTION_OPENSSL_FIPS)dit(bf(tt(fips)))
Enables FIPS mode if compiled in. For info about the FIPS encryption
implementation standard see lurl(http://oss-institute.org/fips-faq.html).
diff --git a/xio-openssl.c b/xio-openssl.c
index 665430d..a04e5bf 100644
--- a/xio-openssl.c
+++ b/xio-openssl.c
@@ -117,6 +117,7 @@ const struct optdesc opt_openssl_compress= { "openssl-compress", "compress
const struct optdesc opt_openssl_fips= { "openssl-fips", "fips", OPT_OPENSSL_FIPS,GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
#endif
const struct optdesc opt_openssl_commonname = { "openssl-commonname", "cn", OPT_OPENSSL_COMMONNAME, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
+const struct optdesc opt_openssl_snihost = { "openssl-snihost", "snihost", OPT_OPENSSL_SNIHOST, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
/* If FIPS is compiled in, we need to track if the user asked for FIPS mode.
@@ -197,6 +198,7 @@ static int
bool opt_ver = true; /* verify peer certificate */
char *opt_cert = NULL; /* file name of client certificate */
const char *opt_commonname = NULL; /* for checking peer certificate */
+ const char *opt_snihost = NULL; /* for sni host */
int result;
if (!(xioflags & XIO_MAYCONVERT)) {
@@ -226,10 +228,15 @@ static int
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
+ retropt_string(opts, OPT_OPENSSL_SNIHOST, (char **)&opt_snihost);
if (opt_commonname == NULL) {
opt_commonname = hostname;
}
+ /* could do this, but might not be desired?
+ if (opt_snihost == NULL) {
+ opt_snihost = hostname;
+ } */
result =
_xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx);
@@ -289,7 +296,7 @@ static int
return result;
}
- result = _xioopen_openssl_connect(xfd, opt_ver, opt_commonname, ctx, level);
+ result = _xioopen_openssl_connect(xfd, opt_ver, opt_commonname, opt_snihost, ctx, level);
switch (result) {
case STAT_OK: break;
#if WITH_RETRY
@@ -358,6 +365,7 @@ static int
int _xioopen_openssl_connect(struct single *xfd,
bool opt_ver,
const char *opt_commonname,
+ const char *opt_snihost,
SSL_CTX *ctx,
int level) {
SSL *ssl;
@@ -382,6 +390,12 @@ int _xioope