libfreerdp-core: merging jsorg71's work on old encryption support
[platform/upstream/freerdp.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         gcc_write_client_monitor_data(s, settings);
360 }
361
362 boolean gcc_read_server_data_blocks(STREAM* s, rdpSettings *settings, int length)
363 {
364         uint16 type;
365         uint16 offset = 0;
366         uint16 blockLength;
367         uint8* holdp;
368
369         while (offset < length)
370         {
371                 holdp = s->p;
372
373                 if (!gcc_read_user_data_header(s, &type, &blockLength))
374                 {
375                         printf("gcc_read_server_data_blocks: gcc_read_user_data_header failed\n");
376                         return False;
377                 }
378
379                 switch (type)
380                 {
381                         case SC_CORE:
382                                 if (!gcc_read_server_core_data(s, settings))
383                                 {
384                                         printf("gcc_read_server_data_blocks: gcc_read_server_core_data failed\n");
385                                         return False;
386                                 }
387                                 break;
388
389                         case SC_SECURITY:
390                                 if (!gcc_read_server_security_data(s, settings))
391                                 {
392                                         printf("gcc_read_server_data_blocks: gcc_read_server_security_data failed\n");
393                                         return False;
394                                 }
395                                 break;
396
397                         case SC_NET:
398                                 if (!gcc_read_server_network_data(s, settings))
399                                 {
400                                         printf("gcc_read_server_data_blocks: gcc_read_server_network_data failed\n");
401                                         return False;
402                                 }
403                                 break;
404
405                         default:
406                                 break;
407                 }
408                 offset += blockLength;
409                 s->p = holdp + blockLength;
410         }
411
412         return True;
413 }
414
415 void gcc_write_server_data_blocks(STREAM* s, rdpSettings *settings)
416 {
417         gcc_write_server_core_data(s, settings);
418         gcc_write_server_network_data(s, settings);
419         gcc_write_server_security_data(s, settings);
420 }
421
422 boolean gcc_read_user_data_header(STREAM* s, uint16* type, uint16* length)
423 {
424         stream_read_uint16(s, *type); /* type */
425         stream_read_uint16(s, *length); /* length */
426
427         if (stream_get_left(s) < *length - 4)
428                 return False;
429
430         return True;
431 }
432
433 /**
434  * Write a user data header (TS_UD_HEADER).\n
435  * @msdn{cc240509}
436  * @param s stream
437  * @param type data block type
438  * @param length data block length
439  */
440
441 void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length)
442 {
443         stream_write_uint16(s, type); /* type */
444         stream_write_uint16(s, length); /* length */
445 }
446
447 /**
448  * Read a client core data block (TS_UD_CS_CORE).\n
449  * @msdn{cc240510}
450  * @param s stream
451  * @param settings rdp settings
452  */
453
454 boolean gcc_read_client_core_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
455 {
456         uint32 version;
457         uint16 colorDepth = 0;
458         uint16 postBeta2ColorDepth = 0;
459         uint16 highColorDepth = 0;
460         uint16 supportedColorDepths = 0;
461         uint16 earlyCapabilityFlags = 0;
462         uint32 serverSelectedProtocol = 0;
463         char* str;
464
465         /* Length of all required fields, until imeFileName */
466         if (blockLength < 128)
467                 return False;
468
469         stream_read_uint32(s, version); /* version */
470         settings->rdp_version = (version == RDP_VERSION_4 ? 4 : 7);
471
472         stream_read_uint16(s, settings->width); /* desktopWidth */
473         stream_read_uint16(s, settings->height); /* desktopHeight */
474         stream_read_uint16(s, colorDepth); /* colorDepth */
475         stream_seek_uint16(s); /* SASSequence (Secure Access Sequence) */
476         stream_read_uint32(s, settings->kbd_layout); /* keyboardLayout */
477         stream_read_uint32(s, settings->client_build); /* clientBuild */
478         
479         /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
480         str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 32);
481         stream_seek(s, 32);
482         snprintf(settings->client_hostname, sizeof(settings->client_hostname), "%s", str);
483         xfree(str);
484
485         stream_read_uint32(s, settings->kbd_type); /* keyboardType */
486         stream_read_uint32(s, settings->kbd_subtype); /* keyboardSubType */
487         stream_read_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */
488
489         stream_seek(s, 64); /* imeFileName */
490
491         blockLength -= 128;
492
493         /**
494          * The following fields are all optional. If one field is present, all of the preceding
495          * fields MUST also be present. If one field is not present, all of the subsequent fields
496          * MUST NOT be present.
497          * We must check the bytes left before reading each field.
498          */
499
500         do
501         {
502                 if (blockLength < 2)
503                         break;
504                 stream_read_uint16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */
505                 blockLength -= 2;
506
507                 if (blockLength < 2)
508                         break;
509                 stream_seek_uint16(s); /* clientProductID */
510                 blockLength -= 2;
511
512                 if (blockLength < 4)
513                         break;
514                 stream_seek_uint32(s); /* serialNumber */
515                 blockLength -= 4;
516
517                 if (blockLength < 2)
518                         break;
519                 stream_read_uint16(s, highColorDepth); /* highColorDepth */
520                 blockLength -= 2;
521
522                 if (blockLength < 2)
523                         break;
524                 stream_read_uint16(s, supportedColorDepths); /* supportedColorDepths */
525                 blockLength -= 2;
526
527                 if (blockLength < 2)
528                         break;
529                 stream_read_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
530                 blockLength -= 2;
531
532                 if (blockLength < 64)
533                         break;
534                 str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64);
535                 stream_seek(s, 64);
536                 snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str);
537                 xfree(str);
538                 blockLength -= 64;
539
540                 if (blockLength < 1)
541                         break;
542                 stream_read_uint8(s, settings->performance_flags); /* connectionType */
543                 blockLength -= 1;
544
545                 if (blockLength < 1)
546                         break;
547                 stream_seek_uint8(s); /* pad1octet */
548                 blockLength -= 1;
549
550                 if (blockLength < 4)
551                         break;
552                 stream_read_uint32(s, serverSelectedProtocol); /* serverSelectedProtocol */
553                 blockLength -= 4;
554
555                 if (settings->selected_protocol != serverSelectedProtocol)
556                         return False;
557         } while (0);
558
559         if (highColorDepth > 0)
560                 settings->color_depth = highColorDepth;
561         else if (postBeta2ColorDepth > 0)
562         {
563                 switch (postBeta2ColorDepth)
564                 {
565                         case RNS_UD_COLOR_4BPP:
566                                 settings->color_depth = 4;
567                                 break;
568                         case RNS_UD_COLOR_8BPP:
569                                 settings->color_depth = 8;
570                                 break;
571                         case RNS_UD_COLOR_16BPP_555:
572                                 settings->color_depth = 15;
573                                 break;
574                         case RNS_UD_COLOR_16BPP_565:
575                                 settings->color_depth = 16;
576                                 break;
577                         case RNS_UD_COLOR_24BPP:
578                                 settings->color_depth = 24;
579                                 break;
580                         default:
581                                 return False;
582                 }
583         }
584         else
585         {
586                 switch (colorDepth)
587                 {
588                         case RNS_UD_COLOR_4BPP:
589                                 settings->color_depth = 4;
590                                 break;
591                         case RNS_UD_COLOR_8BPP:
592                                 settings->color_depth = 8;
593                                 break;
594                         default:
595                                 return False;
596                 }
597         }
598
599         return True;
600 }
601
602 /**
603  * Write a client core data block (TS_UD_CS_CORE).\n
604  * @msdn{cc240510}
605  * @param s stream
606  * @param settings rdp settings
607  */
608
609 void gcc_write_client_core_data(STREAM* s, rdpSettings *settings)
610 {
611         uint32 version;
612         char* clientName;
613         size_t clientNameLength;
614         uint8 connectionType;
615         uint16 highColorDepth;
616         uint16 supportedColorDepths;
617         uint16 earlyCapabilityFlags;
618         char* clientDigProductId;
619         size_t clientDigProductIdLength;
620
621         gcc_write_user_data_header(s, CS_CORE, 216);
622
623         version = settings->rdp_version >= 5 ? RDP_VERSION_5_PLUS : RDP_VERSION_4;
624         clientName = freerdp_uniconv_out(settings->uniconv, settings->client_hostname, &clientNameLength);
625         clientDigProductId = freerdp_uniconv_out(settings->uniconv, settings->client_product_id, &clientDigProductIdLength);
626
627         stream_write_uint32(s, version); /* version */
628         stream_write_uint16(s, settings->width); /* desktopWidth */
629         stream_write_uint16(s, settings->height); /* desktopHeight */
630         stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* colorDepth, ignored because of postBeta2ColorDepth */
631         stream_write_uint16(s, RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */
632         stream_write_uint32(s, settings->kbd_layout); /* keyboardLayout */
633         stream_write_uint32(s, settings->client_build); /* clientBuild */
634
635         /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
636         if (clientNameLength > 30)
637         {
638                 clientNameLength = 30;
639                 clientName[clientNameLength] = 0;
640                 clientName[clientNameLength + 1] = 0;
641         }
642         stream_write(s, clientName, clientNameLength + 2);
643         stream_write_zero(s, 32 - clientNameLength - 2);
644         xfree(clientName);
645
646         stream_write_uint32(s, settings->kbd_type); /* keyboardType */
647         stream_write_uint32(s, settings->kbd_subtype); /* keyboardSubType */
648         stream_write_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */
649
650         stream_write_zero(s, 64); /* imeFileName */
651
652         stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */
653         stream_write_uint16(s, 1); /* clientProductID */
654         stream_write_uint32(s, 0); /* serialNumber (should be initialized to 0) */
655
656         highColorDepth = MIN(settings->color_depth, 24);
657
658         supportedColorDepths =
659                         RNS_UD_24BPP_SUPPORT |
660                         RNS_UD_16BPP_SUPPORT |
661                         RNS_UD_15BPP_SUPPORT;
662
663         connectionType = 0;
664         earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;
665
666         if (settings->performance_flags == PERF_FLAG_NONE)
667         {
668                 earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;
669                 connectionType = CONNECTION_TYPE_LAN;
670         }
671
672         if (settings->color_depth == 32)
673         {
674                 supportedColorDepths |= RNS_UD_32BPP_SUPPORT;
675                 earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
676         }
677
678         stream_write_uint16(s, highColorDepth); /* highColorDepth */
679         stream_write_uint16(s, supportedColorDepths); /* supportedColorDepths */
680
681         stream_write_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
682
683         /* clientDigProductId (64 bytes, null-terminated unicode, truncated to 30 characters) */
684         if (clientDigProductIdLength > 62)
685         {
686                 clientDigProductIdLength = 62;
687                 clientDigProductId[clientDigProductIdLength] = 0;
688                 clientDigProductId[clientDigProductIdLength + 1] = 0;
689         }
690         stream_write(s, clientDigProductId, clientDigProductIdLength + 2);
691         stream_write_zero(s, 64 - clientDigProductIdLength - 2);
692         xfree(clientDigProductId);
693
694         stream_write_uint8(s, connectionType); /* connectionType */
695         stream_write_uint8(s, 0); /* pad1octet */
696
697         stream_write_uint32(s, settings->selected_protocol); /* serverSelectedProtocol */
698 }
699
700 boolean gcc_read_server_core_data(STREAM* s, rdpSettings *settings)
701 {
702         uint32 version;
703         uint32 clientRequestedProtocols;
704
705         stream_read_uint32(s, version); /* version */
706         stream_read_uint32(s, clientRequestedProtocols); /* clientRequestedProtocols */
707
708         if (version == RDP_VERSION_4 && settings->rdp_version > 4)
709                 settings->rdp_version = 4;
710         else if (version == RDP_VERSION_5_PLUS && settings->rdp_version < 5)
711                 settings->rdp_version = 7;
712
713         return True;
714 }
715
716 void gcc_write_server_core_data(STREAM* s, rdpSettings *settings)
717 {
718         gcc_write_user_data_header(s, SC_CORE, 12);
719
720         stream_write_uint32(s, settings->rdp_version == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS);
721         stream_write_uint32(s, settings->requested_protocols); /* clientRequestedProtocols */
722 }
723
724 /**
725  * Read a client security data block (TS_UD_CS_SEC).\n
726  * @msdn{cc240511}
727  * @param s stream
728  * @param settings rdp settings
729  */
730
731 boolean gcc_read_client_security_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
732 {
733         if (blockLength < 8)
734                 return False;
735
736         stream_read_uint32(s, settings->encryption_method); /* encryptionMethods */
737         if (settings->encryption_method == 0)
738                 stream_read_uint32(s, settings->encryption_method); /* extEncryptionMethods */
739
740         return True;
741 }
742
743 /**
744  * Write a client security data block (TS_UD_CS_SEC).\n
745  * @msdn{cc240511}
746  * @param s stream
747  * @param settings rdp settings
748  */
749
750 void gcc_write_client_security_data(STREAM* s, rdpSettings *settings)
751 {
752         gcc_write_user_data_header(s, CS_SECURITY, 12);
753
754         if (settings->encryption)
755         {
756                 stream_write_uint32(s, settings->encryption_method); /* encryptionMethods */
757                 stream_write_uint32(s, 0); /* extEncryptionMethods */
758         }
759         else
760         {
761                 /* French locale, disable encryption */
762                 stream_write_uint32(s, 0); /* encryptionMethods */
763                 stream_write_uint32(s, settings->encryption_method); /* extEncryptionMethods */
764         }
765 }
766
767 boolean gcc_read_server_security_data(STREAM* s, rdpSettings *settings)
768 {
769         uint32 serverRandomLen;
770         uint32 serverCertLen;
771         uint8* data;
772         uint32 len;
773
774         stream_read_uint32(s, settings->encryption_method); /* encryptionMethod */
775         stream_read_uint32(s, settings->encryption_level); /* encryptionLevel */
776
777         if (settings->encryption_method == 0 && settings->encryption_level == 0)
778         {
779                 /* serverRandom and serverRandom must not be present */
780                 settings->encryption = False;
781                 settings->encryption_method = ENCRYPTION_METHOD_NONE;
782                 settings->encryption_level = ENCRYPTION_LEVEL_NONE;
783                 return True;
784         }
785
786         stream_read_uint32(s, serverRandomLen); /* serverRandomLen */
787         stream_read_uint32(s, serverCertLen); /* serverCertLen */
788
789         if (serverRandomLen > 0)
790         {
791                 /* serverRandom */
792                 freerdp_blob_alloc(&settings->server_random, serverRandomLen);
793                 memcpy(settings->server_random.data, s->p, serverRandomLen);
794                 stream_seek(s, serverRandomLen);
795                 freerdp_hexdump(settings->server_random.data, settings->server_random.length);
796         }
797         else
798         {
799                 return False;
800         }
801
802         if (serverCertLen > 0)
803         {
804                 /* serverCertificate */
805                 freerdp_blob_alloc(&settings->server_certificate, serverCertLen);
806                 memcpy(settings->server_certificate.data, s->p, serverCertLen);
807                 stream_seek(s, serverCertLen);
808                 certificate_free(settings->server_cert);
809                 settings->server_cert = certificate_new();
810                 data = settings->server_certificate.data;
811                 len = settings->server_certificate.length;
812                 if (!certificate_read_server_certificate(settings->server_cert, data, len))
813                 {
814                         return False;
815                 }
816         }
817         else
818         {
819                 return False;
820         }
821
822         return True;
823 }
824
825 void gcc_write_server_security_data(STREAM* s, rdpSettings *settings)
826 {
827         gcc_write_user_data_header(s, SC_SECURITY, 12);
828
829         stream_write_uint32(s, ENCRYPTION_METHOD_NONE); /* encryptionMethod */
830         stream_write_uint32(s, ENCRYPTION_LEVEL_NONE); /* encryptionLevel */
831 #if 0
832         stream_write_uint32(s, 0); /* serverRandomLen */
833         stream_write_uint32(s, 0); /* serverCertLen */
834 #endif
835 }
836
837 /**
838  * Read a client network data block (TS_UD_CS_NET).\n
839  * @msdn{cc240512}
840  * @param s stream
841  * @param settings rdp settings
842  */
843
844 boolean gcc_read_client_network_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
845 {
846         int i;
847
848         if (blockLength < 4)
849                 return False;
850
851         stream_read_uint32(s, settings->num_channels); /* channelCount */
852         if (blockLength < 4 + settings->num_channels * 12)
853                 return False;
854         if (settings->num_channels > 16)
855                 return False;
856
857         /* channelDefArray */
858         for (i = 0; i < settings->num_channels; i++)
859         {
860                 /* CHANNEL_DEF */
861                 stream_read(s, settings->channels[i].name, 8); /* name (8 bytes) */
862                 stream_read_uint32(s, settings->channels[i].options); /* options (4 bytes) */
863                 settings->channels[i].chan_id = MCS_GLOBAL_CHANNEL_ID + 1 + i;
864         }
865
866         return True;
867 }
868
869 /**
870  * Write a client network data block (TS_UD_CS_NET).\n
871  * @msdn{cc240512}
872  * @param s stream
873  * @param settings rdp settings
874  */
875
876 void gcc_write_client_network_data(STREAM* s, rdpSettings *settings)
877 {
878         int i;
879         uint16 length;
880
881         if (settings->num_channels > 0)
882         {
883                 length = settings->num_channels * 12 + 8;
884                 gcc_write_user_data_header(s, CS_NET, length);
885
886                 stream_write_uint32(s, settings->num_channels); /* channelCount */
887
888                 /* channelDefArray */
889                 for (i = 0; i < settings->num_channels; i++)
890                 {
891                         /* CHANNEL_DEF */
892                         stream_write(s, settings->channels[i].name, 8); /* name (8 bytes) */
893                         stream_write_uint32(s, settings->channels[i].options); /* options (4 bytes) */
894                 }
895         }
896 }
897
898 boolean gcc_read_server_network_data(STREAM* s, rdpSettings *settings)
899 {
900         int i;
901         uint16 MCSChannelId;
902         uint16 channelCount;
903         uint16 channelId;
904
905         stream_read_uint16(s, MCSChannelId); /* MCSChannelId */
906         stream_read_uint16(s, channelCount); /* channelCount */
907
908         if (channelCount != settings->num_channels)
909         {
910                 printf("requested %d channels, got %d instead\n",
911                                 settings->num_channels, channelCount);
912         }
913
914         for (i = 0; i < channelCount; i++)
915         {
916                 stream_read_uint16(s, channelId); /* channelId */
917                 settings->channels[i].chan_id = channelId;
918         }
919
920         if (channelCount % 2 == 1)
921                 stream_seek(s, 2); /* padding */
922
923         return True;
924 }
925
926 void gcc_write_server_network_data(STREAM* s, rdpSettings *settings)
927 {
928         int i;
929
930         gcc_write_user_data_header(s, SC_NET, 8 + settings->num_channels * 2 + (settings->num_channels % 2 == 1 ? 2 : 0));
931
932         stream_write_uint16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */
933         stream_write_uint16(s, settings->num_channels); /* channelCount */
934
935         for (i = 0; i < settings->num_channels; i++)
936         {
937                 stream_write_uint16(s, settings->channels[i].chan_id);
938         }
939
940         if (settings->num_channels % 2 == 1)
941                 stream_write_uint16(s, 0);
942 }
943
944 /**
945  * Read a client cluster data block (TS_UD_CS_CLUSTER).\n
946  * @msdn{cc240514}
947  * @param s stream
948  * @param settings rdp settings
949  */
950
951 boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
952 {
953         uint32 flags;
954
955         if (blockLength < 8)
956                 return False;
957
958         stream_read_uint32(s, flags); /* flags */
959
960         if ((flags | REDIRECTED_SESSIONID_FIELD_VALID))
961                 stream_read_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
962
963         return True;
964 }
965
966 /**
967  * Write a client cluster data block (TS_UD_CS_CLUSTER).\n
968  * @msdn{cc240514}
969  * @param s stream
970  * @param settings rdp settings
971  */
972
973 void gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings)
974 {
975         uint32 flags;
976
977         gcc_write_user_data_header(s, CS_CLUSTER, 12);
978
979         flags = REDIRECTION_SUPPORTED | (REDIRECTION_VERSION4 << 2);
980
981         if (settings->console_session || settings->redirected_session_id)
982                 flags |= REDIRECTED_SESSIONID_FIELD_VALID;
983
984         stream_write_uint32(s, flags); /* flags */
985         stream_write_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
986 }
987
988 /**
989  * Read a client monitor data block (TS_UD_CS_MONITOR).\n
990  * @msdn{dd305336}
991  * @param s stream
992  * @param settings rdp settings
993  */
994
995 boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
996 {
997         printf("CS_MONITOR\n");
998         return True;
999 }
1000
1001 /**
1002  * Write a client monitor data block (TS_UD_CS_MONITOR).\n
1003  * @msdn{dd305336}
1004  * @param s stream
1005  * @param settings rdp settings
1006  */
1007
1008 void gcc_write_client_monitor_data(STREAM* s, rdpSettings *settings)
1009 {
1010         int i;
1011         uint16 length;
1012         uint32 left, top, right, bottom, flags;
1013
1014         if (settings->num_monitors > 1)
1015         {
1016                 length = (20 * settings->num_monitors) + 12;
1017                 gcc_write_user_data_header(s, CS_MONITOR, length);
1018
1019                 stream_write_uint32(s, 0); /* flags */
1020                 stream_write_uint32(s, settings->num_monitors); /* monitorCount */
1021
1022                 for (i = 0; i < settings->num_monitors; i++)
1023                 {
1024                         left = settings->monitors[i].x;
1025                         top = settings->monitors[i].y;
1026                         right = settings->monitors[i].x + settings->monitors[i].width - 1;
1027                         bottom = settings->monitors[i].y + settings->monitors[i].height - 1;
1028                         flags = settings->monitors[i].is_primary ? MONITOR_PRIMARY : 0;
1029
1030                         stream_write_uint32(s, left); /* left */
1031                         stream_write_uint32(s, top); /* top */
1032                         stream_write_uint32(s, right); /* right */
1033                         stream_write_uint32(s, bottom); /* bottom */
1034                         stream_write_uint32(s, flags); /* flags */
1035                 }
1036         }
1037 }
1038