libfreerdp-core: prepare client-side NLA for event-driven structure
This commit is contained in:
parent
ab5fdcc3f1
commit
eddfee56a3
@ -263,6 +263,8 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO);
|
||||||
|
|
||||||
if (!nego_connect(rdp->nego))
|
if (!nego_connect(rdp->nego))
|
||||||
{
|
{
|
||||||
if (!freerdp_get_last_error(rdp->context))
|
if (!freerdp_get_last_error(rdp->context))
|
||||||
@ -281,10 +283,13 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
|||||||
settings->AutoLogonEnabled = TRUE;
|
settings->AutoLogonEnabled = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdp_set_blocking_mode(rdp, FALSE);
|
/* everything beyond this point is event-driven and non blocking */
|
||||||
|
|
||||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO);
|
rdp->transport->ReceiveCallback = rdp_recv_callback;
|
||||||
rdp->finalize_sc_pdus = 0;
|
rdp->transport->ReceiveExtra = rdp;
|
||||||
|
transport_set_blocking_mode(rdp->transport, FALSE);
|
||||||
|
|
||||||
|
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CONNECT);
|
||||||
|
|
||||||
if (!mcs_send_connect_initial(rdp->mcs))
|
if (!mcs_send_connect_initial(rdp->mcs))
|
||||||
{
|
{
|
||||||
@ -648,38 +653,6 @@ end2:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s)
|
|
||||||
{
|
|
||||||
if (!mcs_recv_connect_response(rdp->mcs, s))
|
|
||||||
{
|
|
||||||
WLog_ERR(TAG, "rdp_client_connect_mcs_connect_response: mcs_recv_connect_response failed");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mcs_send_erect_domain_request(rdp->mcs))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!mcs_send_attach_user_request(rdp->mcs))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s)
|
|
||||||
{
|
|
||||||
if (!mcs_recv_attach_user_confirm(rdp->mcs, s))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
UINT32 i;
|
UINT32 i;
|
||||||
|
@ -51,8 +51,6 @@ BOOL rdp_client_connect(rdpRdp* rdp);
|
|||||||
BOOL rdp_client_disconnect(rdpRdp* rdp);
|
BOOL rdp_client_disconnect(rdpRdp* rdp);
|
||||||
BOOL rdp_client_reconnect(rdpRdp* rdp);
|
BOOL rdp_client_reconnect(rdpRdp* rdp);
|
||||||
BOOL rdp_client_redirect(rdpRdp* rdp);
|
BOOL rdp_client_redirect(rdpRdp* rdp);
|
||||||
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s);
|
|
||||||
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s);
|
|
||||||
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);
|
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);
|
||||||
BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s);
|
BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s);
|
||||||
int rdp_client_connect_license(rdpRdp* rdp, wStream* s);
|
int rdp_client_connect_license(rdpRdp* rdp, wStream* s);
|
||||||
|
@ -1033,8 +1033,6 @@ void nego_init(rdpNego* nego)
|
|||||||
{
|
{
|
||||||
nego->state = NEGO_STATE_INITIAL;
|
nego->state = NEGO_STATE_INITIAL;
|
||||||
nego->RequestedProtocols = PROTOCOL_RDP;
|
nego->RequestedProtocols = PROTOCOL_RDP;
|
||||||
nego->transport->ReceiveCallback = nego_recv;
|
|
||||||
nego->transport->ReceiveExtra = (void*) nego;
|
|
||||||
nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
|
nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
|
||||||
nego->sendNegoData = FALSE;
|
nego->sendNegoData = FALSE;
|
||||||
nego->flags = 0;
|
nego->flags = 0;
|
||||||
@ -1049,11 +1047,12 @@ void nego_init(rdpNego* nego)
|
|||||||
rdpNego* nego_new(rdpTransport* transport)
|
rdpNego* nego_new(rdpTransport* transport)
|
||||||
{
|
{
|
||||||
rdpNego* nego = (rdpNego*) calloc(1, sizeof(rdpNego));
|
rdpNego* nego = (rdpNego*) calloc(1, sizeof(rdpNego));
|
||||||
|
|
||||||
if (!nego)
|
if (!nego)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
nego->transport = transport;
|
nego->transport = transport;
|
||||||
|
|
||||||
nego_init(nego);
|
nego_init(nego);
|
||||||
|
|
||||||
return nego;
|
return nego;
|
||||||
|
@ -105,7 +105,7 @@ SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
|
|||||||
* @param credssp
|
* @param credssp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int nla_ntlm_client_init(rdpNla* nla)
|
int nla_client_init(rdpNla* nla)
|
||||||
{
|
{
|
||||||
char* spn;
|
char* spn;
|
||||||
int length;
|
int length;
|
||||||
@ -117,6 +117,8 @@ int nla_ntlm_client_init(rdpNla* nla)
|
|||||||
settings = nla->settings;
|
settings = nla->settings;
|
||||||
instance = (freerdp*) settings->instance;
|
instance = (freerdp*) settings->instance;
|
||||||
|
|
||||||
|
nla->state = NLA_STATE_INITIAL;
|
||||||
|
|
||||||
if (settings->RestrictedAdminModeRequired)
|
if (settings->RestrictedAdminModeRequired)
|
||||||
settings->DisableCredentialsDelegation = TRUE;
|
settings->DisableCredentialsDelegation = TRUE;
|
||||||
|
|
||||||
@ -251,10 +253,10 @@ int nla_ntlm_client_init(rdpNla* nla)
|
|||||||
|
|
||||||
int nla_client_authenticate(rdpNla* nla)
|
int nla_client_authenticate(rdpNla* nla)
|
||||||
{
|
{
|
||||||
if (nla_ntlm_client_init(nla) < 1)
|
if (nla_client_init(nla) < 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (TRUE)
|
if (nla->state == NLA_STATE_INITIAL)
|
||||||
{
|
{
|
||||||
nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
|
nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
|
||||||
nla->outputBufferDesc.cBuffers = 1;
|
nla->outputBufferDesc.cBuffers = 1;
|
||||||
@ -267,17 +269,69 @@ int nla_client_authenticate(rdpNla* nla)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
|
nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
|
||||||
(nla->haveContext) ? &nla->context : NULL,
|
NULL, nla->ServicePrincipalName, nla->fContextReq, 0,
|
||||||
nla->ServicePrincipalName, nla->fContextReq, 0,
|
SECURITY_NATIVE_DREP, NULL, 0, &nla->context,
|
||||||
SECURITY_NATIVE_DREP, (nla->haveInputBuffer) ? &nla->inputBufferDesc : NULL,
|
&nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
|
||||||
0, &nla->context, &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
|
|
||||||
|
|
||||||
if (nla->haveInputBuffer && (nla->inputBuffer.pvBuffer))
|
if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
|
||||||
{
|
{
|
||||||
free(nla->inputBuffer.pvBuffer);
|
if (nla->table->CompleteAuthToken)
|
||||||
nla->inputBuffer.pvBuffer = NULL;
|
nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
|
||||||
|
|
||||||
|
if (nla->status == SEC_I_COMPLETE_NEEDED)
|
||||||
|
nla->status = SEC_E_OK;
|
||||||
|
else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
|
||||||
|
nla->status = SEC_I_CONTINUE_NEEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nla->status != SEC_I_CONTINUE_NEEDED)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (nla->outputBuffer.cbBuffer < 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
|
||||||
|
nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
|
||||||
|
|
||||||
|
WLog_DBG(TAG, "Sending Authentication Token");
|
||||||
|
winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
|
||||||
|
|
||||||
|
nla_send(nla);
|
||||||
|
nla_buffer_free(nla);
|
||||||
|
|
||||||
|
nla->state = NLA_STATE_NEGO_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_recv(nla) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (nla->state == NLA_STATE_NEGO_TOKEN)
|
||||||
|
{
|
||||||
|
nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
|
||||||
|
nla->inputBufferDesc.cBuffers = 1;
|
||||||
|
nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
|
||||||
|
nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
|
||||||
|
nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
|
||||||
|
nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
|
||||||
|
|
||||||
|
nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
|
||||||
|
nla->outputBufferDesc.cBuffers = 1;
|
||||||
|
nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
|
||||||
|
nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
|
||||||
|
nla->outputBuffer.cbBuffer = nla->cbMaxToken;
|
||||||
|
nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
|
||||||
|
|
||||||
|
if (!nla->outputBuffer.pvBuffer)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
|
||||||
|
&nla->context, nla->ServicePrincipalName, nla->fContextReq, 0,
|
||||||
|
SECURITY_NATIVE_DREP, &nla->inputBufferDesc,
|
||||||
|
0, &nla->context, &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
|
||||||
|
|
||||||
|
free(nla->inputBuffer.pvBuffer);
|
||||||
|
nla->inputBuffer.pvBuffer = NULL;
|
||||||
|
|
||||||
if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
|
if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
|
||||||
{
|
{
|
||||||
if (nla->table->CompleteAuthToken)
|
if (nla->table->CompleteAuthToken)
|
||||||
@ -302,71 +356,55 @@ int nla_client_authenticate(rdpNla* nla)
|
|||||||
nla_encrypt_public_key_echo(nla);
|
nla_encrypt_public_key_echo(nla);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send authentication token to server */
|
if (nla->outputBuffer.cbBuffer < 1)
|
||||||
|
|
||||||
if (nla->outputBuffer.cbBuffer > 0)
|
|
||||||
{
|
|
||||||
nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
|
|
||||||
nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
|
|
||||||
|
|
||||||
WLog_DBG(TAG, "Sending Authentication Token");
|
|
||||||
winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
|
|
||||||
|
|
||||||
nla_send(nla);
|
|
||||||
nla_buffer_free(nla);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nla->status != SEC_I_CONTINUE_NEEDED)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* receive server response and place in input buffer */
|
|
||||||
nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
|
|
||||||
nla->inputBufferDesc.cBuffers = 1;
|
|
||||||
nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
|
|
||||||
nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
|
|
||||||
|
|
||||||
if (nla_recv(nla) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
WLog_DBG(TAG, "Receiving Authentication Token (%d)", (int) nla->negoToken.cbBuffer);
|
nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
|
||||||
|
nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
|
||||||
|
|
||||||
|
WLog_DBG(TAG, "Sending Authentication Token");
|
||||||
winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
|
winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
|
||||||
|
|
||||||
nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
|
nla_send(nla);
|
||||||
nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
|
nla_buffer_free(nla);
|
||||||
nla->haveInputBuffer = TRUE;
|
|
||||||
nla->haveContext = TRUE;
|
nla->state = NLA_STATE_PUB_KEY_AUTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Encrypted Public Key +1 */
|
|
||||||
if (nla_recv(nla) < 0)
|
if (nla_recv(nla) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Verify Server Public Key Echo */
|
if (nla->state == NLA_STATE_PUB_KEY_AUTH)
|
||||||
nla->status = nla_decrypt_public_key_echo(nla);
|
|
||||||
nla_buffer_free(nla);
|
|
||||||
|
|
||||||
if (nla->status != SEC_E_OK)
|
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Could not verify public key echo!");
|
/* Verify Server Public Key Echo */
|
||||||
return -1;
|
nla->status = nla_decrypt_public_key_echo(nla);
|
||||||
|
nla_buffer_free(nla);
|
||||||
|
|
||||||
|
if (nla->status != SEC_E_OK)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "Could not verify public key echo!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send encrypted credentials */
|
||||||
|
nla->status = nla_encrypt_ts_credentials(nla);
|
||||||
|
|
||||||
|
if (nla->status != SEC_E_OK)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "nla_encrypt_ts_credentials status: 0x%08X", nla->status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nla_send(nla);
|
||||||
|
nla_buffer_free(nla);
|
||||||
|
|
||||||
|
nla->state = NLA_STATE_AUTH_INFO;
|
||||||
|
|
||||||
|
/* Free resources */
|
||||||
|
nla->table->FreeCredentialsHandle(&nla->credentials);
|
||||||
|
nla->table->FreeContextBuffer(nla->pPackageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send encrypted credentials */
|
|
||||||
nla->status = nla_encrypt_ts_credentials(nla);
|
|
||||||
|
|
||||||
if (nla->status != SEC_E_OK)
|
|
||||||
{
|
|
||||||
WLog_ERR(TAG, "nla_encrypt_ts_credentials status: 0x%08X", nla->status);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
nla_send(nla);
|
|
||||||
nla_buffer_free(nla);
|
|
||||||
|
|
||||||
/* Free resources */
|
|
||||||
nla->table->FreeCredentialsHandle(&nla->credentials);
|
|
||||||
nla->table->FreeContextBuffer(nla->pPackageInfo);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,7 +413,7 @@ int nla_client_authenticate(rdpNla* nla)
|
|||||||
* @param credssp
|
* @param credssp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int nla_ntlm_server_init(rdpNla* nla)
|
int nla_server_init(rdpNla* nla)
|
||||||
{
|
{
|
||||||
rdpTls* tls = nla->transport->tls;
|
rdpTls* tls = nla->transport->tls;
|
||||||
|
|
||||||
@ -460,7 +498,7 @@ int nla_ntlm_server_init(rdpNla* nla)
|
|||||||
|
|
||||||
int nla_server_authenticate(rdpNla* nla)
|
int nla_server_authenticate(rdpNla* nla)
|
||||||
{
|
{
|
||||||
if (nla_ntlm_server_init(nla) < 1)
|
if (nla_server_init(nla) < 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
@ -1072,30 +1110,11 @@ void nla_send(rdpNla* nla)
|
|||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int nla_recv_ts_request(rdpNla* nla, wStream* s)
|
||||||
* Receive CredSSP message.
|
|
||||||
* @param credssp
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
|
|
||||||
int nla_recv(rdpNla* nla)
|
|
||||||
{
|
{
|
||||||
wStream* s;
|
|
||||||
int length;
|
int length;
|
||||||
int status;
|
|
||||||
UINT32 version;
|
UINT32 version;
|
||||||
|
|
||||||
s = Stream_New(NULL, 4096);
|
|
||||||
|
|
||||||
status = transport_read_pdu(nla->transport, s);
|
|
||||||
|
|
||||||
if (status < 0)
|
|
||||||
{
|
|
||||||
WLog_ERR(TAG, "nla_recv() error: %d", status);
|
|
||||||
Stream_Free(s, TRUE);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TSRequest */
|
/* TSRequest */
|
||||||
if (!ber_read_sequence_tag(s, &length) ||
|
if (!ber_read_sequence_tag(s, &length) ||
|
||||||
!ber_read_contextual_tag(s, 0, &length, TRUE) ||
|
!ber_read_contextual_tag(s, 0, &length, TRUE) ||
|
||||||
@ -1153,6 +1172,28 @@ int nla_recv(rdpNla* nla)
|
|||||||
nla->pubKeyAuth.cbBuffer = length;
|
nla->pubKeyAuth.cbBuffer = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nla_recv(rdpNla* nla)
|
||||||
|
{
|
||||||
|
wStream* s;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
s = Stream_New(NULL, 4096);
|
||||||
|
|
||||||
|
status = transport_read_pdu(nla->transport, s);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "nla_recv() error: %d", status);
|
||||||
|
Stream_Free(s, TRUE);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_recv_ts_request(nla, s) < 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,20 @@ typedef struct rdp_nla rdpNla;
|
|||||||
|
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
|
||||||
|
enum _NLA_STATE
|
||||||
|
{
|
||||||
|
NLA_STATE_INITIAL,
|
||||||
|
NLA_STATE_NEGO_TOKEN,
|
||||||
|
NLA_STATE_PUB_KEY_AUTH,
|
||||||
|
NLA_STATE_AUTH_INFO,
|
||||||
|
NLA_STATE_FINAL
|
||||||
|
};
|
||||||
|
typedef enum _NLA_STATE NLA_STATE;
|
||||||
|
|
||||||
struct rdp_nla
|
struct rdp_nla
|
||||||
{
|
{
|
||||||
BOOL server;
|
BOOL server;
|
||||||
|
NLA_STATE state;
|
||||||
int sendSeqNum;
|
int sendSeqNum;
|
||||||
int recvSeqNum;
|
int recvSeqNum;
|
||||||
freerdp* instance;
|
freerdp* instance;
|
||||||
|
@ -361,7 +361,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
|||||||
rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
|
rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
WLog_ERR(TAG, "DisconnectProviderUltimatum: reason: %d", reason);
|
WLog_ERR(TAG, "DisconnectProviderUltimatum: reason: %d", reason);
|
||||||
rdp->disconnect = TRUE;
|
rdp->disconnect = TRUE;
|
||||||
|
|
||||||
EventArgsInit(&e, "freerdp");
|
EventArgsInit(&e, "freerdp");
|
||||||
@ -748,7 +748,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < (size_t) SrcSize)
|
if (Stream_GetRemainingLength(s) < (size_t) SrcSize)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "bulk_decompress: not enough bytes for compressedLength %d", compressedLength);
|
WLog_ERR(TAG, "bulk_decompress: not enough bytes for compressedLength %d", compressedLength);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,7 +763,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "bulk_decompress() failed");
|
WLog_ERR(TAG, "bulk_decompress() failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -970,13 +970,13 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
|
|||||||
|
|
||||||
if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
|
if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "FATAL: cannot decrypt");
|
WLog_ERR(TAG, "FATAL: cannot decrypt");
|
||||||
return FALSE; /* TODO */
|
return FALSE; /* TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp))
|
if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "FATAL: invalid packet signature");
|
WLog_ERR(TAG, "FATAL: invalid packet signature");
|
||||||
return FALSE; /* TODO */
|
return FALSE; /* TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1000,7 +1000,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
|
|||||||
|
|
||||||
if (memcmp(wmac, cmac, sizeof(wmac)) != 0)
|
if (memcmp(wmac, cmac, sizeof(wmac)) != 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "WARNING: invalid packet signature");
|
WLog_ERR(TAG, "WARNING: invalid packet signature");
|
||||||
/*
|
/*
|
||||||
* Because Standard RDP Security is totally broken,
|
* Because Standard RDP Security is totally broken,
|
||||||
* and cannot protect against MITM, don't treat signature
|
* and cannot protect against MITM, don't treat signature
|
||||||
@ -1032,7 +1032,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
|
|
||||||
if (!rdp_read_header(rdp, s, &length, &channelId))
|
if (!rdp_read_header(rdp, s, &length, &channelId))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Incorrect RDP header.");
|
WLog_ERR(TAG, "Incorrect RDP header.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1053,7 +1053,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
{
|
{
|
||||||
if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
|
if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdp_decrypt failed");
|
WLog_ERR(TAG, "rdp_decrypt failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1088,7 +1088,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
case PDU_TYPE_DATA:
|
case PDU_TYPE_DATA:
|
||||||
if (rdp_recv_data_pdu(rdp, s) < 0)
|
if (rdp_recv_data_pdu(rdp, s) < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdp_recv_data_pdu failed");
|
WLog_ERR(TAG, "rdp_recv_data_pdu failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1108,7 +1108,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WLog_ERR(TAG, "incorrect PDU type: 0x%04X", pduType);
|
WLog_ERR(TAG, "incorrect PDU type: 0x%04X", pduType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1140,7 +1140,7 @@ static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
|
|
||||||
if ((length == 0) || (length > Stream_GetRemainingLength(s)))
|
if ((length == 0) || (length > Stream_GetRemainingLength(s)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "incorrect FastPath PDU header length %d", length);
|
WLog_ERR(TAG, "incorrect FastPath PDU header length %d", length);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,7 +1168,7 @@ static int rdp_recv_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
return rdp_recv_fastpath_pdu(rdp, s);
|
return rdp_recv_fastpath_pdu(rdp, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
rdpRdp* rdp = (rdpRdp*) extra;
|
rdpRdp* rdp = (rdpRdp*) extra;
|
||||||
@ -1179,8 +1179,7 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
|||||||
* enters the active state, an auto-detect PDU can be received
|
* enters the active state, an auto-detect PDU can be received
|
||||||
* on the MCS message channel.
|
* on the MCS message channel.
|
||||||
*/
|
*/
|
||||||
if ((rdp->state > CONNECTION_STATE_MCS_CHANNEL_JOIN) &&
|
if ((rdp->state > CONNECTION_STATE_MCS_CHANNEL_JOIN) && (rdp->state < CONNECTION_STATE_ACTIVE))
|
||||||
(rdp->state < CONNECTION_STATE_ACTIVE))
|
|
||||||
{
|
{
|
||||||
if (rdp_client_connect_auto_detect(rdp, s))
|
if (rdp_client_connect_auto_detect(rdp, s))
|
||||||
return 0;
|
return 0;
|
||||||
@ -1188,14 +1187,42 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
|||||||
|
|
||||||
switch (rdp->state)
|
switch (rdp->state)
|
||||||
{
|
{
|
||||||
case CONNECTION_STATE_NEGO:
|
case CONNECTION_STATE_MCS_CONNECT:
|
||||||
if (!rdp_client_connect_mcs_connect_response(rdp, s))
|
if (!mcs_recv_connect_response(rdp->mcs, s))
|
||||||
status = -1;
|
{
|
||||||
|
WLog_ERR(TAG, "mcs_recv_connect_response failure");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mcs_send_erect_domain_request(rdp->mcs))
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "mcs_send_erect_domain_request failure");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mcs_send_attach_user_request(rdp->mcs))
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "mcs_send_attach_user_request failure");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONNECTION_STATE_MCS_ATTACH_USER:
|
case CONNECTION_STATE_MCS_ATTACH_USER:
|
||||||
if (!rdp_client_connect_mcs_attach_user_confirm(rdp, s))
|
if (!mcs_recv_attach_user_confirm(rdp->mcs, s))
|
||||||
status = -1;
|
{
|
||||||
|
WLog_ERR(TAG, "mcs_recv_attach_user_confirm failure");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId))
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "mcs_send_channel_join_request failure");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
|
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
|
||||||
@ -1226,7 +1253,7 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WLog_ERR(TAG, "Invalid state %d", rdp->state);
|
WLog_ERR(TAG, "Invalid state %d", rdp->state);
|
||||||
status = -1;
|
status = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1256,18 +1283,6 @@ BOOL rdp_send_error_info(rdpRdp* rdp)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set non-blocking mode information.
|
|
||||||
* @param rdp RDP module
|
|
||||||
* @param blocking blocking mode
|
|
||||||
*/
|
|
||||||
void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking)
|
|
||||||
{
|
|
||||||
rdp->transport->ReceiveCallback = rdp_recv_callback;
|
|
||||||
rdp->transport->ReceiveExtra = rdp;
|
|
||||||
transport_set_blocking_mode(rdp->transport, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rdp_check_fds(rdpRdp* rdp)
|
int rdp_check_fds(rdpRdp* rdp)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
@ -213,7 +213,8 @@ int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
|
|||||||
|
|
||||||
void rdp_read_flow_control_pdu(wStream* s, UINT16* type);
|
void rdp_read_flow_control_pdu(wStream* s, UINT16* type);
|
||||||
|
|
||||||
void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking);
|
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra);
|
||||||
|
|
||||||
int rdp_check_fds(rdpRdp* rdp);
|
int rdp_check_fds(rdpRdp* rdp);
|
||||||
|
|
||||||
rdpRdp* rdp_new(rdpContext* context);
|
rdpRdp* rdp_new(rdpContext* context);
|
||||||
|
@ -435,7 +435,7 @@ int transport_read_pdu(rdpTransport* transport, wStream* s)
|
|||||||
/* Make sure there is enough space for the longest header within the stream */
|
/* Make sure there is enough space for the longest header within the stream */
|
||||||
Stream_EnsureCapacity(s, 4);
|
Stream_EnsureCapacity(s, 4);
|
||||||
|
|
||||||
/* Make sure at least two bytes are read for futher processing */
|
/* Make sure at least two bytes are read for further processing */
|
||||||
if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1)
|
if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1)
|
||||||
{
|
{
|
||||||
/* No data available at the moment */
|
/* No data available at the moment */
|
||||||
|
Loading…
Reference in New Issue
Block a user