]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Ssl certificate domain mismatch errors on IP-based URLs
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 17 Apr 2012 16:08:41 +0000 (19:08 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 17 Apr 2012 16:08:41 +0000 (19:08 +0300)
The ssl::certDomainMismatch acl can not be used with ip-based urls. For example
let's assume that a user enters https://74.125.65.99/, using a Google IP addressin the URL instead of www.google.com. If the sslBump used with
"sslproxy_cert_error allow all" and "sslproxy_cert_adapt setCommonName ssl::certDomainMismatch"
the browser displays a browser "Server's certificate does not match the URL"
error.

This is because for all cases we have the ip address instead of the hostname
we are detecting the cert domain mismatch errors when the first GET request
comes. At the time the sslproxy_cert_adatp access list processed the error is
not detected yet.
For intercepted connections this is the desired behaviour.

This patch fix the ssl-bump-first to check for domain-mismatch errors while
retrieving the SSL certificate from the server, hoping that CONNECT is using
a user-entered address (a host name or a user-entered IP).

src/client_side.cc
src/forward.cc

index fb5c12b6435fce86b37ee4ea0adadde1baecda2a..f756ad29bbe942aa87b0f46bb572f89be882f81a 100644 (file)
@@ -3915,10 +3915,12 @@ ConnStateData::httpsPeeked(Comm::ConnectionPointer serverConnection)
         debugs(33, 5, HERE << "Error while bumping: " << sslConnectHostOrIp);
         Ip::Address intendedDest;
         intendedDest = sslConnectHostOrIp.termedBuf();
+        const bool isConnectRequest = !port->spoof_client_ip && !port->intercepted;
+
         // Squid serves its own error page and closes, so we want
         // a CN that causes no additional browser errors. Possible
-        // only when bumping CONNECT which uses a host name.
-        if (intendedDest.IsAnyAddr())
+        // only when bumping CONNECT with a user-typed address.
+        if (intendedDest.IsAnyAddr() || isConnectRequest)
             sslCommonName = sslConnectHostOrIp;
         else if (sslServerBump->serverCert.get())
             sslCommonName = Ssl::CommonHostName(sslServerBump->serverCert.get());
index 20367f33ae9410fef9fe2a21a566a71e24f856e1..1f2babf9976bf70cbc126d51b84e8fc68372af12 100644 (file)
@@ -50,6 +50,7 @@
 #include "MemObject.h"
 #include "pconn.h"
 #include "PeerSelectState.h"
+#include "ProtoPort.h"
 #include "SquidTime.h"
 #include "Store.h"
 #include "icmp/net_db.h"
@@ -679,9 +680,12 @@ FwdState::negotiateSSL(int fd)
                 }
             }
 
-            if (request->flags.sslPeek && request->GetHostIsNumeric()) {
-                // If possible, set host name to server certificate CN unless
-                // we already got the right name (from the CONNECT request).
+            const bool isConnectRequest = !request->clientConnectionManager->port->spoof_client_ip && 
+                !request->clientConnectionManager->port->intercepted;
+            // For intercepted connections, set host name to server
+            // certificate CN. Otherwise, we hope that CONNECT is using
+            // a user-entered address (a host name or a user-entered IP).
+            if (request->flags.sslPeek && !isConnectRequest) {
                 if (X509 *srvX509 = errDetails->peerCert()) {
                     if (const char *name = Ssl::CommonHostName(srvX509)) {
                         request->SetHost(name);
@@ -770,11 +774,12 @@ FwdState::initiateSSL()
     } 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 which used a host name. Some
-        // browsers are using IP addresses in CONNECT requests.
+        // unless it was the CONNECT request with a user-typed address.
         const char *hostname = request->GetHost();
         const bool hostnameIsIp = request->GetHostIsNumeric();
-        if (!request->flags.sslPeek || !hostnameIsIp)
+        const bool isConnectRequest = !request->clientConnectionManager->port->spoof_client_ip && 
+            !request->clientConnectionManager->port->intercepted;
+        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