Blob Blame History Raw
From 3da7c6207ebc4002bc1b0260d7d7c581c2fd635e Mon Sep 17 00:00:00 2001
From: Chris <ccpp@gmx.at>
Date: Mon, 17 Jun 2013 21:19:01 +0200
Subject: [PATCH 3/5] 1) Add support for Wildcard Certificates 2) For Gateway
 connections compare against gateway host name instead of target host

---
 libfreerdp-core/tls.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-------
 libfreerdp-core/tls.h |  1 +
 2 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/libfreerdp-core/tls.c b/libfreerdp-core/tls.c
index b05100e..db09960 100644
--- a/libfreerdp-core/tls.c
+++ b/libfreerdp-core/tls.c
@@ -25,6 +25,7 @@
 boolean tls_connect(rdpTls* tls)
 {
 	int connection_status;
+	char *hostname;
 
 	tls->ctx = SSL_CTX_new(TLSv1_client_method());
 
@@ -80,7 +81,13 @@ boolean tls_connect(rdpTls* tls)
 		return false;
 	}
 
-	if (!tls_verify_certificate(tls, tls->cert, tls->settings->hostname)) {
+	if (tls->settings->ts_gateway)
+		hostname = tls->settings->tsg_hostname;
+	else
+		hostname = tls->settings->hostname;
+
+	if (!tls_verify_certificate(tls, tls->cert, hostname))
+	{
 		printf("tls_connect: certificate not trusted, aborting.\n");
 		tls_disconnect(tls);
 		return false;
@@ -253,6 +260,50 @@ CryptoCert tls_get_certificate(rdpTls* tls)
 	return cert;
 }
 
+boolean tls_match_hostname(char *pattern, int pattern_length, char *hostname)
+{
+	if (strlen(hostname) == pattern_length)
+	{
+		if (memcmp((void*) hostname, (void*) pattern, pattern_length) == 0)
+			return true;
+	}
+
+	/* ccpp: Check for wildcard certificates */
+	if (memchr(pattern, '*', pattern_length) != NULL)
+	{
+		/* The wildcard matches one subdomain level (all except a dot) */
+
+		int pattern_position = 0;
+		int hostname_position = 0;
+
+		for(; hostname[hostname_position] && pattern_position < pattern_length; pattern_position++, hostname_position++)
+		{
+			if( pattern[pattern_position] == '*' ) {
+				while( hostname[hostname_position] != '.' && hostname[hostname_position] != '\0' )
+					hostname_position++;
+
+				pattern_position++;
+			}
+
+			if (hostname[hostname_position] != pattern[pattern_position] )
+			{
+				return false;
+			}
+		}
+	}
+
+	if (pattern_length > 2 && pattern[0] == '*' && pattern[1] == '.')
+	{
+		char *check_hostname = &hostname[ strlen(hostname) - pattern_length+1 ];
+		if (memcmp((void*) check_hostname, (void*) &pattern[1], pattern_length - 1) == 0 )
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
 boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
 {
 	int match;
@@ -288,11 +339,8 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
 
 	if (common_name != NULL)
 	{
-		if (strlen(hostname) == common_name_length)
-		{
-			if (memcmp((void*) hostname, (void*) common_name, common_name_length) == 0)
-				hostname_match = true;
-		}
+		if (tls_match_hostname(common_name, common_name_length, hostname))
+			hostname_match = true;
 	}
 
 	/* compare against alternative names */
@@ -301,10 +349,10 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
 	{
 		for (index = 0; index < alt_names_count; index++)
 		{
-			if (strlen(hostname) == alt_names_lengths[index])
+			if (tls_match_hostname(alt_names[index], alt_names_lengths[index], hostname))
 			{
-				if (memcmp((void*) hostname, (void*) alt_names[index], alt_names_lengths[index]) == 0)
-					hostname_match = true;
+				hostname_match = true;
+				break;
 			}
 		}
 	}
diff --git a/libfreerdp-core/tls.h b/libfreerdp-core/tls.h
index e941dd0..b2218f9 100644
--- a/libfreerdp-core/tls.h
+++ b/libfreerdp-core/tls.h
@@ -50,6 +50,7 @@ int tls_read(rdpTls* tls, uint8* data, int length);
 int tls_write(rdpTls* tls, uint8* data, int length);
 
 CryptoCert tls_get_certificate(rdpTls* tls);
+boolean tls_match_hostname(char *pattern, int pattern_length, char *hostname);
 boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
 void tls_print_certificate_error(char* hostname, char* fingerprint);
 void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
-- 
2.5.5