From 2b86b4b79495cf2e859f0d5e6e9a3d6ece6e0fe7 Mon Sep 17 00:00:00 2001 From: Fumitoshi UKAI Date: Wed, 26 Dec 2001 12:58:49 +0000 Subject: RFC2818 server identity check update --- ChangeLog | 9 ++++- istream.c | 111 +++++++++++++++++++++++++++++++++----------------------------- istream.h | 5 ++- url.c | 12 ++++--- 4 files changed, 77 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index c6b4287..f9b5327 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2001-12-26 Fumitoshi UKAI + + * istream.h: #include deleted + * istream.c: #include + * istream.c (ssl_check_cert_ident): of subjectAltName dNSName found, + don't try commonName + 2001-12-26 Fumitoshi UKAI * [w3m-dev 02743] RFC2818 server identity check @@ -1613,4 +1620,4 @@ * release-0-2-1 * import w3m-0.2.1 -$Id: ChangeLog,v 1.179 2001/12/26 12:18:06 ukai Exp $ +$Id: ChangeLog,v 1.180 2001/12/26 12:58:49 ukai Exp $ diff --git a/istream.c b/istream.c index 1e11e8f..988d818 100644 --- a/istream.c +++ b/istream.c @@ -1,7 +1,10 @@ -/* $Id: istream.c,v 1.7 2001/12/26 12:18:06 ukai Exp $ */ +/* $Id: istream.c,v 1.8 2001/12/26 12:58:49 ukai Exp $ */ #include "fm.h" #include "istream.h" #include +#ifdef USE_SSL +#include +#endif #define uchar unsigned char @@ -380,11 +383,12 @@ ssl_get_certificate(InputStream stream) } Str -ssl_check_cert_ident(SSL *handle, char *hostname) +ssl_check_cert_ident(SSL * handle, char *hostname) { X509 *x; int i; - Str ret = Strnew_charp("SSL error: failed to check certificate chain"); + Str ret = NULL; + int match_ident = FALSE; /* * All we need to do here is check that the CN matches. * @@ -396,67 +400,72 @@ ssl_check_cert_ident(SSL *handle, char *hostname) * Certification Authorities are encouraged to use the dNSName instead. */ x = SSL_get_peer_certificate(handle); - if (!x) { + if (!x) { ret = Strnew_charp("Unable to get peer certificate"); return ret; } i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1); - if (i >= 0) { - X509_EXTENSION *ex; - STACK_OF(GENERAL_NAME) *alt; - - ex = X509_get_ext(x, i); - alt = X509V3_EXT_d2i(ex); - if (alt) { - int n, len1, len2 = 0; - char *domain; - GENERAL_NAME *gn; - X509V3_EXT_METHOD *method; - - len1 = strlen(hostname); - n = sk_GENERAL_NAME_num(alt); - domain = strchr(hostname, '.'); - if (domain) - len2 = len1 - (domain - hostname); - for (i = 0; i < n; i++) { - gn = sk_GENERAL_NAME_value(alt, i); - if (gn->type == GEN_DNS) { - char *sn = ASN1_STRING_data(gn->d.ia5); - int sl = ASN1_STRING_length(gn->d.ia5); - - /* Is this an exact match? */ - if ((len1 == sl) && !strncasecmp(hostname, sn, len1)) - break; - - /* Is this a wildcard match? */ - if ((*sn == '*') && domain && (len2 == sl-1) && - !strncasecmp(domain, sn+1, len2)) - break; - } - } - method = X509V3_EXT_get(ex); - method->ext_free(alt); - if (i < n) /* Found a match */ - ret = NULL; - } + if (i >= 0) { + X509_EXTENSION *ex; + STACK_OF(GENERAL_NAME) * alt; + + ex = X509_get_ext(x, i); + alt = X509V3_EXT_d2i(ex); + if (alt) { + int n, len1, len2 = 0; + char *domain; + GENERAL_NAME *gn; + X509V3_EXT_METHOD *method; + Str seen_dnsname = NULL; + + len1 = strlen(hostname); + n = sk_GENERAL_NAME_num(alt); + domain = strchr(hostname, '.'); + if (domain) + len2 = len1 - (domain - hostname); + for (i = 0; i < n; i++) { + gn = sk_GENERAL_NAME_value(alt, i); + if (gn->type == GEN_DNS) { + char *sn = ASN1_STRING_data(gn->d.ia5); + int sl = ASN1_STRING_length(gn->d.ia5); + + if (!seen_dnsname) + seen_dnsname = Strnew(); + Strcat_m_charp(seen_dnsname, sn, " "); + /* Is this an exact match? */ + if ((len1 == sl) && !strncasecmp(hostname, sn, len1)) + break; + + /* Is this a wildcard match? */ + if ((*sn == '*') && domain && (len2 == sl - 1) && + !strncasecmp(domain, sn + 1, len2)) + break; + } + } + method = X509V3_EXT_get(ex); + method->ext_free(alt); + if (i < n) /* Found a match */ + match_ident = TRUE; + else if (seen_dnsname) + ret = Sprintf("Bad cert ident from %s: dNSName=%s", hostname, + seen_dnsname->ptr); + } } - if (ret != NULL) { - X509_NAME *xn; - char buf[2048]; + if (match_ident == FALSE && ret == NULL) { + X509_NAME *xn; + char buf[2048]; - xn = X509_get_subject_name(x); + xn = X509_get_subject_name(x); - if (X509_NAME_get_text_by_NID(xn, NID_commonName, - buf, sizeof(buf)) == -1) { + if (X509_NAME_get_text_by_NID(xn, NID_commonName, + buf, sizeof(buf)) == -1) ret = Strnew_charp("Unable to get common name from peer cert"); - return ret; - } else if (strcasecmp(hostname, buf)) ret = Sprintf("Bad cert ident %s from %s", buf, hostname); else - ret = NULL; + match_ident = TRUE; } X509_free(x); return ret; diff --git a/istream.h b/istream.h index 20a0fcd..fb0e088 100644 --- a/istream.h +++ b/istream.h @@ -1,4 +1,4 @@ -/* $Id: istream.h,v 1.5 2001/12/26 12:18:06 ukai Exp $ */ +/* $Id: istream.h,v 1.6 2001/12/26 12:58:49 ukai Exp $ */ #ifndef IO_STREAM_H #define IO_STREAM_H @@ -6,7 +6,6 @@ #ifdef USE_SSL #include #include -#include #include #endif #include "Str.h" @@ -127,7 +126,7 @@ extern int ISfileno(InputStream stream); extern int ISeos(InputStream stream); #ifdef USE_SSL extern Str ssl_get_certificate(InputStream stream); -extern Str ssl_check_cert_ident(SSL *handle, char *hostname); +extern Str ssl_check_cert_ident(SSL * handle, char *hostname); #endif #define IST_BASIC 0 diff --git a/url.c b/url.c index 03d03cd..da7d59e 100644 --- a/url.c +++ b/url.c @@ -1,4 +1,4 @@ -/* $Id: url.c,v 1.23 2001/12/26 12:18:06 ukai Exp $ */ +/* $Id: url.c,v 1.24 2001/12/26 12:58:49 ukai Exp $ */ #include "fm.h" #include #include @@ -372,7 +372,8 @@ openSSLHandle(int sock, char *hostname) if (tolower(*ans) == 'y') { amsg = Strnew_charp("Accept unsecure SSL session: " "unverified certificate"); - } else { + } + else { char *e = "This SSL session was rejected " "to prevent security violation"; disp_err_message(e, FALSE); @@ -381,7 +382,7 @@ openSSLHandle(int sock, char *hostname) } } #endif - + emsg = ssl_check_cert_ident(handle, hostname); if (emsg != NULL) { if (emsg->length > COLS - 16) @@ -391,8 +392,9 @@ openSSLHandle(int sock, char *hostname) ans = inputChar(emsg->ptr); if (tolower(*ans) == 'y') { amsg = Strnew_charp("Accept unsecure SSL session:" - "certificate ident mismatch"); - } else { + "certificate ident mismatch"); + } + else { char *e = "This SSL session was rejected " "to prevent security violation"; disp_err_message(e, FALSE); -- cgit v1.2.3