libfreerdp-core: fix reconnection using client random

This commit is contained in:
Marc-André Moreau 2014-08-11 11:23:23 -04:00
parent cff9c16c1e
commit 7171a0b5c1
5 changed files with 78 additions and 24 deletions

View File

@ -536,6 +536,8 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_ServerRandomLength 197
#define FreeRDP_ServerCertificate 198
#define FreeRDP_ServerCertificateLength 199
#define FreeRDP_ClientRandom 200
#define FreeRDP_ClientRandomLength 201
#define FreeRDP_ChannelCount 256
#define FreeRDP_ChannelDefArraySize 257
#define FreeRDP_ChannelDefArray 258
@ -851,11 +853,12 @@ struct rdp_settings
ALIGN64 UINT32 ExtEncryptionMethods; /* 194 */
ALIGN64 UINT32 EncryptionLevel; /* 195 */
ALIGN64 BYTE* ServerRandom; /* 196 */
ALIGN64 DWORD ServerRandomLength; /* 197 */
ALIGN64 UINT32 ServerRandomLength; /* 197 */
ALIGN64 BYTE* ServerCertificate; /* 198 */
ALIGN64 DWORD ServerCertificateLength; /* 199 */
ALIGN64 UINT32 ServerCertificateLength; /* 199 */
ALIGN64 BYTE* ClientRandom; /* 200 */
UINT64 padding0256[256 - 201]; /* 201 */
ALIGN64 UINT32 ClientRandomLength; /* 201 */
UINT64 padding0256[256 - 202]; /* 202 */
/* Client Network Data */
ALIGN64 UINT32 ChannelCount; /* 256 */
@ -1014,7 +1017,7 @@ struct rdp_settings
/* Credentials Cache */
ALIGN64 BYTE* Password51; /* 1280 */
ALIGN64 DWORD Password51Length; /* 1281 */
ALIGN64 UINT32 Password51Length; /* 1281 */
UINT64 padding1344[1344 - 1282]; /* 1282 */
/* Kerberos Authentication */
@ -1120,8 +1123,8 @@ struct rdp_settings
ALIGN64 char* RemoteApplicationFile; /* 2116 */
ALIGN64 char* RemoteApplicationGuid; /* 2117 */
ALIGN64 char* RemoteApplicationCmdLine; /* 2118 */
ALIGN64 DWORD RemoteApplicationExpandCmdLine; /* 2119 */
ALIGN64 DWORD RemoteApplicationExpandWorkingDir; /* 2120 */
ALIGN64 UINT32 RemoteApplicationExpandCmdLine; /* 2119 */
ALIGN64 UINT32 RemoteApplicationExpandWorkingDir; /* 2120 */
ALIGN64 BOOL DisableRemoteAppCapsCheck; /* 2121 */
ALIGN64 UINT32 RemoteAppNumIconCaches; /* 2122 */
ALIGN64 UINT32 RemoteAppNumIconCacheEntries; /* 2123 */

View File

@ -1626,6 +1626,12 @@ UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id)
case FreeRDP_EncryptionLevel:
return settings->EncryptionLevel;
case FreeRDP_ServerRandomLength:
return settings->ServerRandomLength;
case FreeRDP_ClientRandomLength:
return settings->ClientRandomLength;
case FreeRDP_ChannelCount:
return settings->ChannelCount;
@ -1875,6 +1881,14 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
settings->EncryptionLevel = param;
break;
case FreeRDP_ServerRandomLength:
settings->ServerRandomLength = param;
break;
case FreeRDP_ClientRandomLength:
settings->ClientRandomLength = param;
break;
case FreeRDP_ChannelCount:
settings->ChannelCount = param;
break;

View File

