Fixed channel (dis)connect on redirect or reconnect.

This commit is contained in:
Armin Novak 2018-04-09 11:08:46 +02:00
parent 1698a54b04
commit 0a7691de58
2 changed files with 83 additions and 64 deletions

View File

@ -178,12 +178,12 @@ BOOL rdp_client_connect(rdpRdp* rdp)
{
BOOL status;
rdpSettings* settings = rdp->settings;
/* make sure SSL is initialize for earlier enough for crypto, by taking advantage of winpr SSL FIPS flag for openssl initialization */
DWORD flags = WINPR_SSL_INIT_DEFAULT;
if (settings->FIPSMode)
flags |= WINPR_SSL_INIT_ENABLE_FIPS;
winpr_InitializeSSL(flags);
/* FIPS Mode forces the following and overrides the following(by happening later */
@ -221,7 +221,6 @@ BOOL rdp_client_connect(rdpRdp* rdp)
domain = settings->ComputerName;
domain_length = strlen(domain);
cookie_length = domain_length + 1 + user_length;
cookie = (char*) malloc(cookie_length + 1);
@ -236,7 +235,6 @@ BOOL rdp_client_connect(rdpRdp* rdp)
CopyMemory(&cookie[domain_length + 1], user, user_length);
cookie[cookie_length] = '\0';
status = nego_set_cookie(rdp->nego, cookie);
free(cookie);
}
@ -251,13 +249,10 @@ BOOL rdp_client_connect(rdpRdp* rdp)
nego_set_send_preconnection_pdu(rdp->nego, settings->SendPreconnectionPdu);
nego_set_preconnection_id(rdp->nego, settings->PreconnectionId);
nego_set_preconnection_blob(rdp->nego, settings->PreconnectionBlob);
nego_set_negotiation_enabled(rdp->nego, settings->NegotiateSecurityLayer);
nego_set_restricted_admin_mode_required(rdp->nego, settings->RestrictedAdminModeRequired);
nego_set_gateway_enabled(rdp->nego, settings->GatewayEnabled);
nego_set_gateway_bypass_local(rdp->nego, settings->GatewayBypassLocal);
nego_enable_rdp(rdp->nego, settings->RdpSecurity);
nego_enable_tls(rdp->nego, settings->TlsSecurity);
nego_enable_nla(rdp->nego, settings->NlaSecurity);
@ -288,12 +283,11 @@ BOOL rdp_client_connect(rdpRdp* rdp)
if ((rdp->nego->SelectedProtocol & PROTOCOL_TLS) || (rdp->nego->SelectedProtocol == PROTOCOL_RDP))
{
if ((settings->Username != NULL) && ((settings->Password != NULL) ||
(settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0)))
(settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0)))
settings->AutoLogonEnabled = TRUE;
}
/* everything beyond this point is event-driven and non blocking */
rdp->transport->ReceiveCallback = rdp_recv_callback;
rdp->transport->ReceiveExtra = rdp;
transport_set_blocking_mode(rdp->transport, FALSE);
@ -310,6 +304,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
{
if (!freerdp_get_last_error(rdp->context))
freerdp_set_last_error(rdp->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
return FALSE;
}
}
@ -320,22 +315,34 @@ BOOL rdp_client_connect(rdpRdp* rdp)
BOOL rdp_client_disconnect(rdpRdp* rdp)
{
BOOL status;
status = nego_disconnect(rdp->nego);
rdp_reset(rdp);
rdp_client_transition_to_state(rdp, CONNECTION_STATE_INITIAL);
return status;
}
BOOL rdp_client_redirect(rdpRdp* rdp)
{
BOOL status;
rdpSettings* settings = rdp->settings;
rdpSettings* settings;
rdpContext* context;
if (!rdp || !rdp->settings || !rdp->context)
return FALSE;
settings = rdp->settings;
context = rdp->context;
if (!rdp_client_disconnect(rdp))
return FALSE;
if (freerdp_channels_disconnect(context->channels, context->instance) != CHANNEL_RC_OK)
return FALSE;
freerdp_set_last_error(context, FREERDP_ERROR_SUCCESS);
clearChannelError(context);
ResetEvent(context->abortEvent);
rdp_client_disconnect(rdp);
if (rdp_redirection_apply_settings(rdp) != 0)
return FALSE;
@ -350,6 +357,7 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
{
free(settings->ServerHostname);
settings->ServerHostname = _strdup(settings->RedirectionTargetFQDN);
if (!settings->ServerHostname)
return FALSE;
}
@ -357,6 +365,7 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
{
free(settings->ServerHostname);
settings->ServerHostname = _strdup(settings->TargetNetAddress);
if (!settings->ServerHostname)
return FALSE;
}
@ -364,6 +373,7 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
{
free(settings->ServerHostname);
settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName);
if (!settings->ServerHostname)
return FALSE;
}
@ -373,6 +383,7 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
{
free(settings->Username);
settings->Username = _strdup(settings->RedirectionUsername);
if (!settings->Username)
return FALSE;
}
@ -381,12 +392,16 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
{
free(settings->Domain);
settings->Domain = _strdup(settings->RedirectionDomain);
if (!settings->Domain)
return FALSE;
}
status = rdp_client_connect(rdp);
if (status)
status = (freerdp_channels_post_connect(context->channels, context->instance) == CHANNEL_RC_OK);
return status;
}
@ -396,9 +411,15 @@ BOOL rdp_client_reconnect(rdpRdp* rdp)
rdpContext* context = rdp->context;
rdpChannels* channels = context->channels;
freerdp_channels_disconnect(channels, context->instance);
rdp_client_disconnect(rdp);
if (!rdp_client_disconnect(rdp))
return FALSE;
if (freerdp_channels_disconnect(channels, context->instance) != CHANNEL_RC_OK)
return FALSE;
freerdp_set_last_error(context, FREERDP_ERROR_SUCCESS);
clearChannelError(context);
ResetEvent(context->abortEvent);
status = rdp_client_connect(rdp);
if (status)
@ -420,7 +441,6 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
BOOL ret = FALSE;
rdpSettings* settings;
BYTE* crypt_client_random = NULL;
settings = rdp->settings;
if (!settings->UseRdpSecurityLayer)
@ -430,9 +450,7 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
}
/* encrypt client random */
free(settings->ClientRandom);
settings->ClientRandomLength = CLIENT_RANDOM_LENGTH;
settings->ClientRandom = malloc(settings->ClientRandomLength);
@ -443,7 +461,6 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
key_len = settings->RdpServerCertificate->cert_info.ModulusLength;
mod = settings->RdpServerCertificate->cert_info.Modulus;
exp = settings->RdpServerCertificate->cert_info.exponent;
/*
* client random must be (bitlen / 8) + 8 - see [MS-RDPBCGR] 5.3.4.1
* for details
@ -453,8 +470,8 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
if (!crypt_client_random)
return FALSE;
crypto_rsa_public_encrypt(settings->ClientRandom, settings->ClientRandomLength, 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;
s = Stream_New(NULL, length);
@ -468,11 +485,9 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
rdp_write_security_header(s, SEC_EXCHANGE_PKT | SEC_LICENSE_ENCRYPT_SC);
length = key_len + 8;
Stream_Write_UINT32(s, length);
Stream_Write(s, crypt_client_random, length);
Stream_SealLength(s);
status = transport_write(rdp->mcs->transport, s);
Stream_Free(s, TRUE);
@ -496,15 +511,18 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
WINPR_ENCRYPT,
rdp->fips_encrypt_key,
fips_ivec);
if (!rdp->fips_encrypt)
{
WLog_ERR(TAG, "unable to allocate des3 encrypt key");
goto end;
}
rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC,
WINPR_DECRYPT,
rdp->fips_decrypt_key,
fips_ivec);
if (!rdp->fips_decrypt)
{
WLog_ERR(TAG, "unable to allocate des3 decrypt key");
@ -517,19 +535,20 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len);
rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len);
if (!rdp->rc4_decrypt_key || !rdp->rc4_encrypt_key)
goto end;
ret = TRUE;
end:
free(crypt_client_random);
if (!ret)
{
winpr_Cipher_Free(rdp->fips_decrypt);
winpr_Cipher_Free(rdp->fips_encrypt);
winpr_RC4_Free(rdp->rc4_decrypt_key);
winpr_RC4_Free(rdp->rc4_encrypt_key);
rdp->fips_decrypt = NULL;
rdp->fips_encrypt = NULL;
rdp->rc4_decrypt_key = NULL;
@ -586,6 +605,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
key_len = rdp->settings->RdpServerRsaKey->ModulusLength;
client_random = malloc(key_len);
if (!client_random)
return FALSE;
@ -597,6 +617,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
}
crypt_client_random = calloc(1, rand_len);
if (!crypt_client_random)
{
free(client_random);
@ -604,10 +625,11 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
}
Stream_Read(s, crypt_client_random, rand_len);
mod = rdp->settings->RdpServerRsaKey->Modulus;
priv_exp = rdp->settings->RdpServerRsaKey->PrivateExponent;
if (crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp, client_random) <= 0)
if (crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp,
client_random) <= 0)
{
free(client_random);
goto end;
@ -625,9 +647,10 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
rdp->fips_encrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC,
WINPR_ENCRYPT,
rdp->fips_encrypt_key,
fips_ivec);
WINPR_ENCRYPT,
rdp->fips_encrypt_key,
fips_ivec);
if (!rdp->fips_encrypt)
{
WLog_ERR(TAG, "unable to allocate des3 encrypt key");
@ -635,9 +658,10 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
}
rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC,
WINPR_DECRYPT,
rdp->fips_decrypt_key,
fips_ivec);
WINPR_DECRYPT,
rdp->fips_decrypt_key,
fips_ivec);
if (!rdp->fips_decrypt)
{
WLog_ERR(TAG, "unable to allocate des3 decrypt key");
@ -650,6 +674,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len);
rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len);
if (!rdp->rc4_decrypt_key || !rdp->rc4_encrypt_key)
goto end;
@ -663,12 +688,12 @@ end:
winpr_Cipher_Free(rdp->fips_decrypt);
winpr_RC4_Free(rdp->rc4_encrypt_key);
winpr_RC4_Free(rdp->rc4_decrypt_key);
rdp->fips_encrypt = NULL;
rdp->fips_decrypt = NULL;
rdp->rc4_encrypt_key = NULL;
rdp->rc4_decrypt_key = NULL;
}
return ret;
}
@ -743,7 +768,6 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
return FALSE;
mcs->channels[i].joined = TRUE;
break;
}
@ -814,7 +838,6 @@ BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s)
int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
{
int status;
status = license_recv(rdp->license, s);
if (status < 0)
@ -839,24 +862,19 @@ int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
BYTE* mark;
UINT16 width;
UINT16 height;
width = rdp->settings->DesktopWidth;
height = rdp->settings->DesktopHeight;
Stream_GetPointer(s, mark);
if (!rdp_recv_demand_active(rdp, s))
{
UINT16 channelId;
Stream_SetPointer(s, mark);
rdp_recv_get_active_header(rdp, s, &channelId);
/* Was Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
* but the headers aren't always that length,
* so that could result in a bad offset.
*/
return rdp_recv_out_of_sequence_pdu(rdp, s);
}
@ -879,7 +897,6 @@ int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
if (width != rdp->settings->DesktopWidth || height != rdp->settings->DesktopHeight)
{
BOOL status = TRUE;
IFCALLRET(rdp->update->DesktopResize, status, rdp->update->context);
if (!status)
@ -890,7 +907,6 @@ int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
}
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION);
return rdp_client_connect_finalize(rdp);
}
@ -901,7 +917,6 @@ int rdp_client_connect_finalize(rdpRdp* rdp)
* The client-to-server PDUs sent during this phase have no dependencies on any of the server-to-
* client PDUs; they may be sent as a single batch, provided that sequencing is maintained.
*/
if (!rdp_send_client_synchronize_pdu(rdp))
return -1;
@ -910,6 +925,7 @@ int rdp_client_connect_finalize(rdpRdp* rdp)
if (!rdp_send_client_control_pdu(rdp, CTRLACTION_REQUEST_CONTROL))
return -1;
/**
* [MS-RDPBCGR] 2.2.1.17
* Client persistent key list must be sent if a bitmap is
@ -1009,8 +1025,7 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
{
BOOL status;
rdpSettings* settings = rdp->settings;
rdpNego *nego = rdp->nego;
rdpNego* nego = rdp->nego;
transport_set_blocking_mode(rdp->transport, TRUE);
if (!nego_read_request(nego, s))
@ -1018,12 +1033,12 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
nego->SelectedProtocol = 0;
WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d",
(nego->RequestedProtocols & PROTOCOL_NLA) ? 1 : 0,
(nego->RequestedProtocols & PROTOCOL_TLS) ? 1 : 0,
(nego->RequestedProtocols == PROTOCOL_RDP) ? 1 : 0
);
(nego->RequestedProtocols & PROTOCOL_NLA) ? 1 : 0,
(nego->RequestedProtocols & PROTOCOL_TLS) ? 1 : 0,
(nego->RequestedProtocols == PROTOCOL_RDP) ? 1 : 0
);
WLog_INFO(TAG, "Server Security: NLA:%"PRId32" TLS:%"PRId32" RDP:%"PRId32"",
settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity);
settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity);
if ((settings->NlaSecurity) && (nego->RequestedProtocols & PROTOCOL_NLA))
{
@ -1070,10 +1085,10 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
if (!(nego->SelectedProtocol & PROTOCOL_FAILED_NEGO))
{
WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d",
(nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
(nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
(nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0
);
(nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
(nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
(nego->SelectedProtocol == PROTOCOL_RDP) ? 1 : 0
);
}
if (!nego_send_negotiation_response(nego))
@ -1092,9 +1107,7 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
return FALSE;
transport_set_blocking_mode(rdp->transport, FALSE);
rdp_server_transition_to_state(rdp, CONNECTION_STATE_NEGO);
return TRUE;
}
@ -1118,7 +1131,6 @@ BOOL rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, wStream* s)
return FALSE;
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CONNECT);
return TRUE;
}
@ -1128,7 +1140,6 @@ BOOL rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, wStream* s)
return FALSE;
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ERECT_DOMAIN);
return TRUE;
}
@ -1141,7 +1152,6 @@ BOOL rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, wStream* s)
return FALSE;
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
return TRUE;
}
@ -1174,7 +1184,8 @@ BOOL rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, wStream* s)
allJoined = FALSE;
}
if ((mcs->userChannelJoined) && (mcs->globalChannelJoined) && (mcs->messageChannelId == 0 || mcs->messageChannelJoined) && allJoined)
if ((mcs->userChannelJoined) && (mcs->globalChannelJoined) && (mcs->messageChannelId == 0 ||
mcs->messageChannelJoined) && allJoined)
{
rdp_server_transition_to_state(rdp, CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT);
}
@ -1184,7 +1195,7 @@ BOOL rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, wStream* s)
BOOL rdp_server_accept_confirm_active(rdpRdp* rdp, wStream* s)
{
freerdp_peer *peer = rdp->context->peer;
freerdp_peer* peer = rdp->context->peer;
if (rdp->state != CONNECTION_STATE_CAPABILITIES_EXCHANGE)
return FALSE;

View File

@ -235,14 +235,15 @@ BOOL freerdp_connect(freerdp* instance)
pcap_record record;
update = instance->update;
update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE);
status = FALSE;
if (!update->pcap_rfx)
goto freerdp_connect_finally;
else
update->play_rfx = TRUE;
status = TRUE;
while (pcap_has_next_record(update->pcap_rfx) && status)
{
pcap_get_next_record_header(update->pcap_rfx, &record);
@ -481,8 +482,15 @@ BOOL freerdp_disconnect(freerdp* instance)
{
BOOL rc = TRUE;
rdpRdp* rdp;
if (!instance || !instance->context || !instance->context->rdp)
return FALSE;
rdp = instance->context->rdp;
rdp_client_disconnect(rdp);
if (!rdp_client_disconnect(rdp))
rc = FALSE;
update_post_disconnect(instance->update);
if (instance->settings->AsyncInput)