Refactored multitransport

* Implemented server and client multitransport message parsing
This commit is contained in:
Armin Novak
2022-10-10 11:53:15 +02:00
committed by akallabeth
parent 72f7382f2f
commit b4dbdac68b
3 changed files with 165 additions and 22 deletions

View File

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

View File

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

View File

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