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.
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=<string>)))
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=<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)))
Enables FIPS mode if compiled in. For info about the FIPS encryption
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 };
#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 _xioopen_openssl_connect(struct single *xfd,
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);
if (result != STAT_OK) {
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;
#endif
extern const struct optdesc opt_openssl_commonname;
extern const struct optdesc opt_openssl_snihost;
extern int
_xioopen_openssl_prepare(struct opt *opts, struct single *xfd,
@ -38,6 +39,7 @@ extern int
extern int
_xioopen_openssl_connect(struct single *xfd, bool opt_ver,
const char *opt_commonname,
const char *opt_snihost,
SSL_CTX *ctx, int level);
extern int
_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-method", &opt_openssl_method)
IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo)
IF_OPENSSL("openssl-snihost", &opt_openssl_snihost)
IF_OPENSSL("openssl-verify", &opt_openssl_verify)
IF_TERMIOS("opost", &opt_opost)
#if defined(HAVE_TERMIOS_ISPEED) && defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1)
@ -1377,6 +1378,7 @@ const struct optname optionnames[] = {
#ifdef SO_SNDTIMEO
IF_SOCKET ("sndtimeo", &opt_so_sndtimeo)
#endif
IF_OPENSSL("snihost", &opt_openssl_snihost)
#ifdef SO_ACCEPTCONN /* AIX433 */
IF_SOCKET ("so-acceptconn", &opt_so_acceptconn)
#endif /* SO_ACCEPTCONN */

View File

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