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; } 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/capabilities.c b/libfreerdp/core/capabilities.c index 85c6b8b5d..11336c8c3 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 625180a8e..ab17fe6be 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -292,6 +292,7 @@ void gcc_write_conference_create_response(wStream* s, wStream* userData) per_write_object_identifier(s, t124_02_98_oid); /* ConnectData::connectPDU (OCTET_STRING) */ + /* This length MUST be ignored by the client according to [MS-RDPBCGR] */ per_write_length(s, 0x2A); /* ConnectGCCPDU */ 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); diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index faf1cecae..0ad632f7f 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? + */ + sprintf_s(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) { 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);