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