From 1dd33b49d53b458d82e6d2ddf752ce3a433b60a8 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Tue, 17 Jan 2012 10:45:10 +0100 Subject: [PATCH 01/13] The ber_write_length() function can store variable number of bytes (one or three). We can't tell until we write other data and know the length, so don't assume how much space will by consumed to store length. Bug was observed with the mcs_write_connect_response() function, where the function assumed that application tag will take three bytes, but it was taking five. --- libfreerdp-core/mcs.c | 85 +++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 51 deletions(-) diff --git a/libfreerdp-core/mcs.c b/libfreerdp-core/mcs.c index af5f15b72..b2524c6c1 100644 --- a/libfreerdp-core/mcs.c +++ b/libfreerdp-core/mcs.c @@ -273,26 +273,22 @@ boolean mcs_read_domain_parameters(STREAM* s, DomainParameters* domainParameters void mcs_write_domain_parameters(STREAM* s, DomainParameters* domainParameters) { int length; - uint8 *bm, *em; + STREAM* tmps; - stream_get_mark(s, bm); - stream_seek(s, 2); - - ber_write_integer(s, domainParameters->maxChannelIds); - ber_write_integer(s, domainParameters->maxUserIds); - ber_write_integer(s, domainParameters->maxTokenIds); - ber_write_integer(s, domainParameters->numPriorities); - ber_write_integer(s, domainParameters->minThroughput); - ber_write_integer(s, domainParameters->maxHeight); - ber_write_integer(s, domainParameters->maxMCSPDUsize); - ber_write_integer(s, domainParameters->protocolVersion); - - stream_get_mark(s, em); - length = (em - bm) - 2; - stream_set_mark(s, bm); + tmps = stream_new(stream_get_size(s)); + ber_write_integer(tmps, domainParameters->maxChannelIds); + ber_write_integer(tmps, domainParameters->maxUserIds); + ber_write_integer(tmps, domainParameters->maxTokenIds); + ber_write_integer(tmps, domainParameters->numPriorities); + ber_write_integer(tmps, domainParameters->minThroughput); + ber_write_integer(tmps, domainParameters->maxHeight); + ber_write_integer(tmps, domainParameters->maxMCSPDUsize); + ber_write_integer(tmps, domainParameters->protocolVersion); + length = stream_get_length(tmps); ber_write_sequence_tag(s, length); - stream_set_mark(s, em); + stream_write(s, stream_get_head(tmps), length); + stream_free(tmps); } /** @@ -377,41 +373,36 @@ boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s) void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data) { int length; - uint8 *bm, *em; + STREAM* tmps; - int gcc_CCrq_length = stream_get_length(user_data); - - stream_get_mark(s, bm); - stream_seek(s, 5); + tmps = stream_new(stream_get_size(s)); /* callingDomainSelector (OCTET_STRING) */ - ber_write_octet_string(s, callingDomainSelector, sizeof(callingDomainSelector)); + ber_write_octet_string(tmps, callingDomainSelector, sizeof(callingDomainSelector)); /* calledDomainSelector (OCTET_STRING) */ - ber_write_octet_string(s, calledDomainSelector, sizeof(calledDomainSelector)); + ber_write_octet_string(tmps, calledDomainSelector, sizeof(calledDomainSelector)); /* upwardFlag (BOOLEAN) */ - ber_write_boolean(s, true); + ber_write_boolean(tmps, true); /* targetParameters (DomainParameters) */ - mcs_write_domain_parameters(s, &mcs->targetParameters); + mcs_write_domain_parameters(tmps, &mcs->targetParameters); /* minimumParameters (DomainParameters) */ - mcs_write_domain_parameters(s, &mcs->minimumParameters); + mcs_write_domain_parameters(tmps, &mcs->minimumParameters); /* maximumParameters (DomainParameters) */ - mcs_write_domain_parameters(s, &mcs->maximumParameters); + mcs_write_domain_parameters(tmps, &mcs->maximumParameters); /* userData (OCTET_STRING) */ - ber_write_octet_string(s, user_data->data, gcc_CCrq_length); - - stream_get_mark(s, em); - length = (em - bm) - 5; - stream_set_mark(s, bm); + ber_write_octet_string(tmps, user_data->data, stream_get_length(user_data)); + length = stream_get_length(tmps); /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */ ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length); - stream_set_mark(s, em); + stream_write(s, stream_get_head(tmps), length); + stream_free(tmps); } /** @@ -425,28 +416,20 @@ void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data) void mcs_write_connect_response(STREAM* s, rdpMcs* mcs, STREAM* user_data) { int length; - uint8 *bm, *em; - - int gcc_CCrsp_length = stream_get_length(user_data); - - stream_get_mark(s, bm); - stream_seek(s, 3); - - ber_write_enumerated(s, 0, MCS_Result_enum_length); - ber_write_integer(s, 0); /* calledConnectId */ + STREAM* tmps; + tmps = stream_new(stream_get_size(s)); + ber_write_enumerated(tmps, 0, MCS_Result_enum_length); + ber_write_integer(tmps, 0); /* calledConnectId */ mcs->domainParameters = mcs->targetParameters; - mcs_write_domain_parameters(s, &(mcs->domainParameters)); - + mcs_write_domain_parameters(tmps, &(mcs->domainParameters)); /* userData (OCTET_STRING) */ - ber_write_octet_string(s, user_data->data, gcc_CCrsp_length); - - stream_get_mark(s, em); - length = (em - bm) - 3; - stream_set_mark(s, bm); + ber_write_octet_string(tmps, user_data->data, stream_get_length(user_data)); + length = stream_get_length(tmps); ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length); - stream_set_mark(s, em); + stream_write(s, stream_get_head(tmps), length); + stream_free(tmps); } /** From 6f418cb20bd4cdc3a8892df41bd9ac2b9b39434f Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Tue, 17 Jan 2012 17:52:12 +0100 Subject: [PATCH 02/13] PROTOCOL_RDP is 0, so don't perform bitwise operations on it. --- libfreerdp-core/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 3aa60e5ae..e32c4f8a6 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -480,7 +480,7 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s) ret = transport_accept_nla(rdp->transport); else if (rdp->nego->selected_protocol & PROTOCOL_TLS) ret = transport_accept_tls(rdp->transport); - else if (rdp->nego->selected_protocol & PROTOCOL_RDP) + else if (rdp->nego->selected_protocol == PROTOCOL_RDP) /* 0 */ ret = transport_accept_rdp(rdp->transport); if (!ret) From 9b07d525fbbb038601527e29c252070bb32a26f0 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Tue, 17 Jan 2012 17:55:31 +0100 Subject: [PATCH 03/13] Introduce SIGNATURE_ALG_RSA and KEY_EXCHANGE_ALG_RSA defines and use them instead of magic values. --- libfreerdp-core/certificate.c | 2 +- libfreerdp-core/certificate.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libfreerdp-core/certificate.c b/libfreerdp-core/certificate.c index 850e7e06b..fcea2611b 100644 --- a/libfreerdp-core/certificate.c +++ b/libfreerdp-core/certificate.c @@ -279,7 +279,7 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific stream_read_uint32(s, dwSigAlgId); stream_read_uint32(s, dwKeyAlgId); - if (!(dwSigAlgId == 1 && dwKeyAlgId == 1)) + if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)) { printf("certificate_read_server_proprietary_certificate: parse error 1\n"); return false; diff --git a/libfreerdp-core/certificate.h b/libfreerdp-core/certificate.h index b3006e0cc..82962663e 100644 --- a/libfreerdp-core/certificate.h +++ b/libfreerdp-core/certificate.h @@ -36,6 +36,9 @@ #define CERT_PERMANENTLY_ISSUED 0x00000000 #define CERT_TEMPORARILY_ISSUED 0x80000000 +#define SIGNATURE_ALG_RSA 0x00000001 +#define KEY_EXCHANGE_ALG_RSA 0x00000001 + #define BB_RSA_KEY_BLOB 6 #define BB_RSA_SIGNATURE_BLOB 8 From 1de5fbfbbf90ba205f2599c7472c37dd19b38ebc Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 17 Jan 2012 18:22:10 +0100 Subject: [PATCH 04/13] Changed include path for X11 and extensions. X11 and X11/extensions should not be part of X11 include path if X11/xxx.h or X11/extensions/xxx.h is used in source files. --- cmake/FindX11.cmake | 2 +- cmake/FindXKBFile.cmake | 2 +- cmake/FindXShm.cmake | 2 +- cmake/FindXTest.cmake | 2 +- cmake/FindXcursor.cmake | 2 +- cmake/FindXdamage.cmake | 2 +- cmake/FindXext.cmake | 2 +- cmake/FindXfixes.cmake | 2 +- cmake/FindXinerama.cmake | 2 +- cmake/FindXv.cmake | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cmake/FindX11.cmake b/cmake/FindX11.cmake index 91f153339..594b2c022 100644 --- a/cmake/FindX11.cmake +++ b/cmake/FindX11.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(X11_INCLUDE_DIR NAMES Xlib.h +find_path(X11_INCLUDE_DIR NAMES X11/Xlib.h PATH_SUFFIXES X11 DOC "The X11 include directory" ) diff --git a/cmake/FindXKBFile.cmake b/cmake/FindXKBFile.cmake index db76ed6e4..4c0a33374 100644 --- a/cmake/FindXKBFile.cmake +++ b/cmake/FindXKBFile.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XKBFILE_INCLUDE_DIR NAMES XKBfile.h +find_path(XKBFILE_INCLUDE_DIR NAMES X11/extensions/XKBfile.h PATH_SUFFIXES X11/extensions DOC "The XKBFile include directory" ) diff --git a/cmake/FindXShm.cmake b/cmake/FindXShm.cmake index 4ac509168..8213f25e8 100644 --- a/cmake/FindXShm.cmake +++ b/cmake/FindXShm.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XSHM_INCLUDE_DIR NAMES XShm.h +find_path(XSHM_INCLUDE_DIR NAMES X11/extensions/XShm.h PATH_SUFFIXES X11/extensions DOC "The XShm include directory" ) diff --git a/cmake/FindXTest.cmake b/cmake/FindXTest.cmake index ea00dcff8..85fe7b8c8 100644 --- a/cmake/FindXTest.cmake +++ b/cmake/FindXTest.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XTEST_INCLUDE_DIR NAMES XTest.h +find_path(XTEST_INCLUDE_DIR NAMES X11/extensions/XTest.h PATH_SUFFIXES X11/extensions DOC "The XTest include directory" ) diff --git a/cmake/FindXcursor.cmake b/cmake/FindXcursor.cmake index 6217d597e..4eead70bb 100644 --- a/cmake/FindXcursor.cmake +++ b/cmake/FindXcursor.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XCURSOR_INCLUDE_DIR NAMES Xcursor.h +find_path(XCURSOR_INCLUDE_DIR NAMES X11/Xcursor/Xcursor.h PATH_SUFFIXES X11/Xcursor DOC "The Xcursor include directory" ) diff --git a/cmake/FindXdamage.cmake b/cmake/FindXdamage.cmake index 79ea6df9a..61d41587f 100644 --- a/cmake/FindXdamage.cmake +++ b/cmake/FindXdamage.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XDAMAGE_INCLUDE_DIR NAMES Xdamage.h +find_path(XDAMAGE_INCLUDE_DIR NAMES X11/extensions/Xdamage.h PATH_SUFFIXES X11/extensions DOC "The Xdamage include directory" ) diff --git a/cmake/FindXext.cmake b/cmake/FindXext.cmake index 8fd8372c6..8429ec645 100644 --- a/cmake/FindXext.cmake +++ b/cmake/FindXext.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XEXT_INCLUDE_DIR NAMES Xext.h +find_path(XEXT_INCLUDE_DIR NAMES X11/extensions/Xext.h PATH_SUFFIXES X11/extensions DOC "The Xext include directory" ) diff --git a/cmake/FindXfixes.cmake b/cmake/FindXfixes.cmake index f826cf056..c3875766e 100644 --- a/cmake/FindXfixes.cmake +++ b/cmake/FindXfixes.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XFIXES_INCLUDE_DIR NAMES Xfixes.h +find_path(XFIXES_INCLUDE_DIR NAMES X11/extensions/Xfixes.h PATH_SUFFIXES X11/extensions DOC "The Xfixes include directory" ) diff --git a/cmake/FindXinerama.cmake b/cmake/FindXinerama.cmake index c39fb96b4..3f786133b 100644 --- a/cmake/FindXinerama.cmake +++ b/cmake/FindXinerama.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XINERAMA_INCLUDE_DIR NAMES Xinerama.h +find_path(XINERAMA_INCLUDE_DIR NAMES X11/extensions/Xinerama.h PATH_SUFFIXES X11/extensions DOC "The Xinerama include directory" ) diff --git a/cmake/FindXv.cmake b/cmake/FindXv.cmake index 0a4c4e294..e8887d730 100644 --- a/cmake/FindXv.cmake +++ b/cmake/FindXv.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XV_INCLUDE_DIR NAMES Xv.h +find_path(XV_INCLUDE_DIR NAMES X11/extensions/Xv.h PATH_SUFFIXES X11/extensions DOC "The Xv include directory" ) From af5501cdc561a4a5aba98ac02bcdc964f25c8544 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:33:38 +0100 Subject: [PATCH 05/13] Introduce CRYPTO_SHA1_DIGEST_LENGTH and CRYPTO_MD5_DIGEST_LENGTH that hold number of bytes needed for a given hash. --- libfreerdp-core/crypto.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index 47322d5e6..f4eab4130 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -78,11 +78,13 @@ struct crypto_cert_struct X509 * px509; }; +#define CRYPTO_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH typedef struct crypto_sha1_struct* CryptoSha1; CryptoSha1 crypto_sha1_init(void); void crypto_sha1_update(CryptoSha1 sha1, const uint8* data, uint32 length); 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); void crypto_md5_update(CryptoMd5 md5, const uint8* data, uint32 length); From 3bbd2f28c725b252b75d4b7c5b0d0782dd2b9311 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:34:48 +0100 Subject: [PATCH 06/13] Use CRYPTO_*_DIGEST_LENGTH defines instead of magic values. --- libfreerdp-core/security.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libfreerdp-core/security.c b/libfreerdp-core/security.c index 0b17d7dc2..223173281 100644 --- a/libfreerdp-core/security.c +++ b/libfreerdp-core/security.c @@ -118,7 +118,7 @@ static void security_salted_hash(uint8* salt, uint8* input, int length, uint8* s { CryptoMd5 md5; CryptoSha1 sha1; - uint8 sha1_digest[20]; + uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */ @@ -133,7 +133,7 @@ static void security_salted_hash(uint8* salt, uint8* input, int length, uint8* s /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ md5 = crypto_md5_init(); crypto_md5_update(md5, salt, 48); /* Salt (48 bytes) */ - crypto_md5_update(md5, sha1_digest, 20); /* SHA1_Digest */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, output); } @@ -201,7 +201,7 @@ void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* o CryptoMd5 md5; CryptoSha1 sha1; uint8 length_le[4]; - uint8 sha1_digest[20]; + uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; /* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */ @@ -219,7 +219,7 @@ void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* o md5 = crypto_md5_init(); crypto_md5_update(md5, mac_salt_key, 16); /* MacSaltKey */ crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, 20); /* SHA1_Digest */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, output); } @@ -228,8 +228,8 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin CryptoMd5 md5; CryptoSha1 sha1; uint8 length_le[4]; - uint8 md5_digest[16]; - uint8 sha1_digest[20]; + uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; + uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; security_uint32_le(length_le, length); /* length must be little-endian */ @@ -245,7 +245,7 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin md5 = crypto_md5_init(); crypto_md5_update(md5, mac_key, mac_key_length); /* MacKeyN */ crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, 20); /* SHA1_Digest */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, md5_digest); memcpy(output, md5_digest, 8); @@ -313,7 +313,8 @@ boolean security_establish_keys(uint8* client_random, rdpRdp* rdp) if (settings->encryption_method == ENCRYPTION_METHOD_FIPS) { CryptoSha1 sha1; - uint8 client_encrypt_key_t[21], client_decrypt_key_t[21]; + uint8 client_encrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; + uint8 client_decrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; printf("FIPS Compliant encryption level.\n"); @@ -379,7 +380,7 @@ boolean security_establish_keys(uint8* client_random, rdpRdp* rdp) boolean security_key_update(uint8* key, uint8* update_key, int key_len) { - uint8 sha1h[20]; + uint8 sha1h[CRYPTO_SHA1_DIGEST_LENGTH]; CryptoMd5 md5; CryptoSha1 sha1; CryptoRc4 rc4; @@ -394,7 +395,7 @@ boolean security_key_update(uint8* key, uint8* update_key, int key_len) md5 = crypto_md5_init(); crypto_md5_update(md5, update_key, key_len); crypto_md5_update(md5, pad2, sizeof(pad2)); - crypto_md5_update(md5, sha1h, 20); + crypto_md5_update(md5, sha1h, sizeof(sha1h)); crypto_md5_final(md5, key); rc4 = crypto_rc4_init(key, key_len); From a118afa8791bd9acdc502737342121a0b6ecd465 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:39:31 +0100 Subject: [PATCH 07/13] Add Terminal Services Signing Keys. --- libfreerdp-core/crypto.c | 28 ++++++++++++++++++++++++++++ libfreerdp-core/crypto.h | 5 +++++ 2 files changed, 33 insertions(+) diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c index 046fa9562..e9a5f63b5 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -188,6 +188,34 @@ exit: return status; } +/* + * Terminal Services Signing Keys. + * Yes, Terminal Services Private Key is publically available. + */ +const uint8 tssk_modulus[] = { + 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, + 0x4d, 0xbb, 0xc1, 0x1e, 0x4a, 0xba, 0x5f, 0xcb, + 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5, 0xc1, 0xe2, + 0xd7, 0xb7, 0x6b, 0x9a, 0xf2, 0x52, 0x45, 0x95, + 0xce, 0x63, 0x65, 0x6b, 0x58, 0x3a, 0xfe, 0xef, + 0x7c, 0xe7, 0xbf, 0xfe, 0x3d, 0xf6, 0x5c, 0x7d, + 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61, 0xbb, + 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87 +}; +const uint8 tssk_privateExponent[] = { + 0x87, 0xa7, 0x19, 0x32, 0xda, 0x11, 0x87, 0x55, + 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xf8, + 0x24, 0x3e, 0xe6, 0xfa, 0xe9, 0x67, 0x49, 0x94, + 0xcf, 0x92, 0xcc, 0x33, 0x99, 0xe8, 0x08, 0x60, + 0x17, 0x9a, 0x12, 0x9f, 0x24, 0xdd, 0xb1, 0x24, + 0x99, 0xc7, 0x3a, 0xb8, 0x0a, 0x7b, 0x0d, 0xdd, + 0x35, 0x07, 0x79, 0x17, 0x0b, 0x51, 0x9b, 0xb3, + 0xc7, 0x10, 0x01, 0x13, 0xe7, 0x3f, 0xf3, 0x5f +}; +const uint8 tssk_exponent[] = { + 0x5b, 0x7b, 0x88, 0xc0 +}; + void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) { BN_CTX* ctx; diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index f4eab4130..74d48f775 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -120,6 +120,11 @@ boolean x509_verify_cert(CryptoCert cert, rdpSettings* settings); rdpCertData* crypto_get_cert_data(X509* xcert, char* hostname); boolean crypto_cert_get_public_key(CryptoCert cert, rdpBlob* public_key); +#define TSSK_KEY_LENGTH 64 +extern const uint8 tssk_modulus[]; +extern const uint8 tssk_privateExponent[]; +extern const uint8 tssk_exponent[]; + void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); void crypto_reverse(uint8* data, int length); void crypto_nonce(uint8* nonce, int size); From 44663ab332dd4b49205844dcd4ad17bae11f71e1 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:40:29 +0100 Subject: [PATCH 08/13] Introduce more complete RSA API that implements: - crypto_rsa_public_encrypt() - crypto_rsa_public_decrypt() - crypto_rsa_private_encrypt() - crypto_rsa_private_decrypt() --- libfreerdp-core/connection.c | 2 +- libfreerdp-core/crypto.c | 56 +++++++++++++++++++++++++++++++----- libfreerdp-core/crypto.h | 5 +++- libfreerdp-core/license.c | 2 +- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index e32c4f8a6..3d4634e2b 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -203,7 +203,7 @@ static boolean rdp_establish_keys(rdpRdp* rdp) key_len = rdp->settings->server_cert->cert_info.modulus.length; mod = rdp->settings->server_cert->cert_info.modulus.data; exp = rdp->settings->server_cert->cert_info.exponent; - crypto_rsa_encrypt(client_random, 32, key_len, mod, exp, crypt_client_random); + crypto_rsa_public_encrypt(client_random, 32, key_len, mod, exp, crypt_client_random); /* send crypt client random to server */ length = 7 + 8 + 4 + 4 + key_len + 8; diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c index e9a5f63b5..da0f1f310 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -216,7 +216,7 @@ const uint8 tssk_exponent[] = { 0x5b, 0x7b, 0x88, 0xc0 }; -void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +static void crypto_rsa_common(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, int exponent_size, uint8* output) { BN_CTX* ctx; int output_length; @@ -225,14 +225,14 @@ void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* exponent_reverse; BIGNUM mod, exp, x, y; - input_reverse = (uint8*) xmalloc(2 * MODULUS_MAX_SIZE + EXPONENT_MAX_SIZE); - modulus_reverse = input_reverse + MODULUS_MAX_SIZE; - exponent_reverse = modulus_reverse + MODULUS_MAX_SIZE; + input_reverse = (uint8*) xmalloc(2 * key_length + exponent_size); + modulus_reverse = input_reverse + key_length; + exponent_reverse = modulus_reverse + key_length; memcpy(modulus_reverse, modulus, key_length); crypto_reverse(modulus_reverse, key_length); - memcpy(exponent_reverse, exponent, EXPONENT_MAX_SIZE); - crypto_reverse(exponent_reverse, EXPONENT_MAX_SIZE); + memcpy(exponent_reverse, exponent, exponent_size); + crypto_reverse(exponent_reverse, exponent_size); memcpy(input_reverse, input, length); crypto_reverse(input_reverse, length); @@ -243,7 +243,7 @@ void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const BN_init(&y); BN_bin2bn(modulus_reverse, key_length, &mod); - BN_bin2bn(exponent_reverse, EXPONENT_MAX_SIZE, &exp); + BN_bin2bn(exponent_reverse, exponent_size, &exp); BN_bin2bn(input_reverse, length, &x); BN_mod_exp(&y, &x, &exp, &mod, ctx); @@ -261,6 +261,48 @@ void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const xfree(input_reverse); } +static void crypto_rsa_public(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +{ + + crypto_rsa_common(input, length, key_length, modulus, exponent, EXPONENT_MAX_SIZE, output); +} + +static void crypto_rsa_private(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) +{ + + crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); +} + +void crypto_rsa_public_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +{ + + crypto_rsa_public(input, length, key_length, modulus, exponent, output); +} + +void crypto_rsa_public_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +{ + + crypto_rsa_public(input, length, key_length, modulus, exponent, output); +} + +void crypto_rsa_private_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) +{ + + crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); +} + +void crypto_rsa_private_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) +{ + + crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); +} + +void crypto_rsa_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) +{ + + crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); +} + void crypto_reverse(uint8* data, int length) { int i, j; diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index 74d48f775..6b4d30b74 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -125,7 +125,10 @@ extern const uint8 tssk_modulus[]; extern const uint8 tssk_privateExponent[]; extern const uint8 tssk_exponent[]; -void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); +void crypto_rsa_public_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); +void crypto_rsa_public_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); +void crypto_rsa_private_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output); +void crypto_rsa_private_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output); void crypto_reverse(uint8* data, int length); void crypto_nonce(uint8* nonce, int size); diff --git a/libfreerdp-core/license.c b/libfreerdp-core/license.c index 690dafdc5..016b0225f 100644 --- a/libfreerdp-core/license.c +++ b/libfreerdp-core/license.c @@ -329,7 +329,7 @@ void license_encrypt_premaster_secret(rdpLicense* license) encrypted_premaster_secret = (uint8*) xmalloc(MODULUS_MAX_SIZE); memset(encrypted_premaster_secret, 0, MODULUS_MAX_SIZE); - crypto_rsa_encrypt(license->premaster_secret, PREMASTER_SECRET_LENGTH, + crypto_rsa_public_encrypt(license->premaster_secret, PREMASTER_SECRET_LENGTH, key_length, modulus, exponent, encrypted_premaster_secret); license->encrypted_premaster_secret->type = BB_RANDOM_BLOB; From ab4beb787f38f2b8d00e2576833215c3e4fd87dd Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:42:19 +0100 Subject: [PATCH 09/13] Implement signature verification in Server Security Data packet. Because this signature doesn't protect against anything, only warn the user if it is invalid. --- libfreerdp-core/certificate.c | 54 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/libfreerdp-core/certificate.c b/libfreerdp-core/certificate.c index fcea2611b..0d6b3abb0 100644 --- a/libfreerdp-core/certificate.c +++ b/libfreerdp-core/certificate.c @@ -256,9 +256,48 @@ static boolean certificate_process_server_public_key(rdpCertificate* certificate return true; } -static boolean certificate_process_server_public_signature(rdpCertificate* certificate, STREAM* s, uint32 length) +static boolean certificate_process_server_public_signature(rdpCertificate* certificate, uint8* sigdata, int sigdatalen, STREAM* s, uint32 siglen) { - stream_seek(s, length); + uint8 md5hash[CRYPTO_MD5_DIGEST_LENGTH]; + uint8 encsig[TSSK_KEY_LENGTH + 8]; + uint8 sig[TSSK_KEY_LENGTH]; + CryptoMd5 md5ctx; + int i, sum; + + md5ctx = crypto_md5_init(); + crypto_md5_update(md5ctx, sigdata, sigdatalen); + crypto_md5_final(md5ctx, md5hash); + + stream_read(s, encsig, siglen); + /* Last 8 bytes shall be all zero. */ + for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++) + sum += encsig[i]; + if (sum != 0) { + printf("certificate_process_server_public_signature: invalid signature\n"); + //return false; + } + siglen -= 8; + + crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig); + + /* Verify signature. */ + if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) { + printf("certificate_process_server_public_signature: invalid signature\n"); + //return false; + } + /* + * Verify rest of decrypted data: + * The 17th byte is 0x00. + * The 18th through 62nd bytes are each 0xFF. + * The 63rd byte is 0x01. + */ + for (sum = 0, i = 17; i < 62; i++) + sum += sig[i]; + if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01) { + printf("certificate_process_server_public_signature: invalid signature\n"); + //return false; + } + return true; } @@ -276,7 +315,11 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific uint32 wPublicKeyBlobLen; uint32 wSignatureBlobType; uint32 wSignatureBlobLen; + uint8* sigdata; + int sigdatalen; + /* -4, because we need to include dwVersion */ + sigdata = stream_get_tail(s) - 4; stream_read_uint32(s, dwSigAlgId); stream_read_uint32(s, dwKeyAlgId); if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)) @@ -296,6 +339,7 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific printf("certificate_read_server_proprietary_certificate: parse error 3\n"); return false; } + sigdatalen = stream_get_tail(s) - sigdata; stream_read_uint16(s, wSignatureBlobType); if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB) { @@ -303,7 +347,11 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific return false; } stream_read_uint16(s, wSignatureBlobLen); - if (!certificate_process_server_public_signature(certificate, s, wSignatureBlobLen)) + if (wSignatureBlobLen != 72) { + printf("certificate_process_server_public_signature: invalid signature length (got %d, expected %d)\n", wSignatureBlobLen, 64); + return false; + } + if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen)) { printf("certificate_read_server_proprietary_certificate: parse error 5\n"); return false; From 8238f2369dd62da7c10ca4cbdaeb136468810033 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 05:07:30 +0100 Subject: [PATCH 10/13] - Simplify security_mac_signature() API. - Introduce implementation of security_salted_mac_signature() that would be used to handle packets with SEC_SECURE_CHECKSUM flag. --- libfreerdp-core/rdp.c | 13 ++----------- libfreerdp-core/security.c | 40 +++++++++++++++++++++++++++++++++++--- libfreerdp-core/security.h | 3 ++- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 723f15c53..83a87b539 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -274,8 +274,6 @@ void rdp_write_header(rdpRdp* rdp, STREAM* s, uint16 length, uint16 channel_id) static uint32 rdp_security_stream_out(rdpRdp* rdp, STREAM* s, int length) { - uint32 ml; - uint8* mk; uint8* data; uint32 sec_flags; uint32 pad = 0; @@ -314,10 +312,7 @@ static uint32 rdp_security_stream_out(rdpRdp* rdp, STREAM* s, int length) { data = s->p + 8; length = length - (data - s->data); - - mk = rdp->sign_key; - ml = rdp->rc4_key_len; - security_mac_signature(mk, ml, data, length, s->p); + security_mac_signature(rdp, data, length, s->p); stream_seek(s, 8); security_encrypt(s->p, length, rdp); } @@ -583,8 +578,6 @@ boolean rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, STREAM* s) boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length) { uint8 cmac[8], wmac[8]; - uint32 ml; - uint8* mk; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) { @@ -621,9 +614,7 @@ boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length) stream_read(s, wmac, sizeof(wmac)); length -= sizeof(wmac); security_decrypt(s->p, length, rdp); - mk = rdp->sign_key; - ml = rdp->rc4_key_len; - security_mac_signature(mk, ml, s->p, length, cmac); + security_mac_signature(rdp, s->p, length, cmac); if (memcmp(wmac, cmac, sizeof(wmac)) != 0) { printf("FATAL: invalid packet signature\n"); return false; diff --git a/libfreerdp-core/security.c b/libfreerdp-core/security.c index 223173281..e003b213b 100644 --- a/libfreerdp-core/security.c +++ b/libfreerdp-core/security.c @@ -223,7 +223,7 @@ void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* o crypto_md5_final(md5, output); } -void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uint32 length, uint8* output) +void security_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, uint8* output) { CryptoMd5 md5; CryptoSha1 sha1; @@ -235,7 +235,7 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ sha1 = crypto_sha1_init(); - crypto_sha1_update(sha1, mac_key, mac_key_length); /* MacKeyN */ + crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ crypto_sha1_update(sha1, data, length); /* data */ @@ -243,7 +243,41 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ md5 = crypto_md5_init(); - crypto_md5_update(md5, mac_key, mac_key_length); /* MacKeyN */ + crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ + crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ + crypto_md5_final(md5, md5_digest); + + memcpy(output, md5_digest, 8); +} + +void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, boolean encryption, uint8* output) +{ + CryptoMd5 md5; + CryptoSha1 sha1; + uint8 length_le[4]; + uint8 use_count_le[4]; + uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; + uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + + security_uint32_le(length_le, length); /* length must be little-endian */ + if (encryption) + security_uint32_le(use_count_le, rdp->encrypt_use_count); + else + security_uint32_le(use_count_le, rdp->decrypt_use_count); + + /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ + sha1 = crypto_sha1_init(); + crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ + crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ + crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ + crypto_sha1_update(sha1, data, length); /* data */ + crypto_sha1_update(sha1, use_count_le, sizeof(use_count_le)); /* encryptionCount */ + crypto_sha1_final(sha1, sha1_digest); + + /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ + md5 = crypto_md5_init(); + crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, md5_digest); diff --git a/libfreerdp-core/security.h b/libfreerdp-core/security.h index 6d4b0f5d4..7f338d3fa 100644 --- a/libfreerdp-core/security.h +++ b/libfreerdp-core/security.h @@ -32,7 +32,8 @@ void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8* void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output); void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* output); -void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uint32 length, uint8* output); +void security_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, uint8* output); +void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, boolean encryption, uint8* output); boolean security_establish_keys(uint8* client_random, rdpRdp* rdp); boolean security_encrypt(uint8* data, int length, rdpRdp* rdp); From 164c8a0a67a514abd9626970516dbe77315079b3 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 05:36:23 +0100 Subject: [PATCH 11/13] Whitespace fixes. --- libfreerdp-core/crypto.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c index da0f1f310..426481c92 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -193,14 +193,14 @@ exit: * Yes, Terminal Services Private Key is publically available. */ const uint8 tssk_modulus[] = { - 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, - 0x4d, 0xbb, 0xc1, 0x1e, 0x4a, 0xba, 0x5f, 0xcb, - 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5, 0xc1, 0xe2, - 0xd7, 0xb7, 0x6b, 0x9a, 0xf2, 0x52, 0x45, 0x95, - 0xce, 0x63, 0x65, 0x6b, 0x58, 0x3a, 0xfe, 0xef, - 0x7c, 0xe7, 0xbf, 0xfe, 0x3d, 0xf6, 0x5c, 0x7d, - 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61, 0xbb, - 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87 + 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, + 0x4d, 0xbb, 0xc1, 0x1e, 0x4a, 0xba, 0x5f, 0xcb, + 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5, 0xc1, 0xe2, + 0xd7, 0xb7, 0x6b, 0x9a, 0xf2, 0x52, 0x45, 0x95, + 0xce, 0x63, 0x65, 0x6b, 0x58, 0x3a, 0xfe, 0xef, + 0x7c, 0xe7, 0xbf, 0xfe, 0x3d, 0xf6, 0x5c, 0x7d, + 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61, 0xbb, + 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87 }; const uint8 tssk_privateExponent[] = { 0x87, 0xa7, 0x19, 0x32, 0xda, 0x11, 0x87, 0x55, From 3c61b381c6e011c5e48ae113e8a1b66fb5a6b933 Mon Sep 17 00:00:00 2001 From: Mike Gilbert Date: Sun, 22 Jan 2012 12:14:06 -0500 Subject: [PATCH 12/13] cmake: Add options to enable/disable client/server targets. --- CMakeLists.txt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a051c1424..6c306080c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,8 +163,16 @@ if(NOT WIN32) add_subdirectory(channels) endif() -add_subdirectory(client) -add_subdirectory(server) +option(ENABLE_CLIENT "Build client binaries" ON) +if(ENABLE_CLIENT) + add_subdirectory(client) +endif() + +option(ENABLE_SERVER "Build server binaries" OFF) +if(ENABLE_SERVER) + add_subdirectory(server) +endif() + add_subdirectory(keymaps) # Source package From ff10a65c8edfc775541fa23f96aa052873d34000 Mon Sep 17 00:00:00 2001 From: Mike Gilbert Date: Sun, 22 Jan 2012 12:26:30 -0500 Subject: [PATCH 13/13] Change ENABLE_{CLIENT,SERVER} to WITH_{CLIENT,SERVER}. --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c306080c..6899c34af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,13 +163,13 @@ if(NOT WIN32) add_subdirectory(channels) endif() -option(ENABLE_CLIENT "Build client binaries" ON) -if(ENABLE_CLIENT) +option(WITH_CLIENT "Build client binaries" ON) +if(WITH_CLIENT) add_subdirectory(client) endif() -option(ENABLE_SERVER "Build server binaries" OFF) -if(ENABLE_SERVER) +option(WITH_SERVER "Build server binaries" OFF) +if(WITH_SERVER) add_subdirectory(server) endif()