------------------------------------------------------------ revno: 13752 revision-id: squid3@treenet.co.nz-20150210045421-fc4c6n3vk9u87wyf parent: squid3@treenet.co.nz-20150210045244-sr23ttq8x8igrejr author: Christos Tsantilas committer: Amos Jeffries branch nick: 3.5 timestamp: Mon 2015-02-09 20:54:21 -0800 message: SNI information is not set on transparent bumping mode 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 ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20150210045421-fc4c6n3vk9u87wyf # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.5 # testament_sha1: 58660f37badbddd337d4338818bd048a968cacff # timestamp: 2015-02-10 04:55:28 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.5 # base_revision_id: squid3@treenet.co.nz-20150210045244-\ # sr23ttq8x8igrejr # # Begin patch === modified file 'src/ssl/PeerConnector.cc' --- src/ssl/PeerConnector.cc 2015-01-13 09:13:49 +0000 +++ src/ssl/PeerConnector.cc 2015-02-10 04:54:21 +0000 @@ -144,48 +144,57 @@ 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(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(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(b->ptr); + const Ssl::Bio::sslFeatures &features = cltBio->getFeatures(); + if (!features.serverName.isEmpty()) + hostName = 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(b->ptr); + // Inherite client features, like SSL version, SNI and other + srvBio->setClientFeatures(features); + srvBio->recordInput(true); + srvBio->mode(csd->sslBumpMode); + } } - - 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()); + } 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,