Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / gcc.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * T.124 Generic Conference Control (GCC)
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  */
19
20 #include <freerdp/utils/print.h>
21
22 #include "gcc.h"
23 #include "certificate.h"
24
25 /**
26  * T.124 GCC is defined in:
27  *
28  * http://www.itu.int/rec/T-REC-T.124-199802-S/en
29  * ITU-T T.124 (02/98): Generic Conference Control
30  */
31
32 /**
33  * ConnectData ::= SEQUENCE
34  * {
35  *      t124Identifier  Key,
36  *      connectPDU      OCTET_STRING
37  * }
38  *
39  * Key ::= CHOICE
40  * {
41  *      object                          OBJECT_IDENTIFIER,
42  *      h221NonStandard                 H221NonStandardIdentifier
43  * }
44  *
45  * ConnectGCCPDU ::= CHOICE
46  * {
47  *      conferenceCreateRequest         ConferenceCreateRequest,
48  *      conferenceCreateResponse        ConferenceCreateResponse,
49  *      conferenceQueryRequest          ConferenceQueryRequest,
50  *      conferenceQueryResponse         ConferenceQueryResponse,
51  *      conferenceJoinRequest           ConferenceJoinRequest,
52  *      conferenceJoinResponse          ConferenceJoinResponse,
53  *      conferenceInviteRequest         ConferenceInviteRequest,
54  *      conferenceInviteResponse        ConferenceInviteResponse,
55  *      ...
56  * }
57  *
58  * ConferenceCreateRequest ::= SEQUENCE
59  * {
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,
73  *      ...,
74  *      conferencePriority              ConferencePriority OPTIONAL,
75  *      conferenceMode                  ConferenceMode OPTIONAL
76  * }
77  *
78  * ConferenceCreateResponse ::= SEQUENCE
79  * {
80  *      nodeID                          UserID,
81  *      tag                             INTEGER,
82  *      result                          ENUMERATED
83  *      {
84  *              success                         (0),
85  *              userRejected                    (1),
86  *              resourcesNotAvailable           (2),
87  *              rejectedForSymmetryBreaking     (3),
88  *              lockedConferenceNotSupported    (4)
89  *      },
90  *      userData                        UserData OPTIONAL,
91  *      ...
92  * }
93  *
94  * ConferenceName ::= SEQUENCE
95  * {
96  *      numeric                         SimpleNumericString
97  *      text                            SimpleTextString OPTIONAL,
98  *      ...
99  * }
100  *
101  * SimpleNumericString ::= NumericString (SIZE (1..255)) (FROM ("0123456789"))
102  *
103  * UserData ::= SET OF SEQUENCE
104  * {
105  *      key                             Key,
106  *      value                           OCTET_STRING OPTIONAL
107  * }
108  *
109  * H221NonStandardIdentifier ::= OCTET STRING (SIZE (4..255))
110  *
111  * UserID ::= DynamicChannelID
112  *
113  * ChannelID ::= INTEGER (1..65535)
114  * StaticChannelID ::= INTEGER (1..1000)
115  * DynamicChannelID ::= INTEGER (1001..65535)
116  *
117  */
118
119 /*
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"
123  */
124 uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
125
126 uint8 h221_cs_key[4] = "Duca";
127 uint8 h221_sc_key[4] = "McDn";
128
129 /**
130  * Read a GCC Conference Create Request.\n
131  * @msdn{cc240836}
132  * @param s stream
133  * @param settings rdp settings
134  */
135
136 boolean gcc_read_conference_create_request(STREAM* s, rdpSettings* settings)
137 {
138         uint16 length;
139         uint8 choice;
140         uint8 number;
141         uint8 selection;
142
143         /* ConnectData */
144         if (!per_read_choice(s, &choice))
145                 return false;
146         if (!per_read_object_identifier(s, t124_02_98_oid))
147                 return false;
148
149         /* ConnectData::connectPDU (OCTET_STRING) */
150         if (!per_read_length(s, &length))
151                 return false;
152
153         /* ConnectGCCPDU */
154         if (!per_read_choice(s, &choice))
155                 return false;
156         if (!per_read_selection(s, &selection))
157                 return false;
158
159         /* ConferenceCreateRequest::conferenceName */
160         if (!per_read_numeric_string(s, 1)) /* ConferenceName::numeric */
161                 return false;
162         if (!per_read_padding(s, 1)) /* padding */
163                 return false;
164
165         /* UserData (SET OF SEQUENCE) */
166         if (!per_read_number_of_sets(s, &number) || number != 1) /* one set of UserData */
167                 return false;
168         if (!per_read_choice(s, &choice) || choice != 0xC0) /* UserData::value present + select h221NonStandard (1) */
169                 return false;
170
171         /* h221NonStandard */
172         if (!per_read_octet_string(s, h221_cs_key, 4, 4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */
173                 return false;
174
175         /* userData::value (OCTET_STRING) */
176         if (!per_read_length(s, &length))
177                 return false;
178         if (stream_get_left(s) < length)
179                 return false;
180         if (!gcc_read_client_data_blocks(s, settings, length))
181                 return false;
182
183         return true;
184 }
185
186 /**
187  * Write a GCC Conference Create Request.\n
188  * @msdn{cc240836}
189  * @param s stream
190  * @param user_data client data blocks
191  */
192
193 void gcc_write_conference_create_request(STREAM* s, STREAM* user_data)
194 {
195         /* ConnectData */
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 */
198
199         /* ConnectData::connectPDU (OCTET_STRING) */
200         per_write_length(s, stream_get_length(user_data) + 14); /* connectPDU length */
201
202         /* ConnectGCCPDU */
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 */
205
206         /* ConferenceCreateRequest::conferenceName */
207         per_write_numeric_string(s, (uint8*)"1", 1, 1); /* ConferenceName::numeric */
208         per_write_padding(s, 1); /* padding */
209
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) */
213
214         /* h221NonStandard */
215         per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */
216
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 */
219 }
220
221 boolean gcc_read_conference_create_response(STREAM* s, rdpSettings* settings)
222 {
223         uint16 length;
224         uint32 tag;
225         uint16 nodeID;
226         uint8 result;
227         uint8 choice;
228         uint8 number;
229
230         /* ConnectData */
231         per_read_choice(s, &choice);
232         per_read_object_identifier(s, t124_02_98_oid);
233
234         /* ConnectData::connectPDU (OCTET_STRING) */
235         per_read_length(s, &length);
236
237         /* ConnectGCCPDU */
238         per_read_choice(s, &choice);
239
240         /* ConferenceCreateResponse::nodeID (UserID) */
241         per_read_integer16(s, &nodeID, 1001);
242
243         /* ConferenceCreateResponse::tag (INTEGER) */
244         per_read_integer(s, &tag);
245
246         /* ConferenceCreateResponse::result (ENUMERATED) */
247         per_read_enumerated(s, &result, MCS_Result_enum_length);
248
249         /* number of UserData sets */
250         per_read_number_of_sets(s, &number);
251
252         /* UserData::value present + select h221NonStandard (1) */
253         per_read_choice(s, &choice);
254
255         /* h221NonStandard */
256         if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
257                 return false;
258
259         /* userData (OCTET_STRING) */
260         per_read_length(s, &length);
261         if (!gcc_read_server_data_blocks(s, settings, length))
262         {
263                 printf("gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
264                 return false;
265         }
266
267         return true;
268 }
269
270 void gcc_write_conference_create_response(STREAM* s, STREAM* user_data)
271 {
272         /* ConnectData */
273         per_write_choice(s, 0);
274         per_write_object_identifier(s, t124_02_98_oid);
275
276         /* ConnectData::connectPDU (OCTET_STRING) */
277         per_write_length(s, stream_get_length(user_data) + 2);
278
279         /* ConnectGCCPDU */
280         per_write_choice(s, 0x14);
281
282         /* ConferenceCreateResponse::nodeID (UserID) */
283         per_write_integer16(s, 0x79F3, 1001);
284
285         /* ConferenceCreateResponse::tag (INTEGER) */
286         per_write_integer(s, 1);
287
288         /* ConferenceCreateResponse::result (ENUMERATED) */
289         per_write_enumerated(s, 0, MCS_Result_enum_length);
290
291         /* number of UserData sets */
292         per_write_number_of_sets(s, 1);
293
294         /* UserData::value present + select h221NonStandard (1) */
295         per_write_choice(s, 0xC0);
296
297         /* h221NonStandard */
298         per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
299
300         /* userData (OCTET_STRING) */
301         per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of server data blocks */
302 }
303
304 boolean gcc_read_client_data_blocks(STREAM* s, rdpSettings* settings, int length)
305 {
306         uint16 type;
307         uint16 blockLength;
308         int pos;
309
310         while (length > 0)
311         {
312                 pos = stream_get_pos(s);
313                 gcc_read_user_data_header(s, &type, &blockLength);
314
315                 switch (type)
316                 {
317                         case CS_CORE:
318                                 if (!gcc_read_client_core_data(s, settings, blockLength - 4))
319                                         return false;
320                                 break;
321
322                         case CS_SECURITY:
323                                 if (!gcc_read_client_security_data(s, settings, blockLength - 4))
324                                         return false;
325                                 break;
326
327                         case CS_NET:
328                                 if (!gcc_read_client_network_data(s, settings, blockLength - 4))
329                                         return false;
330                                 break;
331
332                         case CS_CLUSTER:
333                                 if (!gcc_read_client_cluster_data(s, settings, blockLength - 4))
334                                         return false;
335                                 break;
336
337                         case CS_MONITOR:
338                                 if (!gcc_read_client_monitor_data(s, settings, blockLength - 4))
339                                         return false;
340                                 break;
341
342                         default:
343                                 break;
344                 }
345
346                 length -= blockLength;
347                 stream_set_pos(s, pos + blockLength);
348         }
349
350         return true;
351 }
352
353 void gcc_write_client_data_blocks(STREAM* s, rdpSettings* settings)
354 {
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);
359
360         /* extended client data supported */
361
362         if (settings->negotiationFlags)
363                 gcc_write_client_monitor_data(s, settings);
364 }
365
366 boolean gcc_read_server_data_blocks(STREAM* s, rdpSettings* settings, int length)
367 {
368         uint16 type;
369         uint16 offset = 0;
370         uint16 blockLength;
371         uint8* holdp;
372
373         while (offset < length)
374         {
375                 holdp = s->p;
376
377                 if (!gcc_read_user_data_header(s, &type, &blockLength))
378                 {
379                         printf("gcc_read_server_data_blocks: gcc_read_user_data_header failed\n");
380                         return false;
381                 }
382
383                 switch (type)
384                 {
385                         case SC_CORE:
386                                 if (!gcc_read_server_core_data(s, settings))
387                                 {
388                                         printf("gcc_read_server_data_blocks: gcc_read_server_core_data failed\n");
389                                         return false;
390                                 }
391                                 break;
392
393                         case SC_SECURITY:
394                                 if (!gcc_read_server_security_data(s, settings))
395                                 {
396                                         printf("gcc_read_server_data_blocks: gcc_read_server_security_data failed\n");
397                                         return false;
398                                 }
399                                 break;
400
401                         case SC_NET:
402                                 if (!gcc_read_server_network_data(s, settings))
403                                 {
404                                         printf("gcc_read_server_data_blocks: gcc_read_server_network_data failed\n");
405                                         return false;
406                                 }
407                                 break;
408
409                         default:
410                                 printf("gcc_read_server_data_blocks: ignoring type=%hu\n", type);
411                                 break;
412                 }
413                 offset += blockLength;
414                 s->p = holdp + blockLength;
415         }
416
417         return true;
418 }
419
420 void gcc_write_server_data_blocks(STREAM* s, rdpSettings* settings)
421 {
422         gcc_write_server_core_data(s, settings);
423         gcc_write_server_network_data(s, settings);
424         gcc_write_server_security_data(s, settings);
425 }
426
427 boolean gcc_read_user_data_header(STREAM* s, uint16* type, uint16* length)
428 {
429         stream_read_uint16(s, *type); /* type */
430         stream_read_uint16(s, *length); /* length */
431
432         if (*length < 4)
433                 return false;
434
435         if (stream_get_left(s) < *length - 4)
436                 return false;
437
438         return true;
439 }
440
441 /**
442  * Write a user data header (TS_UD_HEADER).\n
443  * @msdn{cc240509}
444  * @param s stream
445  * @param type data block type
446  * @param length data block length
447  */
448
449 void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length)
450 {
451         stream_write_uint16(s, type); /* type */
452         stream_write_uint16(s, length); /* length */
453 }
454
455 /**
456  * Read a client core data block (TS_UD_CS_CORE).\n
457  * @msdn{cc240510}
458  * @param s stream
459  * @param settings rdp settings
460  */
461
462 boolean gcc_read_client_core_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
463 {
464         uint32 version;
465         uint16 colorDepth = 0;
466         uint16 postBeta2ColorDepth = 0;
467         uint16 highColorDepth = 0;
468         uint16 supportedColorDepths = 0;
469         uint16 earlyCapabilityFlags = 0;
470         uint32 serverSelectedProtocol = 0;
471         char* str;
472
473         /* Length of all required fields, until imeFileName */
474         if (blockLength < 128)
475                 return false;
476
477         stream_read_uint32(s, version); /* version */
478         settings->rdp_version = (version == RDP_VERSION_4 ? 4 : 7);
479
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 */
486         
487         /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
488         str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 32);
489         stream_seek(s, 32);
490         snprintf(settings->client_hostname, sizeof(settings->client_hostname), "%s", str);
491         xfree(str);
492
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 */
496
497         stream_seek(s, 64); /* imeFileName */
498
499         blockLength -= 128;
500
501         /**
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.
506          */
507
508         do
509         {
510                 if (blockLength < 2)
511                         break;
512                 stream_read_uint16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */
513                 blockLength -= 2;
514
515                 if (blockLength < 2)
516                         break;
517                 stream_seek_uint16(s); /* clientProductID */
518                 blockLength -= 2;
519
520                 if (blockLength < 4)
521                         break;
522                 stream_seek_uint32(s); /* serialNumber */
523                 blockLength -= 4;
524
525                 if (blockLength < 2)
526                         break;
527                 stream_read_uint16(s, highColorDepth); /* highColorDepth */
528                 blockLength -= 2;
529
530                 if (blockLength < 2)
531                         break;
532                 stream_read_uint16(s, supportedColorDepths); /* supportedColorDepths */
533                 blockLength -= 2;
534
535                 if (blockLength < 2)
536                         break;
537                 stream_read_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
538                 blockLength -= 2;
539
540                 if (blockLength < 64)
541                         break;
542                 str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64);
543                 stream_seek(s, 64);
544                 snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str);
545                 xfree(str);
546                 blockLength -= 64;
547
548                 if (blockLength < 1)
549                         break;
550                 stream_read_uint8(s, settings->performance_flags); /* connectionType */
551                 blockLength -= 1;
552
553                 if (blockLength < 1)
554                         break;
555                 stream_seek_uint8(s); /* pad1octet */
556                 blockLength -= 1;
557
558                 if (blockLength < 4)
559                         break;
560                 stream_read_uint32(s, serverSelectedProtocol); /* serverSelectedProtocol */
561                 blockLength -= 4;
562
563                 if (settings->selected_protocol != serverSelectedProtocol)
564                         return false;
565         } while (0);
566
567         if (highColorDepth > 0)
568                 settings->color_depth = highColorDepth;
569         else if (postBeta2ColorDepth > 0)
570         {
571                 switch (postBeta2ColorDepth)
572                 {
573                         case RNS_UD_COLOR_4BPP:
574                                 settings->color_depth = 4;
575                                 break;
576                         case RNS_UD_COLOR_8BPP:
577                                 settings->color_depth = 8;
578                                 break;
579                         case RNS_UD_COLOR_16BPP_555:
580                                 settings->color_depth = 15;
581                                 break;
582                         case RNS_UD_COLOR_16BPP_565:
583                                 settings->color_depth = 16;
584                                 break;
585                         case RNS_UD_COLOR_24BPP:
586                                 settings->color_depth = 24;
587                                 break;
588                         default:
589                                 return false;
590                 }
591         }
592         else
593         {
594                 switch (colorDepth)
595                 {
596                         case RNS_UD_COLOR_4BPP:
597                                 settings->color_depth = 4;
598                                 break;
599                         case RNS_UD_COLOR_8BPP:
600                                 settings->color_depth = 8;
601                                 break;
602                         default:
603                                 return false;
604                 }
605         }
606
607         return true;
608 }
609
610 /**
611  * Write a client core data block (TS_UD_CS_CORE).\n
612  * @msdn{cc240510}
613  * @param s stream
614  * @param settings rdp settings
615  */
616
617 void gcc_write_client_core_data(STREAM* s, rdpSettings* settings)
618 {
619         uint32 version;
620         char* clientName;
621         size_t clientNameLength;
622         uint8 connectionType;
623         uint16 highColorDepth;
624         uint16 supportedColorDepths;
625         uint16 earlyCapabilityFlags;
626         char* clientDigProductId;
627         size_t clientDigProductIdLength;
628
629         gcc_write_user_data_header(s, CS_CORE, 216);
630
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);
634
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 */
642
643         /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
644         if (clientNameLength > 30)
645         {
646                 clientNameLength = 30;
647                 clientName[clientNameLength] = 0;
648                 clientName[clientNameLength + 1] = 0;
649         }
650         stream_write(s, clientName, clientNameLength + 2);
651         stream_write_zero(s, 32 - clientNameLength - 2);
652         xfree(clientName);
653
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 */
657
658         stream_write_zero(s, 64); /* imeFileName */
659
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) */
663
664         highColorDepth = MIN(settings->color_depth, 24);
665
666         supportedColorDepths =
667                         RNS_UD_24BPP_SUPPORT |
668                         RNS_UD_16BPP_SUPPORT |
669                         RNS_UD_15BPP_SUPPORT;
670
671         connectionType = settings->connection_type;
672         earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;
673
674         if (settings->rfx_codec)
675                 connectionType = CONNECTION_TYPE_LAN;
676
677         if (connectionType != 0)
678                 earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;
679
680         if (settings->color_depth == 32)
681         {
682                 supportedColorDepths |= RNS_UD_32BPP_SUPPORT;
683                 earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
684         }
685
686         stream_write_uint16(s, highColorDepth); /* highColorDepth */
687         stream_write_uint16(s, supportedColorDepths); /* supportedColorDepths */
688
689         stream_write_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
690
691         /* clientDigProductId (64 bytes, null-terminated unicode, truncated to 30 characters) */
692         if (clientDigProductIdLength > 62)
693         {
694                 clientDigProductIdLength = 62;
695                 clientDigProductId[clientDigProductIdLength] = 0;
696                 clientDigProductId[clientDigProductIdLength + 1] = 0;
697         }
698         stream_write(s, clientDigProductId, clientDigProductIdLength + 2);
699         stream_write_zero(s, 64 - clientDigProductIdLength - 2);
700         xfree(clientDigProductId);
701
702         stream_write_uint8(s, connectionType); /* connectionType */
703         stream_write_uint8(s, 0); /* pad1octet */
704
705         stream_write_uint32(s, settings->selected_protocol); /* serverSelectedProtocol */
706 }
707
708 boolean gcc_read_server_core_data(STREAM* s, rdpSettings* settings)
709 {
710         uint32 version;
711         uint32 clientRequestedProtocols;
712
713         stream_read_uint32(s, version); /* version */
714         stream_read_uint32(s, clientRequestedProtocols); /* clientRequestedProtocols */
715
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;
720
721         return true;
722 }
723
724 void gcc_write_server_core_data(STREAM* s, rdpSettings* settings)
725 {
726         gcc_write_user_data_header(s, SC_CORE, 12);
727
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 */
730 }
731
732 /**
733  * Read a client security data block (TS_UD_CS_SEC).\n
734  * @msdn{cc240511}
735  * @param s stream
736  * @param settings rdp settings
737  */
738
739 boolean gcc_read_client_security_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
740 {
741         if (blockLength < 8)
742                 return false;
743
744         if (settings->encryption)
745         {
746                 stream_read_uint32(s, settings->encryption_method); /* encryptionMethods */
747                 if (settings->encryption_method == 0)
748                         stream_read_uint32(s, settings->encryption_method); /* extEncryptionMethods */
749         }
750         else
751         {
752                 stream_seek(s, 8);
753         }
754         return true;
755 }
756
757 /**
758  * Write a client security data block (TS_UD_CS_SEC).\n
759  * @msdn{cc240511}
760  * @param s stream
761  * @param settings rdp settings
762  */
763
764 void gcc_write_client_security_data(STREAM* s, rdpSettings* settings)
765 {
766         gcc_write_user_data_header(s, CS_SECURITY, 12);
767
768         if (settings->encryption)
769         {
770                 stream_write_uint32(s, settings->encryption_method); /* encryptionMethods */
771                 stream_write_uint32(s, 0); /* extEncryptionMethods */
772         }
773         else
774         {
775                 /* French locale, disable encryption */
776                 stream_write_uint32(s, 0); /* encryptionMethods */
777                 stream_write_uint32(s, settings->encryption_method); /* extEncryptionMethods */
778         }
779 }
780
781 boolean gcc_read_server_security_data(STREAM* s, rdpSettings* settings)
782 {
783         uint8* data;
784         uint32 length;
785         uint32 serverRandomLen;
786         uint32 serverCertLen;
787
788         stream_read_uint32(s, settings->encryption_method); /* encryptionMethod */
789         stream_read_uint32(s, settings->encryption_level); /* encryptionLevel */
790
791         if (settings->encryption_method == 0 && settings->encryption_level == 0)
792         {
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;
797                 return true;
798         }
799
800         stream_read_uint32(s, serverRandomLen); /* serverRandomLen */
801         stream_read_uint32(s, serverCertLen); /* serverCertLen */
802
803         if (serverRandomLen > 0)
804         {
805                 /* serverRandom */
806                 freerdp_blob_alloc(settings->server_random, serverRandomLen);
807                 stream_read(s, settings->server_random->data, serverRandomLen);
808         }
809         else
810         {
811                 return false;
812         }
813
814         if (serverCertLen > 0)
815         {
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;
823
824                 if (!certificate_read_server_certificate(settings->server_cert, data, length))
825                         return false;
826         }
827         else
828         {
829                 return false;
830         }
831
832         return true;
833 }
834
835 static const uint8 initial_signature[] =
836 {
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
845 };
846
847 void gcc_write_server_security_data(STREAM* s, rdpSettings* settings)
848 {
849         CryptoMd5 md5;
850         uint8* sigData;
851         int expLen, keyLen, sigDataLen;
852         uint8 encryptedSignature[TSSK_KEY_LENGTH];
853         uint8 signature[sizeof(initial_signature)];
854         uint32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen;
855
856         if (!settings->encryption)
857         {
858                 settings->encryption_method = ENCRYPTION_METHOD_NONE;
859                 settings->encryption_level = ENCRYPTION_LEVEL_NONE;
860         }
861         else if ((settings->encryption_method & ENCRYPTION_METHOD_FIPS) != 0)
862         {
863                 settings->encryption_method = ENCRYPTION_METHOD_FIPS;
864         }
865         else if ((settings->encryption_method & ENCRYPTION_METHOD_128BIT) != 0)
866         {
867                 settings->encryption_method = ENCRYPTION_METHOD_128BIT;
868         }
869         else if ((settings->encryption_method & ENCRYPTION_METHOD_40BIT) != 0)
870         {
871                 settings->encryption_method = ENCRYPTION_METHOD_40BIT;
872         }
873
874         if (settings->encryption_method != ENCRYPTION_METHOD_NONE)
875                 settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
876
877         headerLen = 12;
878         keyLen = 0;
879         wPublicKeyBlobLen = 0;
880         serverRandomLen = 0;
881         serverCertLen = 0;
882
883         if (settings->encryption_method != ENCRYPTION_METHOD_NONE ||
884             settings->encryption_level != ENCRYPTION_LEVEL_NONE)
885         {
886                 serverRandomLen = 32;
887
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 */
897
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 */
908
909                 headerLen += sizeof(serverRandomLen);
910                 headerLen += sizeof(serverCertLen);
911                 headerLen += serverRandomLen;
912                 headerLen += serverCertLen;
913         }
914
915         gcc_write_user_data_header(s, SC_SECURITY, headerLen);
916
917         stream_write_uint32(s, settings->encryption_method); /* encryptionMethod */
918         stream_write_uint32(s, settings->encryption_level); /* encryptionLevel */
919
920         if (settings->encryption_method == ENCRYPTION_METHOD_NONE &&
921             settings->encryption_level == ENCRYPTION_LEVEL_NONE)
922         {
923                 return;
924         }
925
926         stream_write_uint32(s, serverRandomLen); /* serverRandomLen */
927         stream_write_uint32(s, serverCertLen); /* serverCertLen */
928
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);
932
933         sigData = stream_get_tail(s);
934
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 */
939
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 */
945
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);
949
950         sigDataLen = stream_get_tail(s) - sigData;
951
952         stream_write_uint16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */
953         stream_write_uint16(s, keyLen + 8); /* wSignatureBlobLen */
954
955         memcpy(signature, initial_signature, sizeof(initial_signature));
956
957         md5 = crypto_md5_init();
958         crypto_md5_update(md5, sigData, sigDataLen);
959         crypto_md5_final(md5, signature);
960
961         crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH,
962                 tssk_modulus, tssk_privateExponent, encryptedSignature);
963
964         stream_write(s, encryptedSignature, sizeof(encryptedSignature));
965         stream_write_zero(s, 8);
966 }
967
968 /**
969  * Read a client network data block (TS_UD_CS_NET).\n
970  * @msdn{cc240512}
971  * @param s stream
972  * @param settings rdp settings
973  */
974
975 boolean gcc_read_client_network_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
976 {
977         int i;
978
979         if (blockLength < 4)
980                 return false;
981
982         stream_read_uint32(s, settings->num_channels); /* channelCount */
983         if (blockLength < 4 + settings->num_channels * 12)
984                 return false;
985         if (settings->num_channels > 16)
986                 return false;
987
988         /* channelDefArray */
989         for (i = 0; i < settings->num_channels; i++)
990         {
991                 /* CHANNEL_DEF */
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;
995         }
996
997         return true;
998 }
999
1000 /**
1001  * Write a client network data block (TS_UD_CS_NET).\n
1002  * @msdn{cc240512}
1003  * @param s stream
1004  * @param settings rdp settings
1005  */
1006
1007 void gcc_write_client_network_data(STREAM* s, rdpSettings* settings)
1008 {
1009         int i;
1010         uint16 length;
1011
1012         if (settings->num_channels > 0)
1013         {
1014                 length = settings->num_channels * 12 + 8;
1015                 gcc_write_user_data_header(s, CS_NET, length);
1016
1017                 stream_write_uint32(s, settings->num_channels); /* channelCount */
1018
1019                 /* channelDefArray */
1020                 for (i = 0; i < settings->num_channels; i++)
1021                 {
1022                         /* CHANNEL_DEF */
1023                         stream_write(s, settings->channels[i].name, 8); /* name (8 bytes) */
1024                         stream_write_uint32(s, settings->channels[i].options); /* options (4 bytes) */
1025                 }
1026         }
1027 }
1028
1029 boolean gcc_read_server_network_data(STREAM* s, rdpSettings* settings)
1030 {
1031         int i;
1032         uint16 MCSChannelId;
1033         uint16 channelCount;
1034         uint16 channelId;
1035
1036         stream_read_uint16(s, MCSChannelId); /* MCSChannelId */
1037         stream_read_uint16(s, channelCount); /* channelCount */
1038
1039         if (channelCount != settings->num_channels)
1040         {
1041                 printf("requested %d channels, got %d instead\n",
1042                                 settings->num_channels, channelCount);
1043         }
1044
1045         for (i = 0; i < channelCount; i++)
1046         {
1047                 stream_read_uint16(s, channelId); /* channelId */
1048                 settings->channels[i].channel_id = channelId;
1049         }
1050
1051         if (channelCount % 2 == 1)
1052                 stream_seek(s, 2); /* padding */
1053
1054         return true;
1055 }
1056
1057 void gcc_write_server_network_data(STREAM* s, rdpSettings* settings)
1058 {
1059         int i;
1060
1061         gcc_write_user_data_header(s, SC_NET, 8 + settings->num_channels * 2 + (settings->num_channels % 2 == 1 ? 2 : 0));
1062
1063         stream_write_uint16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */
1064         stream_write_uint16(s, settings->num_channels); /* channelCount */
1065
1066         for (i = 0; i < settings->num_channels; i++)
1067         {
1068                 stream_write_uint16(s, settings->channels[i].channel_id);
1069         }
1070
1071         if (settings->num_channels % 2 == 1)
1072                 stream_write_uint16(s, 0);
1073 }
1074
1075 /**
1076  * Read a client cluster data block (TS_UD_CS_CLUSTER).\n
1077  * @msdn{cc240514}
1078  * @param s stream
1079  * @param settings rdp settings
1080  */
1081
1082 boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
1083 {
1084         uint32 flags;
1085
1086         if (blockLength < 8)
1087                 return false;
1088
1089         stream_read_uint32(s, flags); /* flags */
1090
1091         if ((flags | REDIRECTED_SESSIONID_FIELD_VALID))
1092                 stream_read_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
1093
1094         return true;
1095 }
1096
1097 /**
1098  * Write a client cluster data block (TS_UD_CS_CLUSTER).\n
1099  * @msdn{cc240514}
1100  * @param s stream
1101  * @param settings rdp settings
1102  */
1103
1104 void gcc_write_client_cluster_data(STREAM* s, rdpSettings* settings)
1105 {
1106         uint32 flags;
1107
1108         gcc_write_user_data_header(s, CS_CLUSTER, 12);
1109
1110         flags = REDIRECTION_SUPPORTED | (REDIRECTION_VERSION4 << 2);
1111
1112         if (settings->console_session || settings->redirected_session_id)
1113                 flags |= REDIRECTED_SESSIONID_FIELD_VALID;
1114
1115         stream_write_uint32(s, flags); /* flags */
1116         stream_write_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
1117 }
1118
1119 /**
1120  * Read a client monitor data block (TS_UD_CS_MONITOR).\n
1121  * @msdn{dd305336}
1122  * @param s stream
1123  * @param settings rdp settings
1124  */
1125
1126 boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings* settings, uint16 blockLength)
1127 {
1128         printf("CS_MONITOR\n");
1129         return true;
1130 }
1131
1132 /**
1133  * Write a client monitor data block (TS_UD_CS_MONITOR).\n
1134  * @msdn{dd305336}
1135  * @param s stream
1136  * @param settings rdp settings
1137  */
1138
1139 void gcc_write_client_monitor_data(STREAM* s, rdpSettings* settings)
1140 {
1141         int i;
1142         uint16 length;
1143         uint32 left, top, right, bottom, flags;
1144
1145         if (settings->num_monitors > 1)
1146         {
1147                 length = (20 * settings->num_monitors) + 12;
1148                 gcc_write_user_data_header(s, CS_MONITOR, length);
1149
1150                 stream_write_uint32(s, 0); /* flags */
1151                 stream_write_uint32(s, settings->num_monitors); /* monitorCount */
1152
1153                 for (i = 0; i < settings->num_monitors; i++)
1154                 {
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;
1160
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 */
1166                 }
1167         }
1168 }
1169