From fa3cf9417ffb67a3433ecb48d18a1c2b3190a03e Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 7 Mar 2022 13:47:43 +0100 Subject: [PATCH] Fixed #7696: Abort freerdp_connect if manually canceled (#7700) If freerdp_abort_connect is called, set FREERDP_ERROR_CONNECT_CANCELLED This way freerdp_reconnect can distinguish between network issues and user interaction and abort a retry attempt. --- libfreerdp/core/connection.c | 8 ++++++-- libfreerdp/core/freerdp.c | 16 +++++++++++----- libfreerdp/core/gateway/rpc_client.c | 3 ++- libfreerdp/core/rdp.c | 7 ++++--- libfreerdp/core/tcp.c | 8 -------- libfreerdp/core/utils.c | 13 +++++++++++++ libfreerdp/core/utils.h | 4 ++++ libfreerdp/crypto/tls.c | 2 +- 8 files changed, 41 insertions(+), 20 deletions(-) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index a9953217c..088578595 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -37,6 +37,8 @@ #include #include +#include "utils.h" + #define TAG FREERDP_TAG("core.connection") /** @@ -434,10 +436,12 @@ BOOL rdp_client_disconnect_and_clear(rdpRdp* rdp) context = rdp->context; WINPR_ASSERT(context); + if (freerdp_get_last_error(context) == FREERDP_ERROR_CONNECT_CANCELLED) + return FALSE; + context->LastError = FREERDP_ERROR_SUCCESS; clearChannelError(context); - ResetEvent(context->abortEvent); - return TRUE; + return utils_reset_abort(context); } static BOOL rdp_client_reconnect_channels(rdpRdp* rdp, BOOL redirect) diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 315d4606f..2b2c62934 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -53,6 +53,7 @@ #include #include "settings.h" +#include "utils.h" #define TAG FREERDP_TAG("core") @@ -84,7 +85,8 @@ BOOL freerdp_connect(freerdp* instance) instance->ConnectionCallbackState = CLIENT_STATE_INITIAL; freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS); clearChannelError(instance->context); - ResetEvent(instance->context->abortEvent); + if (!utils_reset_abort(instance->context)) + return FALSE; rdp = instance->context->rdp; WINPR_ASSERT(rdp); @@ -239,7 +241,8 @@ BOOL freerdp_abort_connect(freerdp* instance) if (!instance || !instance->context) return FALSE; - return SetEvent(instance->context->abortEvent); + freerdp_set_last_error_if_not(instance->context, FREERDP_ERROR_CONNECT_CANCELLED); + return utils_abort_connect(instance->context); } #if defined(WITH_FREERDP_DEPRECATED) @@ -480,7 +483,7 @@ BOOL freerdp_disconnect(freerdp* instance) if (!instance || !instance->context) return FALSE; - freerdp_abort_connect(instance); + utils_abort_connect(instance->context); rdp = instance->context->rdp; if (!rdp_client_disconnect(rdp)) @@ -528,10 +531,13 @@ BOOL freerdp_reconnect(freerdp* instance) WINPR_ASSERT(instance); WINPR_ASSERT(instance->context); + if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED) + return FALSE; + rdp = instance->context->rdp; - WINPR_ASSERT(instance->context->abortEvent); - ResetEvent(instance->context->abortEvent); + if (!utils_reset_abort(instance->context)) + return FALSE; return rdp_client_reconnect(rdp); } diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 2aa786e9f..66f55f177 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -36,6 +36,7 @@ #include "rpc_client.h" #include "rts_signature.h" +#include "../utils.h" #include "../rdp.h" #include "../proxy.h" @@ -360,7 +361,7 @@ static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment) Stream_SetPosition(fragment, StubOffset); Stream_Read_UINT32(fragment, rpc->result); - freerdp_abort_connect(context->instance); + utils_abort_connect(context); tsg_set_state(tsg, TSG_STATE_TUNNEL_CLOSE_PENDING); EventArgsInit(&e, "freerdp"); e.code = 0; diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 24b73cd57..dc2491841 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -25,6 +25,7 @@ #include "rdp.h" #include "info.h" +#include "utils.h" #include "redirection.h" #include @@ -360,7 +361,7 @@ BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo) WLog_ERR(TAG, "%s missing context=%p", __FUNCTION__, context); /* Ensure the connection is terminated */ - freerdp_abort_connect(context->instance); + utils_abort_connect(context); } else { @@ -420,7 +421,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) { if (code == X224_TPDU_DISCONNECT_REQUEST) { - freerdp_abort_connect(rdp->instance); + utils_abort_connect(rdp->instance->context); return TRUE; } @@ -477,7 +478,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) } WLog_DBG(TAG, "DisconnectProviderUltimatum: reason: %d", reason); - freerdp_abort_connect(rdp->instance); + utils_abort_connect(context); EventArgsInit(&e, "freerdp"); e.code = 0; PubSub_OnTerminate(context->pubSub, context, &e); diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index d33560642..011a8efae 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -838,12 +838,7 @@ static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, struct status = WaitForMultipleObjects(count, handles, FALSE, tout); if (WAIT_OBJECT_0 != status) - { - if (status == WAIT_OBJECT_0 + 1) - freerdp_set_last_error_log(context, FREERDP_ERROR_CONNECT_CANCELLED); - goto fail; - } status = recv(sockfd, NULL, 0, 0); @@ -1240,9 +1235,6 @@ int freerdp_tcp_default_connect(rdpContext* context, rdpSettings* settings, cons if (WaitForSingleObject(context->abortEvent, 0) == WAIT_OBJECT_0) { close(sockfd); - - freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED); - return -1; } diff --git a/libfreerdp/core/utils.c b/libfreerdp/core/utils.c index 453a6de06..8f552192a 100644 --- a/libfreerdp/core/utils.c +++ b/libfreerdp/core/utils.c @@ -161,3 +161,16 @@ BOOL utils_str_is_empty(const char* str) return TRUE; return FALSE; } + +BOOL utils_abort_connect(rdpContext* context) +{ + WINPR_ASSERT(context); + + return SetEvent(context->abortEvent); +} + +BOOL utils_reset_abort(rdpContext* context) +{ + WINPR_ASSERT(context); + return ResetEvent(context->abortEvent); +} diff --git a/libfreerdp/core/utils.h b/libfreerdp/core/utils.h index 0397f72b5..3892d74a3 100644 --- a/libfreerdp/core/utils.h +++ b/libfreerdp/core/utils.h @@ -31,8 +31,12 @@ typedef enum AUTH_NO_CREDENTIALS, AUTH_FAILED } auth_status; + auth_status utils_authenticate_gateway(freerdp* instance, rdp_auth_reason reason); auth_status utils_authenticate(freerdp* instance, rdp_auth_reason reason, BOOL override); + +BOOL utils_reset_abort(rdpContext* context); +BOOL utils_abort_connect(rdpContext* context); BOOL utils_sync_credentials(rdpSettings* settings, BOOL toGateway); BOOL utils_str_is_empty(const char* str); diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index c34d654b0..cecb3872f 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -863,7 +863,7 @@ int tls_connect(rdpTls* tls, BIO* underlying) #else if (!tls_prepare(tls, underlying, TLS_client_method(), options, TRUE)) #endif - return FALSE; + return 0; #if !defined(OPENSSL_NO_TLSEXT) && !defined(LIBRESSL_VERSION_NUMBER) SSL_set_tlsext_host_name(tls->ssl, tls->hostname);