[channel,rdpdr] use server general caps

* read server CAP_GENERAL_TYPE
* check if messages are allowed according to caps
This commit is contained in:
Armin Novak 2023-11-03 08:58:59 +01:00 committed by Martin Fleisz
parent 694d95a58b
commit 43fc6bbfdc
3 changed files with 116 additions and 11 deletions

View File

@ -43,28 +43,58 @@ static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s)
WINPR_UNUSED(rdpdr);
const RDPDR_CAPABILITY_HEADER header = { CAP_GENERAL_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH + 36,
GENERAL_CAPABILITY_VERSION_02 };
const UINT32 ioCode1 = rdpdr->clientIOCode1 & rdpdr->serverIOCode1;
const UINT32 ioCode2 = rdpdr->clientIOCode2 & rdpdr->serverIOCode2;
rdpdr_write_capset_header(rdpdr->log, s, &header);
Stream_Write_UINT32(s, 0); /* osType, ignored on receipt */
Stream_Write_UINT32(s, 0); /* osVersion, unused and must be set to zero */
Stream_Write_UINT32(s, rdpdr->clientOsType); /* osType, ignored on receipt */
Stream_Write_UINT32(s, rdpdr->clientOsVersion); /* osVersion, unused and must be set to zero */
Stream_Write_UINT16(s, rdpdr->clientVersionMajor); /* protocolMajorVersion, must be set to 1 */
Stream_Write_UINT16(s, rdpdr->clientVersionMinor); /* protocolMinorVersion */
Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */
Stream_Write_UINT32(s, 0); /* ioCode2, must be set to zero, reserved for future use */
Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU |
RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */
Stream_Write_UINT32(s, 0); /* extraFlags2, must be set to zero, reserved for future use */
Stream_Write_UINT32(s, ioCode1); /* ioCode1 */
Stream_Write_UINT32(s, ioCode2); /* ioCode2, must be set to zero, reserved for future use */
Stream_Write_UINT32(s, rdpdr->clientExtendedPDU); /* extendedPDU */
Stream_Write_UINT32(s, rdpdr->clientExtraFlags1); /* extraFlags1 */
Stream_Write_UINT32(
s, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
s,
rdpdr->clientExtraFlags2); /* extraFlags2, must be set to zero, reserved for future use */
Stream_Write_UINT32(
s, rdpdr->clientSpecialTypeDeviceCap); /* SpecialTypeDeviceCap, number of special devices to
be redirected before logon */
}
/* Process device direction general capability set */
static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s,
const RDPDR_CAPABILITY_HEADER* header)
{
WINPR_ASSERT(header);
Stream_Seek(s, header->CapabilityLength);
if (header->CapabilityLength != 36)
{
WLog_Print(rdpdr->log, WLOG_ERROR,
"CAP_GENERAL_TYPE::CapabilityLength expected 36, got %" PRIu32,
header->CapabilityLength);
return ERROR_INVALID_DATA;
}
if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 36))
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, rdpdr->serverOsType); /* osType, ignored on receipt */
Stream_Read_UINT32(s, rdpdr->serverOsVersion); /* osVersion, unused and must be set to zero */
Stream_Read_UINT16(s, rdpdr->serverVersionMajor); /* protocolMajorVersion, must be set to 1 */
Stream_Read_UINT16(s, rdpdr->serverVersionMinor); /* protocolMinorVersion */
Stream_Read_UINT32(s, rdpdr->serverIOCode1); /* ioCode1 */
Stream_Read_UINT32(
s, rdpdr->serverIOCode2); /* ioCode2, must be set to zero, reserved for future use */
Stream_Read_UINT32(s, rdpdr->serverExtendedPDU); /* extendedPDU */
Stream_Read_UINT32(s, rdpdr->serverExtraFlags1); /* extraFlags1 */
Stream_Read_UINT32(
s,
rdpdr->serverExtraFlags2); /* extraFlags2, must be set to zero, reserved for future use */
Stream_Read_UINT32(
s, rdpdr->serverSpecialTypeDeviceCap); /* SpecialTypeDeviceCap, number of special devices to
be redirected before logon */
return CHANNEL_RC_OK;
}

View File

