Merge pull request #4907 from akallabeth/transport_write_leak_fix
Transport write leak fix
This commit is contained in:
commit
7b0f4f5dc4
@ -56,10 +56,7 @@ BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
||||
BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
rdp_write_synchronize_pdu(s, rdp->settings);
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId);
|
||||
}
|
||||
@ -67,7 +64,6 @@ BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
|
||||
BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT16 messageType;
|
||||
|
||||
rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
@ -80,18 +76,13 @@ BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
||||
/* targetUser (2 bytes) */
|
||||
Stream_Seek_UINT16(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
rdp_write_synchronize_pdu(s, rdp->settings);
|
||||
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId);
|
||||
}
|
||||
|
||||
@ -103,7 +94,6 @@ BOOL rdp_recv_control_pdu(wStream* s, UINT16* action)
|
||||
Stream_Read_UINT16(s, *action); /* action (2 bytes) */
|
||||
Stream_Seek_UINT16(s); /* grantId (2 bytes) */
|
||||
Stream_Seek_UINT32(s); /* controlId (4 bytes) */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -118,7 +108,7 @@ BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT16 action;
|
||||
|
||||
if(rdp_recv_control_pdu(s, &action) == FALSE)
|
||||
if (rdp_recv_control_pdu(s, &action) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
switch (action)
|
||||
@ -138,37 +128,26 @@ BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
||||
BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
Stream_Write_UINT16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */
|
||||
Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */
|
||||
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
|
||||
}
|
||||
|
||||
BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */
|
||||
Stream_Write_UINT16(s, rdp->mcs->userId); /* grantId (2 bytes) */
|
||||
Stream_Write_UINT32(s, 0x03EA); /* controlId (4 bytes) */
|
||||
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
|
||||
}
|
||||
|
||||
BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
rdp_write_client_control_pdu(s, action);
|
||||
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
|
||||
}
|
||||
|
||||
@ -193,17 +172,14 @@ void rdp_write_client_persistent_key_list_pdu(wStream* s, rdpSettings* settings)
|
||||
Stream_Write_UINT8(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU); /* bBitMask (1 byte) */
|
||||
Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */
|
||||
Stream_Write_UINT16(s, 0); /* pad3 (2 bytes) */
|
||||
|
||||
/* entries */
|
||||
}
|
||||
|
||||
BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
rdp_write_client_persistent_key_list_pdu(s, rdp->settings);
|
||||
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId);
|
||||
}
|
||||
|
||||
@ -225,11 +201,8 @@ void rdp_write_client_font_list_pdu(wStream* s, UINT16 flags)
|
||||
|
||||
BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
rdp_write_client_font_list_pdu(s, flags);
|
||||
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId);
|
||||
}
|
||||
|
||||
@ -251,7 +224,7 @@ BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU;
|
||||
|
||||
if(Stream_GetRemainingLength(s) >= 8)
|
||||
if (Stream_GetRemainingLength(s) >= 8)
|
||||
{
|
||||
Stream_Seek_UINT16(s); /* numberEntries (2 bytes) */
|
||||
Stream_Seek_UINT16(s); /* totalNumEntries (2 bytes) */
|
||||
@ -265,14 +238,11 @@ BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s)
|
||||
BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
|
||||
Stream_Write_UINT16(s, 0); /* numberEntries (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* totalNumEntries (2 bytes) */
|
||||
Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */
|
||||
Stream_Write_UINT16(s, 4); /* entrySize (2 bytes) */
|
||||
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->userId);
|
||||
}
|
||||
|
||||
@ -308,7 +278,7 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
|
||||
|
||||
Stream_Seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
|
||||
}
|
||||
while(0);
|
||||
while (0);
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
|
||||
@ -327,22 +297,17 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
|
||||
|
||||
BOOL rdp_send_deactivate_all(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
wStream* s = rdp_send_stream_pdu_init(rdp);
|
||||
BOOL status;
|
||||
|
||||
if (!(s = Stream_New(NULL, 1024)))
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
rdp_init_stream_pdu(rdp, s);
|
||||
|
||||
Stream_Write_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
|
||||
Stream_Write_UINT16(s, 1); /* lengthSourceDescriptor (2 bytes) */
|
||||
Stream_Write_UINT8(s, 0); /* sourceDescriptor (should be 0x00) */
|
||||
|
||||
status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
Stream_Release(s);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -364,30 +329,30 @@ BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
||||
BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
rdpSettings *settings = rdp->settings;
|
||||
freerdp_peer *peer = rdp->context->peer;
|
||||
rdpSettings* settings = rdp->settings;
|
||||
freerdp_peer* peer = rdp->context->peer;
|
||||
|
||||
if (!rdp_recv_client_font_list_pdu(s))
|
||||
return FALSE;
|
||||
|
||||
if (settings->SupportMonitorLayoutPdu && settings->MonitorCount && peer->AdjustMonitorsLayout &&
|
||||
peer->AdjustMonitorsLayout(peer))
|
||||
peer->AdjustMonitorsLayout(peer))
|
||||
{
|
||||
/* client supports the monitorLayout PDU, let's send him the monitors if any */
|
||||
wStream *st;
|
||||
wStream* st = rdp_data_pdu_init(rdp);
|
||||
BOOL r;
|
||||
|
||||
st = rdp_data_pdu_init(rdp);
|
||||
if (!st)
|
||||
return FALSE;
|
||||
|
||||
if (!rdp_write_monitor_layout_pdu(st, settings->MonitorCount, settings->MonitorDefArray))
|
||||
{
|
||||
Stream_Free(st, TRUE);
|
||||
Stream_Release(st);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r = rdp_send_data_pdu(rdp, st, DATA_PDU_TYPE_MONITOR_LAYOUT, 0);
|
||||
|
||||
if (!r)
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -59,100 +59,97 @@ typedef struct
|
||||
UINT16 responseType;
|
||||
} AUTODETECT_RSP_PDU;
|
||||
|
||||
static BOOL autodetect_send_rtt_measure_request(rdpContext* context, UINT16 sequenceNumber, UINT16 requestType)
|
||||
static BOOL autodetect_send_rtt_measure_request(rdpContext* context, UINT16 sequenceNumber,
|
||||
UINT16 requestType)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_message_channel_pdu_init(context->rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending RTT Measure Request PDU");
|
||||
|
||||
Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
|
||||
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
|
||||
|
||||
context->rdp->autodetect->rttMeasureStartTime = GetTickCountPrecise();
|
||||
|
||||
return rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
|
||||
}
|
||||
|
||||
static BOOL autodetect_send_continuous_rtt_measure_request(rdpContext* context, UINT16 sequenceNumber)
|
||||
static BOOL autodetect_send_continuous_rtt_measure_request(rdpContext* context,
|
||||
UINT16 sequenceNumber)
|
||||
{
|
||||
return autodetect_send_rtt_measure_request(context, sequenceNumber, RDP_RTT_REQUEST_TYPE_CONTINUOUS);
|
||||
return autodetect_send_rtt_measure_request(context, sequenceNumber,
|
||||
RDP_RTT_REQUEST_TYPE_CONTINUOUS);
|
||||
}
|
||||
|
||||
BOOL autodetect_send_connecttime_rtt_measure_request(rdpContext* context, UINT16 sequenceNumber)
|
||||
{
|
||||
return autodetect_send_rtt_measure_request(context, sequenceNumber, RDP_RTT_REQUEST_TYPE_CONNECTTIME);
|
||||
return autodetect_send_rtt_measure_request(context, sequenceNumber,
|
||||
RDP_RTT_REQUEST_TYPE_CONNECTTIME);
|
||||
}
|
||||
|
||||
static BOOL autodetect_send_rtt_measure_response(rdpRdp* rdp, UINT16 sequenceNumber)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
/* Send the response PDU to the server */
|
||||
|
||||
s = rdp_message_channel_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending RTT Measure Response PDU");
|
||||
|
||||
Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Write_UINT16(s, RDP_RTT_RESPONSE_TYPE); /* responseType (1 byte) */
|
||||
|
||||
return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP);
|
||||
}
|
||||
|
||||
static BOOL autodetect_send_bandwidth_measure_start(rdpContext* context, UINT16 sequenceNumber, UINT16 requestType)
|
||||
static BOOL autodetect_send_bandwidth_measure_start(rdpContext* context, UINT16 sequenceNumber,
|
||||
UINT16 requestType)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_message_channel_pdu_init(context->rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Start PDU");
|
||||
|
||||
Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
|
||||
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
|
||||
|
||||
return rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
|
||||
}
|
||||
|
||||
static BOOL autodetect_send_continuous_bandwidth_measure_start(rdpContext* context, UINT16 sequenceNumber)
|
||||
static BOOL autodetect_send_continuous_bandwidth_measure_start(rdpContext* context,
|
||||
UINT16 sequenceNumber)
|
||||
{
|
||||
return autodetect_send_bandwidth_measure_start(context, sequenceNumber, RDP_BW_START_REQUEST_TYPE_CONTINUOUS);
|
||||
return autodetect_send_bandwidth_measure_start(context, sequenceNumber,
|
||||
RDP_BW_START_REQUEST_TYPE_CONTINUOUS);
|
||||
}
|
||||
|
||||
BOOL autodetect_send_connecttime_bandwidth_measure_start(rdpContext* context, UINT16 sequenceNumber)
|
||||
{
|
||||
return autodetect_send_bandwidth_measure_start(context, sequenceNumber, RDP_BW_START_REQUEST_TYPE_CONNECTTIME);
|
||||
return autodetect_send_bandwidth_measure_start(context, sequenceNumber,
|
||||
RDP_BW_START_REQUEST_TYPE_CONNECTTIME);
|
||||
}
|
||||
|
||||
BOOL autodetect_send_bandwidth_measure_payload(rdpContext* context, UINT16 payloadLength, UINT16 sequenceNumber)
|
||||
BOOL autodetect_send_bandwidth_measure_payload(rdpContext* context, UINT16 payloadLength,
|
||||
UINT16 sequenceNumber)
|
||||
{
|
||||
wStream* s;
|
||||
UCHAR *buffer = NULL;
|
||||
UCHAR* buffer = NULL;
|
||||
BOOL bResult = FALSE;
|
||||
|
||||
s = rdp_message_channel_pdu_init(context->rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Payload PDU -> payloadLength=%"PRIu16"", payloadLength);
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Payload PDU -> payloadLength=%"PRIu16"",
|
||||
payloadLength);
|
||||
/* 4-bytes aligned */
|
||||
payloadLength &= ~3;
|
||||
|
||||
@ -161,14 +158,15 @@ BOOL autodetect_send_bandwidth_measure_payload(rdpContext* context, UINT16 paylo
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Write_UINT8(s, 0x08); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
|
||||
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Write_UINT16(s, RDP_BW_PAYLOAD_REQUEST_TYPE); /* requestType (2 bytes) */
|
||||
Stream_Write_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
|
||||
|
||||
/* Random data (better measurement in case the line is compressed) */
|
||||
buffer = (UCHAR *)malloc(payloadLength);
|
||||
buffer = (UCHAR*)malloc(payloadLength);
|
||||
|
||||
if (NULL == buffer)
|
||||
{
|
||||
Stream_Release(s);
|
||||
@ -177,40 +175,36 @@ BOOL autodetect_send_bandwidth_measure_payload(rdpContext* context, UINT16 paylo
|
||||
|
||||
winpr_RAND(buffer, payloadLength);
|
||||
Stream_Write(s, buffer, payloadLength);
|
||||
|
||||
bResult = rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
|
||||
if (!bResult)
|
||||
{
|
||||
Stream_Release(s);
|
||||
}
|
||||
free(buffer);
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
static BOOL autodetect_send_bandwidth_measure_stop(rdpContext* context, UINT16 payloadLength, UINT16 sequenceNumber, UINT16 requestType)
|
||||
static BOOL autodetect_send_bandwidth_measure_stop(rdpContext* context, UINT16 payloadLength,
|
||||
UINT16 sequenceNumber, UINT16 requestType)
|
||||
{
|
||||
wStream* s;
|
||||
UCHAR *buffer = NULL;
|
||||
UCHAR* buffer = NULL;
|
||||
BOOL bResult = FALSE;
|
||||
|
||||
s = rdp_message_channel_pdu_init(context->rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Stop PDU -> payloadLength=%"PRIu16"", payloadLength);
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Stop PDU -> payloadLength=%"PRIu16"",
|
||||
payloadLength);
|
||||
/* 4-bytes aligned */
|
||||
payloadLength &= ~3;
|
||||
|
||||
Stream_Write_UINT8(s, requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME ? 0x08 : 0x06); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME ? 0x08 :
|
||||
0x06); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
|
||||
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
|
||||
|
||||
if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
|
||||
{
|
||||
Stream_Write_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
|
||||
|
||||
if (payloadLength > 0)
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(s, payloadLength))
|
||||
@ -221,6 +215,7 @@ static BOOL autodetect_send_bandwidth_measure_stop(rdpContext* context, UINT16 p
|
||||
|
||||
/* Random data (better measurement in case the line is compressed) */
|
||||
buffer = malloc(payloadLength);
|
||||
|
||||
if (NULL == buffer)
|
||||
{
|
||||
Stream_Release(s);
|
||||
@ -233,52 +228,49 @@ static BOOL autodetect_send_bandwidth_measure_stop(rdpContext* context, UINT16 p
|
||||
}
|
||||
|
||||
bResult = rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
|
||||
if (!bResult)
|
||||
{
|
||||
Stream_Release(s);
|
||||
}
|
||||
free(buffer);
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
static BOOL autodetect_send_continuous_bandwidth_measure_stop(rdpContext* context, UINT16 sequenceNumber)
|
||||
static BOOL autodetect_send_continuous_bandwidth_measure_stop(rdpContext* context,
|
||||
UINT16 sequenceNumber)
|
||||
{
|
||||
return autodetect_send_bandwidth_measure_stop(context, 0, sequenceNumber, RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS);
|
||||
return autodetect_send_bandwidth_measure_stop(context, 0, sequenceNumber,
|
||||
RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS);
|
||||
}
|
||||
|
||||
BOOL autodetect_send_connecttime_bandwidth_measure_stop(rdpContext* context, UINT16 payloadLength, UINT16 sequenceNumber)
|
||||
BOOL autodetect_send_connecttime_bandwidth_measure_stop(rdpContext* context, UINT16 payloadLength,
|
||||
UINT16 sequenceNumber)
|
||||
{
|
||||
return autodetect_send_bandwidth_measure_stop(context, payloadLength, sequenceNumber, RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME);
|
||||
return autodetect_send_bandwidth_measure_stop(context, payloadLength, sequenceNumber,
|
||||
RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME);
|
||||
}
|
||||
|
||||
static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 responseType, UINT16 sequenceNumber)
|
||||
static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 responseType,
|
||||
UINT16 sequenceNumber)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
wStream* s;
|
||||
UINT32 timeDelta;
|
||||
|
||||
/* Compute the total time */
|
||||
timeDelta = GetTickCountPrecise() - rdp->autodetect->bandwidthMeasureStartTime;
|
||||
|
||||
/* Send the result PDU to the server */
|
||||
|
||||
s = rdp_message_channel_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Results PDU -> timeDelta=%"PRIu32", byteCount=%"PRIu32"", timeDelta, rdp->autodetect->bandwidthMeasureByteCount);
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG,
|
||||
"sending Bandwidth Measure Results PDU -> timeDelta=%"PRIu32", byteCount=%"PRIu32"", timeDelta,
|
||||
rdp->autodetect->bandwidthMeasureByteCount);
|
||||
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Write_UINT16(s, responseType); /* responseType (1 byte) */
|
||||
Stream_Write_UINT32(s, timeDelta); /* timeDelta (4 bytes) */
|
||||
Stream_Write_UINT32(s, rdp->autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */
|
||||
|
||||
IFCALLRET(rdp->autodetect->ClientBandwidthMeasureResult, success,
|
||||
rdp->context, rdp->autodetect);
|
||||
rdp->context, rdp->autodetect);
|
||||
|
||||
if (!success)
|
||||
return FALSE;
|
||||
@ -289,7 +281,6 @@ static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 respon
|
||||
static BOOL autodetect_send_netchar_result(rdpContext* context, UINT16 sequenceNumber)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
s = rdp_message_channel_pdu_init(context->rdp);
|
||||
|
||||
if (!s)
|
||||
@ -323,38 +314,37 @@ static BOOL autodetect_send_netchar_result(rdpContext* context, UINT16 sequenceN
|
||||
BOOL autodetect_send_netchar_sync(rdpRdp* rdp, UINT16 sequenceNumber)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
/* Send the response PDU to the server */
|
||||
|
||||
s = rdp_message_channel_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "sending Network Characteristics Sync PDU -> bandwidth=%"PRIu32", rtt=%"PRIu32"", rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG,
|
||||
"sending Network Characteristics Sync PDU -> bandwidth=%"PRIu32", rtt=%"PRIu32"",
|
||||
rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Write_UINT16(s, RDP_NETCHAR_SYNC_RESPONSE_TYPE); /* responseType (1 byte) */
|
||||
Stream_Write_UINT32(s, rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
|
||||
Stream_Write_UINT32(s, rdp->autodetect->netCharAverageRTT); /* rtt (4 bytes) */
|
||||
|
||||
return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP);
|
||||
}
|
||||
|
||||
static BOOL autodetect_recv_rtt_measure_request(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
static BOOL autodetect_recv_rtt_measure_request(rdpRdp* rdp, wStream* s,
|
||||
AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
{
|
||||
if (autodetectReqPdu->headerLength != 0x06)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "received RTT Measure Request PDU");
|
||||
|
||||
/* Send a response to the server */
|
||||
return autodetect_send_rtt_measure_response(rdp, autodetectReqPdu->sequenceNumber);
|
||||
}
|
||||
|
||||
static BOOL autodetect_recv_rtt_measure_response(rdpRdp* rdp, wStream* s, AUTODETECT_RSP_PDU* autodetectRspPdu)
|
||||
static BOOL autodetect_recv_rtt_measure_response(rdpRdp* rdp, wStream* s,
|
||||
AUTODETECT_RSP_PDU* autodetectRspPdu)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
|
||||
@ -362,23 +352,25 @@ static BOOL autodetect_recv_rtt_measure_response(rdpRdp* rdp, wStream* s, AUTODE
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "received RTT Measure Response PDU");
|
||||
|
||||
rdp->autodetect->netCharAverageRTT = GetTickCountPrecise() - rdp->autodetect->rttMeasureStartTime;
|
||||
if (rdp->autodetect->netCharBaseRTT == 0 || rdp->autodetect->netCharBaseRTT > rdp->autodetect->netCharAverageRTT)
|
||||
|
||||
if (rdp->autodetect->netCharBaseRTT == 0 ||
|
||||
rdp->autodetect->netCharBaseRTT > rdp->autodetect->netCharAverageRTT)
|
||||
rdp->autodetect->netCharBaseRTT = rdp->autodetect->netCharAverageRTT;
|
||||
|
||||
IFCALLRET(rdp->autodetect->RTTMeasureResponse, success, rdp->context, autodetectRspPdu->sequenceNumber);
|
||||
|
||||
IFCALLRET(rdp->autodetect->RTTMeasureResponse, success, rdp->context,
|
||||
autodetectRspPdu->sequenceNumber);
|
||||
return success;
|
||||
}
|
||||
|
||||
static BOOL autodetect_recv_bandwidth_measure_start(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
static BOOL autodetect_recv_bandwidth_measure_start(rdpRdp* rdp, wStream* s,
|
||||
AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
{
|
||||
if (autodetectReqPdu->headerLength != 0x06)
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Start PDU - time=%"PRIu32"", GetTickCountPrecise());
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Start PDU - time=%"PRIu32"",
|
||||
GetTickCountPrecise());
|
||||
/* Initialize bandwidth measurement parameters */
|
||||
rdp->autodetect->bandwidthMeasureStartTime = GetTickCountPrecise();
|
||||
rdp->autodetect->bandwidthMeasureByteCount = 0;
|
||||
@ -392,7 +384,8 @@ static BOOL autodetect_recv_bandwidth_measure_start(rdpRdp* rdp, wStream* s, AUT
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL autodetect_recv_bandwidth_measure_payload(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
static BOOL autodetect_recv_bandwidth_measure_payload(rdpRdp* rdp, wStream* s,
|
||||
AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
{
|
||||
UINT16 payloadLength;
|
||||
|
||||
@ -403,16 +396,15 @@ static BOOL autodetect_recv_bandwidth_measure_payload(rdpRdp* rdp, wStream* s, A
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
|
||||
|
||||
WLog_DBG(AUTODETECT_TAG, "received Bandwidth Measure Payload PDU -> payloadLength=%"PRIu16"", payloadLength);
|
||||
|
||||
WLog_DBG(AUTODETECT_TAG, "received Bandwidth Measure Payload PDU -> payloadLength=%"PRIu16"",
|
||||
payloadLength);
|
||||
/* Add the payload length to the bandwidth measurement parameters */
|
||||
rdp->autodetect->bandwidthMeasureByteCount += payloadLength;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL autodetect_recv_bandwidth_measure_stop(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
static BOOL autodetect_recv_bandwidth_measure_stop(rdpRdp* rdp, wStream* s,
|
||||
AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
{
|
||||
UINT16 payloadLength;
|
||||
UINT16 responseType;
|
||||
@ -435,8 +427,8 @@ static BOOL autodetect_recv_bandwidth_measure_stop(rdpRdp* rdp, wStream* s, AUTO
|
||||
payloadLength = 0;
|
||||
}
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Stop PDU -> payloadLength=%"PRIu16"", payloadLength);
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Stop PDU -> payloadLength=%"PRIu16"",
|
||||
payloadLength);
|
||||
/* Add the payload length to the bandwidth measurement parameters */
|
||||
rdp->autodetect->bandwidthMeasureByteCount += payloadLength;
|
||||
|
||||
@ -448,12 +440,13 @@ static BOOL autodetect_recv_bandwidth_measure_stop(rdpRdp* rdp, wStream* s, AUTO
|
||||
|
||||
/* Send a response the server */
|
||||
responseType = autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME ?
|
||||
RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME : RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS;
|
||||
|
||||
return autodetect_send_bandwidth_measure_results(rdp, responseType, autodetectReqPdu->sequenceNumber);
|
||||
RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME : RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS;
|
||||
return autodetect_send_bandwidth_measure_results(rdp, responseType,
|
||||
autodetectReqPdu->sequenceNumber);
|
||||
}
|
||||
|
||||
static BOOL autodetect_recv_bandwidth_measure_results(rdpRdp* rdp, wStream* s, AUTODETECT_RSP_PDU* autodetectRspPdu)
|
||||
static BOOL autodetect_recv_bandwidth_measure_results(rdpRdp* rdp, wStream* s,
|
||||
AUTODETECT_RSP_PDU* autodetectRspPdu)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
|
||||
@ -461,56 +454,65 @@ static BOOL autodetect_recv_bandwidth_measure_results(rdpRdp* rdp, wStream* s, A
|
||||
return FALSE;
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Results PDU");
|
||||
|
||||
Stream_Read_UINT32(s, rdp->autodetect->bandwidthMeasureTimeDelta); /* timeDelta (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */
|
||||
|
||||
if (rdp->autodetect->bandwidthMeasureTimeDelta > 0)
|
||||
rdp->autodetect->netCharBandwidth = rdp->autodetect->bandwidthMeasureByteCount * 8 / rdp->autodetect->bandwidthMeasureTimeDelta;
|
||||
rdp->autodetect->netCharBandwidth = rdp->autodetect->bandwidthMeasureByteCount * 8 /
|
||||
rdp->autodetect->bandwidthMeasureTimeDelta;
|
||||
else
|
||||
rdp->autodetect->netCharBandwidth = 0;
|
||||
|
||||
IFCALLRET(rdp->autodetect->BandwidthMeasureResults, success, rdp->context, autodetectRspPdu->sequenceNumber);
|
||||
|
||||
IFCALLRET(rdp->autodetect->BandwidthMeasureResults, success, rdp->context,
|
||||
autodetectRspPdu->sequenceNumber);
|
||||
return success;
|
||||
}
|
||||
|
||||
static BOOL autodetect_recv_netchar_result(rdpRdp* rdp, wStream* s, AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
static BOOL autodetect_recv_netchar_result(rdpRdp* rdp, wStream* s,
|
||||
AUTODETECT_REQ_PDU* autodetectReqPdu)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
|
||||
switch (autodetectReqPdu->requestType)
|
||||
{
|
||||
case 0x0840:
|
||||
/* baseRTT and averageRTT fields are present (bandwidth field is not) */
|
||||
if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8))
|
||||
return FALSE;
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||
break;
|
||||
case 0x0840:
|
||||
|
||||
case 0x0880:
|
||||
/* bandwidth and averageRTT fields are present (baseRTT field is not) */
|
||||
if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8))
|
||||
return FALSE;
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||
break;
|
||||
/* baseRTT and averageRTT fields are present (bandwidth field is not) */
|
||||
if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8))
|
||||
return FALSE;
|
||||
|
||||
case 0x08C0:
|
||||
/* baseRTT, bandwidth, and averageRTT fields are present */
|
||||
if ((autodetectReqPdu->headerLength != 0x12) || (Stream_GetRemainingLength(s) < 12))
|
||||
return FALSE;
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||
break;
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||
break;
|
||||
|
||||
case 0x0880:
|
||||
|
||||
/* bandwidth and averageRTT fields are present (baseRTT field is not) */
|
||||
if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||
break;
|
||||
|
||||
case 0x08C0:
|
||||
|
||||
/* baseRTT, bandwidth, and averageRTT fields are present */
|
||||
if ((autodetectReqPdu->headerLength != 0x12) || (Stream_GetRemainingLength(s) < 12))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
|
||||
Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
|
||||
break;
|
||||
}
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG, "received Network Characteristics Result PDU -> baseRTT=%"PRIu32", bandwidth=%"PRIu32", averageRTT=%"PRIu32"", rdp->autodetect->netCharBaseRTT, rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||
|
||||
IFCALLRET(rdp->autodetect->NetworkCharacteristicsResult, success, rdp->context, autodetectReqPdu->sequenceNumber);
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG,
|
||||
"received Network Characteristics Result PDU -> baseRTT=%"PRIu32", bandwidth=%"PRIu32", averageRTT=%"PRIu32"",
|
||||
rdp->autodetect->netCharBaseRTT, rdp->autodetect->netCharBandwidth,
|
||||
rdp->autodetect->netCharAverageRTT);
|
||||
IFCALLRET(rdp->autodetect->NetworkCharacteristicsResult, success, rdp->context,
|
||||
autodetectReqPdu->sequenceNumber);
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -518,7 +520,7 @@ int rdp_recv_autodetect_request_packet(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
AUTODETECT_REQ_PDU autodetectReqPdu;
|
||||
BOOL success = FALSE;
|
||||
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 6)
|
||||
return -1;
|
||||
|
||||
@ -526,51 +528,50 @@ int rdp_recv_autodetect_request_packet(rdpRdp* rdp, wStream* s)
|
||||
Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId); /* headerTypeId (1 byte) */
|
||||
Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Read_UINT16(s, autodetectReqPdu.requestType); /* requestType (2 bytes) */
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG,
|
||||
"rdp_recv_autodetect_request_packet: headerLength=%"PRIu8", headerTypeId=%"PRIu8", sequenceNumber=%"PRIu16", requestType=%04"PRIx16"",
|
||||
autodetectReqPdu.headerLength, autodetectReqPdu.headerTypeId,
|
||||
autodetectReqPdu.sequenceNumber, autodetectReqPdu.requestType);
|
||||
"rdp_recv_autodetect_request_packet: headerLength=%"PRIu8", headerTypeId=%"PRIu8", sequenceNumber=%"PRIu16", requestType=%04"PRIx16"",
|
||||
autodetectReqPdu.headerLength, autodetectReqPdu.headerTypeId,
|
||||
autodetectReqPdu.sequenceNumber, autodetectReqPdu.requestType);
|
||||
|
||||
if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST)
|
||||
return -1;
|
||||
|
||||
switch (autodetectReqPdu.requestType)
|
||||
{
|
||||
case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
|
||||
case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
|
||||
/* RTT Measure Request (RDP_RTT_REQUEST) - MS-RDPBCGR 2.2.14.1.1 */
|
||||
success = autodetect_recv_rtt_measure_request(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
|
||||
case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
|
||||
/* RTT Measure Request (RDP_RTT_REQUEST) - MS-RDPBCGR 2.2.14.1.1 */
|
||||
success = autodetect_recv_rtt_measure_request(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
|
||||
case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
|
||||
case RDP_BW_START_REQUEST_TYPE_TUNNEL:
|
||||
case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
|
||||
/* Bandwidth Measure Start (RDP_BW_START) - MS-RDPBCGR 2.2.14.1.2 */
|
||||
success = autodetect_recv_bandwidth_measure_start(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
|
||||
case RDP_BW_START_REQUEST_TYPE_TUNNEL:
|
||||
case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
|
||||
/* Bandwidth Measure Start (RDP_BW_START) - MS-RDPBCGR 2.2.14.1.2 */
|
||||
success = autodetect_recv_bandwidth_measure_start(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
|
||||
case RDP_BW_PAYLOAD_REQUEST_TYPE:
|
||||
/* Bandwidth Measure Payload (RDP_BW_PAYLOAD) - MS-RDPBCGR 2.2.14.1.3 */
|
||||
success = autodetect_recv_bandwidth_measure_payload(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
case RDP_BW_PAYLOAD_REQUEST_TYPE:
|
||||
/* Bandwidth Measure Payload (RDP_BW_PAYLOAD) - MS-RDPBCGR 2.2.14.1.3 */
|
||||
success = autodetect_recv_bandwidth_measure_payload(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
|
||||
case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
|
||||
case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
|
||||
case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
|
||||
/* Bandwidth Measure Stop (RDP_BW_STOP) - MS-RDPBCGR 2.2.14.1.4 */
|
||||
success = autodetect_recv_bandwidth_measure_stop(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
|
||||
case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
|
||||
case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
|
||||
/* Bandwidth Measure Stop (RDP_BW_STOP) - MS-RDPBCGR 2.2.14.1.4 */
|
||||
success = autodetect_recv_bandwidth_measure_stop(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
|
||||
case 0x0840:
|
||||
case 0x0880:
|
||||
case 0x08C0:
|
||||
/* Network Characteristics Result (RDP_NETCHAR_RESULT) - MS-RDPBCGR 2.2.14.1.5 */
|
||||
success = autodetect_recv_netchar_result(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
case 0x0840:
|
||||
case 0x0880:
|
||||
case 0x08C0:
|
||||
/* Network Characteristics Result (RDP_NETCHAR_RESULT) - MS-RDPBCGR 2.2.14.1.5 */
|
||||
success = autodetect_recv_netchar_result(rdp, s, &autodetectReqPdu);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return success ? 0 : -1;
|
||||
@ -588,30 +589,29 @@ int rdp_recv_autodetect_response_packet(rdpRdp* rdp, wStream* s)
|
||||
Stream_Read_UINT8(s, autodetectRspPdu.headerTypeId); /* headerTypeId (1 byte) */
|
||||
Stream_Read_UINT16(s, autodetectRspPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Read_UINT16(s, autodetectRspPdu.responseType); /* responseType (2 bytes) */
|
||||
|
||||
WLog_VRB(AUTODETECT_TAG,
|
||||
"rdp_recv_autodetect_response_packet: headerLength=%"PRIu8", headerTypeId=%"PRIu8", sequenceNumber=%"PRIu16", requestType=%04"PRIx16"",
|
||||
autodetectRspPdu.headerLength, autodetectRspPdu.headerTypeId,
|
||||
autodetectRspPdu.sequenceNumber, autodetectRspPdu.responseType);
|
||||
"rdp_recv_autodetect_response_packet: headerLength=%"PRIu8", headerTypeId=%"PRIu8", sequenceNumber=%"PRIu16", requestType=%04"PRIx16"",
|
||||
autodetectRspPdu.headerLength, autodetectRspPdu.headerTypeId,
|
||||
autodetectRspPdu.sequenceNumber, autodetectRspPdu.responseType);
|
||||
|
||||
if (autodetectRspPdu.headerTypeId != TYPE_ID_AUTODETECT_RESPONSE)
|
||||
return -1;
|
||||
|
||||
switch (autodetectRspPdu.responseType)
|
||||
{
|
||||
case RDP_RTT_RESPONSE_TYPE:
|
||||
/* RTT Measure Response (RDP_RTT_RESPONSE) - MS-RDPBCGR 2.2.14.2.1 */
|
||||
success = autodetect_recv_rtt_measure_response(rdp, s, &autodetectRspPdu);
|
||||
break;
|
||||
case RDP_RTT_RESPONSE_TYPE:
|
||||
/* RTT Measure Response (RDP_RTT_RESPONSE) - MS-RDPBCGR 2.2.14.2.1 */
|
||||
success = autodetect_recv_rtt_measure_response(rdp, s, &autodetectRspPdu);
|
||||
break;
|
||||
|
||||
case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
|
||||
case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
|
||||
/* Bandwidth Measure Results (RDP_BW_RESULTS) - MS-RDPBCGR 2.2.14.2.2 */
|
||||
success = autodetect_recv_bandwidth_measure_results(rdp, s, &autodetectRspPdu);
|
||||
break;
|
||||
case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
|
||||
case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
|
||||
/* Bandwidth Measure Results (RDP_BW_RESULTS) - MS-RDPBCGR 2.2.14.2.2 */
|
||||
success = autodetect_recv_bandwidth_measure_results(rdp, s, &autodetectRspPdu);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return success ? 0 : -1;
|
||||
@ -623,9 +623,8 @@ rdpAutoDetect* autodetect_new(void)
|
||||
|
||||
if (autoDetect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
return autoDetect;
|
||||
}
|
||||
|
||||
|
@ -3966,17 +3966,16 @@ BOOL rdp_write_demand_active(wStream* s, rdpSettings* settings)
|
||||
|
||||
BOOL rdp_send_demand_active(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
wStream* s = rdp_send_stream_pdu_init(rdp);
|
||||
BOOL status;
|
||||
|
||||
if (!(s = Stream_New(NULL, 4096)))
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
rdp_init_stream_pdu(rdp, s);
|
||||
rdp->settings->ShareId = 0x10000 + rdp->mcs->userId;
|
||||
status = rdp_write_demand_active(s, rdp->settings) &&
|
||||
rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->userId);
|
||||
Stream_Free(s, TRUE);
|
||||
Stream_Release(s);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -4196,15 +4195,14 @@ BOOL rdp_write_confirm_active(wStream* s, rdpSettings* settings)
|
||||
|
||||
BOOL rdp_send_confirm_active(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
wStream* s = rdp_send_stream_pdu_init(rdp);
|
||||
BOOL status;
|
||||
|
||||
if (!(s = Stream_New(NULL, 4096)))
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
rdp_init_stream_pdu(rdp, s);
|
||||
status = rdp_write_confirm_active(s, rdp->settings) &&
|
||||
rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->userId);
|
||||
Stream_Free(s, TRUE);
|
||||
Stream_Release(s);
|
||||
return status;
|
||||
}
|
||||
|
@ -112,10 +112,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, int s
|
||||
|
||||
/* WLog_DBG(TAG, "%s: sending data (flags=0x%x size=%d)", __FUNCTION__, flags, size); */
|
||||
if (!rdp_send(rdp, s, channelId))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data += chunkSize;
|
||||
left -= chunkSize;
|
||||
|
@ -918,20 +918,24 @@ wStream* fastpath_input_pdu_init(rdpFastPath* fastpath, BYTE eventFlags, BYTE ev
|
||||
|
||||
BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNumEvents)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
rdpRdp* rdp;
|
||||
UINT16 length;
|
||||
BYTE eventHeader;
|
||||
|
||||
if (!fastpath || !fastpath->rdp || !s)
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!fastpath || !fastpath->rdp)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* A maximum of 15 events are allowed per request
|
||||
* if the optional numEvents field isn't used
|
||||
* see MS-RDPBCGR 2.2.8.1.2 for details
|
||||
*/
|
||||
if (iNumEvents > 15)
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
rdp = fastpath->rdp;
|
||||
length = Stream_GetPosition(s);
|
||||
@ -939,7 +943,7 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu
|
||||
if (length >= (2 << 14))
|
||||
{
|
||||
WLog_ERR(TAG, "Maximum FastPath PDU length is 32767");
|
||||
return FALSE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
eventHeader = FASTPATH_INPUT_ACTION_FASTPATH;
|
||||
@ -974,13 +978,13 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu
|
||||
Stream_Write_UINT8(s, pad); /* padding */
|
||||
|
||||
if (!security_hmac_signature(fpInputEvents, fpInputEvents_length, Stream_Pointer(s), rdp))
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
if (pad)
|
||||
memset(fpInputEvents + fpInputEvents_length, 0, pad);
|
||||
|
||||
if (!security_fips_encrypt(fpInputEvents, fpInputEvents_length + pad, rdp))
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
length += pad;
|
||||
}
|
||||
@ -995,7 +999,7 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu
|
||||
status = security_mac_signature(rdp, fpInputEvents, fpInputEvents_length, Stream_Pointer(s));
|
||||
|
||||
if (!status || !security_encrypt(fpInputEvents, fpInputEvents_length, rdp))
|
||||
return FALSE;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1012,9 +1016,12 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu
|
||||
Stream_SealLength(s);
|
||||
|
||||
if (transport_write(fastpath->rdp->transport, s) < 0)
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL fastpath_send_input_pdu(rdpFastPath* fastpath, wStream* s)
|
||||
|
@ -929,9 +929,8 @@ BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s)
|
||||
BOOL rdp_send_client_info(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
rdp->sec_flags |= SEC_INFO_PKT;
|
||||
s = Stream_New(NULL, 2048);
|
||||
s = rdp_send_stream_init(rdp);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
@ -939,11 +938,8 @@ BOOL rdp_send_client_info(rdpRdp* rdp)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp_init_stream(rdp, s);
|
||||
rdp_write_info_packet(rdp, s);
|
||||
status = rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
|
||||
Stream_Free(s, TRUE);
|
||||
return status;
|
||||
return rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
|
||||
}
|
||||
|
||||
static BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info* info)
|
||||
@ -1461,7 +1457,7 @@ BOOL rdp_send_save_session_info(rdpContext* context, UINT32 type, void* data)
|
||||
if (status)
|
||||
status = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SAVE_SESSION_INFO, rdp->mcs->userId);
|
||||
else
|
||||
Stream_Free(s, TRUE);
|
||||
Stream_Release(s);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -121,9 +121,9 @@ static void license_print_product_info(LICENSE_PRODUCT_INFO* productInfo)
|
||||
char* CompanyName = NULL;
|
||||
char* ProductId = NULL;
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) productInfo->pbCompanyName,
|
||||
productInfo->cbCompanyName / 2, &CompanyName, 0, NULL, NULL);
|
||||
productInfo->cbCompanyName / 2, &CompanyName, 0, NULL, NULL);
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) productInfo->pbProductId,
|
||||
productInfo->cbProductId / 2, &ProductId, 0, NULL, NULL);
|
||||
productInfo->cbProductId / 2, &ProductId, 0, NULL, NULL);
|
||||
WLog_INFO(TAG, "ProductInfo:");
|
||||
WLog_INFO(TAG, "\tdwVersion: 0x%08"PRIX32"", productInfo->dwVersion);
|
||||
WLog_INFO(TAG, "\tCompanyName: %s", CompanyName);
|
||||
@ -178,12 +178,16 @@ BOOL license_read_preamble(wStream* s, BYTE* bMsgType, BYTE* flags, UINT16* wMsg
|
||||
* @param wMsgSize message size
|
||||
*/
|
||||
|
||||
void license_write_preamble(wStream* s, BYTE bMsgType, BYTE flags, UINT16 wMsgSize)
|
||||
static BOOL license_write_preamble(wStream* s, BYTE bMsgType, BYTE flags, UINT16 wMsgSize)
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(s, 4))
|
||||
return FALSE;
|
||||
|
||||
/* preamble (4 bytes) */
|
||||
Stream_Write_UINT8(s, bMsgType); /* bMsgType (1 byte) */
|
||||
Stream_Write_UINT8(s, flags); /* flags (1 byte) */
|
||||
Stream_Write_UINT16(s, wMsgSize); /* wMsgSize (2 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -196,7 +200,6 @@ wStream* license_send_stream_init(rdpLicense* license)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL do_crypt = license->rdp->do_crypt;
|
||||
|
||||
license->rdp->sec_flags = SEC_LICENSE_PKT;
|
||||
|
||||
/**
|
||||
@ -213,15 +216,21 @@ wStream* license_send_stream_init(rdpLicense* license)
|
||||
license->rdp->do_crypt = license->rdp->do_crypt_license;
|
||||
}
|
||||
|
||||
s = transport_send_stream_init(license->rdp->transport, 4096);
|
||||
s = rdp_send_stream_init(license->rdp);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
rdp_init_stream(license->rdp, s);
|
||||
|
||||
license->rdp->do_crypt = do_crypt;
|
||||
license->PacketHeaderLength = Stream_GetPosition(s);
|
||||
Stream_Seek(s, LICENSE_PREAMBLE_LENGTH);
|
||||
|
||||
if (!Stream_SafeSeek(s, LICENSE_PREAMBLE_LENGTH))
|
||||
goto fail;
|
||||
|
||||
return s;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -231,13 +240,71 @@ wStream* license_send_stream_init(rdpLicense* license)
|
||||
* @param s stream
|
||||
*/
|
||||
|
||||
BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
|
||||
static BOOL license_send(rdpLicense* license, BYTE type)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
size_t length;
|
||||
BYTE flags;
|
||||
UINT16 wMsgSize;
|
||||
rdpRdp* rdp = license->rdp;
|
||||
rdpRdp* rdp;
|
||||
wStream* s = license_send_stream_init(license);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!license || !license->rdp)
|
||||
goto fail;
|
||||
|
||||
rdp = license->rdp;
|
||||
DEBUG_LICENSE("Sending %s Packet", LICENSE_MESSAGE_STRINGS[type & 0x1F]);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case NEW_LICENSE_REQUEST:
|
||||
if (!license_write_new_license_request_packet(license, s))
|
||||
goto fail;
|
||||
|
||||
break;
|
||||
|
||||
case PLATFORM_CHALLENGE_RESPONSE:
|
||||
{
|
||||
BYTE mac_data[16];
|
||||
size_t length = license->PlatformChallenge->length + HWID_LENGTH;
|
||||
BYTE* buffer = (BYTE*) malloc(length);
|
||||
|
||||
if (!buffer)
|
||||
goto fail;
|
||||
|
||||
CopyMemory(buffer, license->PlatformChallenge->data, license->PlatformChallenge->length);
|
||||
CopyMemory(&buffer[license->PlatformChallenge->length], license->HardwareId, HWID_LENGTH);
|
||||
rc = security_mac_data(license->MacSaltKey, buffer, length, mac_data);
|
||||
free(buffer);
|
||||
|
||||
if (!rc)
|
||||
goto fail;
|
||||
|
||||
if (!license_write_platform_challenge_response_packet(license, s, mac_data))
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case ERROR_ALERT:
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(s, 8))
|
||||
goto fail;
|
||||
|
||||
Stream_Write_UINT32(s, STATUS_VALID_CLIENT); /* dwErrorCode */
|
||||
Stream_Write_UINT32(s, ST_NO_TRANSITION); /* dwStateTransition */
|
||||
|
||||
if (!license_write_binary_blob(s, license->ErrorInfo))
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
length = Stream_GetPosition(s);
|
||||
wMsgSize = length - license->PacketHeaderLength;
|
||||
Stream_SetPosition(s, license->PacketHeaderLength);
|
||||
@ -251,15 +318,21 @@ BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
|
||||
if (!rdp->settings->ServerMode)
|
||||
flags |= EXTENDED_ERROR_MSG_SUPPORTED;
|
||||
|
||||
license_write_preamble(s, type, flags, wMsgSize);
|
||||
if (!license_write_preamble(s, type, flags, wMsgSize))
|
||||
goto fail;
|
||||
|
||||
#ifdef WITH_DEBUG_LICENSE
|
||||
WLog_DBG(TAG, "Sending %s Packet, length %"PRIu16"", LICENSE_MESSAGE_STRINGS[type & 0x1F], wMsgSize);
|
||||
WLog_DBG(TAG, "Sending %s Packet, length %"PRIu16"", LICENSE_MESSAGE_STRINGS[type & 0x1F],
|
||||
wMsgSize);
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(s) - LICENSE_PREAMBLE_LENGTH, wMsgSize);
|
||||
#endif
|
||||
Stream_SetPosition(s, length);
|
||||
rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
|
||||
rc = rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
|
||||
rdp->sec_flags = 0;
|
||||
return TRUE;
|
||||
return rc;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -305,6 +378,7 @@ int license_recv(rdpLicense* license, wStream* s)
|
||||
Stream_Rewind(s, RDP_SECURITY_HEADER_LENGTH);
|
||||
|
||||
status = rdp_recv_out_of_sequence_pdu(license->rdp, s);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "unexpected license packet.");
|
||||
@ -327,6 +401,7 @@ int license_recv(rdpLicense* license, wStream* s)
|
||||
|
||||
if (!license_send_new_license_request_packet(license))
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
case PLATFORM_CHALLENGE:
|
||||
@ -335,6 +410,7 @@ int license_recv(rdpLicense* license, wStream* s)
|
||||
|
||||
if (!license_send_platform_challenge_response_packet(license))
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
case NEW_LICENSE:
|
||||
@ -348,6 +424,7 @@ int license_recv(rdpLicense* license, wStream* s)
|
||||
case ERROR_ALERT:
|
||||
if (!license_read_error_alert_packet(license, s))
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -380,19 +457,20 @@ BOOL license_generate_keys(rdpLicense* license)
|
||||
BOOL ret;
|
||||
|
||||
if (
|
||||
/* MasterSecret */
|
||||
!security_master_secret(license->PremasterSecret, license->ClientRandom,
|
||||
license->ServerRandom, license->MasterSecret) ||
|
||||
/* SessionKeyBlob */
|
||||
!security_session_key_blob(license->MasterSecret, license->ClientRandom,
|
||||
license->ServerRandom, license->SessionKeyBlob))
|
||||
/* MasterSecret */
|
||||
!security_master_secret(license->PremasterSecret, license->ClientRandom,
|
||||
license->ServerRandom, license->MasterSecret) ||
|
||||
/* SessionKeyBlob */
|
||||
!security_session_key_blob(license->MasterSecret, license->ClientRandom,
|
||||
license->ServerRandom, license->SessionKeyBlob))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
security_mac_salt_key(license->SessionKeyBlob, license->ClientRandom,
|
||||
license->ServerRandom, license->MacSaltKey); /* MacSaltKey */
|
||||
license->ServerRandom, license->MacSaltKey); /* MacSaltKey */
|
||||
ret = security_licensing_encryption_key(license->SessionKeyBlob, license->ClientRandom,
|
||||
license->ServerRandom, license->LicensingEncryptionKey); /* LicensingEncryptionKey */
|
||||
license->ServerRandom, license->LicensingEncryptionKey); /* LicensingEncryptionKey */
|
||||
#ifdef WITH_DEBUG_LICENSE
|
||||
WLog_DBG(TAG, "ClientRandom:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, CLIENT_RANDOM_LENGTH);
|
||||
@ -420,14 +498,14 @@ BOOL license_generate_keys(rdpLicense* license)
|
||||
BOOL license_generate_hwid(rdpLicense* license)
|
||||
{
|
||||
BYTE macAddress[6];
|
||||
|
||||
ZeroMemory(macAddress, sizeof(macAddress));
|
||||
ZeroMemory(license->HardwareId, HWID_LENGTH);
|
||||
|
||||
/* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just taking a MD5 hash of the 6 bytes of 0's(macAddress) */
|
||||
/* and filling in the Data1-Data4 fields of the CLIENT_HARDWARE_ID structure(from MS-RDPELE section 2.2.2.3.1). This is for RDP licensing packets */
|
||||
/* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */
|
||||
if (!winpr_Digest_Allow_FIPS(WINPR_MD_MD5, macAddress, sizeof(macAddress), &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH))
|
||||
if (!winpr_Digest_Allow_FIPS(WINPR_MD_MD5, macAddress, sizeof(macAddress),
|
||||
&license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -443,8 +521,8 @@ BOOL license_get_server_rsa_public_key(rdpLicense* license)
|
||||
if (license->ServerCertificate->length < 1)
|
||||
{
|
||||
if (!certificate_read_server_certificate(license->certificate,
|
||||
settings->ServerCertificate, settings->ServerCertificateLength))
|
||||
return FALSE;
|
||||
settings->ServerCertificate, settings->ServerCertificateLength))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Exponent = license->certificate->cert_info.exponent;
|
||||
@ -453,8 +531,10 @@ BOOL license_get_server_rsa_public_key(rdpLicense* license)
|
||||
CopyMemory(license->Exponent, Exponent, 4);
|
||||
license->ModulusLength = ModulusLength;
|
||||
license->Modulus = (BYTE*) malloc(ModulusLength);
|
||||
|
||||
if (!license->Modulus)
|
||||
return FALSE;
|
||||
|
||||
CopyMemory(license->Modulus, Modulus, ModulusLength);
|
||||
return TRUE;
|
||||
}
|
||||
@ -472,8 +552,8 @@ BOOL license_encrypt_premaster_secret(rdpLicense* license)
|
||||
WLog_DBG(TAG, "Exponent:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->Exponent, 4);
|
||||
#endif
|
||||
|
||||
EncryptedPremasterSecret = (BYTE*) calloc(1, license->ModulusLength);
|
||||
|
||||
if (!EncryptedPremasterSecret)
|
||||
return FALSE;
|
||||
|
||||
@ -481,8 +561,8 @@ BOOL license_encrypt_premaster_secret(rdpLicense* license)
|
||||
license->EncryptedPremasterSecret->length = PREMASTER_SECRET_LENGTH;
|
||||
#ifndef LICENSE_NULL_PREMASTER_SECRET
|
||||
license->EncryptedPremasterSecret->length =
|
||||
crypto_rsa_public_encrypt(license->PremasterSecret, PREMASTER_SECRET_LENGTH,
|
||||
license->ModulusLength, license->Modulus, license->Exponent, EncryptedPremasterSecret);
|
||||
crypto_rsa_public_encrypt(license->PremasterSecret, PREMASTER_SECRET_LENGTH,
|
||||
license->ModulusLength, license->Modulus, license->Exponent, EncryptedPremasterSecret);
|
||||
#endif
|
||||
license->EncryptedPremasterSecret->data = EncryptedPremasterSecret;
|
||||
return TRUE;
|
||||
@ -492,27 +572,28 @@ BOOL license_decrypt_platform_challenge(rdpLicense* license)
|
||||
{
|
||||
BOOL rc;
|
||||
WINPR_RC4_CTX* rc4;
|
||||
license->PlatformChallenge->data = (BYTE*)malloc(license->EncryptedPlatformChallenge->length);
|
||||
|
||||
license->PlatformChallenge->data = (BYTE *)malloc(license->EncryptedPlatformChallenge->length);
|
||||
if (!license->PlatformChallenge->data)
|
||||
return FALSE;
|
||||
|
||||
license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length;
|
||||
|
||||
/* Allow FIPS override for use of RC4 here, this is only used for decrypting the MACData field of the */
|
||||
/* Server Platform Challenge packet (from MS-RDPELE section 2.2.2.4). This is for RDP licensing packets */
|
||||
/* which will already be encrypted under FIPS, so the use of RC4 here is not for sensitive data protection. */
|
||||
if ((rc4 = winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey,
|
||||
LICENSING_ENCRYPTION_KEY_LENGTH)) == NULL)
|
||||
LICENSING_ENCRYPTION_KEY_LENGTH)) == NULL)
|
||||
{
|
||||
free(license->PlatformChallenge->data);
|
||||
license->PlatformChallenge->data = NULL;
|
||||
license->PlatformChallenge->length = 0;
|
||||
return FALSE;
|
||||
}
|
||||
rc = winpr_RC4_Update(rc4, license->EncryptedPlatformChallenge->length,
|
||||
license->EncryptedPlatformChallenge->data,
|
||||
license->PlatformChallenge->data);
|
||||
|
||||
rc = winpr_RC4_Update(rc4, license->EncryptedPlatformChallenge->length,
|
||||
license->EncryptedPlatformChallenge->data,
|
||||
license->PlatformChallenge->data);
|
||||
winpr_RC4_Free(rc4);
|
||||
return rc;
|
||||
}
|
||||
@ -541,8 +622,10 @@ BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo)
|
||||
|
||||
productInfo->pbProductId = NULL;
|
||||
productInfo->pbCompanyName = (BYTE*) malloc(productInfo->cbCompanyName);
|
||||
|
||||
if (!productInfo->pbCompanyName)
|
||||
return FALSE;
|
||||
|
||||
Stream_Read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
@ -557,11 +640,12 @@ BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo)
|
||||
goto out_fail;
|
||||
|
||||
productInfo->pbProductId = (BYTE*) malloc(productInfo->cbProductId);
|
||||
|
||||
if (!productInfo->pbProductId)
|
||||
goto out_fail;
|
||||
|
||||
Stream_Read(s, productInfo->pbProductId, productInfo->cbProductId);
|
||||
return TRUE;
|
||||
|
||||
out_fail:
|
||||
free(productInfo->pbCompanyName);
|
||||
free(productInfo->pbProductId);
|
||||
@ -580,8 +664,10 @@ LICENSE_PRODUCT_INFO* license_new_product_info()
|
||||
{
|
||||
LICENSE_PRODUCT_INFO* productInfo;
|
||||
productInfo = (LICENSE_PRODUCT_INFO*) malloc(sizeof(LICENSE_PRODUCT_INFO));
|
||||
|
||||
if (!productInfo)
|
||||
return NULL;
|
||||
|
||||
productInfo->dwVersion = 0;
|
||||
productInfo->cbCompanyName = 0;
|
||||
productInfo->pbCompanyName = NULL;
|
||||
@ -635,13 +721,16 @@ BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob)
|
||||
|
||||
if ((blob->type != wBlobType) && (blob->type != BB_ANY_BLOB))
|
||||
{
|
||||
WLog_ERR(TAG, "license binary blob type (0x%"PRIx16") does not match expected type (0x%"PRIx16").", wBlobType, blob->type);
|
||||
WLog_ERR(TAG, "license binary blob type (0x%"PRIx16") does not match expected type (0x%"PRIx16").",
|
||||
wBlobType, blob->type);
|
||||
}
|
||||
|
||||
blob->type = wBlobType;
|
||||
blob->data = (BYTE*) malloc(blob->length);
|
||||
|
||||
if (!blob->data)
|
||||
return FALSE;
|
||||
|
||||
Stream_Read(s, blob->data, blob->length); /* blobData */
|
||||
return TRUE;
|
||||
}
|
||||
@ -656,17 +745,22 @@ BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob)
|
||||
BOOL license_write_binary_blob(wStream* s, LICENSE_BLOB* blob)
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(s, blob->length + 4))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
|
||||
Stream_Write_UINT16(s, blob->length); /* wBlobLen (2 bytes) */
|
||||
|
||||
if (blob->length > 0)
|
||||
Stream_Write(s, blob->data, blob->length); /* blobData */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL license_write_encrypted_premaster_secret_blob(wStream* s, LICENSE_BLOB* blob, UINT32 ModulusLength)
|
||||
static BOOL license_write_encrypted_premaster_secret_blob(wStream* s, LICENSE_BLOB* blob,
|
||||
UINT32 ModulusLength)
|
||||
{
|
||||
UINT32 length;
|
||||
length = ModulusLength + 8;
|
||||
@ -679,6 +773,7 @@ BOOL license_write_encrypted_premaster_secret_blob(wStream* s, LICENSE_BLOB* blo
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, length + 4))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
|
||||
Stream_Write_UINT16(s, length); /* wBlobLen (2 bytes) */
|
||||
|
||||
@ -699,8 +794,10 @@ LICENSE_BLOB* license_new_binary_blob(UINT16 type)
|
||||
{
|
||||
LICENSE_BLOB* blob;
|
||||
blob = (LICENSE_BLOB*) calloc(1, sizeof(LICENSE_BLOB));
|
||||
|
||||
if (blob)
|
||||
blob->type = type;
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
@ -741,6 +838,7 @@ BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList)
|
||||
|
||||
scopeList->count = scopeCount;
|
||||
scopeList->array = (LICENSE_BLOB*) calloc(scopeCount, sizeof(LICENSE_BLOB));
|
||||
|
||||
if (!scopeList->array)
|
||||
return FALSE;
|
||||
|
||||
@ -829,11 +927,11 @@ BOOL license_read_license_request_packet(rdpLicense* license, wStream* s)
|
||||
|
||||
/* Parse Server Certificate */
|
||||
if (!certificate_read_server_certificate(license->certificate,
|
||||
license->ServerCertificate->data, license->ServerCertificate->length))
|
||||
license->ServerCertificate->data, license->ServerCertificate->length))
|
||||
return FALSE;
|
||||
|
||||
if (!license_generate_keys(license) || !license_generate_hwid(license) ||
|
||||
!license_encrypt_premaster_secret(license))
|
||||
!license_encrypt_premaster_secret(license))
|
||||
return FALSE;
|
||||
|
||||
#ifdef WITH_DEBUG_LICENSE
|
||||
@ -856,7 +954,6 @@ BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
|
||||
{
|
||||
BYTE MacData[16];
|
||||
UINT32 ConnectFlags = 0;
|
||||
|
||||
DEBUG_LICENSE("Receiving Platform Challenge Packet");
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
@ -865,6 +962,7 @@ BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
|
||||
Stream_Read_UINT32(s, ConnectFlags); /* ConnectFlags, Reserved (4 bytes) */
|
||||
/* EncryptedPlatformChallenge */
|
||||
license->EncryptedPlatformChallenge->type = BB_ANY_BLOB;
|
||||
|
||||
if (!license_read_binary_blob(s, license->EncryptedPlatformChallenge))
|
||||
return FALSE;
|
||||
|
||||
@ -874,14 +972,18 @@ BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
|
||||
return FALSE;
|
||||
|
||||
Stream_Read(s, MacData, 16); /* MACData (16 bytes) */
|
||||
|
||||
if (!license_decrypt_platform_challenge(license))
|
||||
return FALSE;
|
||||
|
||||
#ifdef WITH_DEBUG_LICENSE
|
||||
WLog_DBG(TAG, "ConnectFlags: 0x%08"PRIX32"", ConnectFlags);
|
||||
WLog_DBG(TAG, "EncryptedPlatformChallenge:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPlatformChallenge->data, license->EncryptedPlatformChallenge->length);
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPlatformChallenge->data,
|
||||
license->EncryptedPlatformChallenge->length);
|
||||
WLog_DBG(TAG, "PlatformChallenge:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->PlatformChallenge->data, license->PlatformChallenge->length);
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->PlatformChallenge->data,
|
||||
license->PlatformChallenge->length);
|
||||
WLog_DBG(TAG, "MacData:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, MacData, 16);
|
||||
#endif
|
||||
@ -937,7 +1039,7 @@ BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s)
|
||||
|
||||
#ifdef WITH_DEBUG_LICENSE
|
||||
WLog_DBG(TAG, "dwErrorCode: %s, dwStateTransition: %s",
|
||||
error_codes[dwErrorCode], state_transitions[dwStateTransition]);
|
||||
error_codes[dwErrorCode], state_transitions[dwStateTransition]);
|
||||
#endif
|
||||
|
||||
if (dwErrorCode == STATUS_VALID_CLIENT)
|
||||
@ -951,14 +1053,18 @@ BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s)
|
||||
case ST_TOTAL_ABORT:
|
||||
license->state = LICENSE_STATE_ABORTED;
|
||||
break;
|
||||
|
||||
case ST_NO_TRANSITION:
|
||||
license->state = LICENSE_STATE_COMPLETED;
|
||||
break;
|
||||
|
||||
case ST_RESET_PHASE_TO_START:
|
||||
license->state = LICENSE_STATE_AWAIT;
|
||||
break;
|
||||
|
||||
case ST_RESEND_LAST_MESSAGE:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -977,19 +1083,20 @@ BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s)
|
||||
{
|
||||
UINT32 PlatformId;
|
||||
UINT32 PreferredKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
|
||||
|
||||
PlatformId = CLIENT_OS_ID_WINNT_POST_52 | CLIENT_IMAGE_ID_MICROSOFT;
|
||||
Stream_Write_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
|
||||
Stream_Write_UINT32(s, PlatformId); /* PlatformId (4 bytes) */
|
||||
Stream_Write(s, license->ClientRandom, 32); /* ClientRandom (32 bytes) */
|
||||
|
||||
/* EncryptedPremasterSecret */
|
||||
if (!license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret, license->ModulusLength) ||
|
||||
/* ClientUserName */
|
||||
!license_write_binary_blob(s, license->ClientUserName) ||
|
||||
/* ClientMachineName */
|
||||
!license_write_binary_blob(s, license->ClientMachineName))
|
||||
/* EncryptedPremasterSecret */
|
||||
if (!license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
|
||||
license->ModulusLength) ||
|
||||
/* ClientUserName */
|
||||
!license_write_binary_blob(s, license->ClientUserName) ||
|
||||
/* ClientMachineName */
|
||||
!license_write_binary_blob(s, license->ClientMachineName))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -998,9 +1105,12 @@ BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s)
|
||||
WLog_DBG(TAG, "ClientRandom:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, 32);
|
||||
WLog_DBG(TAG, "EncryptedPremasterSecret");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPremasterSecret->data, license->EncryptedPremasterSecret->length);
|
||||
WLog_DBG(TAG, "ClientUserName (%"PRIu16"): %s", license->ClientUserName->length, (char*) license->ClientUserName->data);
|
||||
WLog_DBG(TAG, "ClientMachineName (%"PRIu16"): %s", license->ClientMachineName->length, (char*) license->ClientMachineName->data);
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPremasterSecret->data,
|
||||
license->EncryptedPremasterSecret->length);
|
||||
WLog_DBG(TAG, "ClientUserName (%"PRIu16"): %s", license->ClientUserName->length,
|
||||
(char*) license->ClientUserName->data);
|
||||
WLog_DBG(TAG, "ClientMachineName (%"PRIu16"): %s", license->ClientMachineName->length,
|
||||
(char*) license->ClientMachineName->data);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
@ -1013,12 +1123,8 @@ BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s)
|
||||
|
||||
BOOL license_send_new_license_request_packet(rdpLicense* license)
|
||||
{
|
||||
wStream* s;
|
||||
char* username;
|
||||
DEBUG_LICENSE("Sending New License Packet");
|
||||
s = license_send_stream_init(license);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (license->rdp->settings->Username != NULL)
|
||||
username = license->rdp->settings->Username;
|
||||
@ -1029,11 +1135,9 @@ BOOL license_send_new_license_request_packet(rdpLicense* license)
|
||||
license->ClientUserName->length = strlen(username) + 1;
|
||||
license->ClientMachineName->data = (BYTE*) license->rdp->settings->ClientHostname;
|
||||
license->ClientMachineName->length = strlen(license->rdp->settings->ClientHostname) + 1;
|
||||
if (!license_write_new_license_request_packet(license, s) ||
|
||||
!license_send(license, s, NEW_LICENSE_REQUEST))
|
||||
{
|
||||
|
||||
if (!license_send(license, NEW_LICENSE_REQUEST))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
license->ClientUserName->data = NULL;
|
||||
license->ClientUserName->length = 0;
|
||||
@ -1050,12 +1154,15 @@ BOOL license_send_new_license_request_packet(rdpLicense* license)
|
||||
* @param mac_data signature
|
||||
*/
|
||||
|
||||
BOOL license_write_platform_challenge_response_packet(rdpLicense* license, wStream* s, BYTE* macData)
|
||||
BOOL license_write_platform_challenge_response_packet(rdpLicense* license, wStream* s,
|
||||
BYTE* macData)
|
||||
{
|
||||
if (!license_write_binary_blob(s, license->EncryptedPlatformChallenge) || /* EncryptedPlatformChallengeResponse */
|
||||
!license_write_binary_blob(s, license->EncryptedHardwareId) || /* EncryptedHWID */
|
||||
!Stream_EnsureRemainingCapacity(s, 16))
|
||||
if (!license_write_binary_blob(s, license->EncryptedPlatformChallenge) ||
|
||||
/* EncryptedPlatformChallengeResponse */
|
||||
!license_write_binary_blob(s, license->EncryptedHardwareId) || /* EncryptedHWID */
|
||||
!Stream_EnsureRemainingCapacity(s, 16))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -1071,44 +1178,28 @@ BOOL license_write_platform_challenge_response_packet(rdpLicense* license, wStre
|
||||
|
||||
BOOL license_send_platform_challenge_response_packet(rdpLicense* license)
|
||||
{
|
||||
wStream* s;
|
||||
int length;
|
||||
BYTE* buffer;
|
||||
WINPR_RC4_CTX* rc4;
|
||||
BYTE mac_data[16];
|
||||
BOOL status;
|
||||
|
||||
DEBUG_LICENSE("Sending Platform Challenge Response Packet");
|
||||
s = license_send_stream_init(license);
|
||||
license->EncryptedPlatformChallenge->type = BB_DATA_BLOB;
|
||||
length = license->PlatformChallenge->length + HWID_LENGTH;
|
||||
|
||||
buffer = (BYTE*) malloc(length);
|
||||
if (!buffer)
|
||||
return FALSE;
|
||||
|
||||
CopyMemory(buffer, license->PlatformChallenge->data, license->PlatformChallenge->length);
|
||||
CopyMemory(&buffer[license->PlatformChallenge->length], license->HardwareId, HWID_LENGTH);
|
||||
status = security_mac_data(license->MacSaltKey, buffer, length, mac_data);
|
||||
free(buffer);
|
||||
|
||||
if (!status)
|
||||
return FALSE;
|
||||
|
||||
/* Allow FIPS override for use of RC4 here, this is only used for encrypting the EncryptedHWID field of the */
|
||||
/* Client Platform Challenge Response packet (from MS-RDPELE section 2.2.2.5). This is for RDP licensing packets */
|
||||
/* which will already be encrypted under FIPS, so the use of RC4 here is not for sensitive data protection. */
|
||||
rc4 = winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey,
|
||||
LICENSING_ENCRYPTION_KEY_LENGTH);
|
||||
LICENSING_ENCRYPTION_KEY_LENGTH);
|
||||
|
||||
if (!rc4)
|
||||
return FALSE;
|
||||
|
||||
buffer = (BYTE*) malloc(HWID_LENGTH);
|
||||
|
||||
if (!buffer)
|
||||
return FALSE;
|
||||
|
||||
status = winpr_RC4_Update(rc4, HWID_LENGTH, license->HardwareId, buffer);
|
||||
winpr_RC4_Free(rc4);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
free(buffer);
|
||||
@ -1126,8 +1217,7 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license)
|
||||
WLog_DBG(TAG, "EncryptedHardwareId:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedHardwareId->data, HWID_LENGTH);
|
||||
#endif
|
||||
return license_write_platform_challenge_response_packet(license, s, mac_data) &&
|
||||
license_send(license, s, PLATFORM_CHALLENGE_RESPONSE);
|
||||
return license_send(license, PLATFORM_CHALLENGE_RESPONSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1138,17 +1228,13 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license)
|
||||
|
||||
BOOL license_send_valid_client_error_packet(rdpLicense* license)
|
||||
{
|
||||
wStream* s;
|
||||
s = license_send_stream_init(license);
|
||||
wStream* s = license_send_stream_init(license);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
DEBUG_LICENSE("Sending Error Alert Packet");
|
||||
Stream_Write_UINT32(s, STATUS_VALID_CLIENT); /* dwErrorCode */
|
||||
Stream_Write_UINT32(s, ST_NO_TRANSITION); /* dwStateTransition */
|
||||
|
||||
return license_write_binary_blob(s, license->ErrorInfo) &&
|
||||
license_send(license, s, ERROR_ALERT);
|
||||
return license_send(license, ERROR_ALERT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1161,40 +1247,51 @@ rdpLicense* license_new(rdpRdp* rdp)
|
||||
{
|
||||
rdpLicense* license;
|
||||
license = (rdpLicense*) calloc(1, sizeof(rdpLicense));
|
||||
|
||||
if (!license)
|
||||
return NULL;
|
||||
|
||||
license->rdp = rdp;
|
||||
license->state = LICENSE_STATE_AWAIT;
|
||||
|
||||
if (!(license->certificate = certificate_new()))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->ProductInfo = license_new_product_info()))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->ErrorInfo = license_new_binary_blob(BB_ERROR_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->KeyExchangeList = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->ServerCertificate = license_new_binary_blob(BB_CERTIFICATE_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->ClientUserName = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->ClientMachineName = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->PlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->EncryptedPlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->EncryptedPremasterSecret = license_new_binary_blob(BB_ANY_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->EncryptedHardwareId = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
|
||||
goto out_error;
|
||||
|
||||
if (!(license->ScopeList = license_new_scope_list()))
|
||||
goto out_error;
|
||||
|
||||
license_generate_randoms(license);
|
||||
|
||||
return license;
|
||||
|
||||
out_error:
|
||||
license_free(license);
|
||||
return NULL;
|
||||
|
@ -202,7 +202,6 @@ struct rdp_license
|
||||
};
|
||||
|
||||
FREERDP_LOCAL int license_recv(rdpLicense* license, wStream* s);
|
||||
FREERDP_LOCAL BOOL license_send(rdpLicense* license, wStream* s, BYTE type);
|
||||
|
||||
FREERDP_LOCAL BOOL license_send_valid_client_error_packet(rdpLicense* license);
|
||||
|
||||
|
@ -1831,6 +1831,7 @@ static size_t nla_sizeof_ts_request(size_t length)
|
||||
|
||||
BOOL nla_send(rdpNla* nla)
|
||||
{
|
||||
BOOL rc = TRUE;
|
||||
wStream* s;
|
||||
size_t length;
|
||||
size_t ts_request_length;
|
||||
@ -1933,9 +1934,12 @@ BOOL nla_send(rdpNla* nla)
|
||||
}
|
||||
|
||||
Stream_SealLength(s);
|
||||
transport_write(nla->transport, s);
|
||||
|
||||
if (transport_write(nla->transport, s) < 0)
|
||||
rc = FALSE;
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
return TRUE;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int nla_decode_ts_request(rdpNla* nla, wStream* s)
|
||||
|
@ -171,10 +171,7 @@ static int freerdp_peer_virtual_channel_write(freerdp_peer* client, HANDLE hChan
|
||||
Stream_Write(s, buffer, chunkSize);
|
||||
|
||||
if (!rdp_send(rdp, s, peerChannel->channelId))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer += chunkSize;
|
||||
length -= chunkSize;
|
||||
|
@ -181,14 +181,21 @@ void rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 sh
|
||||
Stream_Write_UINT16(s, 0); /* compressedLength (2 bytes) */
|
||||
}
|
||||
|
||||
static int rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header)
|
||||
static BOOL rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header)
|
||||
{
|
||||
if (!rdp || !s)
|
||||
return FALSE;
|
||||
|
||||
if (rdp->do_crypt)
|
||||
{
|
||||
Stream_Seek(s, 12);
|
||||
if (!Stream_SafeSeek(s, 12))
|
||||
return FALSE;
|
||||
|
||||
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
|
||||
Stream_Seek(s, 4);
|
||||
{
|
||||
if (!Stream_SafeSeek(s, 4))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->sec_flags |= SEC_ENCRYPT;
|
||||
|
||||
@ -197,53 +204,62 @@ static int rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header)
|
||||
}
|
||||
else if (rdp->sec_flags != 0 || sec_header)
|
||||
{
|
||||
Stream_Seek(s, 4);
|
||||
if (!Stream_SafeSeek(s, 4))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rdp_init_stream(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
|
||||
return rdp_security_stream_init(rdp, s, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
wStream* rdp_send_stream_init(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
s = transport_send_stream_init(rdp->transport, 2048);
|
||||
rdp_init_stream(rdp, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
int rdp_init_stream_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
|
||||
rdp_security_stream_init(rdp, s, FALSE);
|
||||
Stream_Seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rdp_init_stream_data_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
|
||||
rdp_security_stream_init(rdp, s, FALSE);
|
||||
Stream_Seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH);
|
||||
Stream_Seek(s, RDP_SHARE_DATA_HEADER_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wStream* rdp_data_pdu_init(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
s = transport_send_stream_init(rdp->transport, 2048);
|
||||
wStream* s = transport_send_stream_init(rdp->transport, 4096);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
rdp_init_stream_data_pdu(rdp, s);
|
||||
if (!Stream_SafeSeek(s, RDP_PACKET_HEADER_MAX_LENGTH))
|
||||
goto fail;
|
||||
|
||||
if (!rdp_security_stream_init(rdp, s, FALSE))
|
||||
goto fail;
|
||||
|
||||
return s;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wStream* rdp_send_stream_pdu_init(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s = rdp_send_stream_init(rdp);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
if (!Stream_SafeSeek(s, RDP_SHARE_CONTROL_HEADER_LENGTH))
|
||||
goto fail;
|
||||
|
||||
return s;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wStream* rdp_data_pdu_init(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s = rdp_send_stream_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
if (!Stream_SafeSeek(s, RDP_SHARE_DATA_HEADER_LENGTH))
|
||||
goto fail;
|
||||
|
||||
return s;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
|
||||
@ -278,15 +294,21 @@ BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
|
||||
|
||||
wStream* rdp_message_channel_pdu_init(rdpRdp* rdp)
|
||||
{
|
||||
wStream* s;
|
||||
s = transport_send_stream_init(rdp->transport, 2048);
|
||||
wStream* s = transport_send_stream_init(rdp->transport, 4096);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
|
||||
rdp_security_stream_init(rdp, s, TRUE);
|
||||
if (!Stream_SafeSeek(s, RDP_PACKET_HEADER_MAX_LENGTH))
|
||||
goto fail;
|
||||
|
||||
if (!rdp_security_stream_init(rdp, s, TRUE))
|
||||
goto fail;
|
||||
|
||||
return s;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -537,23 +559,34 @@ static UINT32 rdp_get_sec_bytes(rdpRdp* rdp, UINT16 sec_flags)
|
||||
|
||||
BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
UINT32 pad;
|
||||
UINT16 length;
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!rdp)
|
||||
goto fail;
|
||||
|
||||
length = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
rdp_write_header(rdp, s, length, channel_id);
|
||||
|
||||
if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
length += pad;
|
||||
Stream_SetPosition(s, length);
|
||||
Stream_SealLength(s);
|
||||
|
||||
if (transport_write(rdp->transport, s) < 0)
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id)
|
||||
@ -562,6 +595,10 @@ BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id)
|
||||
UINT32 sec_bytes;
|
||||
size_t sec_hold;
|
||||
UINT32 pad;
|
||||
|
||||
if (!rdp || !s)
|
||||
return FALSE;
|
||||
|
||||
length = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
|
||||
@ -586,10 +623,18 @@ BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id)
|
||||
|
||||
BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
size_t length;
|
||||
UINT32 sec_bytes;
|
||||
size_t sec_hold;
|
||||
UINT32 pad;
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!rdp)
|
||||
goto fail;
|
||||
|
||||
length = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
|
||||
@ -601,7 +646,7 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
|
||||
Stream_SetPosition(s, sec_hold);
|
||||
|
||||
if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
length += pad;
|
||||
Stream_SetPosition(s, length);
|
||||
@ -610,30 +655,44 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
|
||||
type, Stream_Length(s), channel_id);
|
||||
|
||||
if (transport_write(rdp->transport, s) < 0)
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
UINT16 length;
|
||||
UINT32 pad;
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!rdp)
|
||||
goto fail;
|
||||
|
||||
length = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
rdp_write_header(rdp, s, length, rdp->mcs->messageChannelId);
|
||||
|
||||
if (!rdp_security_stream_out(rdp, s, length, sec_flags, &pad))
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
length += pad;
|
||||
Stream_SetPosition(s, length);
|
||||
Stream_SealLength(s);
|
||||
|
||||
if (transport_write(rdp->transport, s) < 0)
|
||||
return FALSE;
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL rdp_recv_server_shutdown_denied_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
@ -192,20 +192,18 @@ FREERDP_LOCAL BOOL rdp_read_share_data_header(wStream* s, UINT16* length,
|
||||
FREERDP_LOCAL void rdp_write_share_data_header(wStream* s, UINT16 length,
|
||||
BYTE type, UINT32 share_id);
|
||||
|
||||
FREERDP_LOCAL int rdp_init_stream(rdpRdp* rdp, wStream* s);
|
||||
FREERDP_LOCAL wStream* rdp_send_stream_init(rdpRdp* rdp);
|
||||
FREERDP_LOCAL wStream* rdp_send_stream_pdu_init(rdpRdp* rdp);
|
||||
|
||||
FREERDP_LOCAL BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length,
|
||||
UINT16* channel_id);
|
||||
FREERDP_LOCAL void rdp_write_header(rdpRdp* rdp, wStream* s, UINT16 length,
|
||||
UINT16 channel_id);
|
||||
|
||||
FREERDP_LOCAL int rdp_init_stream_pdu(rdpRdp* rdp, wStream* s);
|
||||
FREERDP_LOCAL BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type,
|
||||
UINT16 channel_id);
|
||||
|
||||
FREERDP_LOCAL wStream* rdp_data_pdu_init(rdpRdp* rdp);
|
||||
FREERDP_LOCAL int rdp_init_stream_data_pdu(rdpRdp* rdp, wStream* s);
|
||||
FREERDP_LOCAL BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type,
|
||||
UINT16 channel_id);
|
||||
FREERDP_LOCAL int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
@ -995,21 +995,17 @@ static void update_write_refresh_rect(wStream* s, BYTE count,
|
||||
static BOOL update_send_refresh_rect(rdpContext* context, BYTE count,
|
||||
const RECTANGLE_16* areas)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
||||
if (rdp->settings->RefreshRect)
|
||||
{
|
||||
BOOL ret;
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
update_write_refresh_rect(s, count, areas);
|
||||
ret = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId);
|
||||
Stream_Release(s);
|
||||
return ret;
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -1034,22 +1030,18 @@ static void update_write_suppress_output(wStream* s, BYTE allow,
|
||||
static BOOL update_send_suppress_output(rdpContext* context, BYTE allow,
|
||||
const RECTANGLE_16* area)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
||||
if (rdp->settings->SuppressOutput)
|
||||
{
|
||||
BOOL ret;
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
update_write_suppress_output(s, allow, area);
|
||||
ret = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT,
|
||||
rdp->mcs->userId);
|
||||
Stream_Release(s);
|
||||
return ret;
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT,
|
||||
rdp->mcs->userId);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -1169,22 +1161,18 @@ out_fail:
|
||||
|
||||
static BOOL update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
||||
if (rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
|
||||
{
|
||||
BOOL ret;
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
wStream* s = rdp_data_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT32(s, frameId);
|
||||
ret = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE,
|
||||
rdp->mcs->userId);
|
||||
Stream_Release(s);
|
||||
return ret;
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE,
|
||||
rdp->mcs->userId);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -1244,7 +1232,6 @@ static BOOL update_send_play_sound(rdpContext* context,
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
BOOL ret;
|
||||
|
||||
if (!rdp->settings->ReceivedCapabilities[CAPSET_TYPE_SOUND])
|
||||
{
|
||||
@ -1258,9 +1245,7 @@ static BOOL update_send_play_sound(rdpContext* context,
|
||||
|
||||
Stream_Write_UINT32(s, play_sound->duration);
|
||||
Stream_Write_UINT32(s, play_sound->frequency);
|
||||
ret = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_PLAY_SOUND, rdp->mcs->userId);
|
||||
Stream_Release(s);
|
||||
return ret;
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_PLAY_SOUND, rdp->mcs->userId);
|
||||
}
|
||||
/**
|
||||
* Primary Drawing Orders
|
||||
@ -2065,7 +2050,6 @@ static BOOL update_send_set_keyboard_indicators(rdpContext* context,
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
BOOL ret;
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
@ -2074,10 +2058,8 @@ static BOOL update_send_set_keyboard_indicators(rdpContext* context,
|
||||
Stream_Write_UINT16(s,
|
||||
0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */
|
||||
Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */
|
||||
ret = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS,
|
||||
rdp->mcs->userId);
|
||||
Stream_Release(s);
|
||||
return ret;
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS,
|
||||
rdp->mcs->userId);
|
||||
}
|
||||
|
||||
static BOOL update_send_set_keyboard_ime_status(rdpContext* context,
|
||||
@ -2085,7 +2067,6 @@ static BOOL update_send_set_keyboard_ime_status(rdpContext* context,
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
BOOL ret;
|
||||
s = rdp_data_pdu_init(rdp);
|
||||
|
||||
if (!s)
|
||||
@ -2095,10 +2076,8 @@ static BOOL update_send_set_keyboard_ime_status(rdpContext* context,
|
||||
Stream_Write_UINT16(s, imeId);
|
||||
Stream_Write_UINT32(s, imeState);
|
||||
Stream_Write_UINT32(s, imeConvMode);
|
||||
ret = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS,
|
||||
rdp->mcs->userId);
|
||||
Stream_Release(s);
|
||||
return ret;
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS,
|
||||
rdp->mcs->userId);
|
||||
}
|
||||
|
||||
void update_register_server_callbacks(rdpUpdate* update)
|
||||
|
@ -175,6 +175,7 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size)
|
||||
else
|
||||
{
|
||||
Stream_SetPosition(s, 0);
|
||||
Stream_SetLength(s, Stream_Capacity(s));
|
||||
StreamPool_ShiftAvailable(pool, foundIndex, -1);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user