@ -388,11 +388,14 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
wStream* s;
UINT32 length;
UINT32 key_len;
BYTE *crypt_client_random = NULL;
BOOL ret = FALSE;
int status = 0;
BOOL ret = FALSE;
rdpSettings* settings;
BYTE* crypt_client_random = NULL;
if (!rdp->settings->DisableEncryption)
settings = rdp->settings;
if (!settings->DisableEncryption)
{
/* no RDP encryption */
return TRUE;
@ -400,27 +403,30 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
/* encrypt client random */
if (rdp->settings->ClientRandom)
free(rdp->settings->ClientRandom);
if (settings->ClientRandom)
free(settings->ClientRandom);
rdp->settings->ClientRandom = malloc(CLIENT_RANDOM_LENGTH);
settings->ClientRandomLength = CLIENT_RANDOM_LENGTH;
settings->ClientRandom = malloc(settings->ClientRandomLength);
if (!rdp->settings->ClientRandom)
if (!settings->ClientRandom)
return FALSE;
crypto_nonce(settings->ClientRandom, settings->ClientRandomLength);
key_len = settings->RdpServerCertificate->cert_info.ModulusLength;
mod = settings->RdpServerCertificate->cert_info.Modulus;
exp = settings->RdpServerCertificate->cert_info.exponent;
crypto_nonce(rdp->settings->ClientRandom, CLIENT_RANDOM_LENGTH);
key_len = rdp->settings->RdpServerCertificate->cert_info.ModulusLength;
mod = rdp->settings->RdpServerCertificate->cert_info.Modulus;
exp = rdp->settings->RdpServerCertificate->cert_info.exponent;
/*
* client random must be (bitlen / 8) + 8 - see [MS-RDPBCGR] 5.3.4.1
* for details
*/
crypt_client_random = calloc(1,key_len+8);
crypt_client_random = calloc(1, key_len + 8);
if (!crypt_client_random)
return FALSE;
crypto_rsa_public_encrypt(rdp->settings->ClientRandom, CLIENT_RANDOM_LENGTH, key_len, mod, exp, crypt_client_random);
crypto_rsa_public_encrypt(settings->ClientRandom, settings->ClientRandomLength, key_len, mod, exp, crypt_client_random);
/* send crypt client random to server */
length = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + 4 + key_len + 8;
@ -441,15 +447,15 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
goto end;
/* now calculate encrypt / decrypt and update keys */
if (!security_establish_keys(rdp->settings->ClientRandom, rdp))
if (!security_establish_keys(settings->ClientRandom, rdp))
goto end;
rdp->do_crypt = TRUE;
if (rdp->settings->SaltedChecksum)
if (settings->SaltedChecksum)
rdp->do_secure_checksum = TRUE;
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec);
if (!rdp->fips_encrypt)

View File

@ -105,13 +105,31 @@ BOOL rdp_read_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
void rdp_write_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
{
CryptoHmac hmac;
BYTE nullRandom[32];
BYTE cryptSecurityVerifier[16];
ARC_CS_PRIVATE_PACKET* autoReconnectCookie;
autoReconnectCookie = settings->ClientAutoReconnectCookie;
/* SecurityVerifier = HMAC(AutoReconnectRandom, ClientRandom) */
hmac = crypto_hmac_new();
ZeroMemory(nullRandom, sizeof(nullRandom));
crypto_hmac_md5_init(hmac, autoReconnectCookie->securityVerifier, 16);
if (settings->ClientRandomLength > 0)
crypto_hmac_update(hmac, settings->ClientRandom, settings->ClientRandomLength);
else
crypto_hmac_update(hmac, nullRandom, sizeof(nullRandom));
crypto_hmac_final(hmac, cryptSecurityVerifier, 16);
crypto_hmac_free(hmac);
Stream_Write_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */
Stream_Write_UINT32(s, autoReconnectCookie->version); /* version (4 bytes) */
Stream_Write_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */
Stream_Write(s, autoReconnectCookie->securityVerifier, 16); /* SecurityVerifier */
Stream_Write(s, cryptSecurityVerifier, 16); /* SecurityVerifier */
}
/**

View File

@ -522,6 +522,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
_settings->EncryptionLevel = settings->EncryptionLevel; /* 195 */
_settings->ServerRandomLength = settings->ServerRandomLength; /* 197 */
_settings->ServerCertificateLength = settings->ServerCertificateLength; /* 199 */
_settings->ClientRandomLength = settings->ClientRandomLength; /* 201 */
_settings->ChannelCount = settings->ChannelCount; /* 256 */
_settings->ChannelDefArraySize = settings->ChannelDefArraySize; /* 257 */
_settings->ClusterInfoFlags = settings->ClusterInfoFlags; /* 320 */
@ -725,6 +726,18 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
* Manual Code
*/
if (_settings->ServerRandomLength)
{
_settings->ServerRandom = (BYTE*) malloc(_settings->ServerRandomLength);
CopyMemory(_settings->ServerRandom, settings->ServerRandom, _settings->ServerRandomLength);
}
if (_settings->ClientRandomLength)
{
_settings->ClientRandom = (BYTE*) malloc(_settings->ClientRandomLength);
CopyMemory(_settings->ClientRandom, settings->ClientRandom, _settings->ClientRandomLength);
}
_settings->ChannelCount = settings->ChannelCount;
_settings->ChannelDefArraySize = settings->ChannelDefArraySize;
_settings->ChannelDefArray = (CHANNEL_DEF*) malloc(sizeof(CHANNEL_DEF) * settings->ChannelDefArraySize);
@ -836,7 +849,7 @@ void freerdp_settings_free(rdpSettings* settings)
free(settings->ClientHostname);
free(settings->ClientProductId);
free(settings->ServerRandom);
if (settings->ClientRandom) free(settings->ClientRandom);
free(settings->ClientRandom);
free(settings->ServerCertificate);
free(settings->RdpKeyFile);
certificate_free(settings->RdpServerCertificate);