diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | istream.c | 111 | ||||
-rw-r--r-- | istream.h | 5 | ||||
-rw-r--r-- | url.c | 12 |
4 files changed, 77 insertions, 60 deletions
@@ -1,5 +1,12 @@ 2001-12-26 Fumitoshi UKAI <ukai@debian.or.jp> + * istream.h: #include <x509v3.h> deleted + * istream.c: #include <x509v3.h> + * istream.c (ssl_check_cert_ident): of subjectAltName dNSName found, + don't try commonName + +2001-12-26 Fumitoshi UKAI <ukai@debian.or.jp> + * [w3m-dev 02743] RFC2818 server identity check * NEWS: RFC2818 server identity check * istream.c (ssl_check_cert_ident): added @@ -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 $ @@ -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 <signal.h> +#ifdef USE_SSL +#include <x509v3.h> +#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; @@ -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 <bio.h> #include <x509.h> -#include <x509v3.h> #include <ssl.h> #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 @@ -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 <sys/types.h> #include <sys/socket.h> @@ -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); |