Raw channel send (#7255)

* Added raw channel data write function

* Use nego_set_state

* Added ArrayList_ForEachAP

* Provide va_copy for older VS compilers
This commit is contained in:
akallabeth
2021-08-26 16:17:51 +02:00
committed by GitHub
parent 68f24477f6
commit f1bde376b1
11 changed files with 240 additions and 106 deletions

View File

@@ -197,6 +197,8 @@ extern "C"
typedef BOOL (*pSendChannelData)(freerdp* instance, UINT16 channelId, const BYTE* data,
size_t size);
typedef BOOL (*pSendChannelPacket)(freerdp* instance, UINT16 channelId, size_t totalSize,
UINT32 flags, const BYTE* data, size_t chunkSize);
typedef BOOL (*pReceiveChannelData)(freerdp* instance, UINT16 channelId, const BYTE* data,
size_t size, UINT32 flags, size_t totalSize);
@@ -429,7 +431,14 @@ fingerprint. DEPRECATED: Use VerifyChangedCertificateEx */
VerifyChangedCertificateEx; /**< (offset 67)
Callback for changed certificate validation.
Used when a certificate differs from stored fingerprint. */
UINT64 paddingE[80 - 68]; /* 68 */
ALIGN64 pSendChannelPacket
SendChannelPacket; /* (offset 68)
* Callback for sending RAW data to a channel. In contrast to
* SendChannelData data fragmentation is up to the user and this
* function sends data as is with the provided flags.
*/
UINT64 paddingE[80 - 69]; /* 69 */
};
struct rdp_channel_handles

View File

@@ -54,6 +54,8 @@ typedef BOOL (*psPeerClientCapabilities)(freerdp_peer* peer);
typedef BOOL (*psPeerSendChannelData)(freerdp_peer* peer, UINT16 channelId, const BYTE* data,
size_t size);
typedef BOOL (*psPeerSendChannelPacket)(freerdp_peer* client, UINT16 channelId, size_t totalSize,
UINT32 flags, const BYTE* data, size_t chunkSize);
typedef BOOL (*psPeerReceiveChannelData)(freerdp_peer* peer, UINT16 channelId, const BYTE* data,
size_t size, UINT32 flags, size_t totalSize);
@@ -134,6 +136,8 @@ struct rdp_freerdp_peer
psPeerClientCapabilities ClientCapabilities;
psPeerComputeNtlmHash ComputeNtlmHash;
psPeerLicenseCallback LicenseCallback;
psPeerSendChannelPacket SendChannelPacket;
};
#ifdef __cplusplus

View File

@@ -53,7 +53,6 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_
{
DWORD i;
size_t left;
wStream* s;
UINT32 flags;
size_t chunkSize;
rdpMcs* mcs = rdp->mcs;
@@ -80,11 +79,6 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_
while (left > 0)
{
s = rdp_send_stream_init(rdp);
if (!s)
return FALSE;
if (left > rdp->settings->VirtualChannelChunkSize)
{
chunkSize = rdp->settings->VirtualChannelChunkSize;
@@ -100,19 +94,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
}
Stream_Write_UINT32(s, size);
Stream_Write_UINT32(s, flags);
if (!Stream_EnsureCapacity(s, chunkSize))
{
Stream_Release(s);
return FALSE;
}
Stream_Write(s, data, chunkSize);
/* WLog_DBG(TAG, "%s: sending data (flags=0x%x size=%d)", __FUNCTION__, flags, size); */
if (!rdp_send(rdp, s, channelId))
if (!freerdp_channel_send_packet(rdp, channelId, size, flags, data, chunkSize))
return FALSE;
data += chunkSize;
@@ -299,3 +281,26 @@ const WtsApiFunctionTable* FreeRDP_InitWtsApi(void)
{
return &FreeRDP_WtsApiFunctionTable;
}
BOOL freerdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize, UINT32 flags,
const BYTE* data, size_t chunkSize)
{
wStream* s = rdp_send_stream_init(rdp);
if (!s)
return FALSE;
Stream_Write_UINT32(s, totalSize);
Stream_Write_UINT32(s, flags);
if (!Stream_EnsureCapacity(s, chunkSize))
{
Stream_Release(s);
return FALSE;
}
Stream_Write(s, data, chunkSize);
/* WLog_DBG(TAG, "%s: sending data (flags=0x%x size=%d)", __FUNCTION__, flags, size); */
return rdp_send(rdp, s, channelId);
}

View File

@@ -25,6 +25,8 @@
FREERDP_LOCAL BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data,
size_t size);
FREERDP_LOCAL BOOL freerdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize,
UINT32 flags, const BYTE* data, size_t chunkSize);
FREERDP_LOCAL BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId,
size_t packetLength);
FREERDP_LOCAL BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId);

