diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 3b0563dd0..ca1df26e2 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -71,5 +71,7 @@ void rdp_client_connect(rdpRdp* rdp) rdp_send_client_info(rdp); rdp_recv(rdp); + + rdp_recv(rdp); } diff --git a/libfreerdp-core/license.c b/libfreerdp-core/license.c index b16d171ed..4777b6667 100644 --- a/libfreerdp-core/license.c +++ b/libfreerdp-core/license.c @@ -20,14 +20,88 @@ #include "license.h" /** - * Receive an RDP licensing packet.\n - * @msdn{cc240479} - * @param rdp RDP module + * Read a licensing preamble.\n + * @msdn{cc240480} * @param s stream - * @param sec_flags security flags + * @param bMsgType license message type + * @param flags message flags + * @param wMsgSize message size */ -void license_recv(rdpLicense* license, STREAM* s, uint16 sec_flags) +void license_read_preamble(STREAM* s, uint8* bMsgType, uint8* flags, uint16* wMsgSize) +{ + /* preamble (4 bytes) */ + stream_read_uint8(s, *bMsgType); /* bMsgType (1 byte) */ + stream_read_uint8(s, *flags); /* flags (1 byte) */ + stream_read_uint16(s, *wMsgSize); /* wMsgSize (2 bytes) */ +} + +/** + * Write a licensing preamble.\n + * @msdn{cc240480} + * @param s stream + * @param bMsgType license message type + * @param flags message flags + * @param wMsgSize message size + */ + +void license_write_preamble(STREAM* s, uint8 bMsgType, uint8 flags, uint16 wMsgSize) +{ + /* preamble (4 bytes) */ + stream_write_uint8(s, bMsgType); /* bMsgType (1 byte) */ + stream_write_uint8(s, flags); /* flags (1 byte) */ + stream_write_uint16(s, wMsgSize); /* wMsgSize (2 bytes) */ +} + +/** + * Initialize a license packet stream.\n + * @param license license module + * @return stream + */ + +STREAM* license_send_stream_init(rdpLicense* license) +{ + STREAM* s; + s = transport_send_stream_init(license->rdp->transport, 4096); + stream_seek(s, LICENSE_PACKET_HEADER_LENGTH); + return s; +} + +/** + * Send an RDP licensing packet.\n + * @msdn{cc240479} + * @param license license module + * @param s stream + */ + +void license_send(rdpLicense* license, STREAM* s, uint8 type) +{ + int length; + uint16 wMsgSize; + uint16 sec_flags; + + length = stream_get_length(s); + stream_set_pos(s, 0); + + sec_flags = SEC_LICENSE_PKT; + wMsgSize = length - LICENSE_PACKET_HEADER_LENGTH; + + rdp_write_header(license->rdp, s, length); + rdp_write_security_header(s, sec_flags); + license_write_preamble(s, type, PREAMBLE_VERSION_2_0, wMsgSize); + + stream_set_pos(s, length); + transport_write(license->rdp->transport, s); +} + +/** + * Receive an RDP licensing packet.\n + * @msdn{cc240479} + * @param license license module + * @param s stream + */ + +void license_recv(rdpLicense* license, STREAM* s) { uint8 flags; uint8 bMsgType; @@ -35,10 +109,7 @@ void license_recv(rdpLicense* license, STREAM* s, uint16 sec_flags) printf("SEC_LICENSE_PKT\n"); - /* preamble (4 bytes) */ - stream_read_uint8(s, bMsgType); /* bMsgType (1 byte) */ - stream_read_uint8(s, flags); /* flags (1 byte) */ - stream_read_uint16(s, wMsgSize); /* wMsgSize (2 bytes) */ + license_read_preamble(s, &bMsgType, &flags, &wMsgSize); /* preamble (4 bytes) */ printf("bMsgType:%X, flags:%X, wMsgSize:%02x\n", bMsgType, flags, wMsgSize); @@ -46,6 +117,7 @@ void license_recv(rdpLicense* license, STREAM* s, uint16 sec_flags) { case LICENSE_REQUEST: license_read_license_request_packet(license, s); + license_send_new_license_request_packet(license); break; case PLATFORM_CHALLENGE: @@ -71,7 +143,8 @@ void license_recv(rdpLicense* license, STREAM* s, uint16 sec_flags) } /** - * Read PRODUCT_INFO.\n + * Read Product Information (PRODUCT_INFO).\n + * @msdn{cc241915} * @param s stream * @param productInfo product information */ @@ -91,13 +164,58 @@ void license_read_product_info(STREAM* s, PRODUCT_INFO* productInfo) stream_read(s, productInfo->pbProductId, productInfo->cbProductId); } +/** + * Allocate New Product Information (PRODUCT_INFO).\n + * @msdn{cc241915} + * @return new product information + */ + +PRODUCT_INFO* license_new_product_info() +{ + PRODUCT_INFO* productInfo; + + productInfo = (PRODUCT_INFO*) xmalloc(sizeof(PRODUCT_INFO)); + + productInfo->dwVersion = 0; + productInfo->cbCompanyName = 0; + productInfo->pbCompanyName = NULL; + productInfo->cbProductId = 0; + productInfo->pbProductId = NULL; + + return productInfo; +} + +/** + * Free Product Information (PRODUCT_INFO).\n + * @msdn{cc241915} + * @param productInfo product information + */ + +void license_free_product_info(PRODUCT_INFO* productInfo) +{ + if (productInfo->pbCompanyName != NULL) + xfree(productInfo->pbCompanyName); + + if (productInfo->pbProductId != NULL) + xfree(productInfo->pbProductId); + + xfree(productInfo); +} + +/** + * Read License Binary Blob (LICENSE_BINARY_BLOB).\n + * @msdn{cc240481} + * @param s stream + * @param blob license binary blob + */ + void license_read_binary_blob(STREAM* s, LICENSE_BLOB* blob) { uint16 wBlobType; stream_read_uint16(s, wBlobType); /* wBlobType (2 bytes) */ - if (blob->type != wBlobType && blob->type != 0) + if (blob->type != wBlobType && blob->type != BB_ANY_BLOB) { printf("license binary blob type does not match expected type.\n"); return; @@ -112,6 +230,61 @@ void license_read_binary_blob(STREAM* s, LICENSE_BLOB* blob) stream_read(s, blob->data, blob->length); /* blobData */ } +/** + * Write License Binary Blob (LICENSE_BINARY_BLOB).\n + * @msdn{cc240481} + * @param s stream + * @param blob license binary blob + */ + +void license_write_binary_blob(STREAM* s, LICENSE_BLOB* blob) +{ + stream_write_uint16(s, blob->type); /* wBlobType (2 bytes) */ + stream_write_uint16(s, blob->length); /* wBlobLen (2 bytes) */ + + if (blob->length > 0) + stream_write(s, blob->data, blob->length); /* blobData */ +} + +/** + * Allocate New License Binary Blob (LICENSE_BINARY_BLOB).\n + * @msdn{cc240481} + * @return new license binary blob + */ + +LICENSE_BLOB* license_new_binary_blob(uint16 type) +{ + LICENSE_BLOB* blob; + + blob = (LICENSE_BLOB*) xmalloc(sizeof(LICENSE_BLOB)); + blob->type = type; + blob->length = 0; + blob->data = NULL; + + return blob; +} + +/** + * Free License Binary Blob (LICENSE_BINARY_BLOB).\n + * @msdn{cc240481} + * @param blob license binary blob + */ + +void license_free_binary_blob(LICENSE_BLOB* blob) +{ + if (blob->data != NULL) + xfree(blob->data); + + xfree(blob); +} + +/** + * Read License Scope List (SCOPE_LIST).\n + * @msdn{cc241916} + * @param s stream + * @param scopeList scope list + */ + void license_read_scope_list(STREAM* s, SCOPE_LIST* scopeList) { int i; @@ -130,10 +303,45 @@ void license_read_scope_list(STREAM* s, SCOPE_LIST* scopeList) } } +/** + * Allocate New License Scope List (SCOPE_LIST).\n + * @msdn{cc241916} + * @return new scope list + */ + +SCOPE_LIST* license_new_scope_list() +{ + SCOPE_LIST* scopeList; + + scopeList = (SCOPE_LIST*) xmalloc(sizeof(SCOPE_LIST)); + scopeList->count = 0; + scopeList->array = NULL; + + return scopeList; +} + +/** + * Free License Scope List (SCOPE_LIST).\n + * @msdn{cc241916} + * @param scopeList scope list + */ + +void license_free_scope_list(SCOPE_LIST* scopeList) +{ + int i; + + for (i = 0; i < scopeList->count; i++) + { + license_free_binary_blob(&scopeList->array[i]); + } + + xfree(scopeList); +} + /** * Read a LICENSE_REQUEST packet.\n * @msdn{cc241914} - * @param rdp RDP module + * @param license license module * @param s stream */ @@ -145,22 +353,22 @@ void license_read_license_request_packet(rdpLicense* license, STREAM* s) stream_read(s, license->server_random, 32); /* ProductInfo */ - license_read_product_info(s, &(license->product_info)); + license_read_product_info(s, license->product_info); /* KeyExchangeList */ - license_read_binary_blob(s, &(license->key_exchange_list)); + license_read_binary_blob(s, license->key_exchange_list); /* ServerCertificate */ - license_read_binary_blob(s, &(license->server_certificate)); + license_read_binary_blob(s, license->server_certificate); /* ScopeList */ - license_read_scope_list(s, &(license->scope_list)); + license_read_scope_list(s, license->scope_list); } /** * Read a PLATFORM_CHALLENGE packet.\n * @msdn{cc241921} - * @param rdp RDP module + * @param license license module * @param s stream */ @@ -172,7 +380,7 @@ void license_read_platform_challenge_packet(rdpLicense* license, STREAM* s) /** * Read a NEW_LICENSE packet.\n * @msdn{cc241926} - * @param rdp RDP module + * @param license license module * @param s stream */ @@ -184,7 +392,7 @@ void license_read_new_license_packet(rdpLicense* license, STREAM* s) /** * Read an UPGRADE_LICENSE packet.\n * @msdn{cc241924} - * @param rdp RDP module + * @param license license module * @param s stream */ @@ -196,7 +404,7 @@ void license_read_upgrade_license_packet(rdpLicense* license, STREAM* s) /** * Read an ERROR_ALERT packet.\n * @msdn{cc240482} - * @param rdp RDP module + * @param license license module * @param s stream */ @@ -205,12 +413,62 @@ void license_read_error_alert_packet(rdpLicense* license, STREAM* s) } +/** + * Write Platform ID.\n + * @msdn{cc241918} + * @param license license module + * @param s stream + */ + +void license_write_platform_id(rdpLicense* license, STREAM* s) +{ + stream_write_uint8(s, 0); /* Client Operating System Version */ + stream_write_uint8(s, 0); /* Independent Software Vendor (ISV) */ + stream_write_uint16(s, 0x0201); /* Client Software Build */ +} + +/** + * Write a NEW_LICENSE_REQUEST packet.\n + * @msdn{cc241918} + * @param license license module + * @param s stream + */ + +void license_write_new_license_request_packet(rdpLicense* license, STREAM* s) +{ + stream_write_uint32(s, KEY_EXCHANGE_ALG_RSA); /* PreferredKeyExchangeAlg (4 bytes) */ + license_write_platform_id(license, s); /* PlatformId (4 bytes) */ + stream_write(s, license->client_random, 32); /* ClientRandom (32 bytes) */ + license_write_binary_blob(s, license->encrypted_pre_master_secret); /* EncryptedPreMasterSecret */ + license_write_binary_blob(s, license->client_user_name); /* ClientUserName */ + license_write_binary_blob(s, license->client_machine_name); /* ClientMachineName */ +} + +/** + * Send a NEW_LICENSE_REQUEST packet.\n + * @msdn{cc241918} + * @param license license module + */ + +void license_send_new_license_request_packet(rdpLicense* license) +{ + STREAM* s; + + s = license_send_stream_init(license); + + /* TODO: generate keys */ + + license_write_new_license_request_packet(license, s); + + license_send(license, s, NEW_LICENSE_REQUEST); +} + /** * Instantiate new license module. * @return new license module */ -rdpLicense* license_new() +rdpLicense* license_new(rdpRdp* rdp) { rdpLicense* license; @@ -218,8 +476,14 @@ rdpLicense* license_new() if (license != NULL) { - license->key_exchange_list.type = BB_KEY_EXCHG_ALG_BLOB; - license->server_certificate.type = BB_CERTIFICATE_BLOB; + license->rdp = rdp; + license->product_info = license_new_product_info(); + license->key_exchange_list = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB); + license->server_certificate = license_new_binary_blob(BB_CERTIFICATE_BLOB); + license->encrypted_pre_master_secret = license_new_binary_blob(BB_RANDOM_BLOB); + license->client_user_name = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB); + license->client_machine_name = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB); + license->scope_list = license_new_scope_list(); } return license; @@ -234,6 +498,13 @@ void license_free(rdpLicense* license) { if (license != NULL) { + license_free_product_info(license->product_info); + license_free_binary_blob(license->key_exchange_list); + license_free_binary_blob(license->server_certificate); + license_free_binary_blob(license->encrypted_pre_master_secret); + license_free_binary_blob(license->client_user_name); + license_free_binary_blob(license->client_machine_name); + license_free_scope_list(license->scope_list); xfree(license); } } diff --git a/libfreerdp-core/license.h b/libfreerdp-core/license.h index 5364225f3..b78f5299d 100644 --- a/libfreerdp-core/license.h +++ b/libfreerdp-core/license.h @@ -41,6 +41,9 @@ typedef struct rdp_license rdpLicense; #define LICENSE_PKT_SC_MASK (LICENSE_REQUEST | PLATFORM_CHALLENGE | NEW_LICENSE | UPGRADE_LICENSE | ERROR_ALERT) #define LICENSE_PKT_MASK (LICENSE_PKT_CS_MASK | LICENSE_PKT_SC_MASK) +#define LICENSE_PREAMBLE_LENGTH 4 +#define LICENSE_PACKET_HEADER_LENGTH (RDP_PACKET_HEADER_LENGTH + RDP_SECURITY_HEADER_LENGTH + LICENSE_PREAMBLE_LENGTH) + /* Licensing Preamble Flags */ #define PREAMBLE_VERSION_2_0 0x02 #define PREAMBLE_VERSION_3_0 0x03 @@ -48,6 +51,7 @@ typedef struct rdp_license rdpLicense; #define EXTENDED_ERROR_MSG_SUPPORTED 0x80 /* Licensing Binary Blob Types */ +#define BB_ANY_BLOB 0x0000 #define BB_DATA_BLOB 0x0001 #define BB_RANDOM_BLOB 0x0002 #define BB_CERTIFICATE_BLOB 0x0003 @@ -58,6 +62,7 @@ typedef struct rdp_license rdpLicense; #define BB_CLIENT_USER_NAME_BLOB 0x000F #define BB_CLIENT_MACHINE_NAME_BLOB 0x0010 +/* Key Exchange Algorithms */ #define KEY_EXCHANGE_ALG_RSA 0x00000001 typedef struct @@ -84,17 +89,34 @@ typedef struct struct rdp_license { + struct rdp_rdp* rdp; + uint8 client_random[32]; uint8 server_random[32]; - PRODUCT_INFO product_info; - LICENSE_BLOB key_exchange_list; - LICENSE_BLOB server_certificate; - SCOPE_LIST scope_list; + PRODUCT_INFO* product_info; + LICENSE_BLOB* key_exchange_list; + LICENSE_BLOB* server_certificate; + LICENSE_BLOB* client_user_name; + LICENSE_BLOB* client_machine_name; + LICENSE_BLOB* encrypted_pre_master_secret; + SCOPE_LIST* scope_list; }; -void license_recv(rdpLicense* license, STREAM* s, uint16 sec_flags); +void license_send(rdpLicense* license, STREAM* s, uint8 type); +void license_recv(rdpLicense* license, STREAM* s); +STREAM* license_send_stream_init(rdpLicense* license); +PRODUCT_INFO* license_new_product_info(); +void license_free_product_info(PRODUCT_INFO* productInfo); void license_read_product_info(STREAM* s, PRODUCT_INFO* productInfo); + +LICENSE_BLOB* license_new_binary_blob(uint16 type); +void license_free_binary_blob(LICENSE_BLOB* blob); void license_read_binary_blob(STREAM* s, LICENSE_BLOB* blob); +void license_write_binary_blob(STREAM* s, LICENSE_BLOB* blob); + +SCOPE_LIST* license_new_scope_list(); +void license_free_scope_list(SCOPE_LIST* scopeList); +void license_read_scope_list(STREAM* s, SCOPE_LIST* scopeList); void license_read_license_request_packet(rdpLicense* license, STREAM* s); void license_read_platform_challenge_packet(rdpLicense* license, STREAM* s); @@ -102,7 +124,10 @@ void license_read_new_license_packet(rdpLicense* license, STREAM* s); void license_read_upgrade_license_packet(rdpLicense* license, STREAM* s); void license_read_error_alert_packet(rdpLicense* license, STREAM* s); -rdpLicense* license_new(); +void license_write_new_license_request_packet(rdpLicense* license, STREAM* s); +void license_send_new_license_request_packet(rdpLicense* license); + +rdpLicense* license_new(rdpRdp* rdp); void license_free(rdpLicense* license); #endif /* __LICENSE_H */ diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 18f9d1f2f..14fb84592 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -61,6 +61,22 @@ STREAM* rdp_send_stream_init(rdpRdp* rdp) return s; } +/** + * Write an RDP packet header.\n + * @param rdp rdp module + * @param s stream + * @param length RDP packet length + */ + +void rdp_write_header(rdpRdp* rdp, STREAM* s, int length) +{ + mcs_write_domain_mcspdu_header(s, DomainMCSPDU_SendDataRequest, length); + per_write_integer16(s, rdp->mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator */ + per_write_integer16(s, MCS_GLOBAL_CHANNEL_ID, 0); /* channelId */ + stream_write_uint8(s, 0x70); /* dataPriority + segmentation */ + per_write_length(s, length - RDP_PACKET_HEADER_LENGTH); /* userData (OCTET_STRING) */ +} + /** * Send an RDP packet.\n * @param rdp RDP module @@ -74,12 +90,7 @@ void rdp_send(rdpRdp* rdp, STREAM* s) length = stream_get_length(s); stream_set_pos(s, 0); - mcs_write_domain_mcspdu_header(s, DomainMCSPDU_SendDataRequest, length); - - per_write_integer16(s, rdp->mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator */ - per_write_integer16(s, MCS_GLOBAL_CHANNEL_ID, 0); /* channelId */ - stream_write_uint8(s, 0x70); /* dataPriority + segmentation */ - per_write_length(s, length - RDP_PACKET_HEADER_LENGTH); /* userData (OCTET_STRING) */ + rdp_write_header(rdp, s, length); stream_set_pos(s, length); transport_write(rdp->transport, s); @@ -118,11 +129,11 @@ void rdp_recv(rdpRdp* rdp) switch (sec_flags & SEC_PKT_MASK) { case SEC_LICENSE_PKT: - license_recv(rdp->license, s, sec_flags); + license_recv(rdp->license, s); break; case SEC_REDIRECTION_PKT: - rdp_read_redirection_packet(rdp, s, sec_flags); + rdp_read_redirection_packet(rdp, s); break; default: @@ -147,7 +158,7 @@ rdpRdp* rdp_new() { rdp->settings = settings_new(); rdp->transport = transport_new(rdp->settings); - rdp->license = license_new(rdp->license); + rdp->license = license_new(rdp); rdp->nego = nego_new(rdp->transport); rdp->mcs = mcs_new(rdp->transport); } diff --git a/libfreerdp-core/rdp.h b/libfreerdp-core/rdp.h index 9400b4caa..bfe112f4e 100644 --- a/libfreerdp-core/rdp.h +++ b/libfreerdp-core/rdp.h @@ -51,6 +51,7 @@ typedef struct rdp_rdp rdpRdp; #define SEC_PKT_SC_MASK (SEC_LICENSE_PKT | SEC_REDIRECTION_PKT) #define SEC_PKT_MASK (SEC_PKT_CS_MASK | SEC_PKT_SC_MASK) +#define RDP_SECURITY_HEADER_LENGTH 4 #define RDP_PACKET_HEADER_LENGTH (TPDU_DATA_LENGTH + MCS_SEND_DATA_HEADER_LENGTH) struct rdp_rdp @@ -66,6 +67,7 @@ void rdp_read_security_header(STREAM* s, uint16* flags); void rdp_write_security_header(STREAM* s, uint16 flags); STREAM* rdp_send_stream_init(rdpRdp* rdp); +void rdp_write_header(rdpRdp* rdp, STREAM* s, int length); void rdp_send(rdpRdp* rdp, STREAM* s); void rdp_recv(rdpRdp* rdp); diff --git a/libfreerdp-core/redirection.c b/libfreerdp-core/redirection.c index 215cf4c54..cd9624c23 100644 --- a/libfreerdp-core/redirection.c +++ b/libfreerdp-core/redirection.c @@ -27,7 +27,7 @@ * @param sec_flags security flags */ -void rdp_read_redirection_packet(rdpRdp* rdp, STREAM* s, uint16 sec_flags) +void rdp_read_redirection_packet(rdpRdp* rdp, STREAM* s) { printf("SEC_REDIRECTION_PKT\n"); } diff --git a/libfreerdp-core/redirection.h b/libfreerdp-core/redirection.h index b7a83fa6e..03612b053 100644 --- a/libfreerdp-core/redirection.h +++ b/libfreerdp-core/redirection.h @@ -25,6 +25,6 @@ #include #include -void rdp_read_redirection_packet(rdpRdp* rdp, STREAM* s, uint16 sec_flags); +void rdp_read_redirection_packet(rdpRdp* rdp, STREAM* s); #endif /* __REDIRECTION_H */