diff options
| author | Fumitoshi UKAI <ukai@debian.or.jp> | 2001-12-26 12:58:49 +0000 | 
|---|---|---|
| committer | Fumitoshi UKAI <ukai@debian.or.jp> | 2001-12-26 12:58:49 +0000 | 
| commit | 2b86b4b79495cf2e859f0d5e6e9a3d6ece6e0fe7 (patch) | |
| tree | 5dd42d265151424d64b3ee9224efcf3d50250d69 | |
| parent | [w3m-dev 02743] RFC2818 server identity check (diff) | |
| download | w3m-2b86b4b79495cf2e859f0d5e6e9a3d6ece6e0fe7.tar.gz w3m-2b86b4b79495cf2e859f0d5e6e9a3d6ece6e0fe7.zip | |
RFC2818 server identity check update
| -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); | 
