Recently, I received a query from the Windows Mobile team-- they had observed that visiting https://gmail.com triggers a certificate name mismatch error on IEMobile, but doesn’t seem to trigger any error on Windows 7 when using the desktop versions of Internet Explorer or Firefox.
Now, long-time readers know that I love a good mystery, so I was excited to take a look at what was going on here. I first verified the original problem: IE on Windows Mobile 6.5 does indeed show the name mismatch warning, and desktop IE doesn’t show any warning at all. My next step was to watch the Desktop’s traffic with Fiddler, which, when configured to perform HTTPS decryption, will warn about any certificate errors by default. I was intrigued to find that Fiddler does, in fact, warn about the certificate when visiting https://gmail.com. As you can see, the certificate presented is for “mail.google.com” instead of “gmail.com”:
This name mismatch triggers a warning in Fiddler and should be triggering a similar warning within the browser. My next step was to try opening the site using IE6 inside XP Virtual Mode. There, I found that IE6 reported the same certificate error.
So, what’s going on here? A security bug introduced in the newer desktop versions of Firefox and IE, that prevents proper name matching? Unlikely.
No, actually, something more interesting is going on, and by now I had a hunch about what it was. I tried IE8 running on a Windows XP machine and saw the expected certificate error page. I then switched back to my Windows 7 machine and unticked the “Use TLS 1.0” option inside of IE8’s Advanced Internet Options and revisited the site. This time, I also got a certificate error:
So, the site always yields a certificate error on Windows XP, and on Windows 7 if TLS is disabled. But why?
By now, some of you have probably jumped ahead to solve the case, but I wanted to be very sure. My next tool of choice was Netmon, a packet-monitor that allows me to easily examine the HTTPS handshakes in both the Certificate-Error and No-Certificate-Error cases. I was able to quickly determine that in the No-Certificate-Error case, the GMail site was returning the “CN=gmail.com” certificate while in the Certificate-Error case, it was returning the “CN=mail.google.com” certificate.
More importantly, however, I was able to see the reason why: In the No-Certificate-Error case, the browser was sending the Server Name Indication TLS extension. I first blogged about the SNI extension back in the fall of 2005 when it was introduced in IE7 on Windows Vista. As I explained back then:
When a web browser initiates a HTTPS handshake with a web server, the server immediately sends down a digital certificate. The hostname of the server is listed inside the digital certificate, and the browser compares it to the hostname it was attempting to reach. If these hostnames do not match, the browser raises an error.
The matching-hostnames requirement causes a problem if a single-IP is configured to host multiple sites (sometimes known as “virtual-hosting”). Ordinarily, a virtual-hosting server examines the HTTP Host request header to determine what HTTP content to return. However, in the HTTPS case, the server must provide a digital certificate before it receives the HTTP headers from the browser. SNI resolves this problem by listing the target server’s hostname in the SNI extension field of the initial client handshake with the secure server. A virtual-hosting server may examine the SNI extension to determine which digital certificate to send back to the client.
The GMail server is configured to select a certificate to return based on the SNI sent by the client; the only problem is that pre-Vista versions of IE don’t send the SNI at all, nor will any browser where either SSLv2 is enabled or TLS is disabled. (Even if TLS is enabled, having SSLv2 enabled prevents sending of the TLS extensions because the SSLv2 handshake format cannot carry TLS extensions.)
Unfortunately, SNI support isn’t available on Windows XP, even in IE8. IE relies on SChannel for the implementation of all of its HTTPS protocols. SChannel is an operating system component, and it was only updated with support for TLS extension on Windows Vista and later. The Google folks could avoid the name mismatch problem for downlevel clients by returning a certificate containing multiple hostnames (e.g. “SubjectCN=mail.google.com; SubjectAltNames=DNS Name=gmail.com”) but apparently doing so is problematic because they have so many hostnames in use on their load-balanced servers.
PS: I’m especially glad I investigated this case because it uncovered a bug in Fiddler. Fiddler shouldn’t have encountered this problem (when running on Windows 7) because it should have been using a SSLv3 format handshake and the TLS extensions should have been sent. The bug I found is that Fiddler was incorrectly allowing SSLv2 connections to upstream servers, which forced use of the v2 format handshake, which had the effect of disabling TLS extensions. That bug is now fixed in Fiddler v220.127.116.11.
Of course, when running Fiddler on pre-Vista versions of Windows, it makes no difference: the .NET Framework’s SslStream class also relies on SChannel, and hence TLS extensions aren’t available to .NET applications running on Windows XP either.