From 5feb674d441e9e54b4771b0f0c04399834fd55ca Mon Sep 17 00:00:00 2001 From: pf packet Date: Thu, 16 Oct 2014 22:44:48 +0900 Subject: [PATCH 1/5] wlfreerdp: fix compilation errors This commit fixes the following errors by removing or replacing old functions: wlfreerdp.c:(.text.startup+0xc): undefined reference to `freerdp_channels_global_init' wlfreerdp.c:(.text.startup+0x72): undefined reference to `freerdp_client_parse_command_line_arguments' wlfreerdp.c:(.text.startup+0x9b): undefined reference to `freerdp_channels_global_uninit' --- client/Wayland/wlfreerdp.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 65f8b3226..6155e9120 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -394,8 +394,6 @@ int main(int argc, char* argv[]) int status; freerdp* instance; - freerdp_channels_global_init(); - instance = freerdp_new(); instance->PreConnect = wl_pre_connect; instance->PostConnect = wl_post_connect; @@ -405,16 +403,16 @@ int main(int argc, char* argv[]) instance->ContextFree = wl_context_free; freerdp_context_new(instance); - status = freerdp_client_parse_command_line_arguments(argc, argv, instance->settings); + status = freerdp_client_settings_parse_command_line_arguments(instance->settings, argc, argv); - if (status < 0) + status = freerdp_client_settings_command_line_status_print(instance->settings, status, argc, argv); + + if (status) exit(0); freerdp_client_load_addins(instance->context->channels, instance->settings); wlfreerdp_run(instance); - freerdp_channels_global_uninit(); - return 0; } From 3d28c9dbf13e1ae9c1e6e169869a723f00000989 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 17 Oct 2014 11:43:41 +0200 Subject: [PATCH 2/5] Fixed sspi_CopyAuthIdentity, now checking source struct, if it is ANSI encoded. --- winpr/libwinpr/sspi/sspi_winpr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/sspi/sspi_winpr.c b/winpr/libwinpr/sspi/sspi_winpr.c index dcfb4e2b2..360ad8d99 100644 --- a/winpr/libwinpr/sspi/sspi_winpr.c +++ b/winpr/libwinpr/sspi/sspi_winpr.c @@ -377,7 +377,7 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN { int status; - if (identity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI) + if (srcIdentity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI) { status = sspi_SetAuthIdentity(identity, (char*) srcIdentity->User, (char*) srcIdentity->Domain, (char*) srcIdentity->Password); From 0dc0e0156836bf17f1f760e78ce8a95e43068aa4 Mon Sep 17 00:00:00 2001 From: Jean-Louis Dupond Date: Fri, 17 Oct 2014 12:08:39 +0200 Subject: [PATCH 3/5] Add ipv6 client support --- client/common/cmdline.c | 40 ++++++++++++++++++++++-------- libfreerdp/core/tcp.c | 55 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 02db02e51..f1f964070 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1200,19 +1200,39 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineSwitchCase(arg, "v") { - p = strchr(arg->Value, ':'); - - if (p) + p = strchr(arg->Value, '['); + /* ipv4 */ + if (!p) { - length = (int) (p - arg->Value); - settings->ServerPort = atoi(&p[1]); - settings->ServerHostname = (char*) malloc(length + 1); - strncpy(settings->ServerHostname, arg->Value, length); - settings->ServerHostname[length] = '\0'; + p = strchr(arg->Value, ':'); + if (p) + { + length = (int) (p - arg->Value); + settings->ServerPort = atoi(&p[1]); + settings->ServerHostname = (char*) malloc(length + 1); + strncpy(settings->ServerHostname, arg->Value, length); + settings->ServerHostname[length] = '\0'; + } + else + { + settings->ServerHostname = _strdup(arg->Value); + } } - else + else /* ipv6 */ { - settings->ServerHostname = _strdup(arg->Value); + char *p2 = strchr(arg->Value, ']'); + /* not a valid [] ipv6 addr found */ + if (!p2) + continue; + + length = p2 - p; + settings->ServerHostname = (char*) malloc(length); + strncpy(settings->ServerHostname, p+1, length-1); + if (*(p2 + 1) == ':') + { + settings->ServerPort = atoi(&p2[2]); + } + printf("hostname %s port %d\n", settings->ServerHostname, settings->ServerPort); } } CommandLineSwitchCase(arg, "spn-class") diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index faf1cecae..24e393326 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #ifdef HAVE_POLL_H #include @@ -523,6 +525,7 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) struct timeval tv; #endif +#ifdef NO_IPV6 tcp->socketBio = BIO_new(BIO_s_connect()); if (!tcp->socketBio) @@ -542,6 +545,58 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) if (tcp->sockfd < 0) return FALSE; +#else /* NO_IPV6 */ + struct addrinfo hints = {0}; + struct addrinfo *result; + struct addrinfo *tmp; + char port_str[11]; + + //ZeroMemory(&hints, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_STREAM; + /* + * FIXME: the following is a nasty workaround. Find a cleaner way: + * Either set port manually afterwards or get it passed as string? + */ + snprintf(port_str, 11, "%u", port); + + status = getaddrinfo(hostname, port_str, &hints, &result); + if (status) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + return FALSE; + } + + /* For now prefer IPv4 over IPv6. */ + tmp = result; + if (tmp->ai_family == AF_INET6 && tmp->ai_next != 0) + { + while ((tmp = tmp->ai_next)) + { + if (tmp->ai_family == AF_INET) + break; + } + if (!tmp) + tmp = result; + } + tcp->sockfd = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); + + if (tcp->sockfd < 0) { + freeaddrinfo(result); + return FALSE; + } + + if (connect(tcp->sockfd, tmp->ai_addr, tmp->ai_addrlen) < 0) { + fprintf(stderr, "connect: %s\n", strerror(errno)); + freeaddrinfo(result); + return FALSE; + } + freeaddrinfo(result); + tcp->socketBio = BIO_new_socket(tcp->sockfd, BIO_NOCLOSE); + + /* TODO: make sure the handshake is done by querying the bio */ + // if (BIO_should_retry(tcp->socketBio)) + // return FALSE; +#endif /* NO_IPV6 */ if (status <= 0) { From 4dcc0957f1fca24f6a36eed7308a8e02b49ad179 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Wed, 22 Oct 2014 12:16:40 +0200 Subject: [PATCH 4/5] Fix build on windows Problem was introduces by a non pull request push for ipv6 support --- libfreerdp/core/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index 24e393326..0ad632f7f 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -558,7 +558,7 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) * FIXME: the following is a nasty workaround. Find a cleaner way: * Either set port manually afterwards or get it passed as string? */ - snprintf(port_str, 11, "%u", port); + sprintf_s(port_str, 11, "%u", port); status = getaddrinfo(hostname, port_str, &hints, &result); if (status) { From 9c2e90df7de5d35c83b6f50e32eecd955b5462b1 Mon Sep 17 00:00:00 2001 From: Norbert Federa Date: Wed, 22 Oct 2014 11:24:36 +0200 Subject: [PATCH 5/5] core: fix pointer caps, slowpath kbd and a gcc fix * According to MS-RDPBCGR 2.2.7.1.5 the pointerCacheSize is optional and its absence or a zero value indicates missing client support for the New Pointer Update. * Added and fixed some comments regarding the meaning of the KBDFLAGS_DOWN keyboard flag and how it is currently used in the code. "Fixed" the slow path keyboard input to generate the same keyboard flags as the corresponding fast path code. * Some arbitrary value was used for the ConnectPDULength in the GCC Conference Create Response. According to MS-RDPBCGR 4.1.4 this value must be ignored by the client so we encode a zero value instead. --- libfreerdp/core/capabilities.c | 9 +++++++-- libfreerdp/core/gcc.c | 5 +++-- libfreerdp/core/input.c | 33 +++++++++++++++++++++++---------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 7f8b356e6..38c89d561 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -936,12 +936,17 @@ BOOL rdp_read_pointer_capability_set(wStream* s, UINT16 length, rdpSettings* set UINT16 colorPointerCacheSize; UINT16 pointerCacheSize; - if (length < 10) + if (length < 8) return FALSE; Stream_Read_UINT16(s, colorPointerFlag); /* colorPointerFlag (2 bytes) */ Stream_Read_UINT16(s, colorPointerCacheSize); /* colorPointerCacheSize (2 bytes) */ - Stream_Read_UINT16(s, pointerCacheSize); /* pointerCacheSize (2 bytes) */ + + /* pointerCacheSize is optional */ + if (length >= 10) + Stream_Read_UINT16(s, pointerCacheSize); /* pointerCacheSize (2 bytes) */ + else + pointerCacheSize = 0; if (colorPointerFlag == FALSE) settings->ColorPointerFlag = FALSE; diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 94b3524ec..855da29c2 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -291,8 +291,9 @@ void gcc_write_conference_create_response(wStream* s, wStream* userData) per_write_choice(s, 0); per_write_object_identifier(s, t124_02_98_oid); - /* ConnectData::connectPDU (OCTET_STRING) */ - per_write_length(s, Stream_GetPosition(userData) + 2); + /* ConnectPDULength */ + /* This length MUST be ignored by the client according to [MS-RDPBCGR] */ + per_write_length(s, 0); /* ConnectGCCPDU */ per_write_choice(s, 0x14); diff --git a/libfreerdp/core/input.c b/libfreerdp/core/input.c index 631dceb0e..594a65866 100644 --- a/libfreerdp/core/input.c +++ b/libfreerdp/core/input.c @@ -333,6 +333,25 @@ static BOOL input_recv_keyboard_event(rdpInput* input, wStream* s) Stream_Read_UINT16(s, keyCode); /* keyCode (2 bytes) */ Stream_Seek(s, 2); /* pad2Octets (2 bytes) */ + /** + * Note: A lot of code in FreeRDP and in dependent projects checks the + * KBDFLAGS_DOWN flag in order to detect a key press. + * According to the specs only the absence of the slow-path + * KBDFLAGS_RELEASE flag indicates a key-down event. + * The slow-path KBDFLAGS_DOWN flag merely indicates that the key was + * down prior to this event. + * The checks for KBDFLAGS_DOWN only work successfully because the code + * handling the fast-path keyboard input sets the KBDFLAGS_DOWN flag if + * the FASTPATH_INPUT_KBDFLAGS_RELEASE flag is missing. + * Since the same input callback is used for slow- and fast-path events + * we have to follow that "convention" here. + */ + + if (keyboardFlags & KBD_FLAGS_RELEASE) + keyboardFlags &= ~KBD_FLAGS_DOWN; + else + keyboardFlags |= KBD_FLAGS_DOWN; + IFCALL(input->KeyboardEvent, input, keyboardFlags, keyCode); return TRUE; @@ -349,17 +368,11 @@ static BOOL input_recv_unicode_keyboard_event(rdpInput* input, wStream* s) Stream_Read_UINT16(s, unicodeCode); /* unicodeCode (2 bytes) */ Stream_Seek(s, 2); /* pad2Octets (2 bytes) */ - /* - * According to the specification, the slow path Unicode Keyboard Event - * (TS_UNICODE_KEYBOARD_EVENT) contains KBD_FLAGS_RELEASE flag when key - * is released, but contains no flags when it is pressed. - * This is different from the slow path Keyboard Event - * (TS_KEYBOARD_EVENT) which does contain KBD_FLAGS_DOWN flag when the - * key is pressed. - * Set the KBD_FLAGS_DOWN flag if the KBD_FLAGS_RELEASE flag is missing. - */ + /* "fix" keyboardFlags - see comment in input_recv_keyboard_event() */ - if ((keyboardFlags & KBD_FLAGS_RELEASE) == 0) + if (keyboardFlags & KBD_FLAGS_RELEASE) + keyboardFlags &= ~KBD_FLAGS_DOWN; + else keyboardFlags |= KBD_FLAGS_DOWN; IFCALL(input->UnicodeKeyboardEvent, input, keyboardFlags, unicodeCode);