bagder: curl-www/CVE-2009-2417 curl-7.10.6-CVE-2009-2417.patch, NONE, 1.1 curl-7.11.0-CVE-2009-2417.patch, NONE, 1.1 curl-7.12.1-CVE-2009-2417.patch, NONE, 1.1 curl-7.15.1-CVE-2009-2417.patch, NONE, 1.1 curl-7.15.5-CVE-2009-2417.patch, NONE, 1.1 curl-7.16.4-CVE-2009-2417.patch, NONE, 1.1 curl-7.18.1-CVE-2009-2417.patch, NONE, 1.1 curl-7.19.0-CVE-2009-2417.patch, NONE, 1.1 curl-7.19.5-CVE-2009-2417.patch, NONE, 1.1
[email protected] Mon, 17 Aug 2009 12:54:29 +0000
| Newsgroups | gmane.comp.web.curl.www.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/curl/curl-www/CVE-2009-2417
In directory labb:/tmp/cvs-serv29490/CVE-2009-2417
Added Files:
curl-7.10.6-CVE-2009-2417.patch
curl-7.11.0-CVE-2009-2417.patch
curl-7.12.1-CVE-2009-2417.patch
curl-7.15.1-CVE-2009-2417.patch
curl-7.15.5-CVE-2009-2417.patch
curl-7.16.4-CVE-2009-2417.patch
curl-7.18.1-CVE-2009-2417.patch
curl-7.19.0-CVE-2009-2417.patch
curl-7.19.5-CVE-2009-2417.patch
Log Message:
the patches for CVE-2009-2417
--- NEW FILE: curl-7.11.0-CVE-2009-2417.patch ---
---
lib/ssluse.c | 98 +++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 75 insertions(+), 23 deletions(-)
--- lib/ssluse.c.orig
+++ lib/ssluse.c
@@ -780,7 +780,6 @@ cert_hostcheck(const char *certname, con
static CURLcode verifyhost(struct connectdata *conn,
X509 *server_cert)
{
- char peer_CN[257];
bool matched = FALSE; /* no alternative match yet */
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
int addrlen = 0;
@@ -791,6 +790,7 @@ static CURLcode verifyhost(struct connec
#else
struct in_addr addr;
#endif
+ CURLcode res = CURLE_OK;
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip &&
@@ -839,8 +839,12 @@ static CURLcode verifyhost(struct connec
switch(target) {
case GEN_DNS: /* name comparison */
+ if(altlen == strlen(altptr))
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ ;
/* Is this an exact match? */
- if((hostlen == altlen) &&
+ else if((hostlen == altlen) &&
curl_strnequal(conn->hostname, altptr, hostlen))
matched = TRUE;
@@ -867,11 +871,62 @@ static CURLcode verifyhost(struct connec
/* an alternative name matched the server hostname */
infof(data, "\t subjectAltName: %s matched\n", conn->hostname);
else {
- bool obtain=FALSE;
- if(X509_NAME_get_text_by_NID(X509_get_subject_name(server_cert),
- NID_commonName,
- peer_CN,
- sizeof(peer_CN)) < 0) {
+ /* we have to look to the last occurence of a commonName in the
+ distinguished one to get the most significant one. */
+ int j,i=-1 ;
+
+/* The following is done because of a bug in 0.9.6b */
+
+ unsigned char *nulstr = (unsigned char *)"";
+ unsigned char *peer_CN = nulstr;
+
+ X509_NAME *name = X509_get_subject_name(server_cert) ;
+ if (name)
+ while ((j=X509_NAME_get_index_by_NID(name,NID_commonName,i))>=0)
+ i=j;
+
+ /* we have the name entry and we will now convert this to a string
+ that we can use for comparison. Doing this we support BMPstring,
+ UTF8 etc. */
+
+ if (i>=0) {
+ ASN1_STRING *tmp = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
+
+ /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
+ is already UTF-8 encoded. We check for this case and copy the raw
+ string manually to avoid the problem. This code can be made
+ conditional in the future when OpenSSL has been fixed. Work-around
+ brought by Alexis S. L. Carvalho. */
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
+ }
+ }
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ res = CURLE_SSL_PEER_CERTIFICATE;
+ }
+ }
+ }
+
+ if (peer_CN == nulstr)
+ peer_CN = NULL;
+
+ if(res)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
if(data->set.ssl.verifyhost > 1) {
failf(data,
"SSL: unable to obtain common name from peer certificate");
@@ -883,26 +938,23 @@ static CURLcode verifyhost(struct connec
infof(data, "\t common name: WARNING couldn't obtain\n");
}
}
- else
- obtain = TRUE;
-
- if(obtain) {
- if(!cert_hostcheck(peer_CN, conn->hostname)) {
- if(data->set.ssl.verifyhost > 1) {
- failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", peer_CN, conn->hostname);
- return CURLE_SSL_PEER_CERTIFICATE;
- }
- else
- infof(data, "\t common name: %s (does not match '%s')\n",
- peer_CN, conn->hostname);
+ else if(!cert_hostcheck((const char *)peer_CN, conn->hostname)) {
+ if(data->set.ssl.verifyhost > 1) {
+ failf(data, "SSL: certificate subject name '%s' does not match "
+ "target host name '%s'", peer_CN, conn->hostname);
+ res = CURLE_SSL_PEER_CERTIFICATE;
}
else
- infof(data, "\t common name: %s (matched)\n", peer_CN);
+ infof(data, "\t common name: %s (does not match '%s')\n",
+ peer_CN, conn->hostname);
}
+ else {
+ infof(data, "\t common name: %s (matched)\n", peer_CN);
+ }
+ if(peer_CN)
+ OPENSSL_free(peer_CN);
}
-
- return CURLE_OK;
+ return res;
}
#endif
--- NEW FILE: curl-7.15.5-CVE-2009-2417.patch ---
---
lib/ssluse.c | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
--- lib/ssluse.c.orig
+++ lib/ssluse.c
@@ -929,7 +929,7 @@ static CURLcode verifyhost(struct connec
if(check->type == target) {
/* get data and length */
const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
- int altlen;
+ size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
switch(target) {
case GEN_DNS: /* name/pattern comparison */
@@ -943,14 +943,16 @@ static CURLcode verifyhost(struct connec
"I checked the 0.9.6 and 0.9.8 sources before my patch and
it always 0-terminates an IA5String."
*/
- if (cert_hostcheck(altptr, conn->host.name))
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ cert_hostcheck(altptr, 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 = ASN1_STRING_length(check->d.ia5);
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
matched = TRUE;
break;
@@ -990,18 +992,27 @@ static CURLcode verifyhost(struct connec
string manually to avoid the problem. This code can be made
conditional in the future when OpenSSL has been fixed. Work-around
brought by Alexis S. L. Carvalho. */
- if (tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
- j = ASN1_STRING_length(tmp);
- if (j >= 0) {
- peer_CN = OPENSSL_malloc(j+1);
- if (peer_CN) {
- memcpy(peer_CN, ASN1_STRING_data(tmp), j);
- peer_CN[j] = '\0';
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
}
}
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ res = CURLE_SSL_PEER_CERTIFICATE;
+ }
}
- else /* not a UTF8 name */
- j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
}
if (peer_CN == nulstr)
@@ -1018,7 +1029,10 @@ static CURLcode verifyhost(struct connec
}
#endif /* CURL_DOES_CONVERSIONS */
- if (!peer_CN) {
+ if(res)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
if(data->set.ssl.verifyhost > 1) {
failf(data,
"SSL: unable to obtain common name from peer certificate");
--- NEW FILE: curl-7.19.5-CVE-2009-2417.patch ---
--- lib/ssluse.c-7.19.5 2009-08-03 16:01:58.000000000 +0200
+++ lib/ssluse.c 2009-08-03 16:07:17.000000000 +0200
@@ -1092,7 +1092,8 @@
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 */
@@ -1106,14 +1107,16 @@
"I checked the 0.9.6 and 0.9.8 sources before my patch and
it always 0-terminates an IA5String."
*/
- if(cert_hostcheck(altptr, conn->host.name))
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ cert_hostcheck(altptr, 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;
@@ -1153,18 +1156,27 @@
string manually to avoid the problem. This code can be made
conditional in the future when OpenSSL has been fixed. Work-around
brought by Alexis S. L. Carvalho. */
- if(tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
- j = ASN1_STRING_length(tmp);
- if(j >= 0) {
- peer_CN = OPENSSL_malloc(j+1);
- if(peer_CN) {
- memcpy(peer_CN, ASN1_STRING_data(tmp), j);
- peer_CN[j] = '\0';
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
}
}
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ res = CURLE_PEER_FAILED_VERIFICATION;
+ }
}
- else /* not a UTF8 name */
- j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
}
if(peer_CN == nulstr)
@@ -1182,7 +1194,10 @@
}
#endif /* CURL_DOES_CONVERSIONS */
- if(!peer_CN) {
+ if(res)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
failf(data,
"SSL: unable to obtain common name from peer certificate");
return CURLE_PEER_FAILED_VERIFICATION;
--- NEW FILE: curl-7.12.1-CVE-2009-2417.patch ---
diff -rup curl-7.12.1.orig/lib/ssluse.c curl-7.12.1/lib/ssluse.c
--- curl-7.12.1.orig/lib/ssluse.c 2009-08-08 10:59:35.082595273 +0200
+++ curl-7.12.1/lib/ssluse.c 2009-08-08 10:59:56.406590013 +0200
@@ -868,7 +868,7 @@ static CURLcode verifyhost(struct connec
if(check->type == target) {
/* get data and length */
const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
- int altlen;
+ size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
switch(target) {
case GEN_DNS: /* name/pattern comparison */
@@ -882,14 +882,16 @@ static CURLcode verifyhost(struct connec
"I checked the 0.9.6 and 0.9.8 sources before my patch and
it always 0-terminates an IA5String."
*/
- if (cert_hostcheck(altptr, conn->host.name))
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ cert_hostcheck(altptr, 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 = ASN1_STRING_length(check->d.ia5);
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
matched = TRUE;
break;
@@ -929,18 +931,29 @@ static CURLcode verifyhost(struct connec
string manually to avoid the problem. This code can be made
conditional in the future when OpenSSL has been fixed. Work-around
brought by Alexis S. L. Carvalho. */
- if (tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
- j = ASN1_STRING_length(tmp);
- if (j >= 0) {
- peer_CN = OPENSSL_malloc(j+1);
- if (peer_CN) {
- memcpy(peer_CN, ASN1_STRING_data(tmp), j);
- peer_CN[j] = '\0';
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
}
}
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ if (peer_CN != nulstr)
+ OPENSSL_free(peer_CN);
+ return CURLE_SSL_PEER_CERTIFICATE;
+ }
}
- else /* not a UTF8 name */
- j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
}
if (peer_CN == nulstr)
--- NEW FILE: curl-7.18.1-CVE-2009-2417.patch ---
---
lib/ssluse.c | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
--- lib/ssluse.c.orig
+++ lib/ssluse.c
@@ -1061,7 +1061,7 @@ static CURLcode verifyhost(struct connec
if(check->type == target) {
/* get data and length */
const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
- int altlen;
+ size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
switch(target) {
case GEN_DNS: /* name/pattern comparison */
@@ -1075,14 +1075,16 @@ static CURLcode verifyhost(struct connec
"I checked the 0.9.6 and 0.9.8 sources before my patch and
it always 0-terminates an IA5String."
*/
- if(cert_hostcheck(altptr, conn->host.name))
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ cert_hostcheck(altptr, 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 = ASN1_STRING_length(check->d.ia5);
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
matched = TRUE;
break;
@@ -1122,18 +1124,27 @@ static CURLcode verifyhost(struct connec
string manually to avoid the problem. This code can be made
conditional in the future when OpenSSL has been fixed. Work-around
brought by Alexis S. L. Carvalho. */
- if(tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
- j = ASN1_STRING_length(tmp);
- if(j >= 0) {
- peer_CN = OPENSSL_malloc(j+1);
- if(peer_CN) {
- memcpy(peer_CN, ASN1_STRING_data(tmp), j);
- peer_CN[j] = '\0';
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
}
}
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ res = CURLE_PEER_FAILED_VERIFICATION;
+ }
}
- else /* not a UTF8 name */
- j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
}
if(peer_CN == nulstr)
@@ -1151,7 +1162,10 @@ static CURLcode verifyhost(struct connec
}
#endif /* CURL_DOES_CONVERSIONS */
- if(!peer_CN) {
+ if(res)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
failf(data,
"SSL: unable to obtain common name from peer certificate");
return CURLE_PEER_FAILED_VERIFICATION;
--- NEW FILE: curl-7.19.0-CVE-2009-2417.patch ---
---
lib/ssluse.c | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
--- lib/ssluse.c.orig
+++ lib/ssluse.c
@@ -1064,7 +1064,7 @@ static CURLcode verifyhost(struct connec
if(check->type == target) {
/* get data and length */
const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
- int altlen;
+ size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
switch(target) {
case GEN_DNS: /* name/pattern comparison */
@@ -1078,14 +1078,16 @@ static CURLcode verifyhost(struct connec
"I checked the 0.9.6 and 0.9.8 sources before my patch and
it always 0-terminates an IA5String."
*/
- if(cert_hostcheck(altptr, conn->host.name))
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ cert_hostcheck(altptr, 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 = ASN1_STRING_length(check->d.ia5);
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
matched = TRUE;
break;
@@ -1125,18 +1127,27 @@ static CURLcode verifyhost(struct connec
string manually to avoid the problem. This code can be made
conditional in the future when OpenSSL has been fixed. Work-around
brought by Alexis S. L. Carvalho. */
- if(tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
- j = ASN1_STRING_length(tmp);
- if(j >= 0) {
- peer_CN = OPENSSL_malloc(j+1);
- if(peer_CN) {
- memcpy(peer_CN, ASN1_STRING_data(tmp), j);
- peer_CN[j] = '\0';
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
}
}
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ res = CURLE_PEER_FAILED_VERIFICATION;
+ }
}
- else /* not a UTF8 name */
- j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
}
if(peer_CN == nulstr)
@@ -1154,7 +1165,10 @@ static CURLcode verifyhost(struct connec
}
#endif /* CURL_DOES_CONVERSIONS */
- if(!peer_CN) {
+ if(res)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
failf(data,
"SSL: unable to obtain common name from peer certificate");
return CURLE_PEER_FAILED_VERIFICATION;
--- NEW FILE: curl-7.10.6-CVE-2009-2417.patch ---
diff -rup curl-7.10.6.orig/lib/ssluse.c curl-7.10.6/lib/ssluse.c
--- curl-7.10.6.orig/lib/ssluse.c 2009-08-08 10:41:32.442607231 +0200
+++ curl-7.10.6/lib/ssluse.c 2009-08-08 10:53:52.459515245 +0200
@@ -736,6 +736,95 @@ cert_hostcheck(const char *certname, con
}
#endif
+static CURLcode verifyhost(struct connectdata *conn,
+ X509 *server_cert)
+{
+ struct SessionHandle *data = conn->data;
+
+ /* we have to look to the last occurence of a commonName in the
+ distinguished one to get the most significant one. */
+ int j,i=-1 ;
+
+/* The following is done because of a bug in 0.9.6b */
+
+ unsigned char *nulstr = (unsigned char *)"";
+ unsigned char *peer_CN = nulstr;
+
+ X509_NAME *name = X509_get_subject_name(server_cert) ;
+ if (name)
+ while ((j=X509_NAME_get_index_by_NID(name,NID_commonName,i))>=0)
+ i=j;
+
+ /* we have the name entry and we will now convert this to a string
+ that we can use for comparison. Doing this we support BMPstring,
+ UTF8 etc. */
+
+ if (i>=0) {
+ ASN1_STRING *tmp = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
+
+ /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
+ is already UTF-8 encoded. We check for this case and copy the raw
+ string manually to avoid the problem. This code can be made
+ conditional in the future when OpenSSL has been fixed. Work-around
+ brought by Alexis S. L. Carvalho. */
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
+ }
+ }
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ if (peer_CN != nulstr)
+ OPENSSL_free(peer_CN);
+ return CURLE_SSL_PEER_CERTIFICATE;
+ }
+ }
+ }
+
+ if (peer_CN == nulstr)
+ peer_CN = NULL;
+
+ if (!peer_CN) {
+ if(data->set.ssl.verifyhost > 1) {
+ failf(data,
+ "SSL: unable to obtain common name from peer certificate");
+ return CURLE_SSL_PEER_CERTIFICATE;
+ }
+ else {
+ /* Consider verifyhost == 1 as an "OK" for a missing CN field, but we
+ output a note about the situation */
+ infof(data, "\t common name: WARNING couldn't obtain\n");
+ }
+ }
+ else if(!cert_hostcheck((const char *)peer_CN, conn->hostname)) {
+ if(data->set.ssl.verifyhost > 1) {
+ failf(data, "SSL: certificate subject name '%s' does not match "
+ "target host name '%s'", peer_CN, conn->hostname);
+ OPENSSL_free(peer_CN);
+ return CURLE_SSL_PEER_CERTIFICATE ;
+ }
+ else
+ infof(data, "\t common name: %s (does not match '%s')\n",
+ peer_CN, conn->hostname);
+ }
+ else {
+ infof(data, "\t common name: %s (matched)\n", peer_CN);
+ OPENSSL_free(peer_CN);
+ }
+ return CURLE_OK;
+}
+
/* ====================================================== */
CURLcode
Curl_SSLConnect(struct connectdata *conn)
@@ -1013,32 +1102,12 @@ Curl_SSLConnect(struct connectdata *conn
certdate = X509_get_notAfter(conn->ssl.server_cert);
Curl_ASN1_UTCTIME_output(conn, "\t expire date: ", certdate);
- if (data->set.ssl.verifyhost) {
- char peer_CN[257];
- if (X509_NAME_get_text_by_NID(X509_get_subject_name(conn->ssl.server_cert),
- NID_commonName,
- peer_CN,
- sizeof(peer_CN)) < 0) {
- failf(data, "SSL: unable to obtain common name from peer certificate");
- X509_free(conn->ssl.server_cert);
- return CURLE_SSL_PEER_CERTIFICATE;
- }
-
- if (!cert_hostcheck(peer_CN, conn->hostname)) {
- if (data->set.ssl.verifyhost > 1) {
- failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'",
- peer_CN, conn->hostname);
- X509_free(conn->ssl.server_cert);
- return CURLE_SSL_PEER_CERTIFICATE;
- }
- else
- infof(data,
- "\t common name: %s (does not match '%s')\n",
- peer_CN, conn->hostname);
+ if(data->set.ssl.verifyhost) {
+ retcode = verifyhost(conn, conn->ssl.server_cert);
+ if(retcode) {
+ X509_free(conn->ssl.server_cert);
+ return retcode;
}
- else
- infof(data, "\t common name: %s (matched)\n", peer_CN);
}
str = X509_NAME_oneline (X509_get_issuer_name (conn->ssl.server_cert),
--- NEW FILE: curl-7.15.1-CVE-2009-2417.patch ---
---
lib/ssluse.c | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
--- lib/ssluse.c.orig
+++ lib/ssluse.c
@@ -894,7 +894,7 @@ static CURLcode verifyhost(struct connec
if(check->type == target) {
/* get data and length */
const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
- int altlen;
+ size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
switch(target) {
case GEN_DNS: /* name/pattern comparison */
@@ -908,14 +908,16 @@ static CURLcode verifyhost(struct connec
"I checked the 0.9.6 and 0.9.8 sources before my patch and
it always 0-terminates an IA5String."
*/
- if (cert_hostcheck(altptr, conn->host.name))
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ cert_hostcheck(altptr, 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 = ASN1_STRING_length(check->d.ia5);
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
matched = TRUE;
break;
@@ -955,24 +957,36 @@ static CURLcode verifyhost(struct connec
string manually to avoid the problem. This code can be made
conditional in the future when OpenSSL has been fixed. Work-around
brought by Alexis S. L. Carvalho. */
- if (tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
- j = ASN1_STRING_length(tmp);
- if (j >= 0) {
- peer_CN = OPENSSL_malloc(j+1);
- if (peer_CN) {
- memcpy(peer_CN, ASN1_STRING_data(tmp), j);
- peer_CN[j] = '\0';
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
}
}
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ res = CURLE_SSL_PEER_CERTIFICATE;
+ }
}
- else /* not a UTF8 name */
- j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
}
if (peer_CN == nulstr)
peer_CN = NULL;
- if (!peer_CN) {
+ if(res)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
if(data->set.ssl.verifyhost > 1) {
failf(data,
"SSL: unable to obtain common name from peer certificate");
--- NEW FILE: curl-7.16.4-CVE-2009-2417.patch ---
---
lib/ssluse.c | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
--- lib/ssluse.c.orig
+++ lib/ssluse.c
@@ -1040,7 +1040,7 @@ static CURLcode verifyhost(struct connec
if(check->type == target) {
/* get data and length */
const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
- int altlen;
+ size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
switch(target) {
case GEN_DNS: /* name/pattern comparison */
@@ -1054,14 +1054,16 @@ static CURLcode verifyhost(struct connec
"I checked the 0.9.6 and 0.9.8 sources before my patch and
it always 0-terminates an IA5String."
*/
- if (cert_hostcheck(altptr, conn->host.name))
+ if((altlen == strlen(altptr)) &&
+ /* if this isn't true, there was an embedded zero in the name
+ string and we cannot match it. */
+ cert_hostcheck(altptr, 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 = ASN1_STRING_length(check->d.ia5);
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
matched = TRUE;
break;
@@ -1101,18 +1103,27 @@ static CURLcode verifyhost(struct connec
string manually to avoid the problem. This code can be made
conditional in the future when OpenSSL has been fixed. Work-around
brought by Alexis S. L. Carvalho. */
- if (tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
- j = ASN1_STRING_length(tmp);
- if (j >= 0) {
- peer_CN = OPENSSL_malloc(j+1);
- if (peer_CN) {
- memcpy(peer_CN, ASN1_STRING_data(tmp), j);
- peer_CN[j] = '\0';
+ if(tmp) {
+ if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
+ j = ASN1_STRING_length(tmp);
+ if(j >= 0) {
+ peer_CN = OPENSSL_malloc(j+1);
+ if(peer_CN) {
+ memcpy(peer_CN, ASN1_STRING_data(tmp), j);
+ peer_CN[j] = '\0';
+ }
}
}
+ else /* not a UTF8 name */
+ j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
+
+ if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
+ /* there was a terminating zero before the end of string, this
+ cannot match and we return failure! */
+ failf(data, "SSL: illegal cert name field");
+ res = CURLE_SSL_PEER_CERTIFICATE;
+ }
}
- else /* not a UTF8 name */
- j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
}
if (peer_CN == nulstr)
@@ -1130,7 +1141,10 @@ static CURLcode verifyhost(struct connec
}
#endif /* CURL_DOES_CONVERSIONS */
- if (!peer_CN) {
+ if(res)
+ /* error already detected, pass through */
+ ;
+ else if(!peer_CN) {
if(data->set.ssl.verifyhost > 1) {
failf(data,
"SSL: unable to obtain common name from peer certificate");