Blob Blame History Raw
From 53fa7e1e996f23818e17ab59f1cb1849c533472d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= <marcandre.moreau@gmail.com>
Date: Sun, 12 Feb 2012 12:46:53 -0500
Subject: [PATCH 1/5] libfreerdp-core: verify TLS certificate with both TLS and
 NLA

---
 libfreerdp-core/credssp.c   | 44 ++++++++------------------------------------
 libfreerdp-core/credssp.h   |  1 -
 libfreerdp-core/nego.c      |  5 ++++-
 libfreerdp-core/tls.c       | 19 +++++++++++++++++++
 libfreerdp-core/tls.h       |  2 ++
 libfreerdp-core/transport.c |  1 +
 6 files changed, 34 insertions(+), 38 deletions(-)

diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c
index e269a21..6ef40e1 100644
--- a/libfreerdp-core/credssp.c
+++ b/libfreerdp-core/credssp.c
@@ -119,33 +119,6 @@ int credssp_ntlmssp_init(rdpCredssp* credssp)
 }
 
 /**
- * Get TLS public key.
- * @param credssp
- */
-
-int credssp_get_public_key(rdpCredssp* credssp)
-{
-	int status;
-	CryptoCert cert;
-	
-	cert = tls_get_certificate(credssp->transport->tls);
-
-	if (cert == NULL)
-	{
-		printf("credssp_get_public_key: tls_get_certificate failed to return the server certificate.\n");
-		return 0;
-	}
-
-	if (!tls_verify_certificate(credssp->transport->tls, cert, credssp->transport->settings->hostname))
-		tls_disconnect(credssp->transport->tls);
-
-	status = crypto_cert_get_public_key(cert, &credssp->public_key);
-	crypto_cert_free(cert);
-
-	return status;
-}
-
-/**
  * Authenticate with server using CredSSP.
  * @param credssp
  * @return 1 if authentication is successful
@@ -160,9 +133,6 @@ int credssp_authenticate(rdpCredssp* credssp)
 	if (credssp_ntlmssp_init(credssp) == 0)
 		return 0;
 
-	if (credssp_get_public_key(credssp) == 0)
-		return 0;
-
 	/* NTLMSSP NEGOTIATE MESSAGE */
 	stream_attach(s, negoTokenBuffer, 2048);
 	ntlmssp_send(ntlmssp, s);
