libfreerdp-core: prepare client-side NLA for event-driven structure

This commit is contained in:
Marc-André Moreau 2015-02-15 14:54:10 -05:00
parent ab5fdcc3f1
commit eddfee56a3
8 changed files with 197 additions and 159 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 */