From: Amos Jeffries Date: Wed, 16 Dec 2015 23:10:40 +0000 (+1300) Subject: Shuffle TLS NPN logic to libsecurity X-Git-Tag: SQUID_4_0_4~38 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b05d749de416bb93a4010e8c4ba6a8b0c80111fb;p=thirdparty%2Fsquid.git Shuffle TLS NPN logic to libsecurity Also, adds new config option tls-no-npn to fully disable NPN on selected cache_peer or http(s)_port directives. ICAPS services set TLS NPN to off by default to prevent NPN wrongly advertising them as HTTPS connections. The semantic meaning of NPN is to name the protocol which is being wrapped by TLS, in the case of ICAPS that is ICAP/1.0 but Squid NPN callback is currently hard-coded to send 'http/1.1' --- diff --git a/doc/release-notes/release-4.sgml b/doc/release-notes/release-4.sgml index bc110007da..c8d69c8323 100644 --- a/doc/release-notes/release-4.sgml +++ b/doc/release-notes/release-4.sgml @@ -171,6 +171,7 @@ This section gives a thorough account of those changes in three categories: cache_peer

New option tls-min-version=1.N to set minimum TLS version allowed.

New option tls-no-default-ca replaces sslflags=NO_DEFAULT_CA +

New option tls-no-npn to disable sending TLS NPN extension.

All ssloptions= values for SSLv2 configuration or disabling have been removed.

Removed sslversion= option. Use tls-options= instead. @@ -185,6 +186,7 @@ This section gives a thorough account of those changes in three categories: http_port

New option tls-min-version=1.N to set minimum TLS version allowed.

New option tls-no-default-ca replaces sslflags=NO_DEFAULT_CA +

New option tls-no-npn to disable sending TLS NPN extension.

All option= values for SSLv2 configuration or disabling have been removed.

Removed version= option. Use tls-options= instead. @@ -201,6 +203,7 @@ This section gives a thorough account of those changes in three categories: https_port

New option tls-min-version=1.N to set minimum TLS version allowed.

New option tls-no-default-ca replaces sslflags=NO_DEFAULT_CA +

New option tls-no-npn to disable sending TLS NPN extension.

All options= values for SSLv2 configuration or disabling have been removed.

Removed version= option. Use tls-options= instead. diff --git a/src/adaptation/ServiceConfig.cc b/src/adaptation/ServiceConfig.cc index 79b70ee4a0..7718d6d0a7 100644 --- a/src/adaptation/ServiceConfig.cc +++ b/src/adaptation/ServiceConfig.cc @@ -149,6 +149,11 @@ Adaptation::ServiceConfig::parse() if (!onOverloadSet) onOverload = bypass ? srvBypass : srvWait; + // disable the TLS NPN extension if encrypted. + // Squid advertises "http/1.1", which is wrong for ICAPS. + if (secure.encryptTransport) + secure.parse("no-npn"); + // is the service URI set? if (!grokkedUri) { debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " << diff --git a/src/cf.data.pre b/src/cf.data.pre index e8ef9ad3a3..5aef88209a 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1975,6 +1975,8 @@ DOC_START tls-no-default-ca Do not use the system default Trusted CA. + tls-no-npn Do not use the TLS NPN extension to advertise HTTP/1.1. + sslcontext= SSL session ID context identifier. Other Options: @@ -3283,6 +3285,8 @@ DOC_START tls-no-default-ca Do not use the system default Trusted CA. + tls-no-npn Do not use the TLS NPN extension to advertise HTTP/1.1. + ==== GENERAL OPTIONS ==== connect-timeout=N diff --git a/src/security/PeerOptions.cc b/src/security/PeerOptions.cc index 8142a5ec07..34829919a4 100644 --- a/src/security/PeerOptions.cc +++ b/src/security/PeerOptions.cc @@ -95,6 +95,8 @@ Security::PeerOptions::parse(const char *token) flags.noDefaultCa = true; } else if (strncmp(token, "domain=", 7) == 0) { sslDomain = SBuf(token + 7); + } else if (strncmp(token, "no-npn", 6) == 0) { + flags.tlsNpn = false; } else { debugs(3, DBG_CRITICAL, "ERROR: Unknown TLS option '" << token << "'"); return; @@ -140,6 +142,9 @@ Security::PeerOptions::dumpCfg(Packable *p, const char *pfx) const if (flags.noDefaultCa) p->appendf(" %sno-default-ca", pfx); + + if (!flags.tlsNpn) + p->appendf(" %sno-npn", pfx); } void @@ -248,6 +253,7 @@ Security::PeerOptions::createClientContext(bool setOptions) #endif if (t) { + updateContextNpn(t); updateContextCa(t); updateContextCrl(t); } @@ -528,6 +534,31 @@ Security::PeerOptions::loadCrlFile() #endif } +#if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg) +// Dummy next_proto_neg callback +static int +ssl_next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) +{ + static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'}; + (void)SSL_select_next_proto(out, outlen, in, inlen, supported_protos, sizeof(supported_protos)); + return SSL_TLSEXT_ERR_OK; +} +#endif + +void +Security::PeerOptions::updateContextNpn(Security::ContextPtr &ctx) +{ + if (!flags.tlsNpn) + return; + +#if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg) + SSL_CTX_set_next_proto_select_cb(ctx, &ssl_next_proto_cb, nullptr); +#endif + + // NOTE: GnuTLS does not support the obsolete NPN extension. + // it does support ALPN per-session, not per-context. +} + void Security::PeerOptions::updateContextCa(Security::ContextPtr &ctx) { diff --git a/src/security/PeerOptions.h b/src/security/PeerOptions.h index 02a266a6a7..59f9945bf4 100644 --- a/src/security/PeerOptions.h +++ b/src/security/PeerOptions.h @@ -40,6 +40,9 @@ public: /// sync the context options with tls-min-version=N configuration void updateTlsVersionLimits(); + /// setup the NPN extension details for the given context + void updateContextNpn(Security::ContextPtr &); + /// setup the CA details for the given context void updateContextCa(Security::ContextPtr &); @@ -77,10 +80,13 @@ private: /// flags governing Squid internal TLS operations struct flags_ { - flags_() : noDefaultCa(false) {} + flags_() : noDefaultCa(false), tlsNpn(true) {} /// do not use the system default Trusted CA when verifying the remote end certificate bool noDefaultCa; + + /// whether to use the TLS NPN extension on these connections + bool tlsNpn; } flags; public: diff --git a/src/ssl/support.cc b/src/ssl/support.cc index 429fd81206..eb4ae35d78 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -622,17 +622,6 @@ sslCreateServerContext(AnyP::PortCfg &port) return sslContext; } -#if defined(TLSEXT_TYPE_next_proto_neg) -//Dummy next_proto_neg callback -static int -ssl_next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) -{ - static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'}; - (void)SSL_select_next_proto(out, outlen, in, inlen, supported_protos, sizeof(supported_protos)); - return SSL_TLSEXT_ERR_OK; -} -#endif - Security::ContextPtr sslCreateClientContext(Security::PeerOptions &peer, long options, long fl) { @@ -699,9 +688,6 @@ sslCreateClientContext(Security::PeerOptions &peer, long options, long fl) SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb); } -#if defined(TLSEXT_TYPE_next_proto_neg) - SSL_CTX_set_next_proto_select_cb(sslContext, &ssl_next_proto_cb, NULL); -#endif return sslContext; }