diff options
| author | Sam Varshavchik | 2019-12-05 23:21:07 -0500 | 
|---|---|---|
| committer | Sam Varshavchik | 2019-12-05 23:21:07 -0500 | 
| commit | 308ea8eb3eed15a4b32593346d38c82cbf919f4f (patch) | |
| tree | 72382230f2d0efcfb501f0b53111ed50bfda2d64 /tcpd | |
| parent | a16b12fc62d7deb1ac288eddf6ff826da69787f3 (diff) | |
| download | courier-libs-308ea8eb3eed15a4b32593346d38c82cbf919f4f.tar.bz2 | |
gnutls: UTF-8 and hostname fixes.
Diffstat (limited to 'tcpd')
| -rw-r--r-- | tcpd/libcouriergnutls.c | 89 | 
1 files changed, 72 insertions, 17 deletions
| diff --git a/tcpd/libcouriergnutls.c b/tcpd/libcouriergnutls.c index 65c34cb..7a48ae3 100644 --- a/tcpd/libcouriergnutls.c +++ b/tcpd/libcouriergnutls.c @@ -1,5 +1,5 @@  /* -** Copyright 2007-2018 Double Precision, Inc. +** Copyright 2007-2019 Double Precision, Inc.  ** See COPYING for distribution information.  */  #include	"config.h" @@ -567,10 +567,21 @@ static int name_check(ssl_handle ssl,  	p=idn_domain ? idn_domain:ssl->info_cpy.peer_verify_domain; +	printf("Check %s\n", p);  	rc=gnutls_x509_crt_check_hostname(cert, p);  	if (idn_domain) +	{  		free(idn_domain); + +		/* Now try the ACE-encoded hostname for a filename. */ + +		if (rc == 0) +		{ +			p=ssl->info_cpy.peer_verify_domain; +			rc=gnutls_x509_crt_check_hostname(cert, p); +		} +	}  	return rc;  } @@ -736,10 +747,10 @@ static int dohandshake(ssl_handle ssl, int fd, fd_set *r, fd_set *w)  	return rc;  } -static char *check_cert(const char *filename, -			gnutls_certificate_type_t cert_type, -			const char *req_dn, -			int isvirtual) +static char *check_cert_unicode(const char *filename, +				gnutls_certificate_type_t cert_type, +				const char *req_dn, +				int isvirtual)  {  	if (!filename || !*filename)  		return NULL; @@ -766,6 +777,12 @@ static char *check_cert(const char *filename,  		++req_dn;  	} +	/* +	** We're called with a hostname first. Don't check the defualt +	** filename, we'll be called again with an IP address +	*/ + +	if (!isvirtual)  	{  		char *p=malloc(strlen(filename)+10); @@ -782,6 +799,33 @@ static char *check_cert(const char *filename,  	return NULL;  } +static char *check_cert(const char *filename, +			gnutls_certificate_type_t cert_type, +			const char *req_dn, +			int isvirtual) +{ +	if (isvirtual) +	{ +		char *p; +		char *retfile; + +		if (idna_to_ascii_8z(req_dn, &p, 0) != IDNA_SUCCESS) +			p=0; + +		if (p) +		{ +			retfile=check_cert_unicode(filename, cert_type, p, +						    isvirtual); +			free(p); + +			if (retfile) +				return retfile; +		} +	} + +	return check_cert_unicode(filename, cert_type, req_dn, isvirtual); +} +  static char *check_key(const char *filename,  			gnutls_certificate_type_t cert_type,  			const char *req_dn, @@ -952,39 +996,51 @@ static int get_server_cert(gnutls_session_t session,  	     ++vhost_idx)  	{  		char *p; +		char *utf8; +		char *namebuf; + +		/* Convert to UTF8 */ +		if (idna_to_unicode_8z8z(vhost_buf, &utf8, 0) +		    != IDNA_SUCCESS) +			utf8=0; -		for (p=vhost_buf; *p; p++) +		namebuf=utf8 ? utf8:vhost_buf; + +		for (p=namebuf; *p; p++)  			if (*p == '/')  				*p='.'; /* Script kiddie check */  		if (ssl->ctx->certfile)  			certfilename=check_cert(ssl->ctx->certfile,  						st->cert_type, -						vhost_buf, 1); +						namebuf, 1);  		if (ssl->ctx->keyfile)  			keyfilename=check_key(ssl->ctx->keyfile,  						st->cert_type, -						vhost_buf, 1); +						namebuf, 1); +		if (utf8) +			free(utf8);  		if (certfilename)  			break;  	}  	if (!certfilename)  	{ +		const char *ip= +			safe_getenv(ssl->ctx, +				    "TCPLOCALIP", ""); + +		if (strncmp(ip, "::ffff:", 7) == 0 && strchr(ip, '.')) +			ip += 7; +  		if (ssl->ctx->certfile)  			certfilename=check_cert(ssl->ctx->certfile, -						st->cert_type, -						safe_getenv(ssl->ctx, -							    "TCPLOCALIP", ""), -						0); +						st->cert_type, ip, 0);  		if (ssl->ctx->keyfile)  			keyfilename=check_key(ssl->ctx->keyfile, -						st->cert_type, -						safe_getenv(ssl->ctx, -							    "TCPLOCALIP", ""), -						0); +					      st->cert_type, ip, 0);  	}  	if (!certfilename) @@ -1324,7 +1380,6 @@ static int name_set(ssl_handle ssl, ssl_context ctx)  	p=idn_domain ? idn_domain:ctx->info_cpy.peer_verify_domain; -  	rc=gnutls_server_name_set(ssl->session, GNUTLS_NAME_DNS,  				  p, strlen(p)); | 
