0c7016
From 3da7c6207ebc4002bc1b0260d7d7c581c2fd635e Mon Sep 17 00:00:00 2001
0c7016
From: Chris <ccpp@gmx.at>
0c7016
Date: Mon, 17 Jun 2013 21:19:01 +0200
0c7016
Subject: [PATCH 3/5] 1) Add support for Wildcard Certificates 2) For Gateway
0c7016
 connections compare against gateway host name instead of target host
0c7016
0c7016
---
0c7016
 libfreerdp-core/tls.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-------
0c7016
 libfreerdp-core/tls.h |  1 +
0c7016
 2 files changed, 58 insertions(+), 9 deletions(-)
0c7016
0c7016
diff --git a/libfreerdp-core/tls.c b/libfreerdp-core/tls.c
0c7016
index b05100e..db09960 100644
0c7016
--- a/libfreerdp-core/tls.c
0c7016
+++ b/libfreerdp-core/tls.c
0c7016
@@ -25,6 +25,7 @@
0c7016
 boolean tls_connect(rdpTls* tls)
0c7016
 {
0c7016
 	int connection_status;
0c7016
+	char *hostname;
0c7016
 
0c7016
 	tls->ctx = SSL_CTX_new(TLSv1_client_method());
0c7016
 
0c7016
@@ -80,7 +81,13 @@ boolean tls_connect(rdpTls* tls)
0c7016
 		return false;
0c7016
 	}
0c7016
 
0c7016
-	if (!tls_verify_certificate(tls, tls->cert, tls->settings->hostname)) {
0c7016
+	if (tls->settings->ts_gateway)
0c7016
+		hostname = tls->settings->tsg_hostname;
0c7016
+	else
0c7016
+		hostname = tls->settings->hostname;
0c7016
+
0c7016
+	if (!tls_verify_certificate(tls, tls->cert, hostname))
0c7016
+	{
0c7016
 		printf("tls_connect: certificate not trusted, aborting.\n");
0c7016
 		tls_disconnect(tls);
0c7016
 		return false;
0c7016
@@ -253,6 +260,50 @@ CryptoCert tls_get_certificate(rdpTls* tls)
0c7016
 	return cert;
0c7016
 }
0c7016
 
0c7016
+boolean tls_match_hostname(char *pattern, int pattern_length, char *hostname)
0c7016
+{
0c7016
+	if (strlen(hostname) == pattern_length)
0c7016
+	{
0c7016
+		if (memcmp((void*) hostname, (void*) pattern, pattern_length) == 0)
0c7016
+			return true;
0c7016
+	}
0c7016
+
0c7016
+	/* ccpp: Check for wildcard certificates */
0c7016
+	if (memchr(pattern, '*', pattern_length) != NULL)
0c7016
+	{
0c7016
+		/* The wildcard matches one subdomain level (all except a dot) */
0c7016
+
0c7016
+		int pattern_position = 0;
0c7016
+		int hostname_position = 0;
0c7016
+
0c7016
+		for(; hostname[hostname_position] && pattern_position < pattern_length; pattern_position++, hostname_position++)
0c7016
+		{
0c7016
+			if( pattern[pattern_position] == '*' ) {
0c7016
+				while( hostname[hostname_position] != '.' && hostname[hostname_position] != '\0' )
0c7016
+					hostname_position++;
0c7016
+
0c7016
+				pattern_position++;
0c7016
+			}
0c7016
+
0c7016
+			if (hostname[hostname_position] != pattern[pattern_position] )
0c7016
+			{
0c7016
+				return false;
0c7016
+			}
0c7016
+		}
0c7016
+	}
0c7016
+
0c7016
+	if (pattern_length > 2 && pattern[0] == '*' && pattern[1] == '.')
0c7016
+	{
0c7016
+		char *check_hostname = &hostname[ strlen(hostname) - pattern_length+1 ];
0c7016
+		if (memcmp((void*) check_hostname, (void*) &pattern[1], pattern_length - 1) == 0 )
0c7016
+		{
0c7016
+			return true;
0c7016
+		}
0c7016
+	}
0c7016
+
0c7016
+	return false;
0c7016
+}
0c7016
+
0c7016
 boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
0c7016
 {
0c7016
 	int match;
0c7016
@@ -288,11 +339,8 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
0c7016
 
0c7016
 	if (common_name != NULL)
0c7016
 	{
0c7016
-		if (strlen(hostname) == common_name_length)
0c7016
-		{
0c7016
-			if (memcmp((void*) hostname, (void*) common_name, common_name_length) == 0)
0c7016
-				hostname_match = true;
0c7016
-		}
0c7016
+		if (tls_match_hostname(common_name, common_name_length, hostname))
0c7016
+			hostname_match = true;
0c7016
 	}
0c7016
 
0c7016
 	/* compare against alternative names */
0c7016
@@ -301,10 +349,10 @@ boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
0c7016
 	{
0c7016
 		for (index = 0; index < alt_names_count; index++)
0c7016
 		{
0c7016
-			if (strlen(hostname) == alt_names_lengths[index])
0c7016
+			if (tls_match_hostname(alt_names[index], alt_names_lengths[index], hostname))
0c7016
 			{
0c7016
-				if (memcmp((void*) hostname, (void*) alt_names[index], alt_names_lengths[index]) == 0)
0c7016
-					hostname_match = true;
0c7016
+				hostname_match = true;
0c7016
+				break;
0c7016
 			}
0c7016
 		}
0c7016
 	}
0c7016
diff --git a/libfreerdp-core/tls.h b/libfreerdp-core/tls.h
0c7016
index e941dd0..b2218f9 100644
0c7016
--- a/libfreerdp-core/tls.h
0c7016
+++ b/libfreerdp-core/tls.h
0c7016
@@ -50,6 +50,7 @@ int tls_read(rdpTls* tls, uint8* data, int length);
0c7016
 int tls_write(rdpTls* tls, uint8* data, int length);
0c7016
 
0c7016
 CryptoCert tls_get_certificate(rdpTls* tls);
0c7016
+boolean tls_match_hostname(char *pattern, int pattern_length, char *hostname);
0c7016
 boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
0c7016
 void tls_print_certificate_error(char* hostname, char* fingerprint);
0c7016
 void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
0c7016
-- 
0c7016
2.5.5
0c7016