From a0ff7ce581c41beaab499ebb53cc8f1e2ceb81aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 10 Jul 2011 12:10:24 -0400 Subject: [PATCH] libfreerdp-core: sending of client info packet --- freerdp-ui/test/freerdp.c | 45 ++---- include/freerdp/settings.h | 76 ++++++++-- libfreerdp-core/connection.c | 283 ++++++++++++++++++++++++++++++++++- libfreerdp-core/connection.h | 54 ++++++- libfreerdp-core/mcs.c | 32 +++- libfreerdp-core/mcs.h | 1 + libfreerdp-core/settings.c | 5 + libfreerdp-core/tcp.c | 28 +++- libfreerdp-core/tcp.h | 5 +- libfreerdp-core/transport.c | 2 +- libfreerdp-utils/unicode.c | 22 ++- 11 files changed, 492 insertions(+), 61 deletions(-) diff --git a/freerdp-ui/test/freerdp.c b/freerdp-ui/test/freerdp.c index 9fa73a15c..c0d8ffcdf 100644 --- a/freerdp-ui/test/freerdp.c +++ b/freerdp-ui/test/freerdp.c @@ -25,27 +25,13 @@ #include #include -rdpMcs* mcs; -rdpNego* nego; -rdpSettings* settings; -rdpTransport* transport; -rdpConnection* connection; - int main(int argc, char* argv[]) { - int i; - char* username; - char* hostname; - char* password; - uint16 channelId; + rdpSettings* settings; + rdpConnection* connection; settings = settings_new(); - transport = transport_new(settings); - nego = nego_new(transport); - connection = connection_new(); - connection->nego = nego; - connection->settings = settings; - connection->transport = transport; + connection = connection_new(settings); if (argc < 4) { @@ -53,25 +39,20 @@ int main(int argc, char* argv[]) return 0; } - hostname = (char*) xmalloc(strlen(argv[1])); - memcpy(hostname, argv[1], strlen(argv[1])); - hostname[strlen(argv[1])] = '\0'; + settings->hostname = (uint8*) xmalloc(strlen(argv[1])); + memcpy(settings->hostname, argv[1], strlen(argv[1])); + settings->hostname[strlen(argv[1])] = '\0'; - username = (char*) xmalloc(strlen(argv[2])); - memcpy(username, argv[2], strlen(argv[2])); - username[strlen(argv[2])] = '\0'; + settings->username = (uint8*) xmalloc(strlen(argv[2])); + memcpy(settings->username, argv[2], strlen(argv[2])); + settings->username[strlen(argv[2])] = '\0'; - password = (char*) xmalloc(strlen(argv[3])); - memcpy(password, argv[3], strlen(argv[3])); - password[strlen(argv[3])] = '\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", - hostname, username, password); - - settings->hostname = hostname; - settings->username = username; - settings->password = password; - settings->domain = NULL; + settings->hostname, settings->username, settings->password); connection_client_connect(connection); diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index f5b2d7812..70f4fe932 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -41,6 +41,43 @@ #define ENCRYPTION_56BIT_FLAG 0x00000008 #define ENCRYPTION_FIPS_FLAG 0x00000010 +/* Auto Reconnect Version */ +#define AUTO_RECONNECT_VERSION_1 0x00000001 + +/* SYSTEM_TIME */ +typedef struct +{ + uint16 wYear; + uint16 wMonth; + uint16 wDayOfWeek; + uint16 wDay; + uint16 wHour; + uint16 wMinute; + uint16 wSecond; + uint16 wMilliseconds; +} SYSTEM_TIME; + +/* TIME_ZONE_INFORMATION */ +typedef struct +{ + uint32 bias; + uint8 standardName[32]; + SYSTEM_TIME standardDate; + uint32 standardBias; + uint8 daylightName[32]; + SYSTEM_TIME daylightDate; + uint32 daylightBias; +} TIME_ZONE_INFORMATION; + +/* ARC_CS_PRIVATE_PACKET */ +typedef struct +{ + uint32 cbLen; + uint32 version; + uint32 logonId; + uint8 securityVerifier[16]; +} ARC_CS_PRIVATE_PACKET; + struct rdp_chan { char name[8]; /* ui sets */ @@ -81,7 +118,7 @@ struct rdp_settings BLOB server_random; BLOB server_certificate; - int console_session; + boolean console_session; uint32 redirected_session_id; int num_channels; @@ -90,24 +127,34 @@ struct rdp_settings int num_monitors; struct rdp_monitor monitors[16]; + struct rdp_ext_set extensions[16]; + UNICONV* uniconv; char client_hostname[32]; char client_product_id[32]; - char* hostname; - char* username; - char* password; - char* domain; + uint16 port; + uint8* hostname; + uint8* username; + uint8* password; + uint8* domain; + uint8* shell; + uint8* directory; + uint32 performance_flags; - char shell[256]; - char directory[256]; - int performance_flags; - int tcp_port_rdp; + boolean autologon; + boolean compression; - int encryption; - int tls_security; - int nla_security; - int rdp_security; + boolean ipv6; + uint8* ip_address; + uint8* client_dir; + TIME_ZONE_INFORMATION client_time_zone; + ARC_CS_PRIVATE_PACKET auto_reconnect_cookie; + + boolean encryption; + boolean tls_security; + boolean nla_security; + boolean rdp_security; int remote_app; char app_name[64]; @@ -117,18 +164,15 @@ struct rdp_settings int bitmap_compression; int desktop_save; int polygon_ellipse_orders; - int autologin; int console_audio; int off_screen_bitmaps; int triblt; int new_cursors; int mouse_motion; - int bulk_compression; int rfx_flags; int ui_decode_flags; int use_frame_ack; int software_gdi; - struct rdp_ext_set extensions[16]; }; typedef struct rdp_settings rdpSettings; diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index d7297a41b..35176a245 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -42,6 +42,9 @@ void connection_client_connect(rdpConnection* connection) int i; uint16 channelId; + connection->transport = transport_new(connection->settings); + connection->nego = nego_new(connection->transport); + nego_init(connection->nego); nego_set_target(connection->nego, connection->settings->hostname, 3389); nego_set_cookie(connection->nego, connection->settings->username); @@ -69,15 +72,291 @@ void connection_client_connect(rdpConnection* connection) mcs_recv_channel_join_confirm(connection->mcs); } + connection_send_client_info(connection); + mcs_recv(connection->mcs); } +void connection_write_system_time(STREAM* s, SYSTEM_TIME* system_time) +{ + stream_write_uint16(s, system_time->wYear); /* wYear, must be set to 0 */ + stream_write_uint16(s, system_time->wMonth); /* wMonth */ + stream_write_uint16(s, system_time->wDayOfWeek); /* wDayOfWeek */ + stream_write_uint16(s, system_time->wDay); /* wDay */ + stream_write_uint16(s, system_time->wHour); /* wHour */ + stream_write_uint16(s, system_time->wMinute); /* wMinute */ + stream_write_uint16(s, system_time->wSecond); /* wSecond */ + stream_write_uint16(s, system_time->wMilliseconds); /* wMilliseconds */ +} + +void connection_get_client_time_zone(STREAM* s, rdpSettings* settings) +{ + time_t t; + struct tm* local_time; + TIME_ZONE_INFORMATION* clientTimeZone; + + time(&t); + local_time = localtime(&t); + clientTimeZone = &settings->client_time_zone; + +#if defined(sun) + if(local_time->tm_isdst > 0) + clientTimeZone->bias = (uint32) (altzone / 3600); + else + clientTimeZone->bias = (uint32) (timezone / 3600); +#elif defined(HAVE_TM_GMTOFF) + if(local_time->tm_gmtoff >= 0) + clientTimeZone->bias = (uint32) (local_time->tm_gmtoff / 60); + else + clientTimeZone->bias = (uint32) ((-1 * local_time->tm_gmtoff) / 60 + 720); +#else + clientTimeZone->bias = 0; +#endif + + if(local_time->tm_isdst > 0) + { + clientTimeZone->standardBias = clientTimeZone->bias - 60; + clientTimeZone->daylightBias = clientTimeZone->bias; + } + else + { + clientTimeZone->standardBias = clientTimeZone->bias; + clientTimeZone->daylightBias = clientTimeZone->bias + 60; + } + + strftime(clientTimeZone->standardName, 32, "%Z, Standard Time", local_time); + clientTimeZone->standardName[31] = 0; + strftime(clientTimeZone->daylightName, 32, "%Z, Summer Time", local_time); + clientTimeZone->daylightName[31] = 0; +} + +void connection_write_client_time_zone(STREAM* s, rdpSettings* settings) +{ + size_t length; + uint8* standardName; + uint8* daylightName; + size_t standardNameLength; + size_t daylightNameLength; + TIME_ZONE_INFORMATION* clientTimeZone; + + connection_get_client_time_zone(s, settings); + clientTimeZone = &settings->client_time_zone; + + standardName = freerdp_uniconv_out(settings->uniconv, clientTimeZone->standardName, &length); + standardNameLength = length; + + daylightName = freerdp_uniconv_out(settings->uniconv, clientTimeZone->daylightName, &length); + daylightNameLength = length; + + if (standardNameLength > 62) + standardNameLength = 62; + + if (daylightNameLength > 62) + daylightNameLength = 62; + + stream_write_uint32(s, clientTimeZone->bias); /* Bias */ + + /* standardName (64 bytes) */ + stream_write(s, standardName, standardNameLength); + stream_write_zero(s, 64 - standardNameLength); + + connection_write_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ + stream_write_uint32(s, clientTimeZone->standardBias); /* StandardBias */ + + /* daylightName (64 bytes) */ + stream_write(s, daylightName, daylightNameLength); + stream_write_zero(s, 64 - daylightNameLength); + + connection_write_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ + stream_write_uint32(s, clientTimeZone->daylightBias); /* DaylightBias */ + + xfree(standardName); + xfree(daylightName); +} + +void connection_write_auto_reconnect_cookie(STREAM* s, rdpSettings* settings) +{ + ARC_CS_PRIVATE_PACKET* autoReconnectCookie; + autoReconnectCookie = &settings->auto_reconnect_cookie; + + stream_write_uint32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */ + stream_write_uint32(s, autoReconnectCookie->version); /* version (4 bytes) */ + stream_write_uint32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ + stream_write(s, autoReconnectCookie->securityVerifier, 16); /* SecurityVerifier */ +} + +void connection_write_extended_info_packet(STREAM* s, rdpSettings* settings) +{ + size_t length; + uint16 clientAddressFamily; + uint8* clientAddress; + uint16 cbClientAddress; + uint8* clientDir; + uint16 cbClientDir; + uint16 cbAutoReconnectLen; + + clientAddressFamily = settings->ipv6 ? ADDRESS_FAMILY_INET6 : ADDRESS_FAMILY_INET; + + clientAddress = freerdp_uniconv_out(settings->uniconv, settings->ip_address, &length); + cbClientAddress = length; + + clientDir = freerdp_uniconv_out(settings->uniconv, settings->client_dir, &length); + cbClientDir = length; + + cbAutoReconnectLen = settings->auto_reconnect_cookie.cbLen; + + stream_write_uint16(s, clientAddressFamily); /* clientAddressFamily */ + + stream_write_uint16(s, cbClientAddress + 2); /* cbClientAddress */ + + if (cbClientAddress > 0) + stream_write(s, clientAddress, cbClientAddress); /* clientAddress */ + stream_write_uint16(s, 0); + + stream_write_uint16(s, cbClientDir + 2); /* cbClientDir */ + + if (cbClientDir > 0) + stream_write(s, clientDir, cbClientDir); /* clientDir */ + stream_write_uint16(s, 0); + + connection_write_client_time_zone(s, settings); /* clientTimeZone */ + + stream_write_uint32(s, 0); /* clientSessionId, should be set to 0 */ + stream_write_uint32(s, settings->performance_flags); /* performanceFlags */ + + stream_write_uint16(s, cbAutoReconnectLen); /* cbAutoReconnectLen */ + + if (cbAutoReconnectLen > 0) + connection_write_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */ + + /* reserved1 (2 bytes) */ + /* reserved2 (2 bytes) */ + + xfree(clientAddress); + xfree(clientDir); +} + +void connection_write_info_packet(STREAM* s, rdpSettings* settings) +{ + size_t length; + uint32 flags; + uint8* domain; + uint16 cbDomain; + uint8* userName; + uint16 cbUserName; + uint8* password; + uint16 cbPassword; + uint8* alternateShell; + uint16 cbAlternateShell; + uint8* workingDir; + uint16 cbWorkingDir; + + flags = INFO_UNICODE | + INFO_LOGONERRORS | + INFO_LOGONNOTIFY | + INFO_ENABLEWINDOWSKEY | + RNS_INFO_AUDIOCAPTURE; + + if (settings->autologon) + flags |= INFO_AUTOLOGON; + + if (settings->compression) + flags |= INFO_COMPRESSION | PACKET_COMPR_TYPE_64K; + + domain = freerdp_uniconv_out(settings->uniconv, settings->domain, &length); + cbDomain = length; + + userName = freerdp_uniconv_out(settings->uniconv, settings->username, &length); + cbUserName = length; + + password = freerdp_uniconv_out(settings->uniconv, settings->password, &length); + cbPassword = length; + + alternateShell = freerdp_uniconv_out(settings->uniconv, settings->shell, &length); + cbAlternateShell = length; + + workingDir = freerdp_uniconv_out(settings->uniconv, settings->directory, &length); + cbWorkingDir = length; + + stream_write_uint32(s, 0); /* CodePage */ + stream_write_uint32(s, flags); /* flags */ + + stream_write_uint16(s, cbDomain); /* cbDomain */ + stream_write_uint16(s, cbUserName); /* cbUserName */ + stream_write_uint16(s, cbPassword); /* cbPassword */ + stream_write_uint16(s, cbAlternateShell); /* cbAlternateShell */ + stream_write_uint16(s, cbWorkingDir); /* cbWorkingDir */ + + if (cbDomain > 0) + stream_write(s, domain, cbDomain); + stream_write_uint16(s, 0); + + if (cbUserName > 0) + stream_write(s, userName, cbUserName); + stream_write_uint16(s, 0); + + if (cbPassword > 0) + stream_write(s, password, cbPassword); + stream_write_uint16(s, 0); + + if (cbAlternateShell > 0) + stream_write(s, alternateShell, cbAlternateShell); + stream_write_uint16(s, 0); + + if (cbWorkingDir > 0) + stream_write(s, workingDir, cbWorkingDir); + stream_write_uint16(s, 0); + + xfree(domain); + xfree(userName); + xfree(password); + xfree(alternateShell); + xfree(workingDir); + + if (settings->rdp_version >= 5) + connection_write_extended_info_packet(s, settings); /* extraInfo */ +} + +void connection_send_client_info(rdpConnection* connection) +{ + STREAM* s; + int length; + s = stream_new(1024); + + uint8 *bm, *em; + + stream_get_mark(s, bm); + stream_seek(s, 15); + + /* security header */ + stream_write_uint16(s, SEC_INFO_PKT); /* flags */ + stream_write_uint16(s, 0); /* flagsHi */ + + connection_write_info_packet(s, connection->settings); + + stream_get_mark(s, em); + length = (em - bm); + stream_set_mark(s, bm); + + tpkt_write_header(s, length); + tpdu_write_data(s); + per_write_choice(s, DomainMCSPDU_SendDataRequest << 2); + per_write_integer16(s, connection->mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator */ + per_write_integer16(s, MCS_GLOBAL_CHANNEL_ID, 0); /* channelId */ + stream_write_uint8(s, 0x70); /* dataPriority + segmentation */ + per_write_length(s, length - 15); /* userData (OCTET_STRING) */ + + stream_set_mark(s, em); + + tls_write(connection->transport->tls, s->data, stream_get_length(s)); +} + /** * Instantiate new connection module. * @return new connection module */ -rdpConnection* connection_new() +rdpConnection* connection_new(rdpSettings* settings) { rdpConnection* connection; @@ -85,7 +364,7 @@ rdpConnection* connection_new() if (connection != NULL) { - + connection->settings = settings; } return connection; diff --git a/libfreerdp-core/connection.h b/libfreerdp-core/connection.h index ae40ec82f..ac021273c 100644 --- a/libfreerdp-core/connection.h +++ b/libfreerdp-core/connection.h @@ -21,6 +21,7 @@ #define __CONNECTION_H #include "tpkt.h" +#include "tpdu.h" #include "nego.h" #include "mcs.h" #include "transport.h" @@ -28,6 +29,48 @@ #include #include +/* Client Address Family */ +#define ADDRESS_FAMILY_INET 0x0002 +#define ADDRESS_FAMILY_INET6 0x0017 + +/* Client Info Packet Flags */ +#define INFO_MOUSE 0x00000001 +#define INFO_DISABLECTRLALTDEL 0x00000002 +#define INFO_AUTOLOGON 0x00000008 +#define INFO_UNICODE 0x00000010 +#define INFO_MAXIMIZESHELL 0x00000020 +#define INFO_LOGONNOTIFY 0x00000040 +#define INFO_COMPRESSION 0x00000080 +#define INFO_ENABLEWINDOWSKEY 0x00000100 +#define INFO_REMOTECONSOLEAUDIO 0x00002000 +#define INFO_FORCE_ENCRYPTED_CS_PDU 0x00004000 +#define INFO_RAIL 0x00008000 +#define INFO_LOGONERRORS 0x00010000 +#define INFO_MOUSE_HAS_WHEEL 0x00020000 +#define INFO_PASSWORD_IS_SC_PIN 0x00040000 +#define INFO_NOAUDIOPLAYBACK 0x00080000 +#define INFO_USING_SAVED_CREDS 0x00100000 +#define RNS_INFO_AUDIOCAPTURE 0x00200000 +#define RNS_INFO_VIDEO_DISABLE 0x00400000 +#define CompressionTypeMask 0x00001E00 +#define PACKET_COMPR_TYPE_8K 0x00000100 +#define PACKET_COMPR_TYPE_64K 0x00000200 +#define PACKET_COMPR_TYPE_RDP6 0x00000300 +#define PACKET_COMPR_TYPE_RDP61 0x00000400 + +/* Security Header Flags */ +#define SEC_EXCHANGE_PKT 0x0001 +#define SEC_ENCRYPT 0x0008 +#define SEC_RESET_SEQNO 0x0010 +#define SEC_IGNORE_SEQNO 0x0020 +#define SEC_INFO_PKT 0x0040 +#define SEC_LICENSE_PKT 0x0080 +#define SEC_LICENSE_ENCRYPT_CS 0x0200 +#define SEC_LICENSE_ENCRYPT_SC 0x0200 +#define SEC_REDIRECTION_PKT 0x0400 +#define SEC_SECURE_CHECKSUM 0x0800 +#define SEC_FLAGSHI_VALID 0x8000 + struct rdp_connection { struct rdp_mcs* mcs; @@ -38,8 +81,17 @@ struct rdp_connection typedef struct rdp_connection rdpConnection; void connection_client_connect(rdpConnection* connection); +void connection_send_client_info(rdpConnection* connection); -rdpConnection* connection_new(); +void connection_write_system_time(STREAM* s, SYSTEM_TIME* system_time); +void connection_get_client_time_zone(STREAM* s, rdpSettings* settings); +void connection_write_client_time_zone(STREAM* s, rdpSettings* settings); + +void connection_write_info_packet(STREAM* s, rdpSettings* settings); +void connection_write_extended_info_packet(STREAM* s, rdpSettings* settings); +void connection_write_auto_reconnect_cookie(STREAM* s, rdpSettings* settings); + +rdpConnection* connection_new(rdpSettings* settings); void connection_free(rdpConnection* connection); #endif /* __CONNECTION_H */ diff --git a/libfreerdp-core/mcs.c b/libfreerdp-core/mcs.c index 3bdff7b80..06e69303c 100644 --- a/libfreerdp-core/mcs.c +++ b/libfreerdp-core/mcs.c @@ -110,6 +110,30 @@ * channelId ChannelId OPTIONAL * } * + * SendDataRequest ::= [APPLICATION 25] IMPLICIT SEQUENCE + * { + * initiator UserId, + * channelId ChannelId, + * dataPriority DataPriority, + * segmentation Segmentation, + * userData OCTET_STRING + * } + * + * DataPriority ::= CHOICE + * { + * top NULL, + * high NULL, + * medium NULL, + * low NULL, + * ... + * } + * + * Segmentation ::= BIT_STRING + * { + * begin (0), + * end (1) + * } (SIZE(2)) + * */ uint8 callingDomainSelector[1] = "\x01"; @@ -289,7 +313,7 @@ void mcs_send_connect_initial(rdpMcs* mcs) stream_set_mark(s, bm); tpkt_write_header(s, length); - tpdu_write_data(s, length - 5); + tpdu_write_data(s); stream_set_mark(s, em); tls_write(mcs->transport->tls, s->data, stream_get_length(s)); @@ -326,7 +350,7 @@ void mcs_send_erect_domain_request(rdpMcs* mcs) s = stream_new(length); tpkt_write_header(s, length); - tpdu_write_data(s, length - 5); + tpdu_write_data(s); /* DomainMCSPDU, ErectDomainRequest */ per_write_choice(s, DomainMCSPDU_ErectDomainRequest << 2); @@ -343,7 +367,7 @@ void mcs_send_attach_user_request(rdpMcs* mcs) s = stream_new(length); tpkt_write_header(s, length); - tpdu_write_data(s, length - 5); + tpdu_write_data(s); /* DomainMCSPDU, AttachUserRequest */ per_write_choice(s, DomainMCSPDU_AttachUserRequest << 2); @@ -376,7 +400,7 @@ void mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id) s = stream_new(length); tpkt_write_header(s, length); - tpdu_write_data(s, length - 5); + tpdu_write_data(s); /* DomainMCSPDU, ChannelJoinRequest*/ per_write_choice(s, DomainMCSPDU_ChannelJoinRequest << 2); diff --git a/libfreerdp-core/mcs.h b/libfreerdp-core/mcs.h index 2df758c82..46fd6f57f 100644 --- a/libfreerdp-core/mcs.h +++ b/libfreerdp-core/mcs.h @@ -27,6 +27,7 @@ #include #define MCS_BASE_CHANNEL_ID 1001 +#define MCS_GLOBAL_CHANNEL_ID 1003 enum MCS_Result { diff --git a/libfreerdp-core/settings.c b/libfreerdp-core/settings.c index e83f57cfe..9f26b1b76 100644 --- a/libfreerdp-core/settings.c +++ b/libfreerdp-core/settings.c @@ -21,6 +21,8 @@ #include +static char client_dll[] = "C:\\Windows\\System32\\mstscax.dll"; + rdpSettings* settings_new() { rdpSettings* settings; @@ -52,6 +54,9 @@ rdpSettings* settings_new() ENCRYPTION_40BIT_FLAG | ENCRYPTION_128BIT_FLAG; + settings->client_dir = xmalloc(strlen(client_dll)); + strcpy(settings->client_dir, client_dll); + settings->uniconv = freerdp_uniconv_new(); gethostname(settings->client_hostname, sizeof(settings->client_hostname) - 1); } diff --git a/libfreerdp-core/tcp.c b/libfreerdp-core/tcp.c index 06b213a8d..87aebc61e 100644 --- a/libfreerdp-core/tcp.c +++ b/libfreerdp-core/tcp.c @@ -32,6 +32,30 @@ #include "tcp.h" +static void tcp_get_ip_address(rdpTcp * tcp) +{ + uint8* ip; + socklen_t length; + struct sockaddr_in sockaddr; + + length = sizeof(sockaddr); + + if (getsockname(tcp->sockfd, (struct sockaddr*) &sockaddr, &length) == 0) + { + ip = (uint8*) (&sockaddr.sin_addr); + snprintf(tcp->ip_address, sizeof(tcp->ip_address), + "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + } + + else + strncpy(tcp->ip_address, "127.0.0.1", sizeof(tcp->ip_address)); + + tcp->ip_address[sizeof(tcp->ip_address) - 1] = 0; + + tcp->settings->ipv6 = 0; + tcp->settings->ip_address = tcp->ip_address; +} + boolean tcp_connect(rdpTcp* tcp, const char* hostname, int port) { int status; @@ -76,6 +100,7 @@ boolean tcp_connect(rdpTcp* tcp, const char* hostname, int port) } tcp->sockfd = sockfd; + tcp_get_ip_address(tcp); return True; } @@ -116,13 +141,14 @@ boolean tcp_set_blocking_mode(rdpTcp* tcp, boolean blocking) return True; } -rdpTcp* tcp_new() +rdpTcp* tcp_new(rdpSettings* settings) { rdpTcp* tcp = (rdpTcp*) xzalloc(sizeof(rdpTcp)); if (tcp != NULL) { tcp->sockfd = -1; + tcp->settings = settings; tcp->connect = tcp_connect; tcp->disconnect = tcp_disconnect; tcp->set_blocking_mode = tcp_set_blocking_mode; diff --git a/libfreerdp-core/tcp.h b/libfreerdp-core/tcp.h index bfa25d559..025c8c487 100644 --- a/libfreerdp-core/tcp.h +++ b/libfreerdp-core/tcp.h @@ -22,6 +22,7 @@ #define __TCP_H #include +#include #include typedef struct rdp_tcp rdpTcp; @@ -32,6 +33,8 @@ typedef boolean (*TcpSetBlockingMode) (rdpTcp* tcp, boolean blocking); struct rdp_tcp { int sockfd; + uint8 ip_address[32]; + struct rdp_settings* settings; TcpConnect connect; TcpDisconnect disconnect; TcpSetBlockingMode set_blocking_mode; @@ -41,7 +44,7 @@ boolean tcp_connect(rdpTcp* tcp, const char* hostname, int port); boolean tcp_disconnect(rdpTcp* tcp); boolean tcp_set_blocking_mode(rdpTcp* tcp, boolean blocking); -rdpTcp* tcp_new(); +rdpTcp* tcp_new(rdpSettings* settings); void tcp_free(rdpTcp* tcp); #endif /* __TCP_H */ diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 86ddd9444..d61a4bde0 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -271,7 +271,7 @@ rdpTransport* transport_new(rdpSettings* settings) if (transport != NULL) { - transport->tcp = tcp_new(); + transport->tcp = tcp_new(settings); transport->settings = settings; /* a small 0.1ms delay when transport is blocking. */ diff --git a/libfreerdp-utils/unicode.c b/libfreerdp-utils/unicode.c index c906ecccd..a3c2cb80c 100644 --- a/libfreerdp-utils/unicode.c +++ b/libfreerdp-utils/unicode.c @@ -70,8 +70,23 @@ char* freerdp_uniconv_in(UNICONV *uniconv, unsigned char* pin, size_t in_len) char* freerdp_uniconv_out(UNICONV *uniconv, char *str, size_t *pout_len) { - size_t ibl = strlen(str), obl = 2 * ibl; /* FIXME: worst case */ - char *pin = str, *pout0 = xmalloc(obl + 2), *pout = pout0; + size_t ibl; + size_t obl; + char* pin; + char* pout; + char* pout0; + + if (str == NULL) + { + *pout_len = 0; + return NULL; + } + + ibl = strlen(str); + obl = 2 * ibl; + pin = str; + pout0 = xmalloc(obl + 2); + pout = pout0; #ifdef HAVE_ICONV if (iconv(uniconv->out_iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1) @@ -99,8 +114,9 @@ char* freerdp_uniconv_out(UNICONV *uniconv, char *str, size_t *pout_len) } *pout_len = pout - pout0; - *pout++ = 0; /* Add extra double zero termination */ + *pout++ = 0; /* Add extra double zero termination */ *pout = 0; + return pout0; }