Commit fd142319 for guacamole.apache.org

commit fd14231909bee35250da58bb0802d236da76a00e
Author: jd52ru <jd52ru@gmail.com>
Date:   Sat Oct 24 15:56:50 2026 +0300

    GUACAMOLE-2323: Prevent RDP reconnect loop on user-initiated disconnect

diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c
index 4044a647..1af17619 100644
--- a/src/protocols/rdp/rdp.c
+++ b/src/protocols/rdp/rdp.c
@@ -958,6 +958,15 @@ static int guac_rdp_handle_connection(guac_client* client) {

     guac_rwlock_acquire_write_lock(&(rdp_client->lock));

+    /* GUACAMOLE-2323: Save the error code before cleanup, as the RDP context
+     * will be freed before the check below. FreeRDP 2 and 3 use different
+     * APIs and different numerical values for the same protocol error codes. */
+#if FREERDP_VERSION_MAJOR >= 3
+    UINT32 __guac_error_code = freerdp_get_last_error(rdp_inst->context);
+#else
+    unsigned int __guac_error_code = freerdp_error_info(rdp_inst);
+#endif
+
     /* Clean up print job, if active */
     if (rdp_client->active_job != NULL) {
         guac_rdp_print_job_kill(rdp_client->active_job);
@@ -1007,6 +1016,27 @@ static int guac_rdp_handle_connection(guac_client* client) {
     /* Client is now disconnected */
     guac_client_log(client, GUAC_LOG_INFO, "Internal RDP client disconnected");

+    /* GUACAMOLE-2323: A disconnect initiated by the user (logoff, admin
+     * disconnect, idle/logon timeout, or another connection taking over)
+     * must not trigger the reconnect loop. Stop the client explicitly.
+     * Note: FreeRDP 2 and 3 report these codes differently. */
+#if FREERDP_VERSION_MAJOR >= 3
+    if (__guac_error_code == FREERDP_ERROR_LOGOFF_BY_USER ||
+        __guac_error_code == FREERDP_ERROR_RPC_INITIATED_DISCONNECT ||
+        __guac_error_code == FREERDP_ERROR_RPC_INITIATED_LOGOFF ||
+        __guac_error_code == FREERDP_ERROR_DISCONNECTED_BY_OTHER_CONNECTION) {
+        guac_client_stop(client);
+    }
+#else
+    /* FreeRDP 2: raw ERRINFO_* codes from freerdp_error_info() */
+    if (__guac_error_code == ERRINFO_LOGOFF_BY_USER ||
+        __guac_error_code == ERRINFO_RPC_INITIATED_DISCONNECT ||
+        __guac_error_code == ERRINFO_RPC_INITIATED_LOGOFF ||
+        __guac_error_code == ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION) {
+        guac_client_stop(client);
+    }
+#endif
+
     return 0;

 fail: