Index: lib/ssluse.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/ssluse.c,v
retrieving revision 1.229
diff -u -r1.229 ssluse.c
--- lib/ssluse.c	27 Jul 2009 18:31:48 -0000	1.229
+++ lib/ssluse.c	1 Aug 2009 08:11:55 -0000
@@ -984,14 +984,19 @@
 #define HOST_NOMATCH 0
 #define HOST_MATCH   1
 
-static int hostmatch(const char *hostname, const char *pattern)
+static int hostmatch(const char *hostname, const char *pattern, size_t plen)
 {
   while(1) {
     char c = *pattern++;
+    plen--;
 
-    if(c == '\0')
+    if(!plen)
       return (*hostname ? HOST_NOMATCH : HOST_MATCH);
 
+    if(!c)
+      /* an embedded zero in the pattern can't match a host name */
+      return HOST_NOMATCH;
+
     if(c == '*') {
       c = *pattern;
       if(c == '\0')      /* "*\0" matches anything remaining */
@@ -999,7 +1004,7 @@
 
       while(*hostname) {
         /* The only recursive function in libcurl! */
-        if(hostmatch(hostname++,pattern) == HOST_MATCH)
+        if(hostmatch(hostname++, pattern, plen) == HOST_MATCH)
           return HOST_MATCH;
       }
       break;
@@ -1012,17 +1017,20 @@
 }
 
 static int
-cert_hostcheck(const char *match_pattern, const char *hostname)
+cert_hostcheck(const char *match_pattern, size_t mlen, const char *hostname)
 {
+  size_t hlen = strlen(hostname);
   if(!match_pattern || !*match_pattern ||
-      !hostname || !*hostname) /* sanity check */
+     !hostname || !*hostname) /* sanity check */
     return 0;
 
-  if(Curl_raw_equal(hostname, match_pattern)) /* trivial case */
+  if((hlen == mlen) && !memcmp(hostname, match_pattern, hlen))
+    /* trivial case */
     return 1;
 
-  if(hostmatch(hostname,match_pattern) == HOST_MATCH)
+  if(hostmatch(hostname, match_pattern, mlen) == HOST_MATCH)
     return 1;
+
   return 0;
 }
 
@@ -1095,7 +1103,7 @@
       if(check->type == target) {
         /* get data and length */
         const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
-        size_t altlen;
+        size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
 
         switch(target) {
         case GEN_DNS: /* name/pattern comparison */
@@ -1108,15 +1116,17 @@
              Gisle researched the OpenSSL sources:
              "I checked the 0.9.6 and 0.9.8 sources before my patch and
              it always 0-terminates an IA5String."
+
+             To reduce the risk of an embedded zero before the final zero
+             causing us trouble, we use the length OpenSSL reports!
           */
-          if(cert_hostcheck(altptr, conn->host.name))
+          if(cert_hostcheck(altptr, altlen, conn->host.name))
             matched = TRUE;
           break;
 
         case GEN_IPADD: /* IP address comparison */
           /* compare alternative IP address if the data chunk is the same size
              our server IP address is */
-          altlen = (size_t) ASN1_STRING_length(check->d.ia5);
           if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
             matched = TRUE;
           break;
@@ -1190,7 +1200,8 @@
             "SSL: unable to obtain common name from peer certificate");
       return CURLE_PEER_FAILED_VERIFICATION;
     }
-    else if(!cert_hostcheck((const char *)peer_CN, conn->host.name)) {
+    else if(!cert_hostcheck((const char *)peer_CN, strlen((char *)peer_CN),
+                            conn->host.name)) {
       if(data->set.ssl.verifyhost > 1) {
         failf(data, "SSL: certificate subject name '%s' does not match "
               "target host name '%s'", peer_CN, conn->host.dispname);
