diff --git a/SOURCES/0003-List-plugins-available-in-RHEL-6.patch b/SOURCES/0003-List-plugins-available-in-RHEL-6.patch deleted file mode 100644 index 8078dd6..0000000 --- a/SOURCES/0003-List-plugins-available-in-RHEL-6.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 52c081034c18655865a5c851bfac965ad28a2508 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= -Date: Thu, 8 Aug 2013 12:17:53 -0400 -Subject: [PATCH 3/3] List plugins available in RHEL 6 - -Add a brief explanation of what each plugin does and make a note that -the ALSA backend of the rdpsnd plugin is not supported. - -This patch is not intended for upstream as the list of plugins is -specific to RHEL 6. ---- - client/X11/xfreerdp.1.xml | 45 ++++++++++++++++++++++++++++++++++++++++++--- - 1 files changed, 42 insertions(+), 3 deletions(-) - -diff --git a/client/X11/xfreerdp.1.xml b/client/X11/xfreerdp.1.xml -index 363a245..e0a66b9 100644 ---- a/client/X11/xfreerdp.1.xml -+++ b/client/X11/xfreerdp.1.xml -@@ -486,8 +486,47 @@ - --plugin pluginname - - -- load pluginname -+ Load pluginname - -+ -+ In Red Hat Enterprise Linux 6, the following plugins are -+ available: -+ -+ -+ cliprdr -+ Clipboard support -+ -+ -+ drdynvc -+ Used for multimedia redirection -+ -+ -+ rdpsnd -+ For audio output -+ -+ -+ rail -+ Remote Applications Integrated Locally -+ -+ -+ rdpdbg -+ Debugging Virtual Channel -+ -+ -+ rdpdr -+ File System Support -+ -+ -+ -+ As an example, -+ xfreerdp --plugin -+ rdpsnd server -+ -+ will enable audio output using the PulseAudio backend of -+ the rdpsnd plugin. Please Note that Red Hat Enterprise -+ Linux 6 does not include support for the ALSA backend of -+ the rdpsnd plugin. -+ - - - -@@ -518,7 +557,7 @@ - --ntlm version - - -- force NTLM protocol version to be version, which can be one of 1 or 2. -+ Force NTLM protocol version to be version, which can be one of 1 or 2. - - - -@@ -526,7 +565,7 @@ - --sec proto - - -- force protocol security. proto can be one of rdp, tls or nla. -+ Force protocol security. proto can be one of rdp, tls or nla. - - - --- -1.7.1 - diff --git a/SOURCES/1-Add-support-for-Wildcard-Certificates-2-For-Gatewa.patch b/SOURCES/1-Add-support-for-Wildcard-Certificates-2-For-Gatewa.patch index aea1b6a..fab256a 100644 --- a/SOURCES/1-Add-support-for-Wildcard-Certificates-2-For-Gatewa.patch +++ b/SOURCES/1-Add-support-for-Wildcard-Certificates-2-For-Gatewa.patch @@ -45,7 +45,7 @@ index b05100e..db09960 100644 + if (strlen(hostname) == pattern_length) + { + if (memcmp((void*) hostname, (void*) pattern, pattern_length) == 0) -+ return TRUE; ++ return true; + } + + /* ccpp: Check for wildcard certificates */ @@ -67,7 +67,7 @@ index b05100e..db09960 100644 + + if (hostname[hostname_position] != pattern[pattern_position] ) + { -+ return FALSE; ++ return false; + } + } + } @@ -77,11 +77,11 @@ index b05100e..db09960 100644 + char *check_hostname = &hostname[ strlen(hostname) - pattern_length+1 ]; + if (memcmp((void*) check_hostname, (void*) &pattern[1], pattern_length - 1) == 0 ) + { -+ return TRUE; ++ return true; + } + } + -+ return FALSE; ++ return false; +} + boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname) @@ -97,7 +97,7 @@ index b05100e..db09960 100644 - hostname_match = true; - } + if (tls_match_hostname(common_name, common_name_length, hostname)) -+ hostname_match = TRUE; ++ hostname_match = true; } /* compare against alternative names */ @@ -110,7 +110,7 @@ index b05100e..db09960 100644 { - if (memcmp((void*) hostname, (void*) alt_names[index], alt_names_lengths[index]) == 0) - hostname_match = true; -+ hostname_match = TRUE; ++ hostname_match = true; + break; } } diff --git a/SOURCES/Add-description-for-available-plugins.patch b/SOURCES/Add-description-for-available-plugins.patch new file mode 100644 index 0000000..88ce93e --- /dev/null +++ b/SOURCES/Add-description-for-available-plugins.patch @@ -0,0 +1,163 @@ +From 0c050bb8cde65b0ac368f06bfd5ec36cccf87a83 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Fri, 9 Jun 2017 09:49:11 +0200 +Subject: [PATCH] Add description for available plugins + +The man pages lack info about available plugins and its functionality. +Add description for available plugins and their parameters. + +It is based on info from upstream wiki pages: +https://github.com/FreeRDP/FreeRDP/wiki/Plugins +https://github.com/FreeRDP/FreeRDP/wiki/CommandLineInterface + +Removed mention about ALSA mixer support since it is not built in RHEL. +--- + client/X11/xfreerdp.1.xml | 140 ++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 136 insertions(+), 4 deletions(-) + +diff --git a/client/X11/xfreerdp.1.xml b/client/X11/xfreerdp.1.xml +index 6ccf42fc8..3b1dc675e 100644 +--- a/client/X11/xfreerdp.1.xml ++++ b/client/X11/xfreerdp.1.xml +@@ -438,10 +438,134 @@ + + + +- --plugin pluginname +- +- +- load pluginname ++ --plugin plugin [--data data --] ++ ++ ++ Load one of the following plugin: ++ ++ ++ cliprdr ++ ++ ++ Synchronize client and server clipboard data. ++ ++ ++ ++ ++ drdynvc --data subplugin [subplugin ...] -- ++ ++ ++ Enable multimedia redirection. ++ The subplugin must be one of the following: ++ ++ ++ ++ audin ++ ++ ++ Redirect audio recording device to the server. ++ ++ ++ ++ ++ tsmf ++ ++ ++ Enable video redirection. The --plugin rdpsnd needs to be enabled as well. ++ ++ ++ ++ ++ ++ ++ ++ rdpsnd [--data [subplugin] [latency:latency] --] ++ ++ ++ Enable audio output using one of the following subplugin and with a given latency in ms: ++ ++ ++ ++ pulse ++ ++ ++ Use PulseAudio mixer. ++ ++ ++ ++ ++ ++ ++ ++ rail --data executable[:workingdir[:arguments]] -- ++ ++ ++ Launch one executable in a workingdir with given arguments. ++ You must use --app before you can use rail. ++ ++ ++ ++ ++ rdpdbg ++ ++ ++ Enable debugging virtual channel. ++ ++ ++ ++ ++ rdpdr --data subplugin [subplugin ...] -- ++ ++ ++ Redirect filesystem devices on your client to the server. ++ If you want any redirection to work with Windows Server 2012 and newer you must use --plugin rdpsnd before you use any rdpdr options. ++ The subplugin must be one of the following: ++ ++ ++ ++ drive:name:path ++ ++ ++ Redirect system path as disk with name. ++ ++ ++ ++ ++ smartcard[:name] ++ ++ ++ Redirect smartcard with name. ++ ++ ++ ++ ++ serial:port:device ++ ++ ++ Redirect serial device (e.g. /dev/ttyS0) to port (e.g. COM0). ++ ++ ++ ++ ++ parallel:port:device ++ ++ ++ Redirect parallel device (e.g. /dev/lp0) to port (e.g. LPT0). ++ ++ ++ ++ ++ printer:cupsname:drivername ++ ++ ++ Redirect printer with cupsname and drivername. ++ ++ ++ ++ ++ ++ ++ + + + +-- +2.14.1 + diff --git a/SOURCES/FIPS-mode-support.patch b/SOURCES/FIPS-mode-support.patch new file mode 100644 index 0000000..5787ef3 --- /dev/null +++ b/SOURCES/FIPS-mode-support.patch @@ -0,0 +1,342 @@ +From 1511f1959b2a48cb2d41550441df366276e3c5cb Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Tue, 7 Nov 2017 14:57:12 +0100 +Subject: [PATCH] FIPS mode support + +--- + libfreerdp-core/certificate.c | 17 +++++++----- + libfreerdp-core/connection.c | 3 +++ + libfreerdp-core/crypto.c | 61 ++++++++++++++++++++++++++++++++++++++----- + libfreerdp-core/crypto.h | 6 +++-- + libfreerdp-core/license.c | 15 ++++++++--- + libfreerdp-core/nego.c | 5 +++- + libfreerdp-core/security.c | 33 +++++++++++++++++++---- + libfreerdp-utils/args.c | 3 --- + 8 files changed, 116 insertions(+), 27 deletions(-) + +diff --git a/libfreerdp-core/certificate.c b/libfreerdp-core/certificate.c +index 801ed3609..1fd2cd216 100644 +--- a/libfreerdp-core/certificate.c ++++ b/libfreerdp-core/certificate.c +@@ -276,15 +276,19 @@ static boolean certificate_process_server_public_key(rdpCertificate* certificate + + static boolean certificate_process_server_public_signature(rdpCertificate* certificate, uint8* sigdata, int sigdatalen, STREAM* s, uint32 siglen) + { +- uint8 md5hash[CRYPTO_MD5_DIGEST_LENGTH]; ++ /*uint8 md5hash[CRYPTO_MD5_DIGEST_LENGTH];*/ + uint8 encsig[TSSK_KEY_LENGTH + 8]; + uint8 sig[TSSK_KEY_LENGTH]; +- CryptoMd5 md5ctx; ++ /*CryptoMd5 md5ctx;*/ + int i, sum; + +- md5ctx = crypto_md5_init(); ++ /* Do not bother with validation of server proprietary certificate. The use of MD5 here is not allowed under FIPS. */ ++ /* Since the validation is not protecting against anything since the private/public keys are well known and documented in */ ++ /* MS-RDPBCGR section 5.3.3.1, we are not gaining any security by using MD5 for signature comparison. Rather then use MD5 */ ++ /* here we just dont do the validation to avoid its use. Historically, freerdp has been ignoring a failed validation anyways. */ ++ /*md5ctx = crypto_md5_init(); + crypto_md5_update(md5ctx, sigdata, sigdatalen); +- crypto_md5_final(md5ctx, md5hash); ++ crypto_md5_final(md5ctx, md5hash);*/ + + stream_read(s, encsig, siglen); + +@@ -304,11 +308,12 @@ static boolean certificate_process_server_public_signature(rdpCertificate* certi + crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig); + + /* Verify signature. */ +- if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) ++ /* Do not bother with validation of server proprietary certificate as described above. */ ++ /*if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) + { + printf("certificate_process_server_public_signature: invalid signature\n"); + //return false; +- } ++ }*/ + + /* + * Verify rest of decrypted data: +diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c +index 7e1769ee4..7853c86bd 100644 +--- a/libfreerdp-core/connection.c ++++ b/libfreerdp-core/connection.c +@@ -65,6 +65,9 @@ boolean rdp_client_connect(rdpRdp* rdp) + uint32 selectedProtocol; + rdpSettings* settings = rdp->settings; + ++ if (FIPS_mode() == 1) ++ settings->nla_security = false; ++ + nego_init(rdp->nego); + nego_set_target(rdp->nego, settings->hostname, settings->port); + nego_set_cookie(rdp->nego, settings->username); +diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c +index a0e2ccb9d..e6115b867 100644 +--- a/libfreerdp-core/crypto.c ++++ b/libfreerdp-core/crypto.c +@@ -37,34 +37,81 @@ void crypto_sha1_final(CryptoSha1 sha1, uint8* out_data) + xfree(sha1); + } + +-CryptoMd5 crypto_md5_init(void) ++static CryptoMd5 crypto_md5_init_internal(boolean override_fips) + { + CryptoMd5 md5 = xmalloc(sizeof(*md5)); +- MD5_Init(&md5->md5_ctx); ++ ++ EVP_MD_CTX_init(&md5->md5_ctx); ++ if (override_fips) ++ EVP_MD_CTX_set_flags(&md5->md5_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); ++ if (EVP_DigestInit_ex(&md5->md5_ctx, EVP_md5(), NULL) != 1) ++ { ++ printf("EVP_DigestInit_ex failed\n"); ++ abort(); ++ } ++ + return md5; + } + ++CryptoMd5 crypto_md5_init(void) ++{ ++ return crypto_md5_init_internal(false); ++} ++ ++CryptoMd5 crypto_md5_init_allow_fips(void) ++{ ++ return crypto_md5_init_internal(true); ++} ++ + void crypto_md5_update(CryptoMd5 md5, const uint8* data, uint32 length) + { +- MD5_Update(&md5->md5_ctx, data, length); ++ EVP_DigestUpdate(&md5->md5_ctx, data, length); + } + + void crypto_md5_final(CryptoMd5 md5, uint8* out_data) + { +- MD5_Final(out_data, &md5->md5_ctx); ++ EVP_DigestFinal_ex(&md5->md5_ctx, out_data, NULL); + xfree(md5); + } + +-CryptoRc4 crypto_rc4_init(const uint8* key, uint32 length) ++static CryptoRc4 crypto_rc4_init_internal(const uint8* key, uint32 length, boolean override_fips) + { + CryptoRc4 rc4 = xmalloc(sizeof(*rc4)); +- RC4_set_key(&rc4->rc4_key, length, key); ++ ++ EVP_CIPHER_CTX_init(&rc4->rc4_ctx); ++ if (EVP_EncryptInit_ex(&rc4->rc4_ctx, EVP_rc4(), NULL, NULL, NULL) != 1) ++ { ++ printf("EVP_EncryptInit_ex failed\n"); ++ abort(); ++ } ++ ++ if (override_fips) ++ EVP_CIPHER_CTX_set_flags(&rc4->rc4_ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW); ++ ++ EVP_CIPHER_CTX_set_key_length(&rc4->rc4_ctx, length); ++ if (EVP_EncryptInit_ex(&rc4->rc4_ctx, NULL, NULL, key, NULL) != 1) ++ { ++ printf("EVP_EncryptInit_ex failed\n"); ++ abort(); ++ } ++ + return rc4; + } + ++CryptoRc4 crypto_rc4_init(const uint8* key, uint32 length) ++{ ++ return crypto_rc4_init_internal(key, length, false); ++} ++ ++CryptoRc4 crypto_rc4_init_allow_fips(const uint8* key, uint32 length) ++{ ++ return crypto_rc4_init_internal(key, length, true); ++} ++ + void crypto_rc4(CryptoRc4 rc4, uint32 length, const uint8* in_data, uint8* out_data) + { +- RC4(&rc4->rc4_key, length, in_data, out_data); ++ int outputLength; ++ EVP_CipherUpdate(&rc4->rc4_ctx, out_data, &outputLength, in_data, length); + } + + void crypto_rc4_free(CryptoRc4 rc4) +diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h +index 15afca8a4..a595c3831 100644 +--- a/libfreerdp-core/crypto.h ++++ b/libfreerdp-core/crypto.h +@@ -54,12 +54,12 @@ struct crypto_sha1_struct + + struct crypto_md5_struct + { +- MD5_CTX md5_ctx; ++ EVP_MD_CTX md5_ctx; + }; + + struct crypto_rc4_struct + { +- RC4_KEY rc4_key; ++ EVP_CIPHER_CTX rc4_ctx; + }; + + struct crypto_des3_struct +@@ -86,11 +86,13 @@ void crypto_sha1_final(CryptoSha1 sha1, uint8* out_data); + #define CRYPTO_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH + typedef struct crypto_md5_struct* CryptoMd5; + CryptoMd5 crypto_md5_init(void); ++CryptoMd5 crypto_md5_init_allow_fips(void); + void crypto_md5_update(CryptoMd5 md5, const uint8* data, uint32 length); + void crypto_md5_final(CryptoMd5 md5, uint8* out_data); + + typedef struct crypto_rc4_struct* CryptoRc4; + CryptoRc4 crypto_rc4_init(const uint8* key, uint32 length); ++CryptoRc4 crypto_rc4_init_allow_fips(const uint8* key, uint32 length); + void crypto_rc4(CryptoRc4 rc4, uint32 length, const uint8* in_data, uint8* out_data); + void crypto_rc4_free(CryptoRc4 rc4); + +diff --git a/libfreerdp-core/license.c b/libfreerdp-core/license.c +index 60b9f9366..7e5734069 100644 +--- a/libfreerdp-core/license.c ++++ b/libfreerdp-core/license.c +@@ -295,7 +295,10 @@ void license_generate_hwid(rdpLicense* license) + memset(license->hwid, 0, HWID_LENGTH); + mac_address = license->rdp->transport->tcp->mac_address; + +- md5 = crypto_md5_init(); ++ /* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just taking a MD5 hash of the 6 bytes of 0's(macAddress) */ ++ /* and filling in the Data1-Data4 fields of the CLIENT_HARDWARE_ID structure(from MS-RDPELE section 2.2.2.3.1). This is for RDP licensing packets */ ++ /* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */ ++ md5 = crypto_md5_init_allow_fips(); + crypto_md5_update(md5, mac_address, 6); + crypto_md5_final(md5, &license->hwid[HWID_PLATFORM_ID_LENGTH]); + } +@@ -354,7 +357,10 @@ void license_decrypt_platform_challenge(rdpLicense* license) + license->platform_challenge->length = + license->encrypted_platform_challenge->length; + +- rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); ++ /* Allow FIPS override for use of RC4 here, this is only used for decrypting the MACData field of the */ ++ /* Server Platform Challenge packet (from MS-RDPELE section 2.2.2.4). This is for RDP licensing packets */ ++ /* which will already be encrypted under FIPS, so the use of RC4 here is not for sensitive data protection. */ ++ rc4 = crypto_rc4_init_allow_fips(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); + + crypto_rc4(rc4, license->encrypted_platform_challenge->length, + license->encrypted_platform_challenge->data, +@@ -829,8 +835,11 @@ void license_send_platform_challenge_response_packet(rdpLicense* license) + security_mac_data(license->mac_salt_key, buffer, length, mac_data); + xfree(buffer); + ++ /* Allow FIPS override for use of RC4 here, this is only used for encrypting the EncryptedHWID field of the */ ++ /* Client Platform Challenge Response packet (from MS-RDPELE section 2.2.2.5). This is for RDP licensing packets */ ++ /* which will already be encrypted under FIPS, so the use of RC4 here is not for sensitive data protection. */ + buffer = (uint8*) xmalloc(HWID_LENGTH); +- rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); ++ rc4 = crypto_rc4_init_allow_fips(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); + crypto_rc4(rc4, HWID_LENGTH, license->hwid, buffer); + crypto_rc4_free(rc4); + +diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c +index 7eb810bba..199870408 100644 +--- a/libfreerdp-core/nego.c ++++ b/libfreerdp-core/nego.c +@@ -89,7 +89,10 @@ boolean nego_connect(rdpNego* nego) + if(nego->selected_protocol == PROTOCOL_RDP) + { + nego->transport->settings->encryption = true; +- nego->transport->settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; ++ if (FIPS_mode() != 1) ++ nego->transport->settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; ++ else ++ nego->transport->settings->encryption_method = ENCRYPTION_METHOD_FIPS; + nego->transport->settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; + } + +diff --git a/libfreerdp-core/security.c b/libfreerdp-core/security.c +index d93c3b9a8..d93390de2 100644 +--- a/libfreerdp-core/security.c ++++ b/libfreerdp-core/security.c +@@ -131,7 +131,10 @@ static void security_salted_hash(uint8* salt, uint8* input, int length, uint8* s + crypto_sha1_final(sha1, sha1_digest); + + /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ +- md5 = crypto_md5_init(); ++ /* Allow FIPS override for use of MD5 here, this is used for creating hashes of the premaster_secret and master_secret */ ++ /* used for RDP licensing as described in MS-RDPELE. This is for RDP licensing packets */ ++ /* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */ ++ md5 = crypto_md5_init_allow_fips(); + crypto_md5_update(md5, salt, 48); /* Salt (48 bytes) */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ + crypto_md5_final(md5, output); +@@ -182,10 +185,24 @@ void security_md5_16_32_32(uint8* in0, uint8* in1, uint8* in2, uint8* output) + crypto_md5_final(md5, output); + } + ++void security_md5_16_32_32_allow_fips(uint8* in0, uint8* in1, uint8* in2, uint8* output) ++{ ++ CryptoMd5 md5; ++ ++ md5 = crypto_md5_init_allow_fips(); ++ crypto_md5_update(md5, in0, 16); ++ crypto_md5_update(md5, in1, 32); ++ crypto_md5_update(md5, in2, 32); ++ crypto_md5_final(md5, output); ++} ++ + void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output) + { + /* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */ +- security_md5_16_32_32(&session_key_blob[16], client_random, server_random, output); ++ /* Allow FIPS use of MD5 here, this is just used for creating the licensing encryption key as described in MS-RDPELE. */ ++ /* This is for RDP licensing packets which will already be encrypted under FIPS, so the use of MD5 here is not for */ ++ /* sensitive data protection. */ ++ security_md5_16_32_32_allow_fips(&session_key_blob[16], client_random, server_random, output); + } + + void security_uint32_le(uint8* output, uint32 value) +@@ -216,7 +233,10 @@ void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* o + crypto_sha1_final(sha1, sha1_digest); + + /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */ +- md5 = crypto_md5_init(); ++ /* Allow FIPS override for use of MD5 here, this is only used for creating the MACData field of the */ ++ /* Client Platform Challenge Response packet (from MS-RDPELE section 2.2.2.5). This is for RDP licensing packets */ ++ /* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */ ++ md5 = crypto_md5_init_allow_fips(); + crypto_md5_update(md5, mac_salt_key, 16); /* MacSaltKey */ + crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ +@@ -400,9 +420,12 @@ boolean security_establish_keys(uint8* client_random, rdpRdp* rdp) + security_md5_16_32_32(&session_key_blob[32], client_random, + server_random, rdp->decrypt_key); + } else { +- security_md5_16_32_32(&session_key_blob[16], client_random, ++ /* Allow FIPS use of MD5 here, this is just used for generation of the SessionKeyBlob as described in MS-RDPELE. */ ++ /* This is for RDP licensing packets which will already be encrypted under FIPS, so the use of MD5 here is not */ ++ /* for sensitive data protection. */ ++ security_md5_16_32_32_allow_fips(&session_key_blob[16], client_random, + server_random, rdp->decrypt_key); +- security_md5_16_32_32(&session_key_blob[32], client_random, ++ security_md5_16_32_32_allow_fips(&session_key_blob[32], client_random, + server_random, rdp->encrypt_key); + } + +diff --git a/libfreerdp-utils/args.c b/libfreerdp-utils/args.c +index d9b08c41f..333742536 100644 +--- a/libfreerdp-utils/args.c ++++ b/libfreerdp-utils/args.c +@@ -550,9 +550,6 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, + settings->rdp_security = true; + settings->tls_security = false; + settings->nla_security = false; +- settings->encryption = true; +- settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; +- settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; + } + else if (strncmp("tls", argv[index], 1) == 0) /* TLS */ + { +-- +2.15.0 + diff --git a/SOURCES/Fix-NTLM-on-big-endian.patch b/SOURCES/Fix-NTLM-on-big-endian.patch new file mode 100644 index 0000000..7cf7e0c --- /dev/null +++ b/SOURCES/Fix-NTLM-on-big-endian.patch @@ -0,0 +1,133 @@ +From 25d31015255cf1b80dae76a3654ba0d62c4d71d5 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Wed, 27 Sep 2017 15:56:35 +0200 +Subject: [PATCH 1/2] Fix NTLM on big endian + +Based on fixes from master: +https://github.com/FreeRDP/FreeRDP/pull/3284 +--- + libfreerdp-core/ntlmssp.c | 39 +++++++++++++++++++++++++++++---------- + 1 file changed, 29 insertions(+), 10 deletions(-) + +diff --git a/libfreerdp-core/ntlmssp.c b/libfreerdp-core/ntlmssp.c +index 84ad319c3..8f69878cf 100644 +--- a/libfreerdp-core/ntlmssp.c ++++ b/libfreerdp-core/ntlmssp.c +@@ -126,6 +126,13 @@ static const char* const AV_PAIRS_STRINGS[] = + "MsvChannelBindings" + }; + ++#define Data_Write_UINT32(_d, _v) do { \ ++ *((uint8*) _d) = (_v) & 0xFF; \ ++ *((uint8*) _d + 1) = ((_v) >> 8) & 0xFF; \ ++ *((uint8*) _d + 2) = ((_v) >> 16) & 0xFF; \ ++ *((uint8*) _d + 3) = ((_v) >> 24) & 0xFF; \ ++} while (0) ++ + /** + * Set NTLMSSP username. + * @param ntlmssp +@@ -138,7 +145,9 @@ void ntlmssp_set_username(NTLMSSP* ntlmssp, char* username) + + if (username != NULL) + { +- ntlmssp->username.data = freerdp_uniconv_out(ntlmssp->uniconv, username, (size_t*) &(ntlmssp->username.length)); ++ size_t length; ++ ntlmssp->username.data = freerdp_uniconv_out(ntlmssp->uniconv, username, &length); ++ ntlmssp->username.length = length; + } + } + +@@ -154,7 +163,9 @@ void ntlmssp_set_domain(NTLMSSP* ntlmssp, char* domain) + + if (domain != NULL) + { +- ntlmssp->domain.data = freerdp_uniconv_out(ntlmssp->uniconv, domain, (size_t*) &(ntlmssp->domain.length)); ++ size_t length; ++ ntlmssp->domain.data = freerdp_uniconv_out(ntlmssp->uniconv, domain, &length); ++ ntlmssp->domain.length = length; + } + } + +@@ -170,7 +181,9 @@ void ntlmssp_set_password(NTLMSSP* ntlmssp, char* password) + + if (password != NULL) + { +- ntlmssp->password.data = freerdp_uniconv_out(ntlmssp->uniconv, password, (size_t*) &(ntlmssp->password.length)); ++ size_t length; ++ ntlmssp->password.data = freerdp_uniconv_out(ntlmssp->uniconv, password, &length); ++ ntlmssp->password.length = length; + } + } + +@@ -186,7 +199,9 @@ void ntlmssp_set_workstation(NTLMSSP* ntlmssp, char* workstation) + + if (workstation != NULL) + { +- ntlmssp->workstation.data = freerdp_uniconv_out(ntlmssp->uniconv, workstation, (size_t*) &(ntlmssp->workstation.length)); ++ size_t length; ++ ntlmssp->workstation.data = freerdp_uniconv_out(ntlmssp->uniconv, workstation, &length); ++ ntlmssp->workstation.length = length; + } + } + +@@ -1185,11 +1200,13 @@ void ntlmssp_encrypt_message(NTLMSSP* ntlmssp, rdpBlob* msg, rdpBlob* encrypted_ + uint8 digest[16]; + uint8 checksum[8]; + uint32 version = 1; ++ uint32 value; + + /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,msg) using the client signing key */ + HMAC_CTX_init(&hmac_ctx); + HMAC_Init_ex(&hmac_ctx, ntlmssp->client_signing_key, 16, EVP_md5(), NULL); +- HMAC_Update(&hmac_ctx, (void*) &ntlmssp->send_seq_num, 4); ++ Data_Write_UINT32(&value, ntlmssp->send_seq_num); ++ HMAC_Update(&hmac_ctx, (void*) &value, 4); + HMAC_Update(&hmac_ctx, msg->data, msg->length); + HMAC_Final(&hmac_ctx, digest, NULL); + +@@ -1203,9 +1220,9 @@ void ntlmssp_encrypt_message(NTLMSSP* ntlmssp, rdpBlob* msg, rdpBlob* encrypted_ + crypto_rc4(ntlmssp->send_rc4_seal, 8, digest, checksum); + + /* Concatenate version, ciphertext and sequence number to build signature */ +- memcpy(signature, (void*) &version, 4); ++ Data_Write_UINT32(signature, version); + memcpy(&signature[4], (void*) checksum, 8); +- memcpy(&signature[12], (void*) &(ntlmssp->send_seq_num), 4); ++ Data_Write_UINT32(&signature[12], ntlmssp->send_seq_num); + + HMAC_CTX_cleanup(&hmac_ctx); + +@@ -1230,6 +1247,7 @@ int ntlmssp_decrypt_message(NTLMSSP* ntlmssp, rdpBlob* encrypted_msg, rdpBlob* m + uint8 checksum[8]; + uint32 version = 1; + uint8 expected_signature[16]; ++ uint32 value; + + /* Allocate space for encrypted message */ + freerdp_blob_alloc(msg, encrypted_msg->length); +@@ -1240,7 +1258,8 @@ int ntlmssp_decrypt_message(NTLMSSP* ntlmssp, rdpBlob* encrypted_msg, rdpBlob* m + /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,msg) using the client signing key */ + HMAC_CTX_init(&hmac_ctx); + HMAC_Init_ex(&hmac_ctx, ntlmssp->server_signing_key, 16, EVP_md5(), NULL); +- HMAC_Update(&hmac_ctx, (void*) &ntlmssp->recv_seq_num, 4); ++ Data_Write_UINT32(&value, ntlmssp->recv_seq_num); ++ HMAC_Update(&hmac_ctx, (void*) &value, 4); + HMAC_Update(&hmac_ctx, msg->data, msg->length); + HMAC_Final(&hmac_ctx, digest, NULL); + +@@ -1248,9 +1267,9 @@ int ntlmssp_decrypt_message(NTLMSSP* ntlmssp, rdpBlob* encrypted_msg, rdpBlob* m + crypto_rc4(ntlmssp->recv_rc4_seal, 8, digest, checksum); + + /* Concatenate version, ciphertext and sequence number to build signature */ +- memcpy(expected_signature, (void*) &version, 4); ++ Data_Write_UINT32(expected_signature, version); + memcpy(&expected_signature[4], (void*) checksum, 8); +- memcpy(&expected_signature[12], (void*) &(ntlmssp->recv_seq_num), 4); ++ Data_Write_UINT32(&expected_signature[12], ntlmssp->recv_seq_num); + + if (memcmp(signature, expected_signature, 16) != 0) + { +-- +2.14.2 + diff --git a/SOURCES/Fix-colors-on-big-endian.patch b/SOURCES/Fix-colors-on-big-endian.patch new file mode 100644 index 0000000..4033176 --- /dev/null +++ b/SOURCES/Fix-colors-on-big-endian.patch @@ -0,0 +1,532 @@ +From 5e1aa9e1a4ed8ca4119a6e5b4db554af5367784e Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Tue, 3 Oct 2017 09:25:25 +0200 +Subject: [PATCH 2/2] Fix colors on big endian + +Based on fixes from master: +https://github.com/FreeRDP/FreeRDP/pull/4135 +--- + client/X11/xf_graphics.c | 31 +++++++++++++++++- + client/X11/xfreerdp.c | 4 +++ + libfreerdp-codec/bitmap.c | 7 ++-- + libfreerdp-codec/color.c | 83 +++++++++++++++++++++++++++++++++++------------ + libfreerdp-gdi/16bpp.c | 17 +++++++--- + libfreerdp-gdi/32bpp.c | 21 +++++++++--- + 6 files changed, 129 insertions(+), 34 deletions(-) + +diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c +index ed5f9bc25..0bd4e9378 100644 +--- a/client/X11/xf_graphics.c ++++ b/client/X11/xf_graphics.c +@@ -49,6 +49,8 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) + { + image = XCreateImage(xfi->display, xfi->visual, xfi->depth, + ZPixmap, 0, (char*) data, bitmap->width, bitmap->height, xfi->scanline_pad, 0); ++ image->byte_order = LSBFirst; ++ image->bitmap_bit_order = LSBFirst; + + XPutImage(xfi->display, pixmap, xfi->gc, image, 0, 0, 0, 0, bitmap->width, bitmap->height); + XFree(image); +@@ -89,6 +91,8 @@ void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap) + + image = XCreateImage(xfi->display, xfi->visual, xfi->depth, + ZPixmap, 0, (char*) bitmap->data, bitmap->width, bitmap->height, xfi->scanline_pad, 0); ++ image->byte_order = LSBFirst; ++ image->bitmap_bit_order = LSBFirst; + + XPutImage(xfi->display, xfi->primary, xfi->gc, + image, 0, 0, bitmap->left, bitmap->top, width, height); +@@ -149,6 +153,13 @@ void xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, boolean primar + + /* Pointer Class */ + ++#define Data_Read_UINT32(_d, _v) do { _v = \ ++ (uint32)(*((uint8*) _d)) + \ ++ (((uint32)(*((uint8*) _d + 1))) << 8) + \ ++ (((uint32)(*((uint8*) _d + 2))) << 16) + \ ++ (((uint32)(*((uint8*) _d + 3))) << 24); \ ++} while (0) ++ + void xf_Pointer_New(rdpContext* context, rdpPointer* pointer) + { + XcursorImage ci; +@@ -170,6 +181,25 @@ void xf_Pointer_New(rdpContext* context, rdpPointer* pointer) + pointer->width, pointer->height, pointer->xorBpp, xfi->clrconv); + } + ++ if (xfi->big_endian) ++ { ++ int x, y; ++ uint32* pixel; ++ uint32 value; ++ ++ pixel = (uint32*) ci.pixels; ++ ++ for (y = 0; y < ci.height; y++) ++ { ++ for (x = 0; x < ci.width; x++) ++ { ++ Data_Read_UINT32(pixel, value); ++ *pixel = value; ++ pixel++; ++ } ++ } ++ } ++ + ((xfPointer*) pointer)->cursor = XcursorImageLoadCursor(xfi->display, &ci); + xfree(ci.pixels); + } +@@ -209,7 +239,6 @@ void xf_Glyph_New(rdpContext* context, rdpGlyph* glyph) + + image = XCreateImage(xfi->display, xfi->visual, 1, + ZPixmap, 0, (char*) glyph->aj, glyph->cx, glyph->cy, 8, scanline); +- + image->byte_order = MSBFirst; + image->bitmap_bit_order = MSBFirst; + +diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c +index 2d0e6704d..786cc0bd8 100644 +--- a/client/X11/xfreerdp.c ++++ b/client/X11/xfreerdp.c +@@ -181,6 +181,8 @@ void xf_sw_desktop_resize(rdpContext* context) + XDestroyImage(xfi->image); + xfi->image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, + (char*) gdi->primary_buffer, gdi->width, gdi->height, xfi->scanline_pad, 0); ++ xfi->image->byte_order = LSBFirst; ++ xfi->image->bitmap_bit_order = LSBFirst; + } + } + } +@@ -707,6 +709,8 @@ boolean xf_post_connect(freerdp* instance) + + xfi->image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, + (char*) xfi->primary_buffer, xfi->width, xfi->height, xfi->scanline_pad, 0); ++ xfi->image->byte_order = LSBFirst; ++ xfi->image->bitmap_bit_order = LSBFirst; + + xfi->bmp_codec_none = (uint8*) xmalloc(64 * 64 * 4); + +diff --git a/libfreerdp-codec/bitmap.c b/libfreerdp-codec/bitmap.c +index 635a583aa..aafffc39b 100644 +--- a/libfreerdp-codec/bitmap.c ++++ b/libfreerdp-codec/bitmap.c +@@ -214,9 +214,10 @@ static uint32 ExtractRunLength(uint32 code, uint8* pbOrderHdr, uint32* advance) + #undef WRITEFIRSTLINEFGBGIMAGE + #undef RLEDECOMPRESS + #undef RLEEXTRA +-#define DESTWRITEPIXEL(_buf, _pix) ((uint16*)(_buf))[0] = (uint16)(_pix) +-#define DESTREADPIXEL(_pix, _buf) _pix = ((uint16*)(_buf))[0] +-#define SRCREADPIXEL(_pix, _buf) _pix = ((uint16*)(_buf))[0] ++#define DESTWRITEPIXEL(_buf, _pix) do { (_buf)[0] = (uint8)(_pix); \ ++ (_buf)[1] = (uint8)((_pix) >> 8); } while (0) ++#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) ++#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) + #define DESTNEXTPIXEL(_buf) _buf += 2 + #define SRCNEXTPIXEL(_buf) _buf += 2 + #define WRITEFGBGIMAGE WriteFgBgImage16to16 +diff --git a/libfreerdp-codec/color.c b/libfreerdp-codec/color.c +index ff3bacb79..dbff7b159 100644 +--- a/libfreerdp-codec/color.c ++++ b/libfreerdp-codec/color.c +@@ -25,6 +25,30 @@ + #include + #include + ++#define Data_Read_UINT32(_d, _v) do { _v = \ ++ (uint32)(*((uint8*) _d)) + \ ++ (((uint32)(*((uint8*) _d + 1))) << 8) + \ ++ (((uint32)(*((uint8*) _d + 2))) << 16) + \ ++ (((uint32)(*((uint8*) _d + 3))) << 24); \ ++} while (0) ++ ++#define Data_Write_UINT32(_d, _v) do { \ ++ *((uint8*) _d) = (_v) & 0xFF; \ ++ *((uint8*) _d + 1) = ((_v) >> 8) & 0xFF; \ ++ *((uint8*) _d + 2) = ((_v) >> 16) & 0xFF; \ ++ *((uint8*) _d + 3) = ((_v) >> 24) & 0xFF; \ ++} while (0) ++ ++#define Data_Read_UINT16(_d, _v) do { _v = \ ++ (uint16)(*((uint8*) _d)) + \ ++ (((uint16)(*((uint8*) _d + 1))) << 8); \ ++} while (0) ++ ++#define Data_Write_UINT16(_d, _v) do { \ ++ *((uint8*) _d) = (_v) & 0xFF; \ ++ *((uint8*) _d + 1) = ((_v) >> 8) & 0xFF; \ ++} while (0) ++ + int freerdp_get_pixel(uint8 * data, int x, int y, int width, int height, int bpp) + { + int start; +@@ -32,6 +56,7 @@ int freerdp_get_pixel(uint8 * data, int x, int y, int width, int height, int bpp + uint16 *src16; + uint32 *src32; + int red, green, blue; ++ uint32 pixel; + + switch (bpp) + { +@@ -45,7 +70,9 @@ int freerdp_get_pixel(uint8 * data, int x, int y, int width, int height, int bpp + case 15: + case 16: + src16 = (uint16*) data; +- return src16[y * width + x]; ++ src16 += y * width + x; ++ Data_Read_UINT16 (src16, pixel); ++ return pixel; + case 24: + data += y * width * 3; + data += x * 3; +@@ -55,7 +82,9 @@ int freerdp_get_pixel(uint8 * data, int x, int y, int width, int height, int bpp + return RGB24(red, green, blue); + case 32: + src32 = (uint32*) data; +- return src32[y * width + x]; ++ src32 += y * width + x; ++ Data_Read_UINT32 (src32, pixel); ++ return pixel; + default: + break; + } +@@ -82,7 +111,8 @@ void freerdp_set_pixel(uint8* data, int x, int y, int width, int height, int bpp + else if (bpp == 32) + { + dst32 = (int*) data; +- dst32[y * width + x] = pixel; ++ dst32 += y * width + x; ++ Data_Write_UINT32 (dst32, pixel); + } + } + +@@ -383,7 +413,7 @@ uint8* freerdp_image_convert_8bpp(uint8* srcData, uint8* dstData, int width, int + green = clrconv->palette->entries[pixel].green; + blue = clrconv->palette->entries[pixel].blue; + pixel = (clrconv->invert) ? BGR15(red, green, blue) : RGB15(red, green, blue); +- *dst16 = pixel; ++ Data_Write_UINT16 (dst16, pixel); + dst16++; + } + return dstData; +@@ -402,7 +432,7 @@ uint8* freerdp_image_convert_8bpp(uint8* srcData, uint8* dstData, int width, int + green = clrconv->palette->entries[pixel].green; + blue = clrconv->palette->entries[pixel].blue; + pixel = (clrconv->invert) ? BGR16(red, green, blue) : RGB16(red, green, blue); +- *dst16 = pixel; ++ Data_Write_UINT16 (dst16, pixel); + dst16++; + } + return dstData; +@@ -422,7 +452,7 @@ uint8* freerdp_image_convert_8bpp(uint8* srcData, uint8* dstData, int width, int + green = clrconv->palette->entries[pixel].green; + blue = clrconv->palette->entries[pixel].blue; + pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue); +- *dst32 = pixel; ++ Data_Write_UINT32 (dst32, pixel); + dst32++; + } + return dstData; +@@ -460,11 +490,11 @@ uint8* freerdp_image_convert_15bpp(uint8* srcData, uint8* dstData, int width, in + dst32 = (uint32 *) dstData; + for (i = width * height; i > 0; i--) + { +- pixel = *src16; ++ Data_Read_UINT16 (src16, pixel); + src16++; + GetBGR15(red, green, blue, pixel); + pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue); +- *dst32 = pixel; ++ Data_Write_UINT32 (dst32, pixel); + dst32++; + } + return dstData; +@@ -478,12 +508,12 @@ uint8* freerdp_image_convert_15bpp(uint8* srcData, uint8* dstData, int width, in + dst16 = (uint16 *) dstData; + for (i = width * height; i > 0; i--) + { +- pixel = *src16; ++ Data_Read_UINT16 (src16, pixel); + src16++; + GetRGB_555(red, green, blue, pixel); + RGB_555_565(red, green, blue); + pixel = (clrconv->invert) ? BGR565(red, green, blue) : RGB565(red, green, blue); +- *dst16 = pixel; ++ Data_Write_UINT16 (dst16, pixel); + dst16++; + } + return dstData; +@@ -508,12 +538,15 @@ uint8* freerdp_image_convert_16bpp(uint8* srcData, uint8* dstData, int width, in + uint8 red, green, blue; + uint16* src16 = (uint16 *) srcData; + uint16* dst16 = (uint16 *) dstData; ++ uint32 pixel; + + for (i = width * height; i > 0; i--) + { +- GetRGB_565(red, green, blue, (*src16)); ++ Data_Read_UINT16 (src16, pixel); ++ GetRGB_565(red, green, blue, pixel); + RGB_565_555(red, green, blue); +- (*dst16) = (clrconv->invert) ? BGR555(red, green, blue) : RGB555(red, green, blue); ++ pixel = (clrconv->invert) ? BGR555(red, green, blue) : RGB555(red, green, blue); ++ Data_Write_UINT16 (dst16, pixel); + src16++; + dst16++; + } +@@ -531,6 +564,7 @@ uint8* freerdp_image_convert_16bpp(uint8* srcData, uint8* dstData, int width, in + uint8 *dst8; + uint16 *src16; + uint8 red, green, blue; ++ uint32 pixel; + + if (dstData == NULL) + dstData = (uint8*) malloc(width * height * 3); +@@ -540,7 +574,8 @@ uint8* freerdp_image_convert_16bpp(uint8* srcData, uint8* dstData, int width, in + + for (i = width * height; i > 0; i--) + { +- GetBGR16(red, green, blue, *src16); ++ Data_Read_UINT16 (src16, pixel); ++ GetBGR16(red, green, blue, pixel); + src16++; + + if (clrconv->invert) +@@ -574,11 +609,11 @@ uint8* freerdp_image_convert_16bpp(uint8* srcData, uint8* dstData, int width, in + + for (i = width * height; i > 0; i--) + { +- pixel = *src16; ++ Data_Read_UINT16 (src16, pixel); + src16++; + GetBGR16(red, green, blue, pixel); + pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue); +- *dst32 = pixel; ++ Data_Write_UINT32 (dst32, pixel); + dst32++; + } + return dstData; +@@ -619,6 +654,7 @@ uint8* freerdp_image_convert_32bpp(uint8* srcData, uint8* dstData, int width, in + uint16 *dst16; + uint32 *src32; + uint8 red, green, blue; ++ uint32 pixel; + + if (dstData == NULL) + dstData = (uint8*) malloc(width * height * 2); +@@ -628,8 +664,10 @@ uint8* freerdp_image_convert_32bpp(uint8* srcData, uint8* dstData, int width, in + + for (index = 0; index < width * height; index++) + { +- GetBGR32(blue, green, red, *src32); +- *dst16 = (clrconv->invert) ? BGR16(red, green, blue) : RGB16(red, green, blue); ++ Data_Read_UINT32 (src32, pixel); ++ GetBGR32(blue, green, red, pixel); ++ pixel = (clrconv->invert) ? BGR16(red, green, blue) : RGB16(red, green, blue); ++ Data_Write_UINT16 (dst16, pixel); + src32++; + dst16++; + } +@@ -878,6 +916,7 @@ uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int src + int bitIndex; + uint8 redBg, greenBg, blueBg; + uint8 redFg, greenFg, blueFg; ++ uint32 pixel; + + switch (srcBpp) + { +@@ -941,12 +980,13 @@ uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int src + { + if ((bitMask >> bitIndex) & 0x01) + { +- *dst16 = bgcolor; ++ pixel = bgcolor; + } + else + { +- *dst16 = fgcolor; ++ pixel = fgcolor; + } ++ Data_Write_UINT16 (dst16, pixel); + dst16++; + } + srcData++; +@@ -967,12 +1007,13 @@ uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int src + { + if ((bitMask >> bitIndex) & 0x01) + { +- *dst32 = (clrconv->invert) ? BGR32(redBg, greenBg, blueBg) : RGB32(redBg, greenBg, blueBg); ++ pixel = (clrconv->invert) ? BGR32(redBg, greenBg, blueBg) : RGB32(redBg, greenBg, blueBg); + } + else + { +- *dst32 = (clrconv->invert) ? BGR32(redFg, greenFg, blueFg) : RGB32(redFg, greenFg, blueFg); ++ pixel = (clrconv->invert) ? BGR32(redFg, greenFg, blueFg) : RGB32(redFg, greenFg, blueFg); + } ++ Data_Write_UINT32 (dst32, pixel); + dst32++; + } + srcData++; +diff --git a/libfreerdp-gdi/16bpp.c b/libfreerdp-gdi/16bpp.c +index 1b2a2e65d..dd52060ce 100644 +--- a/libfreerdp-gdi/16bpp.c ++++ b/libfreerdp-gdi/16bpp.c +@@ -66,6 +66,11 @@ uint16 gdi_get_color_16bpp(HGDI_DC hdc, GDI_COLOR color) + return color16; + } + ++#define Data_Write_UINT16(_d, _v) do { \ ++ *((uint8*) _d) = (_v) & 0xFF; \ ++ *((uint8*) _d + 1) = ((_v) >> 8) & 0xFF; \ ++} while (0) ++ + int FillRect_16bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) + { + int x, y; +@@ -90,7 +95,7 @@ int FillRect_16bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) + { + for (x = 0; x < nWidth; x++) + { +- *dstp = color16; ++ Data_Write_UINT16(dstp, color16); + dstp++; + } + } +@@ -373,11 +378,13 @@ static int BitBlt_DSPDxax_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi + uint16 src16; + uint16 color16; + HGDI_BITMAP hSrcBmp; ++ uint16 pat; + + /* D = (S & P) | (~S & D) */ + /* DSPDxax, used to draw glyphs */ + + color16 = gdi_get_color_16bpp(hdcDest, hdcDest->textColor); ++ Data_Write_UINT16(&pat, color16); + + hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; + +@@ -397,7 +404,7 @@ static int BitBlt_DSPDxax_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi + for (x = 0; x < nWidth; x++) + { + src16 = (*srcp << 8) | *srcp; +- *dstp = (src16 & color16) | (~src16 & *dstp); ++ *dstp = (src16 & pat) | (~src16 & *dstp); + srcp++; + dstp++; + } +@@ -580,7 +587,7 @@ static int BitBlt_PATCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi + { + for (x = 0; x < nWidth; x++) + { +- *dstp = color16; ++ Data_Write_UINT16(dstp, color16); + dstp++; + } + } +@@ -613,10 +620,12 @@ static int BitBlt_PATINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n + uint16* dstp; + uint16* patp; + uint16 color16; ++ uint16 pat; + + if (hdcDest->brush->style == GDI_BS_SOLID) + { + color16 = gdi_get_color_16bpp(hdcDest, hdcDest->brush->color); ++ Data_Write_UINT16(&pat, color16); + + for (y = 0; y < nHeight; y++) + { +@@ -626,7 +635,7 @@ static int BitBlt_PATINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n + { + for (x = 0; x < nWidth; x++) + { +- *dstp ^= color16; ++ *dstp ^= pat; + dstp++; + } + } +diff --git a/libfreerdp-gdi/32bpp.c b/libfreerdp-gdi/32bpp.c +index 5e946b0d5..536a7f57b 100644 +--- a/libfreerdp-gdi/32bpp.c ++++ b/libfreerdp-gdi/32bpp.c +@@ -53,6 +53,13 @@ uint32 gdi_get_color_32bpp(HGDI_DC hdc, GDI_COLOR color) + return color32; + } + ++#define Data_Write_UINT32(_d, _v) do { \ ++ *((uint8*) _d) = (_v) & 0xFF; \ ++ *((uint8*) _d + 1) = ((_v) >> 8) & 0xFF; \ ++ *((uint8*) _d + 2) = ((_v) >> 16) & 0xFF; \ ++ *((uint8*) _d + 3) = ((_v) >> 24) & 0xFF; \ ++} while (0) ++ + int FillRect_32bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) + { + int x, y; +@@ -76,7 +83,7 @@ int FillRect_32bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) + { + for (x = 0; x < nWidth; x++) + { +- *dstp = color32; ++ Data_Write_UINT32(dstp, color32); + dstp++; + } + } +@@ -390,11 +397,13 @@ static int BitBlt_DSPDxax_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi + uint8* patp; + uint32 color32; + HGDI_BITMAP hSrcBmp; ++ uint32 pat; + + /* D = (S & P) | (~S & D) */ + /* DSPDxax, used to draw glyphs */ + + color32 = gdi_get_color_32bpp(hdcDest, hdcDest->textColor); ++ Data_Write_UINT32(&pat, color32); + + hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; + srcp = hSrcBmp->data; +@@ -414,7 +423,7 @@ static int BitBlt_DSPDxax_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi + { + for (x = 0; x < nWidth; x++) + { +- patp = (uint8*) &color32; ++ patp = (uint8*) &pat; + + *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); + dstp++; +@@ -609,7 +618,7 @@ static int BitBlt_PATCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi + { + for (x = 0; x < nWidth; x++) + { +- *dstp = color32; ++ Data_Write_UINT32(dstp, color32); + dstp++; + } + } +@@ -642,10 +651,12 @@ static int BitBlt_PATINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n + uint32* dstp; + uint32* patp; + uint32 color32; +- ++ uint32 pat; ++ + if (hdcDest->brush->style == GDI_BS_SOLID) + { + color32 = gdi_get_color_32bpp(hdcDest, hdcDest->brush->color); ++ Data_Write_UINT32(&pat, color32); + + for (y = 0; y < nHeight; y++) + { +@@ -655,7 +666,7 @@ static int BitBlt_PATINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int n + { + for (x = 0; x < nWidth; x++) + { +- *dstp ^= color32; ++ *dstp ^= pat; + dstp++; + } + } +-- +2.14.2 + diff --git a/SOURCES/Fix-smartcard-usage-in-manpage.patch b/SOURCES/Fix-smartcard-usage-in-manpage.patch new file mode 100644 index 0000000..b3dee4f --- /dev/null +++ b/SOURCES/Fix-smartcard-usage-in-manpage.patch @@ -0,0 +1,28 @@ +From ed30c466c91dc3888352ca11bfc4cb36f34f0265 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Thu, 25 Jan 2018 13:19:39 +0100 +Subject: [PATCH] Fix smartcard usage in manpage + +Man page has been updated according to the wiki. Unfortunately, wiki +mentions "smartcard" subplugin, which was introduced later, but +stable-1.0 uses just scard. Let's fix the man page accordingly. +--- + client/X11/xfreerdp.1.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/client/X11/xfreerdp.1.xml b/client/X11/xfreerdp.1.xml +index 3b1dc675e..039e87d92 100644 +--- a/client/X11/xfreerdp.1.xml ++++ b/client/X11/xfreerdp.1.xml +@@ -539,7 +539,7 @@ + + + +- smartcard[:name] ++ scard[:name] + + + Redirect smartcard with name. +-- +2.16.1 + diff --git a/SOURCES/Fixed-a-possible-buffer-overflow-issue.patch b/SOURCES/Fixed-a-possible-buffer-overflow-issue.patch index 9053d62..8871085 100644 --- a/SOURCES/Fixed-a-possible-buffer-overflow-issue.patch +++ b/SOURCES/Fixed-a-possible-buffer-overflow-issue.patch @@ -12,7 +12,7 @@ index 2fbaa2c..ed4d0cb 100644 --- a/libfreerdp-core/tls.c +++ b/libfreerdp-core/tls.c @@ -268,7 +268,7 @@ boolean tls_match_hostname(char *pattern, int pattern_length, char *hostname) - return TRUE; + return true; } - if (pattern_length > 2 && pattern[0] == '*' && pattern[1] == '.') diff --git a/SOURCES/Using-the-more-efficient-code-for-comparing-host-nam.patch b/SOURCES/Using-the-more-efficient-code-for-comparing-host-nam.patch index 617a339..f9943c3 100644 --- a/SOURCES/Using-the-more-efficient-code-for-comparing-host-nam.patch +++ b/SOURCES/Using-the-more-efficient-code-for-comparing-host-nam.patch @@ -12,7 +12,7 @@ index db09960..2fbaa2c 100644 --- a/libfreerdp-core/tls.c +++ b/libfreerdp-core/tls.c @@ -268,30 +268,6 @@ boolean tls_match_hostname(char *pattern, int pattern_length, char *hostname) - return TRUE; + return true; } - /* ccpp: Check for wildcard certificates */ @@ -34,7 +34,7 @@ index db09960..2fbaa2c 100644 - - if (hostname[hostname_position] != pattern[pattern_position] ) - { -- return FALSE; +- return false; - } - } - } diff --git a/SOURCES/release-keys-when-xfreerdp-is-unfocused-to-prevent-s.patch b/SOURCES/release-keys-when-xfreerdp-is-unfocused-to-prevent-s.patch new file mode 100644 index 0000000..c1341c2 --- /dev/null +++ b/SOURCES/release-keys-when-xfreerdp-is-unfocused-to-prevent-s.patch @@ -0,0 +1,47 @@ +From 1d12ad20cbd07b0aeb49ac9544de451c9f43f04c Mon Sep 17 00:00:00 2001 +From: Seray Rosh +Date: Fri, 27 Feb 2015 16:02:40 +0100 +Subject: [PATCH 2/2] release keys when xfreerdp is unfocused to prevent stuck + keys + +https://github.com/FreeRDP/FreeRDP/issues/2104 +https://github.com/FreeRDP/FreeRDP/pull/2430 + +Backported by Ondrej Holy . +--- + client/X11/xf_event.c | 2 ++ + client/X11/xf_keyboard.c | 5 +++++ + 2 files changed, 7 insertions(+) + +diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c +index cbcfc65..1475214 100644 +--- a/client/X11/xf_event.c ++++ b/client/X11/xf_event.c +@@ -356,6 +356,8 @@ boolean xf_event_FocusOut(xfInfo* xfi, XEvent* event, boolean app) + if (event->xfocus.mode == NotifyWhileGrabbed) + XUngrabKeyboard(xfi->display, CurrentTime); + ++ xf_kbd_release_all_keypress(xfi); ++ + if (app) + xf_rail_send_activate(xfi, event->xany.window, false); + +diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c +index e94b362..fb14015 100644 +--- a/client/X11/xf_keyboard.c ++++ b/client/X11/xf_keyboard.c +@@ -63,6 +63,11 @@ void xf_kbd_release_all_keypress(xfInfo* xfi) + { + rdp_scancode = freerdp_kbd_get_scancode_by_keycode(keycode, &extended); + ++ // release tab before releasing the windows key. ++ // this stops the start menu from opening on unfocus event. ++ if (rdp_scancode == 0x5B && extended) /* Left Windows Key */ ++ xfi->instance->input->KeyboardEvent(xfi->instance->input, KBD_FLAGS_RELEASE, 0x0F); /* Tab up */ ++ + flags = KBD_FLAGS_RELEASE; + flags |= (extended) ? KBD_FLAGS_EXTENDED : 0; + xfi->instance->input->KeyboardEvent(xfi->instance->input, flags, rdp_scancode); +-- +2.9.3 + diff --git a/SOURCES/remove-unncessary-NULL-ptr-check.patch b/SOURCES/remove-unncessary-NULL-ptr-check.patch new file mode 100644 index 0000000..e7e0d01 --- /dev/null +++ b/SOURCES/remove-unncessary-NULL-ptr-check.patch @@ -0,0 +1,29 @@ +From 4720596d610e5406d0445433f1a079fc84858fa7 Mon Sep 17 00:00:00 2001 +From: cool +Date: Thu, 9 Feb 2012 22:20:52 -1100 +Subject: [PATCH] remove unncessary NULL ptr check + +--- + libfreerdp-utils/memory.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/libfreerdp-utils/memory.c b/libfreerdp-utils/memory.c +index d4d17a620..676fd3ffa 100644 +--- a/libfreerdp-utils/memory.c ++++ b/libfreerdp-utils/memory.c +@@ -82,12 +82,6 @@ void* xrealloc(void* ptr, size_t size) + if (size < 1) + size = 1; + +- if (ptr == NULL) +- { +- printf("xrealloc: null pointer given\n"); +- return NULL; +- } +- + mem = realloc(ptr, size); + + if (mem == NULL) +-- +2.14.1 + diff --git a/SOURCES/tls-enable-tls-1.patch b/SOURCES/tls-enable-tls-1.patch new file mode 100644 index 0000000..f20d76f --- /dev/null +++ b/SOURCES/tls-enable-tls-1.patch @@ -0,0 +1,32 @@ +diff --git a/libfreerdp-core/tls.c b/libfreerdp-core/tls.c +index 106f9cae3..2e3f32d63 100644 +--- a/libfreerdp-core/tls.c ++++ b/libfreerdp-core/tls.c +@@ -26,8 +26,9 @@ boolean tls_connect(rdpTls* tls) + { + int connection_status; + char *hostname; ++ int options = 0; + +- tls->ctx = SSL_CTX_new(TLSv1_client_method()); ++ tls->ctx = SSL_CTX_new(SSLv23_client_method()); + + if (tls->ctx == NULL) + { +@@ -43,7 +44,15 @@ boolean tls_connect(rdpTls* tls) + * block padding is normally used, but the Microsoft TLS implementation + * won't recognize it and will disconnect you after sending a TLS alert. + */ +- SSL_CTX_set_options(tls->ctx, SSL_OP_ALL); ++ options |= SSL_OP_ALL; ++ ++ /** ++ * disable SSLv2 and SSLv3 ++ */ ++ options |= SSL_OP_NO_SSLv2; ++ options |= SSL_OP_NO_SSLv3; ++ ++ SSL_CTX_set_options(tls->ctx, options); + + tls->ssl = SSL_new(tls->ctx); + diff --git a/SOURCES/x11-release-all-pressed-keys-when-window-is-unmapped.patch b/SOURCES/x11-release-all-pressed-keys-when-window-is-unmapped.patch new file mode 100644 index 0000000..097ce39 --- /dev/null +++ b/SOURCES/x11-release-all-pressed-keys-when-window-is-unmapped.patch @@ -0,0 +1,75 @@ +From 4db610f292aca3ae4ed0bb59ed1972202a1c6b27 Mon Sep 17 00:00:00 2001 +From: Vic Lee +Date: Wed, 11 Apr 2012 12:37:47 +0800 +Subject: [PATCH 1/2] x11: release all pressed keys when window is unmapped. + +https://github.com/FreeRDP/FreeRDP/pull/547 + +Backported by Ondrej Holy . +--- + client/X11/xf_event.c | 2 ++ + client/X11/xf_keyboard.c | 22 ++++++++++++++++++++++ + client/X11/xf_keyboard.h | 1 + + 3 files changed, 25 insertions(+) + +diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c +index b5c381f..cbcfc65 100644 +--- a/client/X11/xf_event.c ++++ b/client/X11/xf_event.c +@@ -507,6 +507,8 @@ boolean xf_event_UnmapNotify(xfInfo* xfi, XEvent* event, boolean app) + rdpWindow* window; + rdpRail* rail = ((rdpContext*) xfi->context)->rail; + ++ xf_kbd_release_all_keypress(xfi); ++ + if (app != true) + return true; + +diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c +index cb82fa4..e94b362 100644 +--- a/client/X11/xf_keyboard.c ++++ b/client/X11/xf_keyboard.c +@@ -50,6 +50,28 @@ void xf_kbd_unset_keypress(xfInfo* xfi, uint8 keycode) + return; + } + ++void xf_kbd_release_all_keypress(xfInfo* xfi) ++{ ++ int keycode; ++ uint16 flags; ++ uint8 rdp_scancode; ++ boolean extended; ++ ++ for (keycode = 0; keycode < sizeof(xfi->pressed_keys) / sizeof(xfi->pressed_keys[0]); keycode++) ++ { ++ if (xfi->pressed_keys[keycode] != NoSymbol) ++ { ++ rdp_scancode = freerdp_kbd_get_scancode_by_keycode(keycode, &extended); ++ ++ flags = KBD_FLAGS_RELEASE; ++ flags |= (extended) ? KBD_FLAGS_EXTENDED : 0; ++ xfi->instance->input->KeyboardEvent(xfi->instance->input, flags, rdp_scancode); ++ ++ xfi->pressed_keys[keycode] = NoSymbol; ++ } ++ } ++} ++ + boolean xf_kbd_key_pressed(xfInfo* xfi, KeySym keysym) + { + KeyCode keycode = XKeysymToKeycode(xfi->display, keysym); +diff --git a/client/X11/xf_keyboard.h b/client/X11/xf_keyboard.h +index 92e08fc..e316f07 100644 +--- a/client/X11/xf_keyboard.h ++++ b/client/X11/xf_keyboard.h +@@ -28,6 +28,7 @@ + void xf_kbd_init(xfInfo* xfi); + void xf_kbd_set_keypress(xfInfo* xfi, uint8 keycode, KeySym keysym); + void xf_kbd_unset_keypress(xfInfo* xfi, uint8 keycode); ++void xf_kbd_release_all_keypress(xfInfo* xfi); + boolean xf_kbd_key_pressed(xfInfo* xfi, KeySym keysym); + void xf_kbd_send_key(xfInfo* xfi, boolean down, uint8 keycode); + int xf_kbd_read_keyboard_state(xfInfo* xfi); +-- +2.9.3 + diff --git a/SPECS/freerdp.spec b/SPECS/freerdp.spec index 64c1cac..2a39343 100644 --- a/SPECS/freerdp.spec +++ b/SPECS/freerdp.spec @@ -1,6 +1,6 @@ Name: freerdp Version: 1.0.2 -Release: 10%{?dist} +Release: 15%{?dist} Summary: Remote Desktop Protocol client Group: Applications/Communications @@ -30,7 +30,6 @@ Requires: %{name}-plugins%{?_isa} = %{version}-%{release} Patch0: 0001-xfreerdp.1.xml-Don-t-claim-to-support-multiple-conne.patch Patch1: 0002-Replace-itemizedlist-s-with-variablelist-s.patch -Patch2: 0003-List-plugins-available-in-RHEL-6.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1186916 Patch3: libfreerdp-core-fix-issue-436.patch @@ -54,6 +53,36 @@ Patch9: 1-Add-support-for-Wildcard-Certificates-2-For-Gatewa.patch Patch10: Using-the-more-efficient-code-for-comparing-host-nam.patch Patch11: Fixed-a-possible-buffer-overflow-issue.patch +# Prevent stucked keys on focus out and unmap events +# https://bugzilla.redhat.com/show_bug.cgi?id=1415069 +Patch12: x11-release-all-pressed-keys-when-window-is-unmapped.patch +Patch13: release-keys-when-xfreerdp-is-unfocused-to-prevent-s.patch + +# Fix crashes when copying images +# https://bugzilla.redhat.com/show_bug.cgi?id=1417536 +Patch14: remove-unncessary-NULL-ptr-check.patch + +# Enable TLS 1.1 connections and later +# https://bugzilla.redhat.com/show_bug.cgi?id=1312967 +Patch15: tls-enable-tls-1.patch + +# Add description for available plugins +# https://bugzilla.redhat.com/show_bug.cgi?id=1428041 +Patch16: Add-description-for-available-plugins.patch +Patch20: Fix-smartcard-usage-in-manpage.patch + +# Fix NTLM on big endian +# https://bugzilla.redhat.com/show_bug.cgi?id=1204742 +Patch17: Fix-NTLM-on-big-endian.patch + +# Fix colors on big endian +# https://bugzilla.redhat.com/show_bug.cgi?id=1308810 +Patch18: Fix-colors-on-big-endian.patch + +# Add FIPS mode support +# https://bugzilla.redhat.com/show_bug.cgi?id=1363811 +Patch19: FIPS-mode-support.patch + %description The xfreerdp Remote Desktop Protocol (RDP) client from the FreeRDP project. @@ -101,7 +130,6 @@ developing applications that use %{name}-libs. %patch0 -p1 %patch1 -p1 -%patch2 -p1 %patch3 -p1 -b .fix-invalid-dereference %patch4 -p1 -b .fix-crashes-in-pulseaudio %patch5 -p1 -b .rdpsnd-pulse-fix-crash-if-device-isn-t-specified @@ -111,6 +139,15 @@ developing applications that use %{name}-libs. %patch9 -p1 -b .1-Add-support-for-Wildcard-Certificates-2-For-Gatewa %patch10 -p1 -b .Using-the-more-efficient-code-for-comparing-host-nam %patch11 -p1 -b .Fixed-a-possible-buffer-overflow-issue +%patch12 -p1 -b .x11-release-all-pressed-keys-when-window-is-unmapped +%patch13 -p1 -b .release-keys-when-xfreerdp-is-unfocused-to-prevent-s +%patch14 -p1 -b .remove-unncessary-NULL-ptr-check +%patch15 -p1 -b .tls-enable-tls-1 +%patch16 -p1 -b .Add-description-for-available-plugins +%patch17 -p1 -b .Fix-NTLM-on-big-endian +%patch18 -p1 -b .Fix-colors-on-big-endian +%patch19 -p1 -b .FIPS-mode-support +%patch20 -p1 -b .Fix-smartcard-usage-in-manpage cat << EOF > xfreerdp.desktop [Desktop Entry] @@ -200,6 +237,25 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %changelog +* Wed Jan 31 2018 Ondrej Holy - 1.0.2-15 +- Fix smartcard usage in manpage (#1428041) + +* Thu Nov 23 2017 Ondrej Holy - 1.0.2-14 +- Add FIPS mode support (#1363811) + +* Thu Oct 5 2017 Ondrej Holy - 1.0.2-13 +- Fix NTLM on big endian (#1204742) +- Fix colors on big endian (#1308810) + +* Thu Sep 21 2017 Ondrej Holy - 1.0.2-12 +- Add description for available plugins (#1428041) + +* Thu Sep 7 2017 Ondrej Holy - 1.0.2-11 +- Use boolean types defined stdbool.h (#1404575) +- Prevent stucked keys on focus out and unmap events (#1415069) +- Fix crashes when copying images (#1417536) +- Enable TLS 1.1 connections and later (#1312967) + * Mon Apr 18 2016 Ondrej Holy - 1.0.2-10 - Add support for wildcard certificates (#1275241)