[channels,rdpdr] relax state checks for PAKID_CORE_CLIENTID_CONFIRM

This missage might be sent before PAKID_CORE_SERVER_CAPABILITY by some
servers. Do accept these.
This commit is contained in:
akallabeth
2025-03-27 13:26:44 +01:00
parent 0ed1548974
commit 7939a44ce5
3 changed files with 45 additions and 13 deletions

View File

@@ -189,7 +189,6 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s)
if (!rdpdr || !s) if (!rdpdr || !s)
return CHANNEL_RC_NULL_DATA; return CHANNEL_RC_NULL_DATA;
WINPR_ASSERT(rdpdr->state == RDPDR_CHANNEL_STATE_SERVER_CAPS);
rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_CLIENT_CAPS); rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_CLIENT_CAPS);
if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4)) if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))

View File

@@ -1681,7 +1681,9 @@ static BOOL rdpdr_check_channel_state(rdpdrPlugin* rdpdr, UINT16 packetid)
RDPDR_CHANNEL_STATE_READY, RDPDR_CHANNEL_STATE_CLIENT_CAPS, RDPDR_CHANNEL_STATE_READY, RDPDR_CHANNEL_STATE_CLIENT_CAPS,
RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, RDPDR_CHANNEL_STATE_USER_LOGGEDON); RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, RDPDR_CHANNEL_STATE_USER_LOGGEDON);
case PAKID_CORE_CLIENTID_CONFIRM: case PAKID_CORE_CLIENTID_CONFIRM:
return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, 3, return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, 5,
RDPDR_CHANNEL_STATE_NAME_REQUEST,
RDPDR_CHANNEL_STATE_SERVER_CAPS,
RDPDR_CHANNEL_STATE_CLIENT_CAPS, RDPDR_CHANNEL_STATE_READY, RDPDR_CHANNEL_STATE_CLIENT_CAPS, RDPDR_CHANNEL_STATE_READY,
RDPDR_CHANNEL_STATE_USER_LOGGEDON); RDPDR_CHANNEL_STATE_USER_LOGGEDON);
case PAKID_CORE_USER_LOGGEDON: case PAKID_CORE_USER_LOGGEDON:
@@ -1700,6 +1702,24 @@ static BOOL rdpdr_check_channel_state(rdpdrPlugin* rdpdr, UINT16 packetid)
} }
} }
static BOOL tryAdvance(rdpdrPlugin* rdpdr)
{
if (rdpdr->haveClientId && rdpdr->haveServerCaps)
{
const UINT error = rdpdr_send_device_list_announce_request(rdpdr, FALSE);
if (error)
{
WLog_Print(rdpdr->log, WLOG_ERROR,
"rdpdr_send_device_list_announce_request failed with error %" PRIu32 "",
error);
return FALSE;
}
if (!rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_READY))
return FALSE;
}
return TRUE;
}
/** /**
* Function description * Function description
* *
@@ -1730,6 +1750,8 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
switch (packetId) switch (packetId)
{ {
case PAKID_CORE_SERVER_ANNOUNCE: case PAKID_CORE_SERVER_ANNOUNCE:
rdpdr->haveClientId = FALSE;
rdpdr->haveServerCaps = FALSE;
if ((error = rdpdr_process_server_announce_request(rdpdr, s))) if ((error = rdpdr_process_server_announce_request(rdpdr, s)))
{ {
} }
@@ -1763,6 +1785,12 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
"rdpdr_send_capability_response failed with error %" PRIu32 "", "rdpdr_send_capability_response failed with error %" PRIu32 "",
error); error);
} }
else
{
rdpdr->haveServerCaps = TRUE;
if (!tryAdvance(rdpdr))
error = ERROR_INTERNAL_ERROR;
}
break; break;
@@ -1770,28 +1798,31 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s))) if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s)))
{ {
} }
else if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) else
{ {
WLog_Print( rdpdr->haveClientId = TRUE;
rdpdr->log, WLOG_ERROR, if (!tryAdvance(rdpdr))
"rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", error = ERROR_INTERNAL_ERROR;
error);
}
else if (!rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_READY))
{
error = ERROR_INTERNAL_ERROR;
} }
break; break;
case PAKID_CORE_USER_LOGGEDON: case PAKID_CORE_USER_LOGGEDON:
if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) if (!rdpdr->haveServerCaps)
{
WLog_Print(rdpdr->log, WLOG_ERROR,
"Wrong state %s for %s. [serverCaps=%d, clientId=%d]",
rdpdr_state_str(rdpdr->state), rdpdr_packetid_string(packetId),
rdpdr->haveServerCaps, rdpdr->haveClientId);
error = ERROR_INTERNAL_ERROR;
}
else if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE)))
{ {
WLog_Print( WLog_Print(
rdpdr->log, WLOG_ERROR, rdpdr->log, WLOG_ERROR,
"rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "",
error); error);
} }
else if (!rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_READY)) else if (!tryAdvance(rdpdr))
{ {
error = ERROR_INTERNAL_ERROR; error = ERROR_INTERNAL_ERROR;
} }

View File

@@ -111,6 +111,8 @@ typedef struct
wLog* log; wLog* log;
BOOL async; BOOL async;
BOOL capabilities[6]; BOOL capabilities[6];
BOOL haveClientId;
BOOL haveServerCaps;
} rdpdrPlugin; } rdpdrPlugin;
BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next); BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next);