Add OpenSSL snihost option for TLS SNI extension

This commit is contained in:
Travis Burtrum 2015-07-17 22:08:00 -04:00
parent 8fda559e8d
commit 268432bf42
5 changed files with 27 additions and 3 deletions

View File

@ -502,13 +502,15 @@ label(ADDRESS_OPENSSL_CONNECT)dit(bf(tt(OPENSSL:<host>:<port>)))
link(openssl-commonname)(OPTION_OPENSSL_COMMONNAME) option. link(openssl-commonname)(OPTION_OPENSSL_COMMONNAME) option.
Socat tries to match it against the certificates subject commonName, Socat tries to match it against the certificates subject commonName,
and the certifications extension subjectAltName DNS names. Wildcards in the 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() 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: Useful options:
link(cipher)(OPTION_OPENSSL_CIPHERLIST), link(cipher)(OPTION_OPENSSL_CIPHERLIST),
link(method)(OPTION_OPENSSL_METHOD), link(method)(OPTION_OPENSSL_METHOD),
link(verify)(OPTION_OPENSSL_VERIFY), 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(cafile)(OPTION_OPENSSL_CAFILE),
link(capath)(OPTION_OPENSSL_CAPATH), link(capath)(OPTION_OPENSSL_CAPATH),
link(certificate)(OPTION_OPENSSL_CERTIFICATE), link(certificate)(OPTION_OPENSSL_CERTIFICATE),
@ -2700,6 +2702,9 @@ label(OPTION_OPENSSL_COMMONNAME)dit(bf(tt(commonname=<string>)))
certificates commonname. This option has only meaning when option certificates commonname. This option has only meaning when option
link(verify)(OPTION_OPENSSL_VERIFY) is not disabled and the choosen cipher link(verify)(OPTION_OPENSSL_VERIFY) is not disabled and the choosen cipher
provides a peer certificate. provides a peer certificate.
label(OPTION_OPENSSL_SNIHOST)dit(bf(tt(snihost=<string>)))
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))) label(OPTION_OPENSSL_FIPS)dit(bf(tt(fips)))
Enables FIPS mode if compiled in. For info about the FIPS encryption Enables FIPS mode if compiled in. For info about the FIPS encryption
implementation standard see lurl(http://oss-institute.org/fips-faq.html). implementation standard see lurl(http://oss-institute.org/fips-faq.html).

View File

@ -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 }; const struct optdesc opt_openssl_fips = { "openssl-fips", "fips", OPT_OPENSSL_FIPS, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
#endif #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_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. /* 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 */ bool opt_ver = true; /* verify peer certificate */
char *opt_cert = NULL; /* file name of client certificate */ char *opt_cert = NULL; /* file name of client certificate */
const char *opt_commonname = NULL; /* for checking peer certificate */ const char *opt_commonname = NULL; /* for checking peer certificate */
const char *opt_snihost = NULL; /* for sni host */
int result; int result;
if (!(xioflags & XIO_MAYCONVERT)) { if (!(xioflags & XIO_MAYCONVERT)) {
@ -226,10 +228,15 @@ static int
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert); retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname); retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
retropt_string(opts, OPT_OPENSSL_SNIHOST, (char **)&opt_snihost);
if (opt_commonname == NULL) { if (opt_commonname == NULL) {
opt_commonname = hostname; opt_commonname = hostname;
} }
/* could do this, but might not be desired?
if (opt_snihost == NULL) {
opt_snihost = hostname;
} */
result = result =
_xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx); _xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx);
@ -289,7 +296,7 @@ static int
return result; 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) { switch (result) {
case STAT_OK: break; case STAT_OK: break;
#if WITH_RETRY #if WITH_RETRY
@ -358,6 +365,7 @@ static int
int _xioopen_openssl_connect(struct single *xfd, int _xioopen_openssl_connect(struct single *xfd,
bool opt_ver, bool opt_ver,
const char *opt_commonname, const char *opt_commonname,
const char *opt_snihost,
SSL_CTX *ctx, SSL_CTX *ctx,
int level) { int level) {
SSL *ssl; SSL *ssl;
@ -382,6 +390,12 @@ int _xioopen_openssl_connect(struct single *xfd,
return result; return result;
} }
if (opt_snihost && !SSL_set_tlsext_host_name(ssl, opt_snihost)) {
sycSSL_free(xfd->para.openssl.ssl);
xfd->para.openssl.ssl = NULL;
return STAT_NORETRY;
}
result = xioSSL_connect(xfd, opt_commonname, opt_ver, level); result = xioSSL_connect(xfd, opt_commonname, opt_ver, level);
if (result != STAT_OK) { if (result != STAT_OK) {
sycSSL_free(xfd->para.openssl.ssl); sycSSL_free(xfd->para.openssl.ssl);

View File

@ -30,6 +30,7 @@ extern const struct optdesc opt_openssl_compress;
extern const struct optdesc opt_openssl_fips; extern const struct optdesc opt_openssl_fips;
#endif #endif
extern const struct optdesc opt_openssl_commonname; extern const struct optdesc opt_openssl_commonname;
extern const struct optdesc opt_openssl_snihost;
extern int extern int
_xioopen_openssl_prepare(struct opt *opts, struct single *xfd, _xioopen_openssl_prepare(struct opt *opts, struct single *xfd,
@ -38,6 +39,7 @@ extern int
extern int extern int
_xioopen_openssl_connect(struct single *xfd, bool opt_ver, _xioopen_openssl_connect(struct single *xfd, bool opt_ver,
const char *opt_commonname, const char *opt_commonname,
const char *opt_snihost,
SSL_CTX *ctx, int level); SSL_CTX *ctx, int level);
extern int extern int
_xioopen_openssl_listen(struct single *xfd, bool opt_ver, _xioopen_openssl_listen(struct single *xfd, bool opt_ver,

View File

@ -1109,6 +1109,7 @@ const struct optname optionnames[] = {
IF_OPENSSL("openssl-key", &opt_openssl_key) IF_OPENSSL("openssl-key", &opt_openssl_key)
IF_OPENSSL("openssl-method", &opt_openssl_method) IF_OPENSSL("openssl-method", &opt_openssl_method)
IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo) IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo)
IF_OPENSSL("openssl-snihost", &opt_openssl_snihost)
IF_OPENSSL("openssl-verify", &opt_openssl_verify) IF_OPENSSL("openssl-verify", &opt_openssl_verify)
IF_TERMIOS("opost", &opt_opost) IF_TERMIOS("opost", &opt_opost)
#if defined(HAVE_TERMIOS_ISPEED) && defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1) #if defined(HAVE_TERMIOS_ISPEED) && defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1)
@ -1377,6 +1378,7 @@ const struct optname optionnames[] = {
#ifdef SO_SNDTIMEO #ifdef SO_SNDTIMEO
IF_SOCKET ("sndtimeo", &opt_so_sndtimeo) IF_SOCKET ("sndtimeo", &opt_so_sndtimeo)
#endif #endif
IF_OPENSSL("snihost", &opt_openssl_snihost)
#ifdef SO_ACCEPTCONN /* AIX433 */ #ifdef SO_ACCEPTCONN /* AIX433 */
IF_SOCKET ("so-acceptconn", &opt_so_acceptconn) IF_SOCKET ("so-acceptconn", &opt_so_acceptconn)
#endif /* SO_ACCEPTCONN */ #endif /* SO_ACCEPTCONN */

View File

@ -483,6 +483,7 @@ enum e_optcode {
OPT_OPENSSL_KEY, OPT_OPENSSL_KEY,
OPT_OPENSSL_METHOD, OPT_OPENSSL_METHOD,
OPT_OPENSSL_PSEUDO, OPT_OPENSSL_PSEUDO,
OPT_OPENSSL_SNIHOST,
OPT_OPENSSL_VERIFY, OPT_OPENSSL_VERIFY,
OPT_OPOST, /* termios.c_oflag */ OPT_OPOST, /* termios.c_oflag */
OPT_OSPEED, /* termios.c_ospeed */ OPT_OSPEED, /* termios.c_ospeed */