]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Shuffle TLS NPN logic to libsecurity
authorAmos Jeffries <squid3@treenet.co.nz>
Wed, 16 Dec 2015 23:10:40 +0000 (12:10 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Wed, 16 Dec 2015 23:10:40 +0000 (12:10 +1300)
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'

doc/release-notes/release-4.sgml
src/adaptation/ServiceConfig.cc
src/cf.data.pre
src/security/PeerOptions.cc
src/security/PeerOptions.h
src/ssl/support.cc

index bc110007da2ccde89ecf4b7a653386c7503c0efb..c8d69c83236b61c747bc0f37f773e3e948ce6c36 100644 (file)
@@ -171,6 +171,7 @@ This section gives a thorough account of those changes in three categories:
        <tag>cache_peer</tag>
        <p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
        <p>New option <em>tls-no-default-ca</em> replaces <em>sslflags=NO_DEFAULT_CA</em>
+       <p>New option <em>tls-no-npn</em> to disable sending TLS NPN extension.
        <p>All <em>ssloptions=</em> values for SSLv2 configuration or disabling
           have been removed.
        <p>Removed <em>sslversion=</em> option. Use <em>tls-options=</em> instead.
@@ -185,6 +186,7 @@ This section gives a thorough account of those changes in three categories:
        <tag>http_port</tag>
        <p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
        <p>New option <em>tls-no-default-ca</em> replaces <em>sslflags=NO_DEFAULT_CA</em>
+       <p>New option <em>tls-no-npn</em> to disable sending TLS NPN extension.
        <p>All <em>option=</em> values for SSLv2 configuration or disabling
           have been removed.
        <p>Removed <em>version=</em> option. Use <em>tls-options=</em> instead.
@@ -201,6 +203,7 @@ This section gives a thorough account of those changes in three categories:
        <tag>https_port</tag>
        <p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
        <p>New option <em>tls-no-default-ca</em> replaces <em>sslflags=NO_DEFAULT_CA</em>
+       <p>New option <em>tls-no-npn</em> to disable sending TLS NPN extension.
        <p>All <em>options=</em> values for SSLv2
           configuration or disabling have been removed.
        <p>Removed <em>version=</em> option. Use <em>tls-options=</em> instead.
index 79b70ee4a0b8a80c35bcc26e79e2553f78ceff01..7718d6d0a7812344b771e32a6621f842b0c5a58f 100644 (file)
@@ -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 << ": " <<
index e8ef9ad3a3db1ba4f0f8d86a2b657d7d7ba95152..5aef88209a8c00b68d806d199a5c376b333a1554 100644 (file)
@@ -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
index 8142a5ec07793d82e8eacabb54f1b69cbf2f4f6b..34829919a4351add370718ca3588480c1d59af00 100644 (file)
@@ -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)
 {
index 02a266a6a7c8082a2521edf997f4f3b6158097c3..59f9945bf4c484a539e4bf5ddf885206b14903af 100644 (file)
@@ -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:
index 429fd812068208c496bbcf15da79970e92e51007..eb4ae35d78cb441e8bd510aab0531a90538a7b4d 100644 (file)
@@ -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;
 }