@ -102,6 +102,7 @@ static const char* rdpdr_state_str(enum RDPDR_CHANNEL_STATE state)
return "RDPDR_CHANNEL_STATE_UNKNOWN";
}
}
static const char* rdpdr_device_type_string(UINT32 type)
{
switch (type)
@ -121,6 +122,44 @@ static const char* rdpdr_device_type_string(UINT32 type)
}
}
static const char* support_str(BOOL val)
{
if (val)
return "supported";
return "not found";
}
static const char* rdpdr_caps_pdu_str(UINT32 flag)
{
switch (flag)
{
case RDPDR_DEVICE_REMOVE_PDUS:
return "RDPDR_USER_LOGGEDON_PDU";
case RDPDR_CLIENT_DISPLAY_NAME_PDU:
return "RDPDR_CLIENT_DISPLAY_NAME_PDU";
case RDPDR_USER_LOGGEDON_PDU:
return "RDPDR_USER_LOGGEDON_PDU";
default:
return "RDPDR_UNKNONW";
}
}
static BOOL rdpdr_check_extended_pdu_flag(rdpdrPlugin* rdpdr, UINT32 flag)
{
WINPR_ASSERT(rdpdr);
const BOOL client = (rdpdr->clientExtendedPDU & flag) != 0;
const BOOL server = (rdpdr->serverExtendedPDU & flag) != 0;
if (!client || !server)
{
WLog_Print(rdpdr->log, WLOG_WARN, "Checking ExtendedPDU::%s, client %s, server %s",
rdpdr_caps_pdu_str(flag), support_str(client), support_str(server));
return FALSE;
}
return TRUE;
}
BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next)
{
WINPR_ASSERT(rdpdr);
@ -201,6 +240,9 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou
if (count == 0)
return CHANNEL_RC_OK;
if (!rdpdr_check_extended_pdu_flag(rdpdr, RDPDR_DEVICE_REMOVE_PDUS))
return CHANNEL_RC_OK;
s = StreamPool_Take(rdpdr->pool, count * sizeof(UINT32) + 8);
if (!s)
@ -1629,6 +1671,9 @@ static BOOL rdpdr_check_channel_state(rdpdrPlugin* rdpdr, UINT16 packetid)
return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, 1,
RDPDR_CHANNEL_STATE_CLIENT_CAPS);
case PAKID_CORE_USER_LOGGEDON:
if (!rdpdr_check_extended_pdu_flag(rdpdr, RDPDR_USER_LOGGEDON_PDU))
return FALSE;
return rdpdr_state_check(
rdpdr, packetid, RDPDR_CHANNEL_STATE_USER_LOGGEDON, 4,
RDPDR_CHANNEL_STATE_NAME_REQUEST, RDPDR_CHANNEL_STATE_CLIENT_CAPS,
@ -2209,6 +2254,18 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS p
}
rdpdr->log = WLog_Get(TAG);
rdpdr->clientExtendedPDU =
RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU;
rdpdr->clientIOCode1 =
RDPDR_IRP_MJ_CREATE | RDPDR_IRP_MJ_CLEANUP | RDPDR_IRP_MJ_CLOSE | RDPDR_IRP_MJ_READ |
RDPDR_IRP_MJ_WRITE | RDPDR_IRP_MJ_FLUSH_BUFFERS | RDPDR_IRP_MJ_SHUTDOWN |
RDPDR_IRP_MJ_DEVICE_CONTROL | RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION |
RDPDR_IRP_MJ_SET_VOLUME_INFORMATION | RDPDR_IRP_MJ_QUERY_INFORMATION |
RDPDR_IRP_MJ_SET_INFORMATION | RDPDR_IRP_MJ_DIRECTORY_CONTROL | RDPDR_IRP_MJ_LOCK_CONTROL |
RDPDR_IRP_MJ_QUERY_SECURITY | RDPDR_IRP_MJ_SET_SECURITY;
rdpdr->clientExtraFlags1 = ENABLE_ASYNCIO;
rdpdr->pool = StreamPool_New(TRUE, 1024);
if (!rdpdr->pool)
{

View File

@ -70,10 +70,28 @@ typedef struct
DEVMAN* devman;
BOOL ignoreInvalidDevices;
UINT32 serverOsType;
UINT32 serverOsVersion;
UINT16 serverVersionMajor;
UINT16 serverVersionMinor;
UINT32 serverExtendedPDU;
UINT32 serverIOCode1;
UINT32 serverIOCode2;
UINT32 serverExtraFlags1;
UINT32 serverExtraFlags2;
UINT32 serverSpecialTypeDeviceCap;
UINT32 clientOsType;
UINT32 clientOsVersion;
UINT16 clientVersionMajor;
UINT16 clientVersionMinor;
UINT32 clientExtendedPDU;
UINT32 clientIOCode1;
UINT32 clientIOCode2;
UINT32 clientExtraFlags1;
UINT32 clientExtraFlags2;
UINT32 clientSpecialTypeDeviceCap;
UINT32 clientID;
char computerName[256];