Merge pull request #1553 from dpoe/master
commandline session reconnect
This commit is contained in:
commit
5ef8d929dc
@ -29,6 +29,7 @@
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include <freerdp/client/cmdline.h>
|
||||
@ -140,6 +141,8 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
||||
{ "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "print help" },
|
||||
{ "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "<pcap file>", NULL, NULL, -1, NULL, "Replay rfx pcap file" },
|
||||
{ "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only." },
|
||||
{ "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "<base64 cookie>", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" },
|
||||
{ "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -1669,6 +1672,27 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
|
||||
{
|
||||
settings->AuthenticationOnly = arg->Value ? TRUE : FALSE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "reconnect-cookie")
|
||||
{
|
||||
BYTE *base64;
|
||||
int length;
|
||||
crypto_base64_decode((BYTE *) (arg->Value),
|
||||
(int) strlen(arg->Value), &base64, &length);
|
||||
if ((base64 != NULL) && (length == sizeof(ARC_SC_PRIVATE_PACKET)))
|
||||
{
|
||||
memcpy(settings->ServerAutoReconnectCookie, base64, length);
|
||||
free(base64);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "reconnect-cookie: invalid base64 '%s'\n",
|
||||
arg->Value);
|
||||
}
|
||||
}
|
||||
CommandLineSwitchCase(arg, "print-reconnect-cookie")
|
||||
{
|
||||
settings->PrintReconnectCookie = arg->Value ? TRUE : FALSE;
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ typedef struct crypto_hmac_struct* CryptoHmac;
|
||||
|
||||
FREERDP_API CryptoHmac crypto_hmac_new(void);
|
||||
FREERDP_API void crypto_hmac_sha1_init(CryptoHmac hmac, const BYTE *data, UINT32 length);
|
||||
FREERDP_API void crypto_hmac_md5_init(CryptoHmac hmac, const BYTE *data, UINT32 length);
|
||||
FREERDP_API void crypto_hmac_update(CryptoHmac hmac, const BYTE *data, UINT32 length);
|
||||
FREERDP_API void crypto_hmac_final(CryptoHmac hmac, BYTE *out_data, UINT32 length);
|
||||
FREERDP_API void crypto_hmac_free(CryptoHmac hmac);
|
||||
|
@ -795,7 +795,8 @@ struct rdp_settings
|
||||
ALIGN64 DWORD ServerRandomLength; /* 197 */
|
||||
ALIGN64 BYTE* ServerCertificate; /* 198 */
|
||||
ALIGN64 DWORD ServerCertificateLength; /* 199 */
|
||||
UINT64 padding0256[256 - 200]; /* 200 */
|
||||
ALIGN64 BYTE* ClientRandom; /* 200 */
|
||||
UINT64 padding0256[256 - 201]; /* 201 */
|
||||
|
||||
/* Client Network Data */
|
||||
ALIGN64 UINT32 ChannelCount; /* 256 */
|
||||
@ -870,7 +871,8 @@ struct rdp_settings
|
||||
ALIGN64 UINT32 AutoReconnectMaxRetries; /* 833 */
|
||||
ALIGN64 ARC_CS_PRIVATE_PACKET* ClientAutoReconnectCookie; /* 834 */
|
||||
ALIGN64 ARC_SC_PRIVATE_PACKET* ServerAutoReconnectCookie; /* 835 */
|
||||
UINT64 padding0896[896 - 835]; /* 835 */
|
||||
ALIGN64 BOOL PrintReconnectCookie; /* 836 */
|
||||
UINT64 padding0896[896 - 837]; /* 837 */
|
||||
|
||||
/* Client Info (Time Zone) */
|
||||
ALIGN64 TIME_ZONE_INFO* ClientTimeZone; /* 896 */
|
||||
|
@ -380,7 +380,6 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
|
||||
UINT32 length;
|
||||
UINT32 key_len;
|
||||
BYTE crypt_client_random[256 + 8];
|
||||
BYTE client_random[CLIENT_RANDOM_LENGTH];
|
||||
|
||||
if (!rdp->settings->DisableEncryption)
|
||||
{
|
||||
@ -389,12 +388,15 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
|
||||
}
|
||||
|
||||
/* encrypt client random */
|
||||
if (rdp->settings->ClientRandom) free(rdp->settings->ClientRandom);
|
||||
rdp->settings->ClientRandom = malloc(CLIENT_RANDOM_LENGTH);
|
||||
if (rdp->settings->ClientRandom == NULL) return FALSE;
|
||||
ZeroMemory(crypt_client_random, sizeof(crypt_client_random));
|
||||
crypto_nonce(client_random, sizeof(client_random));
|
||||
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;
|
||||
crypto_rsa_public_encrypt(client_random, sizeof(client_random), key_len, mod, exp, crypt_client_random);
|
||||
crypto_rsa_public_encrypt(rdp->settings->ClientRandom, CLIENT_RANDOM_LENGTH, 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;
|
||||
@ -416,7 +418,7 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
/* now calculate encrypt / decrypt and update keys */
|
||||
if (!security_establish_keys(client_random, rdp))
|
||||
if (!security_establish_keys(rdp->settings->ClientRandom, rdp))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "timezone.h"
|
||||
|
||||
@ -60,6 +62,14 @@ BOOL rdp_read_server_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
|
||||
Stream_Read_UINT32(s, autoReconnectCookie->version); /* version (4 bytes) */
|
||||
Stream_Read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */
|
||||
Stream_Read(s, autoReconnectCookie->arcRandomBits, 16); /* arcRandomBits (16 bytes) */
|
||||
if ((settings->PrintReconnectCookie) && (autoReconnectCookie->cbLen > 0))
|
||||
{
|
||||
char *base64;
|
||||
base64 = crypto_base64_encode((BYTE *) autoReconnectCookie,
|
||||
sizeof(ARC_SC_PRIVATE_PACKET));
|
||||
fprintf(stderr, "Reconnect-cookie: %s\n", base64);
|
||||
free(base64);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -188,7 +198,7 @@ void rdp_write_extended_info_packet(wStream* s, rdpSettings* settings)
|
||||
|
||||
cbClientDir = ConvertToUnicode(CP_UTF8, 0, settings->ClientDir, -1, &clientDir, 0) * 2;
|
||||
|
||||
cbAutoReconnectLen = (int) settings->ClientAutoReconnectCookie->cbLen;
|
||||
cbAutoReconnectLen = (int) settings->ServerAutoReconnectCookie->cbLen;
|
||||
|
||||
Stream_Write_UINT16(s, clientAddressFamily); /* clientAddressFamily */
|
||||
|
||||
@ -214,7 +224,41 @@ void rdp_write_extended_info_packet(wStream* s, rdpSettings* settings)
|
||||
Stream_Write_UINT16(s, cbAutoReconnectLen); /* cbAutoReconnectLen */
|
||||
|
||||
if (cbAutoReconnectLen > 0)
|
||||
{
|
||||
CryptoHmac hmac;
|
||||
ARC_SC_PRIVATE_PACKET* serverCookie;
|
||||
ARC_CS_PRIVATE_PACKET* clientCookie;
|
||||
|
||||
printf("Sending auto reconnect\n");
|
||||
serverCookie = settings->ServerAutoReconnectCookie;
|
||||
clientCookie = settings->ClientAutoReconnectCookie;
|
||||
|
||||
clientCookie->cbLen = serverCookie->cbLen;
|
||||
clientCookie->version = serverCookie->version;
|
||||
clientCookie->logonId = serverCookie->logonId;
|
||||
|
||||
hmac = crypto_hmac_new();
|
||||
crypto_hmac_md5_init(hmac, serverCookie->arcRandomBits, 16);
|
||||
if (settings->SelectedProtocol == PROTOCOL_RDP)
|
||||
{
|
||||
crypto_hmac_update(hmac, (BYTE *) (settings->ClientRandom), 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Anthony Tong's version had 16 zeroes here; I'm not sure why.
|
||||
* I do know that 16 did not reconnect correctly vs Win2008RDVH,
|
||||
* and 32 did.
|
||||
*/
|
||||
const BYTE zeros[32] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
|
||||
crypto_hmac_update(hmac, zeros, 32);
|
||||
}
|
||||
crypto_hmac_final(hmac, clientCookie->securityVerifier, 16);
|
||||
|
||||
rdp_write_client_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */
|
||||
/* mark as used */
|
||||
settings->ServerAutoReconnectCookie->cbLen = 0;
|
||||
}
|
||||
|
||||
/* reserved1 (2 bytes) */
|
||||
/* reserved2 (2 bytes) */
|
||||
|
@ -450,6 +450,7 @@ void freerdp_settings_free(rdpSettings* settings)
|
||||
free(settings->ClientHostname);
|
||||
free(settings->ClientProductId);
|
||||
free(settings->ServerRandom);
|
||||
if (settings->ClientRandom) free(settings->ClientRandom);
|
||||
free(settings->ServerCertificate);
|
||||
free(settings->RdpKeyFile);
|
||||
certificate_free(settings->RdpServerCertificate);
|
||||
|
@ -132,6 +132,11 @@ void crypto_hmac_sha1_init(CryptoHmac hmac, const BYTE* data, UINT32 length)
|
||||
HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_sha1(), NULL);
|
||||
}
|
||||
|
||||
void crypto_hmac_md5_init(CryptoHmac hmac, const BYTE* data, UINT32 length)
|
||||
{
|
||||
HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_md5(), NULL);
|
||||
}
|
||||
|
||||
void crypto_hmac_update(CryptoHmac hmac, const BYTE* data, UINT32 length)
|
||||
{
|
||||
HMAC_Update(&hmac->hmac_ctx, data, length);
|
||||
|
Loading…
Reference in New Issue
Block a user