@@ -223,16 +193,18 @@ int credssp_authenticate(rdpCredssp* credssp)
 void credssp_encrypt_public_key(rdpCredssp* credssp, rdpBlob* d)
 {
 	uint8* p;
+	rdpTls* tls;
 	uint8 signature[16];
 	rdpBlob encrypted_public_key;
 	NTLMSSP *ntlmssp = credssp->ntlmssp;
+	tls = credssp->transport->tls;
 
-	freerdp_blob_alloc(d, credssp->public_key.length + 16);
-	ntlmssp_encrypt_message(ntlmssp, &credssp->public_key, &encrypted_public_key, signature);
+	freerdp_blob_alloc(d, tls->public_key.length + 16);
+	ntlmssp_encrypt_message(ntlmssp, &tls->public_key, &encrypted_public_key, signature);
 
 #ifdef WITH_DEBUG_NLA
-	printf("Public Key (length = %d)\n", credssp->public_key.length);
-	freerdp_hexdump(credssp->public_key.data, credssp->public_key.length);
+	printf("Public Key (length = %d)\n", tls->public_key.length);
+	freerdp_hexdump(tls->public_key.data, tls->public_key.length);
 	printf("\n");
 
 	printf("Encrypted Public Key (length = %d)\n", encrypted_public_key.length);
@@ -264,6 +236,7 @@ int credssp_verify_public_key(rdpCredssp* credssp, rdpBlob* d)
 	uint8* signature;
 	rdpBlob public_key;
 	rdpBlob encrypted_public_key;
+	rdpTls* tls = credssp->transport->tls;
 
 	signature = d->data;
 	encrypted_public_key.data = (void*) (signature + 16);
@@ -271,7 +244,7 @@ int credssp_verify_public_key(rdpCredssp* credssp, rdpBlob* d)
 
 	ntlmssp_decrypt_message(credssp->ntlmssp, &encrypted_public_key, &public_key, signature);
 
-	p1 = (uint8*) credssp->public_key.data;
+	p1 = (uint8*) tls->public_key.data;
 	p2 = (uint8*) public_key.data;
 
 	p2[0]--;
@@ -661,7 +634,6 @@ void credssp_free(rdpCredssp* credssp)
 {
 	if (credssp != NULL)
 	{
-		freerdp_blob_free(&credssp->public_key);
 		freerdp_blob_free(&credssp->ts_credentials);
 
 		ntlmssp_free(credssp->ntlmssp);
diff --git a/libfreerdp-core/credssp.h b/libfreerdp-core/credssp.h
index 3277425..d98554a 100644
--- a/libfreerdp-core/credssp.h
+++ b/libfreerdp-core/credssp.h
@@ -40,7 +40,6 @@ struct rdp_credssp
 	rdpBlob pubKeyAuth;
 	rdpBlob authInfo;
 	int send_seq_num;
-	rdpBlob public_key;
 	rdpBlob ts_credentials;
 	rdpSettings* settings;
 	CryptoRc4 rc4_seal_state;
diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c
index 7eb810b..ab4da37 100644
--- a/libfreerdp-core/nego.c
+++ b/libfreerdp-core/nego.c
@@ -256,8 +256,10 @@ void nego_attempt_rdp(rdpNego* nego)
 boolean nego_recv_response(rdpNego* nego)
 {
 	STREAM* s = transport_recv_stream_init(nego->transport, 1024);
+
 	if (transport_read(nego->transport, s) < 0)
 		return false;
+
 	return nego_recv(nego->transport, s, nego->transport->recv_extra);
 }
 
@@ -319,6 +321,7 @@ boolean nego_read_request(rdpNego* nego, STREAM* s)
 
 	tpkt_read_header(s);
 	li = tpdu_read_connection_request(s);
+
 	if (li != stream_get_left(s) + 6)
 	{
 		printf("Incorrect TPDU length indicator.\n");
@@ -403,7 +406,7 @@ boolean nego_send_negotiation_request(rdpNego* nego)
 	{
 		int cookie_length = strlen(nego->cookie);
 		stream_write(s, "Cookie: mstshash=", 17);
-		stream_write(s, (uint8*)nego->cookie, cookie_length);
+		stream_write(s, (uint8*) nego->cookie, cookie_length);
 		stream_write_uint8(s, 0x0D); /* CR */
 		stream_write_uint8(s, 0x0A); /* LF */
 		length += cookie_length + 19;
diff --git a/libfreerdp-core/tls.c b/libfreerdp-core/tls.c
index 106f9ca..942b430 100644
--- a/libfreerdp-core/tls.c
+++ b/libfreerdp-core/tls.c
@@ -66,6 +66,23 @@ boolean tls_connect(rdpTls* tls)
 			return false;
 	}
 
+	tls->cert = tls_get_certificate(tls);
+
+	if (tls->cert == NULL)
+	{
+		printf("tls_connect: tls_get_certificate failed to return the server certificate.\n");
+		return false;
+	}
+
+	if (!crypto_cert_get_public_key(tls->cert, &tls->public_key))
+	{
+		printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");
+		return false;
+	}
+
+	if (!tls_verify_certificate(tls, tls->cert, tls->settings->hostname))
+		tls_disconnect(tls);
+
 	return true;
 }
 
@@ -433,6 +450,8 @@ void tls_free(rdpTls* tls)
 		if (tls->ctx)
 			SSL_CTX_free(tls->ctx);
 
+		freerdp_blob_free(&tls->public_key);
+
 		certificate_store_free(tls->certificate_store);
 
 		xfree(tls);
diff --git a/libfreerdp-core/tls.h b/libfreerdp-core/tls.h
index c3f2f59..e941dd0 100644
--- a/libfreerdp-core/tls.h
+++ b/libfreerdp-core/tls.h
@@ -36,6 +36,8 @@ struct rdp_tls
 	SSL* ssl;
 	int sockfd;
 	SSL_CTX* ctx;
+	CryptoCert cert;
+	rdpBlob public_key;
 	rdpSettings* settings;
 	rdpCertificateStore* certificate_store;
 };
diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c
index df43a8e..f4c28d8 100644
--- a/libfreerdp-core/transport.c
+++ b/libfreerdp-core/transport.c
@@ -72,6 +72,7 @@ boolean transport_disconnect(rdpTransport* transport)
 {
 	if (transport->layer == TRANSPORT_LAYER_TLS)
 		tls_disconnect(transport->tls);
+
 	return tcp_disconnect(transport->tcp);
 }
 
-- 
2.5.5