View File

@@ -410,9 +410,22 @@ int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD id)
static BOOL freerdp_send_channel_data(freerdp* instance, UINT16 channelId, const BYTE* data,
size_t size)
{
WINPR_ASSERT(instance);
WINPR_ASSERT(instance->context);
WINPR_ASSERT(instance->context->rdp);
return rdp_send_channel_data(instance->context->rdp, channelId, data, size);
}
static BOOL freerdp_send_channel_packet(freerdp* instance, UINT16 channelId, size_t totalSize,
UINT32 flags, const BYTE* data, size_t chunkSize)
{
WINPR_ASSERT(instance);
WINPR_ASSERT(instance->context);
WINPR_ASSERT(instance->context->rdp);
return rdp_channel_send_packet(instance->context->rdp, channelId, totalSize, flags, data,
chunkSize);
}
BOOL freerdp_disconnect(freerdp* instance)
{
BOOL rc = TRUE;
@@ -869,6 +882,7 @@ freerdp* freerdp_new(void)
instance->ContextSize = sizeof(rdpContext);
instance->SendChannelData = freerdp_send_channel_data;
instance->SendChannelPacket = freerdp_send_channel_packet;
instance->ReceiveChannelData = freerdp_channels_data;
return instance;
}

View File

@@ -25,6 +25,7 @@
#endif
#include <winpr/crt.h>
#include <winpr/assert.h>
#include <freerdp/log.h>
@@ -103,30 +104,33 @@ static BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s);
BOOL nego_connect(rdpNego* nego)
{
rdpSettings* settings = nego->transport->settings;
if (nego->state == NEGO_STATE_INITIAL)
rdpSettings* settings;
WINPR_ASSERT(nego);
WINPR_ASSERT(nego->transport);
settings = nego->transport->settings;
WINPR_ASSERT(settings);
if (nego_get_state(nego) == NEGO_STATE_INITIAL)
{
if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
{
nego->state = NEGO_STATE_EXT;
nego_set_state(nego, NEGO_STATE_EXT);
}
else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
{
nego->state = NEGO_STATE_NLA;
nego_set_state(nego, NEGO_STATE_NLA);
}
else if (nego->EnabledProtocols[PROTOCOL_SSL])
{
nego->state = NEGO_STATE_TLS;
nego_set_state(nego, NEGO_STATE_TLS);
}
else if (nego->EnabledProtocols[PROTOCOL_RDP])
{
nego->state = NEGO_STATE_RDP;
nego_set_state(nego, NEGO_STATE_RDP);
}
else
{
WLog_ERR(TAG, "No security protocol is enabled");
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return FALSE;
}
@@ -139,26 +143,28 @@ BOOL nego_connect(rdpNego* nego)
nego->EnabledProtocols[PROTOCOL_RDP] = FALSE;
nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = FALSE;
if (nego->state == NEGO_STATE_EXT)
switch (nego_get_state(nego))
{
nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
nego->SelectedProtocol = PROTOCOL_HYBRID_EX;
}
else if (nego->state == NEGO_STATE_NLA)
{
nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
nego->SelectedProtocol = PROTOCOL_HYBRID;
}
else if (nego->state == NEGO_STATE_TLS)
{
nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
nego->SelectedProtocol = PROTOCOL_SSL;
}
else if (nego->state == NEGO_STATE_RDP)
{
nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
nego->SelectedProtocol = PROTOCOL_RDP;
case NEGO_STATE_EXT:
nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
nego->SelectedProtocol = PROTOCOL_HYBRID_EX;
break;
case NEGO_STATE_NLA:
nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
nego->SelectedProtocol = PROTOCOL_HYBRID;
break;
case NEGO_STATE_TLS:
nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
nego->SelectedProtocol = PROTOCOL_SSL;
break;
case NEGO_STATE_RDP:
nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
nego->SelectedProtocol = PROTOCOL_RDP;
break;
default:
WLog_ERR(TAG, "Invalid NEGO state 0x%08" PRIx32, nego_get_state(nego));
return FALSE;
}
}
@@ -167,7 +173,7 @@ BOOL nego_connect(rdpNego* nego)
if (!nego_send_preconnection_pdu(nego))
{
WLog_ERR(TAG, "Failed to send preconnection pdu");
nego->state = NEGO_STATE_FINAL;
nego_set_state(nego, NEGO_STATE_FINAL);
return FALSE;
}
}
@@ -175,24 +181,24 @@ BOOL nego_connect(rdpNego* nego)
if (!nego->NegotiateSecurityLayer)
{
nego->state = NEGO_STATE_FINAL;
nego_set_state(nego, NEGO_STATE_FINAL);
}
else
{
do
{
WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
WLog_DBG(TAG, "state: %s", nego_state_string(nego_get_state(nego)));
nego_send(nego);
if (nego->state == NEGO_STATE_FAIL)
if (nego_get_state(nego) == NEGO_STATE_FAIL)
{
if (freerdp_get_last_error(nego->transport->context) == FREERDP_ERROR_SUCCESS)
WLog_ERR(TAG, "Protocol Security Negotiation Failure");
nego->state = NEGO_STATE_FINAL;
nego_set_state(nego, NEGO_STATE_FINAL);
return FALSE;
}
} while (nego->state != NEGO_STATE_FINAL);
} while (nego_get_state(nego) != NEGO_STATE_FINAL);
}
WLog_DBG(TAG, "Negotiated %s security", protocol_security_string(nego->SelectedProtocol));
@@ -229,13 +235,15 @@ BOOL nego_connect(rdpNego* nego)
BOOL nego_disconnect(rdpNego* nego)
{
nego->state = NEGO_STATE_INITIAL;
WINPR_ASSERT(nego);
nego_set_state(nego, NEGO_STATE_INITIAL);
return nego_transport_disconnect(nego);
}
/* connect to selected security layer */
BOOL nego_security_connect(rdpNego* nego)
{
WINPR_ASSERT(nego);
if (!nego->TcpConnected)
{
nego->SecurityConnected = FALSE;
@@ -275,6 +283,7 @@ BOOL nego_security_connect(rdpNego* nego)
static BOOL nego_tcp_connect(rdpNego* nego)
{
WINPR_ASSERT(nego);
if (!nego->TcpConnected)
{
const UINT32 TcpConnectTimeout = freerdp_settings_get_uint32(
@@ -318,6 +327,7 @@ static BOOL nego_tcp_connect(rdpNego* nego)
BOOL nego_transport_connect(rdpNego* nego)
{
WINPR_ASSERT(nego);
if (!nego_tcp_connect(nego))
return FALSE;
@@ -335,6 +345,7 @@ BOOL nego_transport_connect(rdpNego* nego)
BOOL nego_transport_disconnect(rdpNego* nego)
{
WINPR_ASSERT(nego);
if (nego->TcpConnected)
transport_disconnect(nego->transport);
@@ -355,6 +366,9 @@ BOOL nego_send_preconnection_pdu(rdpNego* nego)
UINT32 cbSize;
UINT16 cchPCB = 0;
WCHAR* wszPCB = NULL;
WINPR_ASSERT(nego);
WLog_DBG(TAG, "Sending preconnection PDU");
if (!nego_tcp_connect(nego))
@@ -410,41 +424,42 @@ BOOL nego_send_preconnection_pdu(rdpNego* nego)
static void nego_attempt_ext(rdpNego* nego)
{
WINPR_ASSERT(nego);
nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL | PROTOCOL_HYBRID_EX;
WLog_DBG(TAG, "Attempting NLA extended security");
if (!nego_transport_connect(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (!nego_send_negotiation_request(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (!nego_recv_response(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
WLog_DBG(TAG, "state: %s", nego_state_string(nego_get_state(nego)));
if (nego->state != NEGO_STATE_FINAL)
if (nego_get_state(nego) != NEGO_STATE_FINAL)
{
nego_transport_disconnect(nego);
if (nego->EnabledProtocols[PROTOCOL_HYBRID])
nego->state = NEGO_STATE_NLA;
nego_set_state(nego, NEGO_STATE_NLA);
else if (nego->EnabledProtocols[PROTOCOL_SSL])
nego->state = NEGO_STATE_TLS;
nego_set_state(nego, NEGO_STATE_TLS);
else if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP;
nego_set_state(nego, NEGO_STATE_RDP);
else
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
}
}
@@ -455,39 +470,40 @@ static void nego_attempt_ext(rdpNego* nego)
static void nego_attempt_nla(rdpNego* nego)
{
WINPR_ASSERT(nego);
nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL;
WLog_DBG(TAG, "Attempting NLA security");
if (!nego_transport_connect(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (!nego_send_negotiation_request(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (!nego_recv_response(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
WLog_DBG(TAG, "state: %s", nego_state_string(nego_get_state(nego)));
if (nego->state != NEGO_STATE_FINAL)
if (nego_get_state(nego) != NEGO_STATE_FINAL)
{
nego_transport_disconnect(nego);
if (nego->EnabledProtocols[PROTOCOL_SSL])
nego->state = NEGO_STATE_TLS;
nego_set_state(nego, NEGO_STATE_TLS);
else if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP;
nego_set_state(nego, NEGO_STATE_RDP);
else
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
}
}
@@ -498,35 +514,36 @@ static void nego_attempt_nla(rdpNego* nego)
static void nego_attempt_tls(rdpNego* nego)
{
WINPR_ASSERT(nego);
nego->RequestedProtocols = PROTOCOL_SSL;
WLog_DBG(TAG, "Attempting TLS security");
if (!nego_transport_connect(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (!nego_send_negotiation_request(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (!nego_recv_response(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (nego->state != NEGO_STATE_FINAL)
if (nego_get_state(nego) != NEGO_STATE_FINAL)
{
nego_transport_disconnect(nego);
if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP;
nego_set_state(nego, NEGO_STATE_RDP);
else
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
}
}
@@ -537,24 +554,25 @@ static void nego_attempt_tls(rdpNego* nego)
static void nego_attempt_rdp(rdpNego* nego)
{
WINPR_ASSERT(nego);
nego->RequestedProtocols = PROTOCOL_RDP;
WLog_DBG(TAG, "Attempting RDP security");
if (!nego_transport_connect(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (!nego_send_negotiation_request(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
if (!nego_recv_response(nego))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return;
}
}
@@ -568,6 +586,8 @@ BOOL nego_recv_response(rdpNego* nego)
{
int status;
wStream* s;
WINPR_ASSERT(nego);
s = Stream_New(NULL, 1024);
if (!s)
@@ -608,6 +628,7 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
UINT16 length;
rdpNego* nego = (rdpNego*)extra;
WINPR_ASSERT(nego);
if (!tpkt_read_header(s, &length))
return -1;
@@ -633,18 +654,18 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
if ((nego->SelectedProtocol == PROTOCOL_HYBRID) &&
(!nego->EnabledProtocols[PROTOCOL_HYBRID]))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
}
if ((nego->SelectedProtocol == PROTOCOL_SSL) &&
(!nego->EnabledProtocols[PROTOCOL_SSL]))
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
}
}
else if (!nego->EnabledProtocols[PROTOCOL_RDP])
{
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
}
break;
@@ -660,14 +681,14 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
WLog_DBG(TAG, "no rdpNegData");
if (!nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
else
nego->state = NEGO_STATE_FINAL;
nego_set_state(nego, NEGO_STATE_FINAL);
}
else
{
WLog_ERR(TAG, "invalid negotiation response");
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
}
if (!tpkt_ensure_stream_consumed(s, length))
@@ -701,6 +722,9 @@ static BOOL nego_read_request_token_or_cookie(rdpNego* nego, wStream* s)
BOOL result = FALSE;
BOOL isToken = FALSE;
size_t remain = Stream_GetRemainingLength(s);
WINPR_ASSERT(nego);
str = Stream_Pointer(s);
pos = Stream_GetPosition(s);
@@ -772,6 +796,9 @@ BOOL nego_read_request(rdpNego* nego, wStream* s)
BYTE type;
UINT16 length;
WINPR_ASSERT(nego);
WINPR_ASSERT(s);
if (!tpkt_read_header(s, &length))
return FALSE;
@@ -815,16 +842,26 @@ BOOL nego_read_request(rdpNego* nego, wStream* s)
void nego_send(rdpNego* nego)
{
if (nego->state == NEGO_STATE_EXT)
nego_attempt_ext(nego);
else if (nego->state == NEGO_STATE_NLA)
nego_attempt_nla(nego);
else if (nego->state == NEGO_STATE_TLS)
nego_attempt_tls(nego);
else if (nego->state == NEGO_STATE_RDP)
nego_attempt_rdp(nego);
else
WLog_ERR(TAG, "invalid negotiation state for sending");
WINPR_ASSERT(nego);
switch (nego_get_state(nego))
{
case NEGO_STATE_EXT:
nego_attempt_ext(nego);
break;
case NEGO_STATE_NLA:
nego_attempt_nla(nego);
break;
case NEGO_STATE_TLS:
nego_attempt_tls(nego);
break;
case NEGO_STATE_RDP:
nego_attempt_rdp(nego);
break;
default:
WLog_ERR(TAG, "invalid negotiation state for sending");
break;
}
}
/**
@@ -844,6 +881,7 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
size_t cookie_length;
s = Stream_New(NULL, 512);
WINPR_ASSERT(nego);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@@ -930,13 +968,16 @@ BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s)
BYTE flags;
UINT16 length;
WINPR_ASSERT(nego);
WINPR_ASSERT(s);
if (Stream_GetRemainingLength(s) < 7)
return FALSE;
Stream_Read_UINT8(s, flags);
Stream_Read_UINT16(s, length);
Stream_Read_UINT32(s, nego->RequestedProtocols);
WLog_DBG(TAG, "RDP_NEG_REQ: RequestedProtocol: 0x%08" PRIX32 "", nego->RequestedProtocols);
nego->state = NEGO_STATE_FINAL;
nego_set_state(nego, NEGO_STATE_FINAL);
return TRUE;
}
@@ -951,17 +992,20 @@ BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s)
UINT16 length;
WLog_DBG(TAG, "RDP_NEG_RSP");
WINPR_ASSERT(nego);
WINPR_ASSERT(s);
if (Stream_GetRemainingLength(s) < 7)
{
WLog_ERR(TAG, "Invalid RDP_NEG_RSP");
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return FALSE;
}
Stream_Read_UINT8(s, nego->flags);
Stream_Read_UINT16(s, length);
Stream_Read_UINT32(s, nego->SelectedProtocol);
nego->state = NEGO_STATE_FINAL;
nego_set_state(nego, NEGO_STATE_FINAL);
return TRUE;
}
@@ -976,6 +1020,10 @@ BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s)
BYTE flags;
UINT16 length;
UINT32 failureCode;
WINPR_ASSERT(nego);
WINPR_ASSERT(s);
WLog_DBG(TAG, "RDP_NEG_FAILURE");
if (Stream_GetRemainingLength(s) < 7)
return FALSE;
@@ -1012,7 +1060,7 @@ BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s)
break;
}
nego->state = NEGO_STATE_FAIL;
nego_set_state(nego, NEGO_STATE_FAIL);
return TRUE;
}
@@ -1029,8 +1077,14 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
wStream* s;
BYTE flags;
rdpSettings* settings;
WINPR_ASSERT(nego);
WINPR_ASSERT(nego->transport);
status = TRUE;
settings = nego->transport->settings;
WINPR_ASSERT(settings);
s = Stream_New(NULL, 512);
if (!s)
@@ -1151,7 +1205,8 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
void nego_init(rdpNego* nego)
{
nego->state = NEGO_STATE_INITIAL;
WINPR_ASSERT(nego);
nego_set_state(nego, NEGO_STATE_INITIAL);
nego->RequestedProtocols = PROTOCOL_RDP;
nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
nego->sendNegoData = FALSE;

View File

@@ -844,6 +844,17 @@ static BOOL freerdp_peer_send_channel_data(freerdp_peer* client, UINT16 channelI
return rdp_send_channel_data(client->context->rdp, channelId, data, size);
}
static BOOL freerdp_peer_send_channel_packet(freerdp_peer* client, UINT16 channelId,
size_t totalSize, UINT32 flags, const BYTE* data,
size_t chunkSize)
{
WINPR_ASSERT(client);
WINPR_ASSERT(client->context);
WINPR_ASSERT(client->context->rdp);
return rdp_channel_send_packet(client->context->rdp, channelId, totalSize, flags, data,
chunkSize);
}
static BOOL freerdp_peer_is_write_blocked(freerdp_peer* peer)
{
rdpTransport* transport;
@@ -1013,6 +1024,7 @@ freerdp_peer* freerdp_peer_new(int sockfd)
client->Close = freerdp_peer_close;
client->Disconnect = freerdp_peer_disconnect;
client->SendChannelData = freerdp_peer_send_channel_data;
client->SendChannelPacket = freerdp_peer_send_channel_packet;
client->IsWriteBlocked = freerdp_peer_is_write_blocked;
client->DrainOutputBuffer = freerdp_peer_drain_output_buffer;
client->HasMoreToRead = freerdp_peer_has_more_to_read;

View File

@@ -283,7 +283,12 @@ static BOOL rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header)
wStream* rdp_send_stream_init(rdpRdp* rdp)
{
wStream* s = transport_send_stream_init(rdp->transport, 4096);
wStream* s;
WINPR_ASSERT(rdp);
WINPR_ASSERT(rdp->transport);
s = transport_send_stream_init(rdp->transport, 4096);
if (!s)
return NULL;
@@ -1682,6 +1687,12 @@ BOOL rdp_send_channel_data(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size
return freerdp_channel_send(rdp, channelId, data, size);
}
BOOL rdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize, UINT32 flags,
const BYTE* data, size_t chunkSize)
{
return freerdp_channel_send_packet(rdp, channelId, totalSize, flags, data, chunkSize);
}
BOOL rdp_send_error_info(rdpRdp* rdp)
{
wStream* s;

View File

@@ -210,6 +210,8 @@ FREERDP_LOCAL BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channelId);
FREERDP_LOCAL BOOL rdp_send_channel_data(rdpRdp* rdp, UINT16 channelId, const BYTE* data,
size_t size);
FREERDP_LOCAL BOOL rdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize,
UINT32 flags, const BYTE* data, size_t chunkSize);
FREERDP_LOCAL wStream* rdp_message_channel_pdu_init(rdpRdp* rdp);
FREERDP_LOCAL BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags);

View File

@@ -120,6 +120,7 @@ extern "C"
typedef BOOL (*ArrayList_ForEachFkt)(void* data, size_t index, va_list ap);
WINPR_API BOOL ArrayList_ForEach(wArrayList* arrayList, ArrayList_ForEachFkt fkt, ...);
WINPR_API BOOL ArrayList_ForEachAP(wArrayList* arrayList, ArrayList_ForEachFkt fkt, va_list ap);
WINPR_API void ArrayList_Clear(wArrayList* arrayList);
WINPR_API BOOL ArrayList_Contains(wArrayList* arrayList, const void* obj);

View File

@@ -21,10 +21,16 @@
#include "config.h"
#endif
#include <stdarg.h>
#include <winpr/crt.h>
#include <winpr/assert.h>
#include <winpr/collections.h>
#if defined(_WIN32) && (_MSC_VER < 1800)
#define va_copy(dest, src) (dest = src)
#endif
struct _wArrayList
{
size_t capacity;
@@ -508,23 +514,36 @@ wObject* ArrayList_Object(wArrayList* arrayList)
BOOL ArrayList_ForEach(wArrayList* arrayList, ArrayList_ForEachFkt fkt, ...)
{
size_t index, count;
BOOL rc;
va_list ap;
va_start(ap, fkt);
rc = ArrayList_ForEachAP(arrayList, fkt, ap);
va_end(ap);
return rc;
}
BOOL ArrayList_ForEachAP(wArrayList* arrayList, ArrayList_ForEachFkt fkt, va_list ap)
{
size_t index, count;
BOOL rc = FALSE;
va_list cap;
WINPR_ASSERT(arrayList);
WINPR_ASSERT(fkt);
ArrayList_Lock_Conditional(arrayList);
count = ArrayList_Count(arrayList);
va_start(ap, fkt);
for (index = 0; index < count; index++)
{
BOOL rs;
void* obj = ArrayList_GetItem(arrayList, index);
if (!fkt(obj, index, ap))
va_copy(cap, ap);
rs = fkt(obj, index, cap);
va_end(cap);
if (!rs)
goto fail;
}
va_end(ap);
rc = TRUE;
fail:
ArrayList_Unlock_Conditional(arrayList);