free web page counters

Windows Mobile Pocket PC Smartphone Programming

==>Click here for the SiteMap<==. Original contents with decent amount of source codes.

Tuesday, March 28, 2006

Windows Mobile Secure Socket Implementation Series 3: X.509 Certificate and Wildcard Certificate

====>SiteMap of this Blog<===

Windows Mobile Secure Socket Implementation Series 3: X.509 Certificate and Wildcard Certificate

In previous two posts on Windows Mobile secure socket implementation, I talked about general ideas, and the source code to prepare a socket for secure connection, to crack a BLOB into a X.509 Certificate, and the callback to validate a X.509 certificate.

More on X.509 Certificate, Subject and CN (Common Name)

The function parsing a subject name to retrieve the CN, ParseCN(), is intentionally left out in the source code in previous post. What is a subject, what is CN, and why do we care the subject and CN when we need to validate a certificate?

To answer the above questions, some basic knowledge of X.509 certificate is required. Below are two good and quick readings:

Subject can be roughly understood as the name of an entity, who can be identified by the certificate. CN refers to common name, and in the internet, most probably a host name. Below is Amazon.com's server certificate. Notice the subject line and CN.

CN = www.amazon.com, O = Amazon.com Inc., L = Seattle, ST = Washington, C = US


Now we can answer the question why we need to care subject and CN, because we need to compare CN to the remote host name, to see whether they match. Below is the function to extract CN from the subject line:


char* ParseCN(char* pchSubjLine)
{
   char* pchCommonName = NULL;
   char* pchEnd = NULL;

   if (!pchSubjLine) return NULL;

   pchSubjLine = _strlwr(pchSubjLine);
   pchCommonName = strstr(pchSubjLine, "cn=");
   if (!pchCommonName) {
      return NULL;
   }

   pchCommonName += 3;
   pchEnd = pchCommonName;
   // find the next separator: , or \t or space, or apos
   while ('\0' != *pchEnd && ',' != *pchEnd && ' ' != *pchEnd
      && '\t' != *pchEnd && '\'' != *pchEnd) {
      pchEnd++;
   }
   if ('\0' != pchEnd) pchEnd = '\0';

   return pchCommonName;
}

Wildcard Certificate

If you go back to the source code in my previous post, you may notice that I did a literal match between CN and the remote host name by simply using _stricmp(). This simple literal match should work for most sites, but recently there is an industry trend to use a wildcard certificate, and literal match won't work against such certificate.

What is a wildcard certificate? Let us say a company "example.com" wants to expose 10 web servers to the public internet, all supporting HTTPS:

  • https://www.example.com
  • https://www01.example.com
  • ...
  • https://www09.example.com

The company can buy 10 certificates from CA , each using the fully qualified host name as the CN. Alternatively, the company can buy ONE certificate from CA, using "*.example.com" as the CN. The price of a wildcard certificate is definitely higher than a "normal" certificate, but if the company has a lot of web servers, wildcard certificate can save big. A little bit more information regarding wildcard certificate can be found in "Publishing Multiple Web Sites using a Wildcard Certificate in ISA Server 2004".

Modern browsers like Firefox and IE have no difficulty supporting wildcard certificate and do not complain. Interestingly enough, I found that Pocket IE in both Windows Mobile 2003 devices and Windows Mobile 5.0 devices complains that a wildcard certificate is not a good match to the remote host.

Back to our code. We need to modify the simple literal match to a slightly more advanced one:

if ('*' == *pchCN && '.' == *(pchCN+1)) {
   while ('\0' != *pchRemoteHost && '.' != *pchRemoteHost)
      pchRemoteHost++;
   if ('.' == *pchRemoteHost) {
      bMatched = !(_stricmp(pchRemoteHost+1, pchCN+2));
   }
   // if there is no dot, bMatch remains FALSE
} else {
   bMatched = !(_stricmp(pchRemoteHost, pchCN));
}




Category: [SSL / Socket / Networking / Connection Manager]

====>SiteMap of this Blog<===