From 7939a44ce5b597ac675d33e35c1c3ba5e20003b8 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 27 Mar 2025 13:26:44 +0100 Subject: [PATCH] [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. --- channels/rdpdr/client/rdpdr_capabilities.c | 1 - channels/rdpdr/client/rdpdr_main.c | 55 +++++++++++++++++----- channels/rdpdr/client/rdpdr_main.h | 2 + 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_capabilities.c b/channels/rdpdr/client/rdpdr_capabilities.c index 7d807b5fa..64a847b5a 100644 --- a/channels/rdpdr/client/rdpdr_capabilities.c +++ b/channels/rdpdr/client/rdpdr_capabilities.c @@ -189,7 +189,6 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) if (!rdpdr || !s) return CHANNEL_RC_NULL_DATA; - WINPR_ASSERT(rdpdr->state == RDPDR_CHANNEL_STATE_SERVER_CAPS); rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_CLIENT_CAPS); if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4)) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 4522e3724..6c7647783 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -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_CLIENTID_CONFIRM, RDPDR_CHANNEL_STATE_USER_LOGGEDON); 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_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 * @@ -1730,6 +1750,8 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) switch (packetId) { case PAKID_CORE_SERVER_ANNOUNCE: + rdpdr->haveClientId = FALSE; + rdpdr->haveServerCaps = FALSE; 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 "", error); } + else + { + rdpdr->haveServerCaps = TRUE; + if (!tryAdvance(rdpdr)) + error = ERROR_INTERNAL_ERROR; + } break; @@ -1770,28 +1798,31 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* 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->log, WLOG_ERROR, - "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", - error); - } - else if (!rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_READY)) - { - error = ERROR_INTERNAL_ERROR; + rdpdr->haveClientId = TRUE; + if (!tryAdvance(rdpdr)) + error = ERROR_INTERNAL_ERROR; } break; 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( rdpdr->log, WLOG_ERROR, "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", error); } - else if (!rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_READY)) + else if (!tryAdvance(rdpdr)) { error = ERROR_INTERNAL_ERROR; } diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index b0fa1c9f3..f69dc81df 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -111,6 +111,8 @@ typedef struct wLog* log; BOOL async; BOOL capabilities[6]; + BOOL haveClientId; + BOOL haveServerCaps; } rdpdrPlugin; BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next);