]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Errors served using invalid certificates when dealing with SSL server errors.
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Thu, 16 Jul 2015 07:14:42 +0000 (00:14 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Thu, 16 Jul 2015 07:14:42 +0000 (00:14 -0700)
When bumping Squid needs to send an Squid-generated error "page" over a
secure connection, Squid needs to generate a certificate for that connection.
Prior to these changes, several scenarios could lead to Squid generating
a certificate that clients could not validate. In those cases, the user would
get a cryptic and misleading browser error instead of a Squid-generated
error page with useful details about the problem.

For example, is a server certificate that is rejected by the certificate
validation helper. Squid no longer uses CN from that certificate to generate
a fake certificate.

Another example is a user accessing an origin server using one of its
"alternative names" and getting a Squid-generated certificate containing just
the server common name (CN).

These changes make sure that certificate for error pages is generated using
SNI (when peeking or staring, if available) or CONNECT host name (including
server-first bumping mode). We now update the ConnStateData::sslCommonName
field (used as CN field for generated certificates) only _after_ the server
certificate is successfully validated.

This is a Measurement Factory project.

src/ssl/PeerConnector.cc
src/ssl/PeerConnector.h

index b4dfd8ff1a4a9d1514896bfa02ddb2c537b0d13a..d5deac9c4da7aa854a6d836ab173f4a5c57f5faf 100644 (file)
@@ -274,10 +274,6 @@ Ssl::PeerConnector::handleServerCertificate()
 
         serverCertificateHandled = true;
 
-        csd->resetSslCommonName(Ssl::CommonHostName(serverCert.get()));
-        debugs(83, 5, "HTTPS server CN: " << csd->sslCommonName() <<
-               " bumped: " << *serverConnection());
-
         // remember the server certificate for later use
         if (Ssl::ServerBump *serverBump = csd->serverBump()) {
             serverBump->serverCert.reset(serverCert.release());
@@ -285,6 +281,26 @@ Ssl::PeerConnector::handleServerCertificate()
     }
 }
 
+void
+Ssl::PeerConnector::serverCertificateVerified()
+{
+    if (ConnStateData *csd = request->clientConnectionManager.valid()) {
+        Ssl::X509_Pointer serverCert;
+        if(Ssl::ServerBump *serverBump = csd->serverBump())
+            serverCert.resetAndLock(serverBump->serverCert.get());
+        else {
+            const int fd = serverConnection()->fd;
+            SSL *ssl = fd_table[fd].ssl;
+            serverCert.reset(SSL_get_peer_certificate(ssl));
+        }
+        if (serverCert.get()) {
+            csd->resetSslCommonName(Ssl::CommonHostName(serverCert.get()));
+            debugs(83, 5, "HTTPS server CN: " << csd->sslCommonName() <<
+                   " bumped: " << *serverConnection());
+        }
+    }
+}
+
 bool
 Ssl::PeerConnector::sslFinalized()
 {
@@ -338,6 +354,8 @@ Ssl::PeerConnector::sslFinalized()
             return true;
         }
     }
+
+    serverCertificateVerified();
     return true;
 }
 
@@ -435,6 +453,7 @@ Ssl::PeerConnector::sslCrtvdHandleReply(Ssl::CertValidationResponse const &valid
         validatorFailed = true;
 
     if (!errDetails && !validatorFailed) {
+        serverCertificateVerified();
         if (splice)
             switchToTunnel(request.getRaw(), clientConn, serverConn);
         else
index 2c397843dce31ab25a26e5150f00d8e3b8eed0de..88d04489c76b4b66cfbefab33048bffd1d883ca2 100644 (file)
@@ -158,6 +158,10 @@ private:
     /// if the server certificate was received from the server.
     void handleServerCertificate();
 
+    /// Runs after the server certificate verified to update client
+    /// connection manager members
+    void serverCertificateVerified();
+
     /// Callback function called when squid receive message from cert validator helper
     static void sslCrtvdHandleReplyWrapper(void *data, Ssl::CertValidationResponse const &);