2 * FreeRDP: A Remote Desktop Protocol Client
3 * T.124 Generic Conference Control (GCC)
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 #include <freerdp/utils/print.h>
23 #include "certificate.h"
26 * T.124 GCC is defined in:
28 * http://www.itu.int/rec/T-REC-T.124-199802-S/en
29 * ITU-T T.124 (02/98): Generic Conference Control
33 * ConnectData ::= SEQUENCE
36 * connectPDU OCTET_STRING
41 * object OBJECT_IDENTIFIER,
42 * h221NonStandard H221NonStandardIdentifier
45 * ConnectGCCPDU ::= CHOICE
47 * conferenceCreateRequest ConferenceCreateRequest,
48 * conferenceCreateResponse ConferenceCreateResponse,
49 * conferenceQueryRequest ConferenceQueryRequest,
50 * conferenceQueryResponse ConferenceQueryResponse,
51 * conferenceJoinRequest ConferenceJoinRequest,
52 * conferenceJoinResponse ConferenceJoinResponse,
53 * conferenceInviteRequest ConferenceInviteRequest,
54 * conferenceInviteResponse ConferenceInviteResponse,
58 * ConferenceCreateRequest ::= SEQUENCE
60 * conferenceName ConferenceName,
61 * convenerPassword Password OPTIONAL,
62 * password Password OPTIONAL,
63 * lockedConference BOOLEAN,
64 * listedConference BOOLEAN,
65 * conductibleConference BOOLEAN,
66 * terminationMethod TerminationMethod,
67 * conductorPrivileges SET OF Privilege OPTIONAL,
68 * conductedPrivileges SET OF Privilege OPTIONAL,
69 * nonConductedPrivileges SET OF Privilege OPTIONAL,
70 * conferenceDescription TextString OPTIONAL,
71 * callerIdentifier TextString OPTIONAL,
72 * userData UserData OPTIONAL,
74 * conferencePriority ConferencePriority OPTIONAL,
75 * conferenceMode ConferenceMode OPTIONAL
78 * ConferenceCreateResponse ::= SEQUENCE
86 * resourcesNotAvailable (2),
87 * rejectedForSymmetryBreaking (3),
88 * lockedConferenceNotSupported (4)
90 * userData UserData OPTIONAL,
94 * ConferenceName ::= SEQUENCE
96 * numeric SimpleNumericString
97 * text SimpleTextString OPTIONAL,
101 * SimpleNumericString ::= NumericString (SIZE (1..255)) (FROM ("0123456789"))
103 * UserData ::= SET OF SEQUENCE
106 * value OCTET_STRING OPTIONAL
109 * H221NonStandardIdentifier ::= OCTET STRING (SIZE (4..255))
111 * UserID ::= DynamicChannelID
113 * ChannelID ::= INTEGER (1..65535)
114 * StaticChannelID ::= INTEGER (1..1000)
115 * DynamicChannelID ::= INTEGER (1001..65535)
120 * OID = 0.0.20.124.0.1
121 * { itu-t(0) recommendation(0) t(20) t124(124) version(0) 1 }
122 * v.1 of ITU-T Recommendation T.124 (Feb 1998): "Generic Conference Control"
124 uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
126 uint8 h221_cs_key[4] = "Duca";
127 uint8 h221_sc_key[4] = "McDn";
130 * Read a GCC Conference Create Request.\n
133 * @param settings rdp settings
136 boolean gcc_read_conference_create_request(STREAM* s, rdpSettings* settings)
144 if (!per_read_choice(s, &choice))
146 if (!per_read_object_identifier(s, t124_02_98_oid))
149 /* ConnectData::connectPDU (OCTET_STRING) */
150 if (!per_read_length(s, &length))
154 if (!per_read_choice(s, &choice))
156 if (!per_read_selection(s, &selection))
159 /* ConferenceCreateRequest::conferenceName */
160 if (!per_read_numeric_string(s, 1)) /* ConferenceName::numeric */
162 if (!per_read_padding(s, 1)) /* padding */
165 /* UserData (SET OF SEQUENCE) */
166 if (!per_read_number_of_sets(s, &number) || number != 1) /* one set of UserData */
168 if (!per_read_choice(s, &choice) || choice != 0xC0) /* UserData::value present + select h221NonStandard (1) */
171 /* h221NonStandard */
172 if (!per_read_octet_string(s, h221_cs_key, 4, 4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */
175 /* userData::value (OCTET_STRING) */
176 if (!per_read_length(s, &length))
178 if (stream_get_left(s) < length)
180 if (!gcc_read_client_data_blocks(s, settings, length))
187 * Write a GCC Conference Create Request.\n
190 * @param user_data client data blocks
193 void gcc_write_conference_create_request(STREAM* s, STREAM* user_data)
196 per_write_choice(s, 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */
197 per_write_object_identifier(s, t124_02_98_oid); /* ITU-T T.124 (02/98) OBJECT_IDENTIFIER */
199 /* ConnectData::connectPDU (OCTET_STRING) */
200 per_write_length(s, stream_get_length(user_data) + 14); /* connectPDU length */
203 per_write_choice(s, 0); /* From ConnectGCCPDU select conferenceCreateRequest (0) of type ConferenceCreateRequest */
204 per_write_selection(s, 0x08); /* select optional userData from ConferenceCreateRequest */
206 /* ConferenceCreateRequest::conferenceName */
207 per_write_numeric_string(s, (uint8*)"1", 1, 1); /* ConferenceName::numeric */
208 per_write_padding(s, 1); /* padding */
210 /* UserData (SET OF SEQUENCE) */
211 per_write_number_of_sets(s, 1); /* one set of UserData */
212 per_write_choice(s, 0xC0); /* UserData::value present + select h221NonStandard (1) */
214 /* h221NonStandard */
215 per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */
217 /* userData::value (OCTET_STRING) */
218 per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of client data blocks */
221 boolean gcc_read_conference_create_response(STREAM* s, rdpSettings* settings)
231 per_read_choice(s, &choice);
232 per_read_object_identifier(s, t124_02_98_oid);
234 /* ConnectData::connectPDU (OCTET_STRING) */
235 per_read_length(s, &length);
238 per_read_choice(s, &choice);
240 /* ConferenceCreateResponse::nodeID (UserID) */
241 per_read_integer16(s, &nodeID, 1001);
243 /* ConferenceCreateResponse::tag (INTEGER) */
244 per_read_integer(s, &tag);
246 /* ConferenceCreateResponse::result (ENUMERATED) */
247 per_read_enumerated(s, &result, MCS_Result_enum_length);
249 /* number of UserData sets */
250 per_read_number_of_sets(s, &number);
252 /* UserData::value present + select h221NonStandard (1) */
253 per_read_choice(s, &choice);
255 /* h221NonStandard */
256 if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
259 /* userData (OCTET_STRING) */
260 per_read_length(s, &length);
261 if (!gcc_read_server_data_blocks(s, settings, length))
263 printf("gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
270 void gcc_write_conference_create_response(STREAM* s, STREAM* user_data)
273 per_write_choice(s, 0);
274 per_write_object_identifier(s, t124_02_98_oid);
276 /* ConnectData::connectPDU (OCTET_STRING) */
277 per_write_length(s, stream_get_length(user_data) + 2);
280 per_write_choice(s, 0x14);
282 /* ConferenceCreateResponse::nodeID (UserID) */
283 per_write_integer16(s, 0x79F3, 1001);
285 /* ConferenceCreateResponse::tag (INTEGER) */
286 per_write_integer(s, 1);
288 /* ConferenceCreateResponse::result (ENUMERATED) */
289 per_write_enumerated(s, 0, MCS_Result_enum_length);
291 /* number of UserData sets */
292 per_write_number_of_sets(s, 1);
294 /* UserData::value present + select h221NonStandard (1) */
295 per_write_choice(s, 0xC0);
297 /* h221NonStandard */
298 per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
300 /* userData (OCTET_STRING) */
301 per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of server data blocks */
304 boolean gcc_read_client_data_blocks(STREAM* s, rdpSettings* settings, int length)
312 pos = stream_get_pos(s);
313 gcc_read_user_data_header(s, &type, &blockLength);
318 if (!gcc_read_client_core_data(s, settings, blockLength - 4))
323 if (!gcc_read_client_security_data(s, settings, blockLength - 4))
328 if (!gcc_read_client_network_data(s, settings, blockLength - 4))
333 if (!gcc_read_client_cluster_data(s, settings, blockLength - 4))
338 if (!gcc_read_client_monitor_data(s, settings, blockLength - 4))
346 length -= blockLength;
347 stream_set_pos(s, pos + blockLength);
353 void gcc_write_client_data_blocks(STREAM* s, rdpSettings* settings)
355 gcc_write_client_core_data(s, settings);
356 gcc_write_client_cluster_data(s, settings);
357 gcc_write_client_security_data(s, settings);
358 gcc_write_client_network_data(s, settings);
360 /* extended client data supported */
362 if (settings->negotiationFlags)
363 gcc_write_client_monitor_data(s, settings);
366 boolean gcc_read_server_data_blocks(STREAM* s, rdpSettings* settings, int length)
373 while (offset < length)
377 if (!gcc_read_user_data_header(s, &type, &blockLength))
379 printf("gcc_read_server_data_blocks: gcc_read_user_data_header failed\n");
386 if (!gcc_read_server_core_data(s, settings))
388 printf("gcc_read_server_data_blocks: gcc_read_server_core_data failed\n");
394 if (!gcc_read_server_security_data(s, settings))
396 printf("gcc_read_server_data_blocks: gcc_read_server_security_data failed\n");
402 if (!gcc_read_server_network_data(s, settings))
404 printf("gcc_read_server_data_blocks: gcc_read_server_network_data failed\n");
410 printf("gcc_read_server_data_blocks: ignoring type=%hu\n", type);
413 offset += blockLength;
414 s->p = holdp + blockLength;
420 void gcc_write_server_data_blocks(STREAM* s, rdpSettings* settings)
422 gcc_write_server_core_data(s, settings);
423 gcc_write_server_network_data(s, settings);
424 gcc_write_server_security_data(s, settings);
427 boolean gcc_read_user_data_header(STREAM* s, uint16* type, uint16* length)
429 stream_read_uint16(s, *type); /* type */
430 stream_read_uint16(s, *length); /* length */
435 if (stream_get_left(s) < *length - 4)
442 * Write a user data header (TS_UD_HEADER).\n
445 * @param type data block type
446 * @param length data block length
449 void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length)
451 stream_write_uint16(s, type); /* type */
452 stream_write_uint16(s, length); /* length */
456 * Read a client core data block (TS_UD_CS_CORE).\n
459 * @param settings rdp settings
462 boolean gcc_read_client_core_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
465 uint16 colorDepth = 0;
466 uint16 postBeta2ColorDepth = 0;
467 uint16 highColorDepth = 0;
468 uint16 supportedColorDepths = 0;
469 uint16 earlyCapabilityFlags = 0;
470 uint32 serverSelectedProtocol = 0;
473 /* Length of all required fields, until imeFileName */
474 if (blockLength < 128)
477 stream_read_uint32(s, version); /* version */
478 settings->rdp_version = (version == RDP_VERSION_4 ? 4 : 7);
480 stream_read_uint16(s, settings->width); /* desktopWidth */
481 stream_read_uint16(s, settings->height); /* desktopHeight */
482 stream_read_uint16(s, colorDepth); /* colorDepth */
483 stream_seek_uint16(s); /* SASSequence (Secure Access Sequence) */
484 stream_read_uint32(s, settings->kbd_layout); /* keyboardLayout */
485 stream_read_uint32(s, settings->client_build); /* clientBuild */
487 /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
488 str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 32);
490 snprintf(settings->client_hostname, sizeof(settings->client_hostname), "%s", str);
493 stream_read_uint32(s, settings->kbd_type); /* keyboardType */
494 stream_read_uint32(s, settings->kbd_subtype); /* keyboardSubType */
495 stream_read_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */
497 stream_seek(s, 64); /* imeFileName */
502 * The following fields are all optional. If one field is present, all of the preceding
503 * fields MUST also be present. If one field is not present, all of the subsequent fields
504 * MUST NOT be present.
505 * We must check the bytes left before reading each field.
512 stream_read_uint16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */
517 stream_seek_uint16(s); /* clientProductID */
522 stream_seek_uint32(s); /* serialNumber */
527 stream_read_uint16(s, highColorDepth); /* highColorDepth */
532 stream_read_uint16(s, supportedColorDepths); /* supportedColorDepths */
537 stream_read_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
540 if (blockLength < 64)
542 str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64);
544 snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str);
550 stream_read_uint8(s, settings->performance_flags); /* connectionType */
555 stream_seek_uint8(s); /* pad1octet */
560 stream_read_uint32(s, serverSelectedProtocol); /* serverSelectedProtocol */
563 if (settings->selected_protocol != serverSelectedProtocol)
567 if (highColorDepth > 0)
568 settings->color_depth = highColorDepth;
569 else if (postBeta2ColorDepth > 0)
571 switch (postBeta2ColorDepth)
573 case RNS_UD_COLOR_4BPP:
574 settings->color_depth = 4;
576 case RNS_UD_COLOR_8BPP:
577 settings->color_depth = 8;
579 case RNS_UD_COLOR_16BPP_555:
580 settings->color_depth = 15;
582 case RNS_UD_COLOR_16BPP_565:
583 settings->color_depth = 16;
585 case RNS_UD_COLOR_24BPP:
586 settings->color_depth = 24;
596 case RNS_UD_COLOR_4BPP:
597 settings->color_depth = 4;
599 case RNS_UD_COLOR_8BPP:
600 settings->color_depth = 8;
611 * Write a client core data block (TS_UD_CS_CORE).\n
614 * @param settings rdp settings
617 void gcc_write_client_core_data(STREAM* s, rdpSettings* settings)
621 size_t clientNameLength;
622 uint8 connectionType;
623 uint16 highColorDepth;
624 uint16 supportedColorDepths;
625 uint16 earlyCapabilityFlags;
626 char* clientDigProductId;
627 size_t clientDigProductIdLength;
629 gcc_write_user_data_header(s, CS_CORE, 216);
631 version = settings->rdp_version >= 5 ? RDP_VERSION_5_PLUS : RDP_VERSION_4;
632 clientName = freerdp_uniconv_out(settings->uniconv, settings->client_hostname, &clientNameLength);
633 clientDigProductId = freerdp_uniconv_out(settings->uniconv, settings->client_product_id, &clientDigProductIdLength);
635 stream_write_uint32(s, version); /* version */
636 stream_write_uint16(s, settings->width); /* desktopWidth */
637 stream_write_uint16(s, settings->height); /* desktopHeight */
638 stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* colorDepth, ignored because of postBeta2ColorDepth */
639 stream_write_uint16(s, RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */
640 stream_write_uint32(s, settings->kbd_layout); /* keyboardLayout */
641 stream_write_uint32(s, settings->client_build); /* clientBuild */
643 /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
644 if (clientNameLength > 30)
646 clientNameLength = 30;
647 clientName[clientNameLength] = 0;
648 clientName[clientNameLength + 1] = 0;
650 stream_write(s, clientName, clientNameLength + 2);
651 stream_write_zero(s, 32 - clientNameLength - 2);
654 stream_write_uint32(s, settings->kbd_type); /* keyboardType */
655 stream_write_uint32(s, settings->kbd_subtype); /* keyboardSubType */
656 stream_write_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */
658 stream_write_zero(s, 64); /* imeFileName */
660 stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */
661 stream_write_uint16(s, 1); /* clientProductID */
662 stream_write_uint32(s, 0); /* serialNumber (should be initialized to 0) */
664 highColorDepth = MIN(settings->color_depth, 24);
666 supportedColorDepths =
667 RNS_UD_24BPP_SUPPORT |
668 RNS_UD_16BPP_SUPPORT |
669 RNS_UD_15BPP_SUPPORT;
671 connectionType = settings->connection_type;
672 earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;
674 if (settings->rfx_codec)
675 connectionType = CONNECTION_TYPE_LAN;
677 if (connectionType != 0)
678 earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;
680 if (settings->color_depth == 32)
682 supportedColorDepths |= RNS_UD_32BPP_SUPPORT;
683 earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
686 stream_write_uint16(s, highColorDepth); /* highColorDepth */
687 stream_write_uint16(s, supportedColorDepths); /* supportedColorDepths */
689 stream_write_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
691 /* clientDigProductId (64 bytes, null-terminated unicode, truncated to 30 characters) */
692 if (clientDigProductIdLength > 62)
694 clientDigProductIdLength = 62;
695 clientDigProductId[clientDigProductIdLength] = 0;
696 clientDigProductId[clientDigProductIdLength + 1] = 0;
698 stream_write(s, clientDigProductId, clientDigProductIdLength + 2);
699 stream_write_zero(s, 64 - clientDigProductIdLength - 2);
700 xfree(clientDigProductId);
702 stream_write_uint8(s, connectionType); /* connectionType */
703 stream_write_uint8(s, 0); /* pad1octet */
705 stream_write_uint32(s, settings->selected_protocol); /* serverSelectedProtocol */
708 boolean gcc_read_server_core_data(STREAM* s, rdpSettings* settings)
711 uint32 clientRequestedProtocols;
713 stream_read_uint32(s, version); /* version */
714 stream_read_uint32(s, clientRequestedProtocols); /* clientRequestedProtocols */
716 if (version == RDP_VERSION_4 && settings->rdp_version > 4)
717 settings->rdp_version = 4;
718 else if (version == RDP_VERSION_5_PLUS && settings->rdp_version < 5)
719 settings->rdp_version = 7;
724 void gcc_write_server_core_data(STREAM* s, rdpSettings* settings)
726 gcc_write_user_data_header(s, SC_CORE, 12);
728 stream_write_uint32(s, settings->rdp_version == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS);
729 stream_write_uint32(s, settings->requested_protocols); /* clientRequestedProtocols */
733 * Read a client security data block (TS_UD_CS_SEC).\n
736 * @param settings rdp settings
739 boolean gcc_read_client_security_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
744 if (settings->encryption)
746 stream_read_uint32(s, settings->encryption_method); /* encryptionMethods */
747 if (settings->encryption_method == 0)
748 stream_read_uint32(s, settings->encryption_method); /* extEncryptionMethods */
758 * Write a client security data block (TS_UD_CS_SEC).\n
761 * @param settings rdp settings
764 void gcc_write_client_security_data(STREAM* s, rdpSettings* settings)
766 gcc_write_user_data_header(s, CS_SECURITY, 12);
768 if (settings->encryption)
770 stream_write_uint32(s, settings->encryption_method); /* encryptionMethods */
771 stream_write_uint32(s, 0); /* extEncryptionMethods */
775 /* French locale, disable encryption */
776 stream_write_uint32(s, 0); /* encryptionMethods */
777 stream_write_uint32(s, settings->encryption_method); /* extEncryptionMethods */
781 boolean gcc_read_server_security_data(STREAM* s, rdpSettings* settings)
785 uint32 serverRandomLen;
786 uint32 serverCertLen;
788 stream_read_uint32(s, settings->encryption_method); /* encryptionMethod */
789 stream_read_uint32(s, settings->encryption_level); /* encryptionLevel */
791 if (settings->encryption_method == 0 && settings->encryption_level == 0)
793 /* serverRandom and serverRandom must not be present */
794 settings->encryption = false;
795 settings->encryption_method = ENCRYPTION_METHOD_NONE;
796 settings->encryption_level = ENCRYPTION_LEVEL_NONE;
800 stream_read_uint32(s, serverRandomLen); /* serverRandomLen */
801 stream_read_uint32(s, serverCertLen); /* serverCertLen */
803 if (serverRandomLen > 0)
806 freerdp_blob_alloc(settings->server_random, serverRandomLen);
807 stream_read(s, settings->server_random->data, serverRandomLen);
814 if (serverCertLen > 0)
816 /* serverCertificate */
817 freerdp_blob_alloc(settings->server_certificate, serverCertLen);
818 stream_read(s, settings->server_certificate->data, serverCertLen);
819 certificate_free(settings->server_cert);
820 settings->server_cert = certificate_new();
821 data = settings->server_certificate->data;
822 length = settings->server_certificate->length;
824 if (!certificate_read_server_certificate(settings->server_cert, data, length))
835 static const uint8 initial_signature[] =
837 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
838 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
839 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
840 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
841 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
842 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
843 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
844 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01
847 void gcc_write_server_security_data(STREAM* s, rdpSettings* settings)
851 int expLen, keyLen, sigDataLen;
852 uint8 encryptedSignature[TSSK_KEY_LENGTH];
853 uint8 signature[sizeof(initial_signature)];
854 uint32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen;
856 if (!settings->encryption)
858 settings->encryption_method = ENCRYPTION_METHOD_NONE;
859 settings->encryption_level = ENCRYPTION_LEVEL_NONE;
861 else if ((settings->encryption_method & ENCRYPTION_METHOD_FIPS) != 0)
863 settings->encryption_method = ENCRYPTION_METHOD_FIPS;
865 else if ((settings->encryption_method & ENCRYPTION_METHOD_128BIT) != 0)
867 settings->encryption_method = ENCRYPTION_METHOD_128BIT;
869 else if ((settings->encryption_method & ENCRYPTION_METHOD_40BIT) != 0)
871 settings->encryption_method = ENCRYPTION_METHOD_40BIT;
874 if (settings->encryption_method != ENCRYPTION_METHOD_NONE)
875 settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
879 wPublicKeyBlobLen = 0;
883 if (settings->encryption_method != ENCRYPTION_METHOD_NONE ||
884 settings->encryption_level != ENCRYPTION_LEVEL_NONE)
886 serverRandomLen = 32;
888 keyLen = settings->server_key->modulus.length;
889 expLen = sizeof(settings->server_key->exponent);
890 wPublicKeyBlobLen = 4; /* magic (RSA1) */
891 wPublicKeyBlobLen += 4; /* keylen */
892 wPublicKeyBlobLen += 4; /* bitlen */
893 wPublicKeyBlobLen += 4; /* datalen */
894 wPublicKeyBlobLen += expLen;
895 wPublicKeyBlobLen += keyLen;
896 wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */
898 serverCertLen = 4; /* dwVersion */
899 serverCertLen += 4; /* dwSigAlgId */
900 serverCertLen += 4; /* dwKeyAlgId */
901 serverCertLen += 2; /* wPublicKeyBlobType */
902 serverCertLen += 2; /* wPublicKeyBlobLen */
903 serverCertLen += wPublicKeyBlobLen;
904 serverCertLen += 2; /* wSignatureBlobType */
905 serverCertLen += 2; /* wSignatureBlobLen */
906 serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */
907 serverCertLen += 8; /* 8 bytes of zero padding */
909 headerLen += sizeof(serverRandomLen);
910 headerLen += sizeof(serverCertLen);
911 headerLen += serverRandomLen;
912 headerLen += serverCertLen;
915 gcc_write_user_data_header(s, SC_SECURITY, headerLen);
917 stream_write_uint32(s, settings->encryption_method); /* encryptionMethod */
918 stream_write_uint32(s, settings->encryption_level); /* encryptionLevel */
920 if (settings->encryption_method == ENCRYPTION_METHOD_NONE &&
921 settings->encryption_level == ENCRYPTION_LEVEL_NONE)
926 stream_write_uint32(s, serverRandomLen); /* serverRandomLen */
927 stream_write_uint32(s, serverCertLen); /* serverCertLen */
929 freerdp_blob_alloc(settings->server_random, serverRandomLen);
930 crypto_nonce(settings->server_random->data, serverRandomLen);
931 stream_write(s, settings->server_random->data, serverRandomLen);
933 sigData = stream_get_tail(s);
935 stream_write_uint32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */
936 stream_write_uint32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */
937 stream_write_uint32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */
938 stream_write_uint16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */
940 stream_write_uint16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */
941 stream_write(s, "RSA1", 4); /* magic */
942 stream_write_uint32(s, keyLen + 8); /* keylen */
943 stream_write_uint32(s, keyLen * 8); /* bitlen */
944 stream_write_uint32(s, keyLen - 1); /* datalen */
946 stream_write(s, settings->server_key->exponent, expLen);
947 stream_write(s, settings->server_key->modulus.data, keyLen);
948 stream_write_zero(s, 8);
950 sigDataLen = stream_get_tail(s) - sigData;
952 stream_write_uint16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */
953 stream_write_uint16(s, keyLen + 8); /* wSignatureBlobLen */
955 memcpy(signature, initial_signature, sizeof(initial_signature));
957 md5 = crypto_md5_init();
958 crypto_md5_update(md5, sigData, sigDataLen);
959 crypto_md5_final(md5, signature);
961 crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH,
962 tssk_modulus, tssk_privateExponent, encryptedSignature);
964 stream_write(s, encryptedSignature, sizeof(encryptedSignature));
965 stream_write_zero(s, 8);
969 * Read a client network data block (TS_UD_CS_NET).\n
972 * @param settings rdp settings
975 boolean gcc_read_client_network_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
982 stream_read_uint32(s, settings->num_channels); /* channelCount */
983 if (blockLength < 4 + settings->num_channels * 12)
985 if (settings->num_channels > 16)
988 /* channelDefArray */
989 for (i = 0; i < settings->num_channels; i++)
992 stream_read(s, settings->channels[i].name, 8); /* name (8 bytes) */
993 stream_read_uint32(s, settings->channels[i].options); /* options (4 bytes) */
994 settings->channels[i].channel_id = MCS_GLOBAL_CHANNEL_ID + 1 + i;
1001 * Write a client network data block (TS_UD_CS_NET).\n
1004 * @param settings rdp settings
1007 void gcc_write_client_network_data(STREAM* s, rdpSettings* settings)
1012 if (settings->num_channels > 0)
1014 length = settings->num_channels * 12 + 8;
1015 gcc_write_user_data_header(s, CS_NET, length);
1017 stream_write_uint32(s, settings->num_channels); /* channelCount */
1019 /* channelDefArray */
1020 for (i = 0; i < settings->num_channels; i++)
1023 stream_write(s, settings->channels[i].name, 8); /* name (8 bytes) */
1024 stream_write_uint32(s, settings->channels[i].options); /* options (4 bytes) */
1029 boolean gcc_read_server_network_data(STREAM* s, rdpSettings* settings)
1032 uint16 MCSChannelId;
1033 uint16 channelCount;
1036 stream_read_uint16(s, MCSChannelId); /* MCSChannelId */
1037 stream_read_uint16(s, channelCount); /* channelCount */
1039 if (channelCount != settings->num_channels)
1041 printf("requested %d channels, got %d instead\n",
1042 settings->num_channels, channelCount);
1045 for (i = 0; i < channelCount; i++)
1047 stream_read_uint16(s, channelId); /* channelId */
1048 settings->channels[i].channel_id = channelId;
1051 if (channelCount % 2 == 1)
1052 stream_seek(s, 2); /* padding */
1057 void gcc_write_server_network_data(STREAM* s, rdpSettings* settings)
1061 gcc_write_user_data_header(s, SC_NET, 8 + settings->num_channels * 2 + (settings->num_channels % 2 == 1 ? 2 : 0));
1063 stream_write_uint16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */
1064 stream_write_uint16(s, settings->num_channels); /* channelCount */
1066 for (i = 0; i < settings->num_channels; i++)
1068 stream_write_uint16(s, settings->channels[i].channel_id);
1071 if (settings->num_channels % 2 == 1)
1072 stream_write_uint16(s, 0);
1076 * Read a client cluster data block (TS_UD_CS_CLUSTER).\n
1079 * @param settings rdp settings
1082 boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
1086 if (blockLength < 8)
1089 stream_read_uint32(s, flags); /* flags */
1091 if ((flags | REDIRECTED_SESSIONID_FIELD_VALID))
1092 stream_read_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
1098 * Write a client cluster data block (TS_UD_CS_CLUSTER).\n
1101 * @param settings rdp settings
1104 void gcc_write_client_cluster_data(STREAM* s, rdpSettings* settings)
1108 gcc_write_user_data_header(s, CS_CLUSTER, 12);
1110 flags = REDIRECTION_SUPPORTED | (REDIRECTION_VERSION4 << 2);
1112 if (settings->console_session || settings->redirected_session_id)
1113 flags |= REDIRECTED_SESSIONID_FIELD_VALID;
1115 stream_write_uint32(s, flags); /* flags */
1116 stream_write_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
1120 * Read a client monitor data block (TS_UD_CS_MONITOR).\n
1123 * @param settings rdp settings
1126 boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
1128 printf("CS_MONITOR\n");
1133 * Write a client monitor data block (TS_UD_CS_MONITOR).\n
1136 * @param settings rdp settings
1139 void gcc_write_client_monitor_data(STREAM* s, rdpSettings* settings)
1143 uint32 left, top, right, bottom, flags;
1145 if (settings->num_monitors > 1)
1147 length = (20 * settings->num_monitors) + 12;
1148 gcc_write_user_data_header(s, CS_MONITOR, length);
1150 stream_write_uint32(s, 0); /* flags */
1151 stream_write_uint32(s, settings->num_monitors); /* monitorCount */
1153 for (i = 0; i < settings->num_monitors; i++)
1155 left = settings->monitors[i].x;
1156 top = settings->monitors[i].y;
1157 right = settings->monitors[i].x + settings->monitors[i].width - 1;
1158 bottom = settings->monitors[i].y + settings->monitors[i].height - 1;
1159 flags = settings->monitors[i].is_primary ? MONITOR_PRIMARY : 0;
1161 stream_write_uint32(s, left); /* left */
1162 stream_write_uint32(s, top); /* top */
1163 stream_write_uint32(s, right); /* right */
1164 stream_write_uint32(s, bottom); /* bottom */
1165 stream_write_uint32(s, flags); /* flags */