diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 436ce4fe4..cfabb078c 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -21,6 +21,7 @@ #include +#include #include #include "rdp.h" @@ -715,6 +716,8 @@ BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings) WINPR_ASSERT(instance); + rdp_log_build_warnings(); + instance->context = context = (rdpContext*)calloc(1, instance->ContextSize); if (!context) diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 7e373a0ec..bdbe720d9 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -1504,6 +1504,8 @@ BOOL freerdp_peer_context_new_ex(freerdp_peer* client, const rdpSettings* settin rdpContext* context; BOOL ret = TRUE; + rdp_log_build_warnings(); + if (!client) return FALSE; diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 7dc929f0a..f02be272d 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -36,6 +36,7 @@ #include #include #include +#include #define TAG FREERDP_TAG("core.rdp") @@ -2559,3 +2560,167 @@ BOOL rdp_reset_runtime_settings(rdpRdp* rdp) return FALSE; return rdp_reset_remote_settings(rdp); } + +static BOOL starts_with(const char* tok, const char* val) +{ + const size_t len = strlen(val); + if (strncmp(tok, val, len) != 0) + return FALSE; + if (tok[len] != '=') + return FALSE; + return TRUE; +} + +static BOOL option_equals(const char* what, const char* val) +{ + return _stricmp(what, val) == 0; +} + +static BOOL parse_on_off_option(const char* value) +{ + WINPR_ASSERT(value); + const char* sep = strchr(value, '='); + if (!sep) + return TRUE; + if (option_equals("on", &sep[1])) + return TRUE; + if (option_equals("true", &sep[1])) + return TRUE; + if (option_equals("off", &sep[1])) + return FALSE; + if (option_equals("false", &sep[1])) + return FALSE; + + errno = 0; + long val = strtol(value, NULL, 0); + if (errno == 0) + return val == 0 ? FALSE : TRUE; + + return FALSE; +} + +#define STR(x) #x + +static BOOL option_is_experimental(const char* tok) +{ + const char* experimental[] = { STR(WITH_DSP_EXPERIMENTAL), STR(WITH_VAAPI) }; + for (size_t x = 0; x < ARRAYSIZE(experimental); x++) + { + const char* opt = experimental[x]; + if (starts_with(tok, opt)) + { + return parse_on_off_option(tok); + } + } + return FALSE; +} + +static BOOL option_is_debug(const char* tok) +{ + const char* debug[] = { STR(WITH_DEBUG_ALL), + STR(WITH_DEBUG_CERTIFICATE), + STR(WITH_DEBUG_CAPABILITIES), + STR(WITH_DEBUG_CHANNELS), + STR(WITH_DEBUG_CLIPRDR), + STR(WITH_DEBUG_CODECS), + STR(WITH_DEBUG_RDPGFX), + STR(WITH_DEBUG_DVC), + STR(WITH_DEBUG_TSMF), + STR(WITH_DEBUG_KBD), + STR(WITH_DEBUG_LICENSE), + STR(WITH_DEBUG_NEGO), + STR(WITH_DEBUG_NLA), + STR(WITH_DEBUG_TSG), + STR(WITH_DEBUG_RAIL), + STR(WITH_DEBUG_RDP), + STR(WITH_DEBUG_RDPEI), + STR(WITH_DEBUG_REDIR), + STR(WITH_DEBUG_RDPDR), + STR(WITH_DEBUG_RFX), + STR(WITH_DEBUG_SCARD), + STR(WITH_DEBUG_SND), + STR(WITH_DEBUG_SVC), + STR(WITH_DEBUG_TRANSPORT), + STR(WITH_DEBUG_TIMEZONE), + STR(WITH_DEBUG_WND), + STR(WITH_DEBUG_X11_CLIPRDR), + STR(WITH_DEBUG_X11_LOCAL_MOVESIZE), + STR(WITH_DEBUG_X11), + STR(WITH_DEBUG_XV), + STR(WITH_DEBUG_RINGBUFFER), + STR(WITH_DEBUG_SYMBOLS), + STR(WITH_DEBUG_EVENTS), + STR(WITH_DEBUG_MUTEX), + STR(WITH_DEBUG_NTLM), + STR(WITH_DEBUG_SDL_EVENTS), + STR(WITH_DEBUG_SDL_KBD_EVENTS), + STR(WITH_DEBUG_THREADS), + STR(WITH_DEBUG_URBDRC) }; + + for (size_t x = 0; x < ARRAYSIZE(debug); x++) + { + const char* opt = debug[x]; + if (starts_with(tok, opt)) + return parse_on_off_option(tok); + } + + if (starts_with(tok, "WITH_DEBUG")) + { + WLog_WARN(TAG, "[BUG] Unmapped Debug-Build option '%s'.", tok); + return parse_on_off_option(tok); + } + + return FALSE; +} + +static void log_build_warn(const char* what, const char* msg, BOOL (*cmp)(const char* tok)) +{ + size_t len = sizeof(FREERDP_BUILD_CONFIG); + char* list = calloc(len, sizeof(char)); + char* config = _strdup(FREERDP_BUILD_CONFIG); + if (config && list) + { + char* tok = strtok(config, " "); + while (tok) + { + if (cmp(tok)) + winpr_str_append(tok, list, len, " "); + + tok = strtok(NULL, " "); + } + } + free(config); + + if (list) + { + if (strlen(list) > 0) + { + WLog_WARN(TAG, "*************************************************"); + WLog_WARN(TAG, "This build is using [%s] build options:", what); + char* tok = strtok(list, " "); + while (tok) + { + WLog_WARN(TAG, "* '%s'", tok); + tok = strtok(NULL, " "); + } + WLog_WARN(TAG, ""); + WLog_WARN(TAG, "[%s] build options %s", what, msg); + WLog_WARN(TAG, "*************************************************"); + } + } + free(list); +} + +void rdp_log_build_warnings(void) +{ + static unsigned count = 0; + + /* Since this function is called in context creation routines stop logging + * this issue repetedly. This is required for proxy, which would otherwise + * spam the log with these. */ + if (count > 0) + return; + count++; + log_build_warn("experimental", "might crash the application", option_is_experimental); + log_build_warn("debug", "might leak sensitive information (credentials, ...)", option_is_debug); +} diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index 6389c8e84..5ade733f1 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -289,4 +289,6 @@ const char* rdp_security_flag_string(UINT32 securityFlags, char* buffer, size_t BOOL rdp_set_backup_settings(rdpRdp* rdp); BOOL rdp_reset_runtime_settings(rdpRdp* rdp); +void rdp_log_build_warnings(void); + #endif /* FREERDP_LIB_CORE_RDP_H */