mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
Refactored multitransport
* Implemented server and client multitransport message parsing
This commit is contained in:
@@ -17,35 +17,155 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "multitransport.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "rdp.h"
|
||||
#include "multitransport.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.multitransport")
|
||||
|
||||
int rdp_recv_multitransport_packet(rdpRdp* rdp, wStream* s)
|
||||
struct rdp_multitransport
|
||||
{
|
||||
UINT32 requestId;
|
||||
UINT16 requestedProtocol;
|
||||
UINT16 reserved;
|
||||
BYTE securityCookie[16];
|
||||
rdpRdp* rdp;
|
||||
|
||||
UINT32 requestId; /* requestId (4 bytes) */
|
||||
UINT16 requestedProtocol; /* requestedProtocol (2 bytes) */
|
||||
UINT16 reserved; /* reserved (2 bytes) */
|
||||
BYTE securityCookie[16]; /* securityCookie (16 bytes) */
|
||||
};
|
||||
|
||||
static BOOL multitransport_compare(const rdpMultitransport* srv, const rdpMultitransport* client)
|
||||
{
|
||||
BOOL abortOnError = !freerdp_settings_get_bool(srv->rdp->settings, FreeRDP_TransportDumpReplay);
|
||||
WINPR_ASSERT(srv);
|
||||
WINPR_ASSERT(client);
|
||||
|
||||
if (srv->requestId != client->requestId)
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Multitransport PDU::requestId mismatch expected 0x08%" PRIx32
|
||||
", got 0x08%" PRIx32,
|
||||
srv->requestId, client->requestId);
|
||||
if (abortOnError)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (srv->requestedProtocol != client->requestedProtocol)
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Multitransport PDU::requestedProtocol mismatch expected 0x08%" PRIx32
|
||||
", got 0x08%" PRIx32,
|
||||
srv->requestedProtocol, client->requestedProtocol);
|
||||
if (abortOnError)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (memcmp(srv->securityCookie, client->securityCookie, sizeof(srv->securityCookie)) != 0)
|
||||
{
|
||||
WLog_WARN(TAG, "Multitransport PDU::securityCookie mismatch");
|
||||
if (abortOnError)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int multitransport_client_recv_request(rdpMultitransport* multitransport, wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(multitransport);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 24))
|
||||
return -1;
|
||||
|
||||
Stream_Read_UINT32(s, requestId); /* requestId (4 bytes) */
|
||||
Stream_Read_UINT16(s, requestedProtocol); /* requestedProtocol (2 bytes) */
|
||||
Stream_Read_UINT16(s, reserved); /* reserved (2 bytes) */
|
||||
Stream_Read(s, securityCookie, 16); /* securityCookie (16 bytes) */
|
||||
Stream_Read_UINT32(s, multitransport->requestId); /* requestId (4 bytes) */
|
||||
Stream_Read_UINT16(s, multitransport->requestedProtocol); /* requestedProtocol (2 bytes) */
|
||||
Stream_Read_UINT16(s, multitransport->reserved); /* reserved (2 bytes) */
|
||||
Stream_Read(s, multitransport->securityCookie,
|
||||
sizeof(multitransport->securityCookie)); /* securityCookie (16 bytes) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdpMultitransport* multitransport_new(void)
|
||||
BOOL multitransport_server_send_request(rdpMultitransport* multitransport)
|
||||
{
|
||||
return (rdpMultitransport*)calloc(1, sizeof(rdpMultitransport));
|
||||
WINPR_ASSERT(multitransport);
|
||||
wStream* s = rdp_message_channel_pdu_init(multitransport->rdp);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 24))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, multitransport->requestId); /* requestId (4 bytes) */
|
||||
Stream_Write_UINT16(s, multitransport->requestedProtocol); /* requestedProtocol (2 bytes) */
|
||||
Stream_Write_UINT16(s, multitransport->reserved); /* reserved (2 bytes) */
|
||||
Stream_Write(s, multitransport->securityCookie,
|
||||
sizeof(multitransport->securityCookie)); /* securityCookie (16 bytes) */
|
||||
|
||||
return rdp_send_message_channel_pdu(multitransport->rdp, s, SEC_TRANSPORT_REQ);
|
||||
}
|
||||
|
||||
BOOL multitransport_client_send_response(rdpMultitransport* multitransport, HRESULT hr)
|
||||
{
|
||||
WINPR_ASSERT(multitransport);
|
||||
|
||||
wStream* s = rdp_message_channel_pdu_init(multitransport->rdp);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 28))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, multitransport->requestId); /* requestId (4 bytes) */
|
||||
Stream_Write_UINT16(s, multitransport->requestedProtocol); /* requestedProtocol (2 bytes) */
|
||||
Stream_Write_UINT16(s, multitransport->reserved); /* reserved (2 bytes) */
|
||||
Stream_Write(s, multitransport->securityCookie,
|
||||
sizeof(multitransport->securityCookie)); /* securityCookie (16 bytes) */
|
||||
Stream_Write_UINT32(s, hr);
|
||||
return rdp_send_message_channel_pdu(multitransport->rdp, s, SEC_TRANSPORT_REQ);
|
||||
}
|
||||
|
||||
BOOL multitransport_server_recv_response(rdpMultitransport* multitransport, wStream* s, HRESULT* hr)
|
||||
{
|
||||
rdpMultitransport multi = { 0 };
|
||||
|
||||
WINPR_ASSERT(multitransport);
|
||||
WINPR_ASSERT(hr);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 28))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT32(s, multi.requestId); /* requestId (4 bytes) */
|
||||
Stream_Read_UINT16(s, multi.requestedProtocol); /* requestedProtocol (2 bytes) */
|
||||
Stream_Read_UINT16(s, multi.reserved); /* reserved (2 bytes) */
|
||||
Stream_Read(s, multi.securityCookie,
|
||||
sizeof(multi.securityCookie)); /* securityCookie (16 bytes) */
|
||||
Stream_Read_UINT32(s, *hr);
|
||||
if (!multitransport_compare(multitransport, &multi))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rdpMultitransport* multitransport_new(rdpRdp* rdp, UINT16 protocol)
|
||||
{
|
||||
rdpMultitransport* multi = calloc(1, sizeof(rdpMultitransport));
|
||||
if (multi)
|
||||
{
|
||||
WINPR_ASSERT(rdp);
|
||||
multi->rdp = rdp;
|
||||
winpr_RAND(&multi->requestId, sizeof(multi->requestId));
|
||||
multi->requestedProtocol = protocol;
|
||||
winpr_RAND(&multi->securityCookie, sizeof(multi->securityCookie));
|
||||
}
|
||||
return multi;
|
||||
}
|
||||
|
||||
void multitransport_free(rdpMultitransport* multitransport)
|
||||
|
||||
@@ -29,14 +29,21 @@ typedef struct rdp_multitransport rdpMultitransport;
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
struct rdp_multitransport
|
||||
typedef enum
|
||||
{
|
||||
UINT32 placeholder;
|
||||
};
|
||||
INITIATE_REQUEST_PROTOCOL_UDPFECR = 0x01,
|
||||
INITIATE_REQUEST_PROTOCOL_UDPFECL = 0x02
|
||||
} MultitransportRequestProtocol;
|
||||
|
||||
FREERDP_LOCAL int rdp_recv_multitransport_packet(rdpRdp* rdp, wStream* s);
|
||||
FREERDP_LOCAL int multitransport_client_recv_request(rdpMultitransport* multitransport, wStream* s);
|
||||
FREERDP_LOCAL BOOL multitransport_server_send_request(rdpMultitransport* multitransport);
|
||||
|
||||
FREERDP_LOCAL rdpMultitransport* multitransport_new(void);
|
||||
FREERDP_LOCAL BOOL multitransport_server_recv_response(rdpMultitransport* multitransport,
|
||||
wStream* s, HRESULT* hr);
|
||||
FREERDP_LOCAL BOOL multitransport_client_send_response(rdpMultitransport* multitransport,
|
||||
HRESULT hr);
|
||||
|
||||
FREERDP_LOCAL rdpMultitransport* multitransport_new(rdpRdp* rdp, UINT16 protocol);
|
||||
FREERDP_LOCAL void multitransport_free(rdpMultitransport* multitransport);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_MULTITRANSPORT_H */
|
||||
|
||||
@@ -1194,11 +1194,26 @@ int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 securityFlags)
|
||||
|
||||
if (securityFlags & SEC_TRANSPORT_REQ)
|
||||
{
|
||||
HRESULT hr = E_ABORT;
|
||||
/* Initiate Multitransport Request PDU */
|
||||
return rdp_recv_multitransport_packet(rdp, s);
|
||||
// TODO: This message is server -> client only
|
||||
int rc = multitransport_client_recv_request(rdp->multitransport, s);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (!multitransport_client_send_response(rdp->multitransport, hr))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
if (securityFlags & SEC_TRANSPORT_RSP)
|
||||
{
|
||||
/* Initiate Multitransport Request PDU */
|
||||
HRESULT hr; // TODO: Do something with this result
|
||||
// TODO: This message is client -> server only
|
||||
return multitransport_server_recv_response(rdp->multitransport, s, &hr) ? 0 : -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
|
||||
@@ -1969,7 +1984,8 @@ rdpRdp* rdp_new(rdpContext* context)
|
||||
if (!rdp->heartbeat)
|
||||
goto fail;
|
||||
|
||||
rdp->multitransport = multitransport_new();
|
||||
rdp->multitransport = multitransport_new(rdp, INITIATE_REQUEST_PROTOCOL_UDPFECL |
|
||||
INITIATE_REQUEST_PROTOCOL_UDPFECR);
|
||||
|
||||
if (!rdp->multitransport)
|
||||
goto fail;
|
||||
|
||||
Reference in New Issue
Block a user