aboutsummaryrefslogtreecommitdiff
path: root/lib/ssluse.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2004-05-17 22:01:16 +0000
committerDaniel Stenberg <daniel@haxx.se>2004-05-17 22:01:16 +0000
commita9893ca79aa8ee090da91089e89c7f43f6b83443 (patch)
tree678129f3213c1242a352a397d59d30c181d824b4 /lib/ssluse.c
parentf39f7c28f0286ac7f8b20642592cc6b287cc8e3b (diff)
Peter Sylvester's patch that addresses two flaws in the peer certificate name
verification: - when multiple common names are used (as in the curl tests), the last name needs to be selected. - allow comparing with encoded values, at least with BMP and ISO latin1 encoded T61strings.
Diffstat (limited to 'lib/ssluse.c')
-rw-r--r--lib/ssluse.c65
1 files changed, 42 insertions, 23 deletions
diff --git a/lib/ssluse.c b/lib/ssluse.c
index 8a18597fe..727a2e82a 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -787,7 +787,6 @@ cert_hostcheck(const char *certname, const char *hostname)
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;
@@ -872,13 +871,36 @@ static CURLcode verifyhost(struct connectdata *conn,
if(matched)
/* an alternative name matched the server hostname */
- infof(data, "\t subjectAltName: %s matched\n", conn->host.name);
+ infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
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) {
+ j = ASN1_STRING_to_UTF8(&peer_CN,
+ X509_NAME_ENTRY_get_data(
+ X509_NAME_get_entry(name,i)));
+ }
+
+ 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");
@@ -890,25 +912,22 @@ static CURLcode verifyhost(struct connectdata *conn,
infof(data, "\t common name: WARNING couldn't obtain\n");
}
}
- else
- obtain = TRUE;
-
- if(obtain) {
- if(!cert_hostcheck(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.name);
- return CURLE_SSL_PEER_CERTIFICATE;
- }
- else
- infof(data, "\t common name: %s (does not match '%s')\n",
- peer_CN, conn->host.name);
+ else if(!cert_hostcheck((const 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);
+ OPENSSL_free(peer_CN);
+ return 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->host.dispname);
}
- }
-
+ else {
+ infof(data, "\t common name: %s (matched)\n", peer_CN);
+ OPENSSL_free(peer_CN);
+ }
+ }
return CURLE_OK;
}
#endif