]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
SNI information is not set on transparent bumping mode
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Mon, 9 Feb 2015 16:13:27 +0000 (18:13 +0200)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Mon, 9 Feb 2015 16:13:27 +0000 (18:13 +0200)
Forward SNI (obtained from an intercepted client connection) to servers
when SslBump peeks or stares at the server certificate.

SslBump was not forwarding SNI to servers when Squid obtained SNI from an
intercepted client while peeking (or staring) at client Hello.

This is a Measurement Factory project

src/ssl/PeerConnector.cc

index bb3c415d9c7c4ad6a2cef0ad7cddafd03b868784..0abf94890b09e5e4595392011352d8e05c3bae40 100644 (file)
@@ -144,48 +144,57 @@ Ssl::PeerConnector::initializeSsl()
 
         if (peer->sslSession)
             SSL_set_session(ssl, peer->sslSession);
-
-    } else if (request->clientConnectionManager->sslBumpMode == Ssl::bumpPeek || request->clientConnectionManager->sslBumpMode == Ssl::bumpStare) {
-        // client connection is required for Peek or Stare mode in the case we need to splice
+    } else if (const ConnStateData *csd = request->clientConnectionManager.valid()) {
+        // client connection is required in the case we need to splice
         // or terminate client and server connections
         assert(clientConn != NULL);
-        SSL *clientSsl = fd_table[request->clientConnectionManager->clientConnection->fd].ssl;
-        BIO *b = SSL_get_rbio(clientSsl);
-        Ssl::ClientBio *clnBio = static_cast<Ssl::ClientBio *>(b->ptr);
-        const Ssl::Bio::sslFeatures &features = clnBio->getFeatures();
-        if (features.sslVersion != -1) {
-            features.applyToSSL(ssl);
-            // Should we allow it for all protocols?
-            if (features.sslVersion >= 3) {
-                b = SSL_get_rbio(ssl);
-                Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
-                srvBio->setClientFeatures(features);
-                srvBio->recordInput(true);
-                srvBio->mode(request->clientConnectionManager->sslBumpMode);
-            }
+        const char *hostName = NULL;
+        Ssl::ClientBio *cltBio = NULL;
+
+        // In server-first bumping mode, clientSsl is NULL.
+        if (SSL *clientSsl = fd_table[clientConn->fd].ssl) {
+            BIO *b = SSL_get_rbio(clientSsl);
+            cltBio = static_cast<Ssl::ClientBio *>(b->ptr);
+            const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
+            if (!features.serverName.isEmpty())
+                hostName = features.serverName.c_str();
+        }
 
-            const bool isConnectRequest = request->clientConnectionManager.valid() &&
-                                          !request->clientConnectionManager->port->flags.isIntercepted();
-            if (isConnectRequest)
-                SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)request->GetHost());
-            else if (!features.serverName.isEmpty())
-                SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)features.serverName.c_str());
+        if (!hostName) {
+            // While we are peeking at the certificate, we may not know the server
+            // name that the client will request (after interception or CONNECT)
+            // unless it was the CONNECT request with a user-typed address.
+            const bool isConnectRequest = !csd->port->flags.isIntercepted();
+            if (!request->flags.sslPeek || isConnectRequest)
+                hostName = request->GetHost();
+        }
+
+        if (hostName)
+            SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostName);
+
+        if (csd->sslBumpMode == Ssl::bumpPeek || csd->sslBumpMode == Ssl::bumpStare) {
+            assert(cltBio);
+            const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
+            if (features.sslVersion != -1) {
+                features.applyToSSL(ssl);
+                // Should we allow it for all protocols?
+                if (features.sslVersion >= 3) {
+                    BIO *b = SSL_get_rbio(ssl);
+                    Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
+                    // Inherite client features, like SSL version, SNI and other
+                    srvBio->setClientFeatures(features);
+                    srvBio->recordInput(true);
+                    srvBio->mode(csd->sslBumpMode);
+                }
+            }
+        } else {
+            // Use SNI TLS extension only when we connect directly
+            // to the origin server and we know the server host name.
+            const char *sniServer = hostName ? hostName : 
+                                    (!request->GetHostIsNumeric() ? request->GetHost() : NULL);
+            if (sniServer)
+                Ssl::setClientSNI(ssl, sniServer);
         }
-    } else {
-        // While we are peeking at the certificate, we may not know the server
-        // name that the client will request (after interception or CONNECT)
-        // unless it was the CONNECT request with a user-typed address.
-        const char *hostname = request->GetHost();
-        const bool hostnameIsIp = request->GetHostIsNumeric();
-        const bool isConnectRequest = request->clientConnectionManager.valid() &&
-                                      !request->clientConnectionManager->port->flags.isIntercepted();
-        if (!request->flags.sslPeek || isConnectRequest)
-            SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostname);
-
-        // Use SNI TLS extension only when we connect directly
-        // to the origin server and we know the server host name.
-        if (!hostnameIsIp)
-            Ssl::setClientSNI(ssl, hostname);
     }
 
     // If CertValidation Helper used do not lookup checklist for errors,