From: Christos Tsantilas Date: Mon, 9 Feb 2015 16:13:27 +0000 (+0200) Subject: SNI information is not set on transparent bumping mode X-Git-Tag: merge-candidate-3-v1~275 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76b64c80331b28b666856e083c828ae5c5a1bdac;p=thirdparty%2Fsquid.git 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 --- diff --git a/src/ssl/PeerConnector.cc b/src/ssl/PeerConnector.cc index bb3c415d9c..0abf94890b 100644 --- a/src/ssl/PeerConnector.cc +++ b/src/ssl/PeerConnector.cc @@ -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(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(); + } - 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(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,