From 1a2dc6f3d94180e3a4265adc23193531478448ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 17 Jul 2011 23:16:31 -0400 Subject: [PATCH] libfreerdp-core: refactoring of licensing code, refactoring of connection sequence --- .gitignore | 2 +- CMakeLists.txt | 3 +- {freerdp-ui => client}/CMakeLists.txt | 2 +- {freerdp-ui => client}/test/CMakeLists.txt | 0 client/test/freerdp.c | 208 +++++++++++++++++++++ freerdp-ui/test/freerdp.c | 60 ------ include/freerdp/constants.h | 22 --- include/freerdp/settings.h | 2 +- libfreerdp-core/connection.c | 24 ++- libfreerdp-core/connection.h | 2 +- libfreerdp-core/license.c | 27 +++ libfreerdp-core/license.h | 2 + libfreerdp-core/nego.c | 6 +- libfreerdp-core/nego.h | 20 +- libfreerdp-core/tls.c | 16 +- 15 files changed, 294 insertions(+), 102 deletions(-) rename {freerdp-ui => client}/CMakeLists.txt (96%) rename {freerdp-ui => client}/test/CMakeLists.txt (100%) create mode 100644 client/test/freerdp.c delete mode 100644 freerdp-ui/test/freerdp.c diff --git a/.gitignore b/.gitignore index d78aa8e44..c70648dc3 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ docs/api *.so.* *.dylib cunit/test_freerdp -freerdp-ui/test/freerdp-test +client/test/freerdp-test diff --git a/CMakeLists.txt b/CMakeLists.txt index ff17832f4..484bb175a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,4 +88,5 @@ add_subdirectory(libfreerdp-gdi) add_subdirectory(libfreerdp-chanman) add_subdirectory(libfreerdp-core) add_subdirectory(channels) -add_subdirectory(freerdp-ui) + +add_subdirectory(client) diff --git a/freerdp-ui/CMakeLists.txt b/client/CMakeLists.txt similarity index 96% rename from freerdp-ui/CMakeLists.txt rename to client/CMakeLists.txt index e2fd4ca31..f699877f0 100644 --- a/freerdp-ui/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,5 +1,5 @@ # FreeRDP: A Remote Desktop Protocol Client -# FreeRDP User Interfaces +# FreeRDP Client User Interfaces # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador diff --git a/freerdp-ui/test/CMakeLists.txt b/client/test/CMakeLists.txt similarity index 100% rename from freerdp-ui/test/CMakeLists.txt rename to client/test/CMakeLists.txt diff --git a/client/test/freerdp.c b/client/test/freerdp.c new file mode 100644 index 000000000..7dd6a5def --- /dev/null +++ b/client/test/freerdp.c @@ -0,0 +1,208 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * FreeRDP Test UI + * + * Copyright 2010 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "connection.h" + +#include +#include + +#define PARAM_EQUALS(_param) (strcmp(_param, argv[*i]) == 0) + +#define CHECK_VALUE_PRESENT(_msg) do { \ + *i = *i + 1; \ + if (*i == argc) \ + { printf(_msg "\n"); return False; } \ + } while(0) + +#define STRING_COPY(_str) do { \ + settings->_str = (uint8*) xmalloc(strlen(argv[*i])); \ + memcpy(settings->_str, argv[*i], strlen(argv[*i])); \ + settings->_str[strlen(argv[*i])] = '\0'; \ + } while(0) + +boolean freerdp_process_params(int argc, char* argv[], rdpSettings* settings, int* i) +{ + char* p; + + if (argc < *i + 1) + { + if (*i == 1) + printf("no parameters specified.\n"); + + return False; + } + + while (*i < argc) + { + if (PARAM_EQUALS("-a")) + { + CHECK_VALUE_PRESENT("missing server depth"); + settings->color_depth = atoi(argv[*i]); + } + else if (strcmp("-u", argv[*i]) == 0) + { + CHECK_VALUE_PRESENT("missing username"); + STRING_COPY(username); + } + else if (PARAM_EQUALS("-p")) + { + CHECK_VALUE_PRESENT("missing password"); + STRING_COPY(password); + } + else if (PARAM_EQUALS("-d")) + { + CHECK_VALUE_PRESENT("missing domain"); + STRING_COPY(domain); + } + else if (PARAM_EQUALS("-g")) + { + CHECK_VALUE_PRESENT("missing screen dimensions"); + + settings->width = strtol(argv[*i], &p, 10); + + if (*p == 'x') + settings->height = strtol(p + 1, &p, 10); + + if ((settings->width < 16) || (settings->height < 16) || + (settings->width > 4096) || (settings->height > 4096)) + { + printf("invalid screen dimensions\n"); + return False; + } + } + else if (PARAM_EQUALS("-n")) + { + CHECK_VALUE_PRESENT("missing hostname"); + STRING_COPY(hostname); + } + else if (PARAM_EQUALS("-o")) + { + settings->console_audio = True; + } + else if (PARAM_EQUALS("-0")) + { + settings->console_session = True; + } + else if (PARAM_EQUALS("-z")) + { + settings->compression = True; + } + else if (PARAM_EQUALS("--sec")) + { + CHECK_VALUE_PRESENT("missing protocol security"); + + if (PARAM_EQUALS("rdp")) /* Standard RDP */ + { + settings->rdp_security = 1; + settings->tls_security = 0; + settings->nla_security = 0; + } + else if (PARAM_EQUALS("tls")) /* TLS */ + { + settings->rdp_security = 0; + settings->tls_security = 1; + settings->nla_security = 0; + } + else if (PARAM_EQUALS("nla")) /* NLA */ + { + settings->rdp_security = 0; + settings->tls_security = 0; + settings->nla_security = 1; + } + else + { + printf("unknown protocol security\n"); + return False; + } + } + else if (PARAM_EQUALS("-h") || PARAM_EQUALS("--help")) + { + printf("help\n"); + return False; + } + else if (argv[*i][0] != '-') + { + if (argv[*i][0] == '[' && (p = strchr(argv[*i], ']')) + && (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':')))) + { + /* Either "[...]" or "[...]:..." with at most one : after the brackets */ + settings->hostname = (uint8*) xmalloc(strlen(argv[*i] + 1)); + strncpy(settings->hostname, argv[*i] + 1, strlen(argv[*i] + 1)); + + if ((p = strchr(settings->hostname, ']'))) + { + *p = 0; + if (p[1] == ':') + settings->port = (uint16) atoi(p + 2); + } + } + else + { + /* Port number is cut off and used if exactly one : in the string */ + settings->hostname = (uint8*) xmalloc(strlen(argv[*i])); + strncpy(settings->hostname, argv[*i], strlen(argv[*i])); + + if ((p = strchr(settings->hostname, ':')) && !strchr(p + 1, ':')) + { + *p = 0; + settings->port = (uint16) atoi(p + 1); + } + } + + /* + * server hostname is the last argument for the current session. + * arguments followed will be parsed for the next session. + */ + + *i = *i + 1; + + return True; + } + + *i = *i + 1; + } + + return True; +} + +int main(int argc, char* argv[]) +{ + rdpRdp* rdp; + int index = 1; + rdpSettings* settings; + + rdp = rdp_new(); + settings = rdp->settings; + + if (freerdp_process_params(argc, argv, settings, &index) != True) + { + printf("failed to process parameters.\n"); + return 0; + } + + printf("hostname:%s username:%s password:%s\n", + settings->hostname, settings->username, settings->password); + + rdp_client_connect(rdp); + + return 0; +} diff --git a/freerdp-ui/test/freerdp.c b/freerdp-ui/test/freerdp.c deleted file mode 100644 index a342fe319..000000000 --- a/freerdp-ui/test/freerdp.c +++ /dev/null @@ -1,60 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Client - * FreeRDP Test UI - * - * Copyright 2010 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "connection.h" - -#include -#include - -int main(int argc, char* argv[]) -{ - rdpRdp* rdp; - rdpSettings* settings; - - rdp = rdp_new(); - settings = rdp->settings; - - if (argc < 4) - { - printf("Usage: freerdp-test \n"); - return 0; - } - - settings->hostname = (uint8*) xmalloc(strlen(argv[1])); - memcpy(settings->hostname, argv[1], strlen(argv[1])); - settings->hostname[strlen(argv[1])] = '\0'; - - settings->username = (uint8*) xmalloc(strlen(argv[2])); - memcpy(settings->username, argv[2], strlen(argv[2])); - settings->username[strlen(argv[2])] = '\0'; - - settings->password = (uint8*) xmalloc(strlen(argv[3])); - memcpy(settings->password, argv[3], strlen(argv[3])); - settings->password[strlen(argv[3])] = '\0'; - - printf("hostname: %s username: %s password: %s\n", - settings->hostname, settings->username, settings->password); - - rdp_client_connect(rdp); - - return 0; -} diff --git a/include/freerdp/constants.h b/include/freerdp/constants.h index c970dc0a7..8fa5f5592 100644 --- a/include/freerdp/constants.h +++ b/include/freerdp/constants.h @@ -20,28 +20,6 @@ #ifndef __FREERDP_CONSTANTS #define __FREERDP_CONSTANTS -/** - * Protocol Security Negotiation Protocols - */ -enum RDP_NEG_PROTOCOLS -{ - PROTOCOL_RDP = 0x00000000, - PROTOCOL_TLS = 0x00000001, - PROTOCOL_NLA = 0x00000002 -}; - -/** - * Protocol Security Negotiation Failure Codes - */ -enum RDP_NEG_FAILURE_FAILURECODES -{ - SSL_REQUIRED_BY_SERVER = 0x00000001, - SSL_NOT_ALLOWED_BY_SERVER = 0x00000002, - SSL_CERT_NOT_ON_SERVER = 0x00000003, - INCONSISTENT_FLAGS = 0x00000004, - HYBRID_REQUIRED_BY_SERVER = 0x00000005 -}; - /** * Static Virtual Channel Flags */ diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 70f4fe932..77730eb26 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -118,6 +118,7 @@ struct rdp_settings BLOB server_random; BLOB server_certificate; + boolean console_audio; boolean console_session; uint32 redirected_session_id; @@ -164,7 +165,6 @@ struct rdp_settings int bitmap_compression; int desktop_save; int polygon_ellipse_orders; - int console_audio; int off_screen_bitmaps; int triblt; int new_cursors; diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 89a9edc11..db2ae1ec8 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -55,7 +55,7 @@ * @param rdp RDP module */ -void rdp_client_connect(rdpRdp* rdp) +boolean rdp_client_connect(rdpRdp* rdp) { rdp->settings->autologon = 1; @@ -63,18 +63,26 @@ void rdp_client_connect(rdpRdp* rdp) nego_set_target(rdp->nego, rdp->settings->hostname, 3389); nego_set_cookie(rdp->nego, rdp->settings->username); nego_set_protocols(rdp->nego, 1, 1, 1); - nego_connect(rdp->nego); - transport_connect_nla(rdp->transport); + if (nego_connect(rdp->nego) == False) + { + printf("Error: protocol security negotiation failure\n"); + return False; + } + + if (rdp->nego->selected_protocol & PROTOCOL_NLA) + transport_connect_nla(rdp->transport); + else if (rdp->nego->selected_protocol & PROTOCOL_TLS) + transport_connect_tls(rdp->transport); + else if (rdp->nego->selected_protocol & PROTOCOL_RDP) + transport_connect_rdp(rdp->transport); mcs_connect(rdp->mcs); rdp_send_client_info(rdp); - rdp_recv(rdp); - rdp_recv(rdp); - rdp_recv(rdp); - rdp_recv(rdp); - rdp_recv(rdp); + license_connect(rdp->license); + + return True; } diff --git a/libfreerdp-core/connection.h b/libfreerdp-core/connection.h index 5e97720bd..073f64fd4 100644 --- a/libfreerdp-core/connection.h +++ b/libfreerdp-core/connection.h @@ -30,6 +30,6 @@ #include #include -void rdp_client_connect(rdpRdp* rdp); +boolean rdp_client_connect(rdpRdp* rdp); #endif /* __CONNECTION_H */ diff --git a/libfreerdp-core/license.c b/libfreerdp-core/license.c index 3149918a8..fb2edf104 100644 --- a/libfreerdp-core/license.c +++ b/libfreerdp-core/license.c @@ -45,6 +45,33 @@ uint8 state_transitions[][32] = "ST_RESEND_LAST_MESSAGE" }; +/** + * Perform licensing phase of connection sequence.\n + * @param license license module + * @return + */ + +boolean license_connect(rdpLicense* license) +{ + while (1) + { + rdp_recv(license->rdp); + + if (license->state == LICENSE_STATE_COMPLETED) + { + printf("license connection sequence completed.\n"); + return True; + } + else if (license->state == LICENSE_STATE_ABORTED) + { + printf("license connection sequence aborted.\n"); + return False; + } + } + + return False; +} + /** * Read a licensing preamble.\n * @msdn{cc240480} diff --git a/libfreerdp-core/license.h b/libfreerdp-core/license.h index 51c71e6fa..16d164db5 100644 --- a/libfreerdp-core/license.h +++ b/libfreerdp-core/license.h @@ -156,6 +156,8 @@ struct rdp_license SCOPE_LIST* scope_list; }; +boolean license_connect(rdpLicense* license); + void license_send(rdpLicense* license, STREAM* s, uint8 type); void license_recv(rdpLicense* license, STREAM* s); STREAM* license_send_stream_init(rdpLicense* license); diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c index 1321a4b6f..a16b354a2 100644 --- a/libfreerdp-core/nego.c +++ b/libfreerdp-core/nego.c @@ -50,7 +50,7 @@ char PROTOCOL_SECURITY_STRINGS[3][4] = * @return */ -int nego_connect(rdpNego* nego) +boolean nego_connect(rdpNego* nego) { if (nego->state == NEGO_STATE_INITIAL) { @@ -74,7 +74,7 @@ int nego_connect(rdpNego* nego) { DEBUG_NEGO("Protocol Security Negotiation Failure"); nego->state = NEGO_STATE_FINAL; - return 0; + return False; } } while (nego->state != NEGO_STATE_FINAL); @@ -84,7 +84,7 @@ int nego_connect(rdpNego* nego) /* update settings with negotiated protocol security */ nego->transport->settings->selected_protocol = nego->selected_protocol; - return 1; + return True; } /** diff --git a/libfreerdp-core/nego.h b/libfreerdp-core/nego.h index d45bd2f1d..9eb6a7532 100644 --- a/libfreerdp-core/nego.h +++ b/libfreerdp-core/nego.h @@ -26,6 +26,24 @@ #include #include +/* Protocol Security Negotiation Protocols */ +enum RDP_NEG_PROTOCOLS +{ + PROTOCOL_RDP = 0x00000000, + PROTOCOL_TLS = 0x00000001, + PROTOCOL_NLA = 0x00000002 +}; + +/* Protocol Security Negotiation Failure Codes */ +enum RDP_NEG_FAILURE_FAILURECODES +{ + SSL_REQUIRED_BY_SERVER = 0x00000001, + SSL_NOT_ALLOWED_BY_SERVER = 0x00000002, + SSL_CERT_NOT_ON_SERVER = 0x00000003, + INCONSISTENT_FLAGS = 0x00000004, + HYBRID_REQUIRED_BY_SERVER = 0x00000005 +}; + enum _NEGO_STATE { NEGO_STATE_INITIAL, @@ -65,7 +83,7 @@ struct rdp_nego }; typedef struct rdp_nego rdpNego; -int nego_connect(rdpNego* nego); +boolean nego_connect(rdpNego* nego); void nego_attempt_nla(rdpNego* nego); void nego_attempt_tls(rdpNego* nego); diff --git a/libfreerdp-core/tls.c b/libfreerdp-core/tls.c index 324b6be7b..bda2da4fc 100644 --- a/libfreerdp-core/tls.c +++ b/libfreerdp-core/tls.c @@ -40,12 +40,22 @@ boolean tls_connect(rdpTls* tls) return False; } - do + while (1) { - /* SSL_WANT_READ errors are normal, just try again if it happens */ connection_status = SSL_connect(tls->ssl); + + /* + * SSL_WANT_READ and SSL_WANT_WRITE errors are normal, + * just try again if it happens + */ + + if (connection_status == SSL_ERROR_WANT_READ) + continue; + else if (connection_status == SSL_ERROR_WANT_WRITE) + continue; + else + break; } - while (SSL_get_error(tls->ssl, connection_status) == SSL_ERROR_WANT_READ); if (connection_status < 0) {