/[rdesktop]/sourceforge.net/trunk/rdesktop/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 733 - (show annotations)
Mon Jul 5 19:09:07 2004 UTC (19 years, 10 months ago) by jsorg71
File MIME type: text/plain
File size: 27935 byte(s)
bring the rdp5 packets through the various layers

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <time.h>
22 #include "rdesktop.h"
23
24 extern uint16 g_mcs_userid;
25 extern char g_username[16];
26 extern BOOL g_bitmap_compression;
27 extern BOOL g_orders;
28 extern BOOL g_encryption;
29 extern BOOL g_desktop_save;
30 extern BOOL g_use_rdp5;
31 extern uint16 g_server_rdp_version;
32 extern uint32 g_rdp5_performanceflags;
33 extern int g_server_bpp;
34 extern int g_width;
35 extern int g_height;
36 extern BOOL g_bitmap_cache;
37 extern BOOL g_bitmap_cache_persist_enable;
38
39 uint8 *g_next_packet;
40 uint32 g_rdp_shareid;
41
42 extern RDPCOMP g_mppc_dict;
43
44 #if WITH_DEBUG
45 static uint32 g_packetno;
46 #endif
47
48 /* Receive an RDP packet */
49 static STREAM
50 rdp_recv(uint8 * type)
51 {
52 static STREAM rdp_s;
53 uint16 length, pdu_type;
54 uint8 rdpver;
55
56 if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
57 {
58 rdp_s = sec_recv(&rdpver);
59 if (rdp_s == NULL)
60 return NULL;
61 if (rdpver != 3)
62 {
63 /* rdp5_process should move g_next_packet ok */
64 rdp5_process(rdp_s);
65 *type = 0;
66 return rdp_s;
67 }
68
69 g_next_packet = rdp_s->p;
70 }
71 else
72 {
73 rdp_s->p = g_next_packet;
74 }
75
76 in_uint16_le(rdp_s, length);
77 /* 32k packets are really 8, keepalive fix */
78 if (length == 0x8000)
79 {
80 g_next_packet += 8;
81 *type = 0;
82 return rdp_s;
83 }
84 in_uint16_le(rdp_s, pdu_type);
85 in_uint8s(rdp_s, 2); /* userid */
86 *type = pdu_type & 0xf;
87
88 #if WITH_DEBUG
89 DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
90 hexdump(g_next_packet, length);
91 #endif /* */
92
93 g_next_packet += length;
94 return rdp_s;
95 }
96
97 /* Initialise an RDP data packet */
98 static STREAM
99 rdp_init_data(int maxlen)
100 {
101 STREAM s;
102
103 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
104 s_push_layer(s, rdp_hdr, 18);
105
106 return s;
107 }
108
109 /* Send an RDP data packet */
110 static void
111 rdp_send_data(STREAM s, uint8 data_pdu_type)
112 {
113 uint16 length;
114
115 s_pop_layer(s, rdp_hdr);
116 length = s->end - s->p;
117
118 out_uint16_le(s, length);
119 out_uint16_le(s, (RDP_PDU_DATA | 0x10));
120 out_uint16_le(s, (g_mcs_userid + 1001));
121
122 out_uint32_le(s, g_rdp_shareid);
123 out_uint8(s, 0); /* pad */
124 out_uint8(s, 1); /* streamid */
125 out_uint16_le(s, (length - 14));
126 out_uint8(s, data_pdu_type);
127 out_uint8(s, 0); /* compress_type */
128 out_uint16(s, 0); /* compress_len */
129
130 sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
131 }
132
133 /* Output a string in Unicode */
134 void
135 rdp_out_unistr(STREAM s, char *string, int len)
136 {
137 int i = 0, j = 0;
138
139 len += 2;
140
141 while (i < len)
142 {
143 s->p[i++] = string[j++];
144 s->p[i++] = 0;
145 }
146
147 s->p += len;
148 }
149
150 /* Input a string in Unicode
151 *
152 * Returns str_len of string
153 */
154 int
155 rdp_in_unistr(STREAM s, char *string, int uni_len)
156 {
157 int i = 0;
158
159 while (i < uni_len / 2)
160 {
161 in_uint8a(s, &string[i++], 1);
162 in_uint8s(s, 1);
163 }
164
165 return i - 1;
166 }
167
168
169 /* Parse a logon info packet */
170 static void
171 rdp_send_logon_info(uint32 flags, char *domain, char *user,
172 char *password, char *program, char *directory)
173 {
174 char *ipaddr = tcp_get_address();
175 int len_domain = 2 * strlen(domain);
176 int len_user = 2 * strlen(user);
177 int len_password = 2 * strlen(password);
178 int len_program = 2 * strlen(program);
179 int len_directory = 2 * strlen(directory);
180 int len_ip = 2 * strlen(ipaddr);
181 int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
182 int packetlen = 0;
183 uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
184 STREAM s;
185 time_t t = time(NULL);
186 time_t tzone;
187
188 #if 0
189 /* enable rdp compression */
190 /* some problems still exist with rdp5 */
191 flags |= RDP_COMPRESSION;
192 #endif
193
194 if (!g_use_rdp5 || 1 == g_server_rdp_version)
195 {
196 DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
197
198 s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
199 + len_program + len_directory + 10);
200
201 out_uint32(s, 0);
202 out_uint32_le(s, flags);
203 out_uint16_le(s, len_domain);
204 out_uint16_le(s, len_user);
205 out_uint16_le(s, len_password);
206 out_uint16_le(s, len_program);
207 out_uint16_le(s, len_directory);
208 rdp_out_unistr(s, domain, len_domain);
209 rdp_out_unistr(s, user, len_user);
210 rdp_out_unistr(s, password, len_password);
211 rdp_out_unistr(s, program, len_program);
212 rdp_out_unistr(s, directory, len_directory);
213 }
214 else
215 {
216
217 flags |= RDP_LOGON_BLOB;
218 DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
219 packetlen = 4 + /* Unknown uint32 */
220 4 + /* flags */
221 2 + /* len_domain */
222 2 + /* len_user */
223 (flags & RDP_LOGON_AUTO ? 2 : 0) + /* len_password */
224 (flags & RDP_LOGON_BLOB ? 2 : 0) + /* Length of BLOB */
225 2 + /* len_program */
226 2 + /* len_directory */
227 (0 < len_domain ? len_domain : 2) + /* domain */
228 len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */
229 (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
230 (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */
231 2 + /* Client ip length */
232 len_ip + /* Client ip */
233 2 + /* DLL string length */
234 len_dll + /* DLL string */
235 2 + /* Unknown */
236 2 + /* Unknown */
237 64 + /* Time zone #0 */
238 2 + /* Unknown */
239 64 + /* Time zone #1 */
240 32; /* Unknown */
241
242 s = sec_init(sec_flags, packetlen);
243 DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
244
245 out_uint32(s, 0); /* Unknown */
246 out_uint32_le(s, flags);
247 out_uint16_le(s, len_domain);
248 out_uint16_le(s, len_user);
249 if (flags & RDP_LOGON_AUTO)
250 {
251 out_uint16_le(s, len_password);
252
253 }
254 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
255 {
256 out_uint16_le(s, 0);
257 }
258 out_uint16_le(s, len_program);
259 out_uint16_le(s, len_directory);
260 if (0 < len_domain)
261 rdp_out_unistr(s, domain, len_domain);
262 else
263 out_uint16_le(s, 0);
264 rdp_out_unistr(s, user, len_user);
265 if (flags & RDP_LOGON_AUTO)
266 {
267 rdp_out_unistr(s, password, len_password);
268 }
269 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
270 {
271 out_uint16_le(s, 0);
272 }
273 if (0 < len_program)
274 {
275 rdp_out_unistr(s, program, len_program);
276
277 }
278 else
279 {
280 out_uint16_le(s, 0);
281 }
282 if (0 < len_directory)
283 {
284 rdp_out_unistr(s, directory, len_directory);
285 }
286 else
287 {
288 out_uint16_le(s, 0);
289 }
290 out_uint16_le(s, 2);
291 out_uint16_le(s, len_ip + 2); /* Length of client ip */
292 rdp_out_unistr(s, ipaddr, len_ip);
293 out_uint16_le(s, len_dll + 2);
294 rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
295
296 tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
297 out_uint32_le(s, tzone);
298
299 rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
300 out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
301
302 out_uint32_le(s, 0x0a0000);
303 out_uint32_le(s, 0x050000);
304 out_uint32_le(s, 3);
305 out_uint32_le(s, 0);
306 out_uint32_le(s, 0);
307
308 rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
309 out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
310
311 out_uint32_le(s, 0x30000);
312 out_uint32_le(s, 0x050000);
313 out_uint32_le(s, 2);
314 out_uint32(s, 0);
315 out_uint32_le(s, 0xffffffc4);
316 out_uint32_le(s, 0xfffffffe);
317 out_uint32_le(s, g_rdp5_performanceflags);
318 out_uint32(s, 0);
319
320
321 }
322 s_mark_end(s);
323 sec_send(s, sec_flags);
324 }
325
326 /* Send a control PDU */
327 static void
328 rdp_send_control(uint16 action)
329 {
330 STREAM s;
331
332 s = rdp_init_data(8);
333
334 out_uint16_le(s, action);
335 out_uint16(s, 0); /* userid */
336 out_uint32(s, 0); /* control id */
337
338 s_mark_end(s);
339 rdp_send_data(s, RDP_DATA_PDU_CONTROL);
340 }
341
342 /* Send a synchronisation PDU */
343 static void
344 rdp_send_synchronise(void)
345 {
346 STREAM s;
347
348 s = rdp_init_data(4);
349
350 out_uint16_le(s, 1); /* type */
351 out_uint16_le(s, 1002);
352
353 s_mark_end(s);
354 rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
355 }
356
357 /* Send a single input event */
358 void
359 rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
360 {
361 STREAM s;
362
363 s = rdp_init_data(16);
364
365 out_uint16_le(s, 1); /* number of events */
366 out_uint16(s, 0); /* pad */
367
368 out_uint32_le(s, time);
369 out_uint16_le(s, message_type);
370 out_uint16_le(s, device_flags);
371 out_uint16_le(s, param1);
372 out_uint16_le(s, param2);
373
374 s_mark_end(s);
375 rdp_send_data(s, RDP_DATA_PDU_INPUT);
376 }
377
378 /* Inform the server on the contents of the persistent bitmap cache */
379 static void
380 rdp_enum_bmpcache2(void)
381 {
382 STREAM s;
383 uint8 idlist[BMPCACHE2_NUM_PSTCELLS * sizeof(BITMAP_ID)];
384 uint32 nids, offset, count, flags;
385
386 offset = 0;
387 nids = pstcache_enumerate(2, idlist);
388
389 while (offset < nids)
390 {
391 count = MIN(nids - offset, 169);
392
393 s = rdp_init_data(24 + count * sizeof(BITMAP_ID));
394
395 flags = 0;
396 if (offset == 0)
397 flags |= PDU_FLAG_FIRST;
398 if (nids - offset <= 169)
399 flags |= PDU_FLAG_LAST;
400
401 /* header */
402 out_uint32_le(s, 0);
403 out_uint16_le(s, count);
404 out_uint16_le(s, 0);
405 out_uint16_le(s, 0);
406 out_uint16_le(s, 0);
407 out_uint16_le(s, 0);
408 out_uint16_le(s, nids);
409 out_uint32_le(s, 0);
410 out_uint32_le(s, flags);
411
412 /* list */
413 out_uint8a(s, idlist + offset * sizeof(BITMAP_ID),
414 count * sizeof(BITMAP_ID));
415
416 s_mark_end(s);
417 rdp_send_data(s, 0x2b);
418
419 offset += 169;
420 }
421 }
422
423 /* Send an (empty) font information PDU */
424 static void
425 rdp_send_fonts(uint16 seq)
426 {
427 STREAM s;
428
429 s = rdp_init_data(8);
430
431 out_uint16(s, 0); /* number of fonts */
432 out_uint16_le(s, 0); /* pad? */
433 out_uint16_le(s, seq); /* unknown */
434 out_uint16_le(s, 0x32); /* entry size */
435
436 s_mark_end(s);
437 rdp_send_data(s, RDP_DATA_PDU_FONT2);
438 }
439
440 /* Output general capability set */
441 static void
442 rdp_out_general_caps(STREAM s)
443 {
444 out_uint16_le(s, RDP_CAPSET_GENERAL);
445 out_uint16_le(s, RDP_CAPLEN_GENERAL);
446
447 out_uint16_le(s, 1); /* OS major type */
448 out_uint16_le(s, 3); /* OS minor type */
449 out_uint16_le(s, 0x200); /* Protocol version */
450 out_uint16(s, 0); /* Pad */
451 out_uint16(s, 0); /* Compression types */
452 out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
453 /* Pad, according to T.128. 0x40d seems to
454 trigger
455 the server to start sending RDP5 packets.
456 However, the value is 0x1d04 with W2KTSK and
457 NT4MS. Hmm.. Anyway, thankyou, Microsoft,
458 for sending such information in a padding
459 field.. */
460 out_uint16(s, 0); /* Update capability */
461 out_uint16(s, 0); /* Remote unshare capability */
462 out_uint16(s, 0); /* Compression level */
463 out_uint16(s, 0); /* Pad */
464 }
465
466 /* Output bitmap capability set */
467 static void
468 rdp_out_bitmap_caps(STREAM s)
469 {
470 out_uint16_le(s, RDP_CAPSET_BITMAP);
471 out_uint16_le(s, RDP_CAPLEN_BITMAP);
472
473 out_uint16_le(s, g_server_bpp); /* Preferred BPP */
474 out_uint16_le(s, 1); /* Receive 1 BPP */
475 out_uint16_le(s, 1); /* Receive 4 BPP */
476 out_uint16_le(s, 1); /* Receive 8 BPP */
477 out_uint16_le(s, 800); /* Desktop width */
478 out_uint16_le(s, 600); /* Desktop height */
479 out_uint16(s, 0); /* Pad */
480 out_uint16(s, 1); /* Allow resize */
481 out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
482 out_uint16(s, 0); /* Unknown */
483 out_uint16_le(s, 1); /* Unknown */
484 out_uint16(s, 0); /* Pad */
485 }
486
487 /* Output order capability set */
488 static void
489 rdp_out_order_caps(STREAM s)
490 {
491 uint8 order_caps[32];
492
493
494 memset(order_caps, 0, 32);
495 order_caps[0] = 1; /* dest blt */
496 order_caps[1] = 1; /* pat blt */
497 order_caps[2] = 1; /* screen blt */
498 order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */
499 order_caps[8] = 1; /* line */
500 order_caps[9] = 1; /* line */
501 order_caps[10] = 1; /* rect */
502 order_caps[11] = (g_desktop_save == False ? 0 : 1); /* desksave */
503 order_caps[13] = 1; /* memblt */
504 order_caps[14] = 1; /* triblt */
505 order_caps[22] = 1; /* polyline */
506 order_caps[27] = 1; /* text2 */
507 out_uint16_le(s, RDP_CAPSET_ORDER);
508 out_uint16_le(s, RDP_CAPLEN_ORDER);
509
510 out_uint8s(s, 20); /* Terminal desc, pad */
511 out_uint16_le(s, 1); /* Cache X granularity */
512 out_uint16_le(s, 20); /* Cache Y granularity */
513 out_uint16(s, 0); /* Pad */
514 out_uint16_le(s, 1); /* Max order level */
515 out_uint16_le(s, 0x147); /* Number of fonts */
516 out_uint16_le(s, 0x2a); /* Capability flags */
517 out_uint8p(s, order_caps, 32); /* Orders supported */
518 out_uint16_le(s, 0x6a1); /* Text capability flags */
519 out_uint8s(s, 6); /* Pad */
520 out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */
521 out_uint32(s, 0); /* Unknown */
522 out_uint32_le(s, 0x4e4); /* Unknown */
523 }
524
525 /* Output bitmap cache capability set */
526 static void
527 rdp_out_bmpcache_caps(STREAM s)
528 {
529 int Bpp;
530 out_uint16_le(s, RDP_CAPSET_BMPCACHE);
531 out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
532
533 Bpp = (g_server_bpp + 7) / 8;
534 out_uint8s(s, 24); /* unused */
535 out_uint16_le(s, 0x258); /* entries */
536 out_uint16_le(s, 0x100 * Bpp); /* max cell size */
537 out_uint16_le(s, 0x12c); /* entries */
538 out_uint16_le(s, 0x400 * Bpp); /* max cell size */
539 out_uint16_le(s, 0x106); /* entries */
540 out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
541 }
542
543 /* Output bitmap cache v2 capability set */
544 static void
545 rdp_out_bmpcache2_caps(STREAM s)
546 {
547 out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
548 out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
549
550 out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0); /* version */
551
552 out_uint16_le(s, 0x0300); /* flags? number of caches? */
553
554 out_uint32_le(s, BMPCACHE2_C0_CELLS);
555 out_uint32_le(s, BMPCACHE2_C1_CELLS);
556 if (pstcache_init(2))
557 {
558 out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
559 }
560 else
561 {
562 out_uint32_le(s, BMPCACHE2_C2_CELLS);
563 }
564 out_uint8s(s, 20); /* other bitmap caches not used */
565 }
566
567 /* Output control capability set */
568 static void
569 rdp_out_control_caps(STREAM s)
570 {
571 out_uint16_le(s, RDP_CAPSET_CONTROL);
572 out_uint16_le(s, RDP_CAPLEN_CONTROL);
573
574 out_uint16(s, 0); /* Control capabilities */
575 out_uint16(s, 0); /* Remote detach */
576 out_uint16_le(s, 2); /* Control interest */
577 out_uint16_le(s, 2); /* Detach interest */
578 }
579
580 /* Output activation capability set */
581 static void
582 rdp_out_activate_caps(STREAM s)
583 {
584 out_uint16_le(s, RDP_CAPSET_ACTIVATE);
585 out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
586
587 out_uint16(s, 0); /* Help key */
588 out_uint16(s, 0); /* Help index key */
589 out_uint16(s, 0); /* Extended help key */
590 out_uint16(s, 0); /* Window activate */
591 }
592
593 /* Output pointer capability set */
594 static void
595 rdp_out_pointer_caps(STREAM s)
596 {
597 out_uint16_le(s, RDP_CAPSET_POINTER);
598 out_uint16_le(s, RDP_CAPLEN_POINTER);
599
600 out_uint16(s, 0); /* Colour pointer */
601 out_uint16_le(s, 20); /* Cache size */
602 }
603
604 /* Output share capability set */
605 static void
606 rdp_out_share_caps(STREAM s)
607 {
608 out_uint16_le(s, RDP_CAPSET_SHARE);
609 out_uint16_le(s, RDP_CAPLEN_SHARE);
610
611 out_uint16(s, 0); /* userid */
612 out_uint16(s, 0); /* pad */
613 }
614
615 /* Output colour cache capability set */
616 static void
617 rdp_out_colcache_caps(STREAM s)
618 {
619 out_uint16_le(s, RDP_CAPSET_COLCACHE);
620 out_uint16_le(s, RDP_CAPLEN_COLCACHE);
621
622 out_uint16_le(s, 6); /* cache size */
623 out_uint16(s, 0); /* pad */
624 }
625
626 static uint8 caps_0x0d[] = {
627 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
628 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00
638 };
639
640 static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
641
642 static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
643
644 static uint8 caps_0x10[] = {
645 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
646 0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
647 0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
648 0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
649 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
650 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
651 };
652
653 /* Output unknown capability sets */
654 static void
655 rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 *caps)
656 {
657 out_uint16_le(s, id);
658 out_uint16_le(s, length);
659
660 out_uint8p(s, caps, length - 4);
661 }
662
663 #define RDP5_FLAG 0x0030
664 /* Send a confirm active PDU */
665 static void
666 rdp_send_confirm_active(void)
667 {
668 STREAM s;
669 uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
670 uint16 caplen =
671 RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
672 RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
673 RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
674 RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
675 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
676 4 /* w2k fix, why? */ ;
677
678 s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
679
680 out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
681 out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
682 out_uint16_le(s, (g_mcs_userid + 1001));
683
684 out_uint32_le(s, g_rdp_shareid);
685 out_uint16_le(s, 0x3ea); /* userid */
686 out_uint16_le(s, sizeof(RDP_SOURCE));
687 out_uint16_le(s, caplen);
688
689 out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
690 out_uint16_le(s, 0xd); /* num_caps */
691 out_uint8s(s, 2); /* pad */
692
693 rdp_out_general_caps(s);
694 rdp_out_bitmap_caps(s);
695 rdp_out_order_caps(s);
696 g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
697 rdp_out_colcache_caps(s);
698 rdp_out_activate_caps(s);
699 rdp_out_control_caps(s);
700 rdp_out_pointer_caps(s);
701 rdp_out_share_caps(s);
702
703 rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
704 rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
705 rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
706 rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
707
708 s_mark_end(s);
709 sec_send(s, sec_flags);
710 }
711
712 /* Process a general capability set */
713 static void
714 rdp_process_general_caps(STREAM s)
715 {
716 uint16 pad2octetsB; /* rdp5 flags? */
717
718 in_uint8s(s, 10);
719 in_uint16_le(s, pad2octetsB);
720
721 if (!pad2octetsB)
722 g_use_rdp5 = False;
723 }
724
725 /* Process a bitmap capability set */
726 static void
727 rdp_process_bitmap_caps(STREAM s)
728 {
729 uint16 width, height, bpp;
730
731 in_uint16_le(s, bpp);
732 in_uint8s(s, 6);
733
734 in_uint16_le(s, width);
735 in_uint16_le(s, height);
736
737 DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
738
739 /*
740 * The server may limit bpp and change the size of the desktop (for
741 * example when shadowing another session).
742 */
743 if (g_server_bpp != bpp)
744 {
745 warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
746 g_server_bpp = bpp;
747 }
748 if (g_width != width || g_height != height)
749 {
750 warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
751 width, height);
752 g_width = width;
753 g_height = height;
754 ui_resize_window();
755 }
756 }
757
758 /* Process server capabilities */
759 void
760 rdp_process_server_caps(STREAM s, uint16 length)
761 {
762 int n;
763 uint8 *next, *start;
764 uint16 ncapsets, capset_type, capset_length;
765
766 start = s->p;
767
768 in_uint16_le(s, ncapsets);
769 in_uint8s(s, 2); /* pad */
770
771 for (n = 0; n < ncapsets; n++)
772 {
773 if (s->p > start + length)
774 return;
775
776 in_uint16_le(s, capset_type);
777 in_uint16_le(s, capset_length);
778
779 next = s->p + capset_length - 4;
780
781 switch (capset_type)
782 {
783 case RDP_CAPSET_GENERAL:
784 rdp_process_general_caps(s);
785 break;
786
787 case RDP_CAPSET_BITMAP:
788 rdp_process_bitmap_caps(s);
789 break;
790 }
791
792 s->p = next;
793 }
794 }
795
796 /* Respond to a demand active PDU */
797 static void
798 process_demand_active(STREAM s)
799 {
800 uint8 type;
801 uint16 len_src_descriptor, len_combined_caps;
802
803 in_uint32_le(s, g_rdp_shareid);
804 in_uint16_le(s, len_src_descriptor);
805 in_uint16_le(s, len_combined_caps);
806 in_uint8s(s, len_src_descriptor);
807
808 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
809 rdp_process_server_caps(s, len_combined_caps);
810
811 rdp_send_confirm_active();
812 rdp_send_synchronise();
813 rdp_send_control(RDP_CTL_COOPERATE);
814 rdp_send_control(RDP_CTL_REQUEST_CONTROL);
815 rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
816 rdp_recv(&type); /* RDP_CTL_COOPERATE */
817 rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
818 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
819
820 if (g_use_rdp5)
821 {
822 rdp_enum_bmpcache2();
823 rdp_send_fonts(3);
824 }
825 else
826 {
827 rdp_send_fonts(1);
828 rdp_send_fonts(2);
829 }
830
831 rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
832 reset_order_state();
833 }
834
835 /* Process a colour pointer PDU */
836 void
837 process_colour_pointer_pdu(STREAM s)
838 {
839 uint16 x, y, width, height, cache_idx, masklen, datalen;
840 uint8 *mask, *data;
841 HCURSOR cursor;
842
843 in_uint16_le(s, cache_idx);
844 in_uint16_le(s, x);
845 in_uint16_le(s, y);
846 in_uint16_le(s, width);
847 in_uint16_le(s, height);
848 in_uint16_le(s, masklen);
849 in_uint16_le(s, datalen);
850 in_uint8p(s, data, datalen);
851 in_uint8p(s, mask, masklen);
852 cursor = ui_create_cursor(x, y, width, height, mask, data);
853 ui_set_cursor(cursor);
854 cache_put_cursor(cache_idx, cursor);
855 }
856
857 /* Process a cached pointer PDU */
858 void
859 process_cached_pointer_pdu(STREAM s)
860 {
861 uint16 cache_idx;
862
863 in_uint16_le(s, cache_idx);
864 ui_set_cursor(cache_get_cursor(cache_idx));
865 }
866
867 /* Process a system pointer PDU */
868 void
869 process_system_pointer_pdu(STREAM s)
870 {
871 uint16 system_pointer_type;
872
873 in_uint16(s, system_pointer_type);
874 switch (system_pointer_type)
875 {
876 case RDP_NULL_POINTER:
877 ui_set_null_cursor();
878 break;
879
880 default:
881 unimpl("System pointer message 0x%x\n", system_pointer_type);
882 }
883 }
884
885 /* Process a pointer PDU */
886 static void
887 process_pointer_pdu(STREAM s)
888 {
889 uint16 message_type;
890 uint16 x, y;
891
892 in_uint16_le(s, message_type);
893 in_uint8s(s, 2); /* pad */
894
895 switch (message_type)
896 {
897 case RDP_POINTER_MOVE:
898 in_uint16_le(s, x);
899 in_uint16_le(s, y);
900 if (s_check(s))
901 ui_move_pointer(x, y);
902 break;
903
904 case RDP_POINTER_COLOR:
905 process_colour_pointer_pdu(s);
906 break;
907
908 case RDP_POINTER_CACHED:
909 process_cached_pointer_pdu(s);
910 break;
911
912 case RDP_POINTER_SYSTEM:
913 process_system_pointer_pdu(s);
914 break;
915
916 default:
917 unimpl("Pointer message 0x%x\n", message_type);
918 }
919 }
920
921 /* Process bitmap updates */
922 void
923 process_bitmap_updates(STREAM s)
924 {
925 uint16 num_updates;
926 uint16 left, top, right, bottom, width, height;
927 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
928 uint8 *data, *bmpdata;
929 int i;
930
931 in_uint16_le(s, num_updates);
932
933 for (i = 0; i < num_updates; i++)
934 {
935 in_uint16_le(s, left);
936 in_uint16_le(s, top);
937 in_uint16_le(s, right);
938 in_uint16_le(s, bottom);
939 in_uint16_le(s, width);
940 in_uint16_le(s, height);
941 in_uint16_le(s, bpp);
942 Bpp = (bpp + 7) / 8;
943 in_uint16_le(s, compress);
944 in_uint16_le(s, bufsize);
945
946 cx = right - left + 1;
947 cy = bottom - top + 1;
948
949 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
950 left, top, right, bottom, width, height, Bpp, compress));
951
952 if (!compress)
953 {
954 int y;
955 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
956 for (y = 0; y < height; y++)
957 {
958 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
959 width * Bpp);
960 }
961 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
962 xfree(bmpdata);
963 continue;
964 }
965
966
967 if (compress & 0x400)
968 {
969 size = bufsize;
970 }
971 else
972 {
973 in_uint8s(s, 2); /* pad */
974 in_uint16_le(s, size);
975 in_uint8s(s, 4); /* line_size, final_size */
976 }
977 in_uint8p(s, data, size);
978 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
979 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
980 {
981 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
982 }
983 else
984 {
985 DEBUG_RDP5(("Failed to decompress data\n"));
986 }
987
988 xfree(bmpdata);
989 }
990 }
991
992 /* Process a palette update */
993 void
994 process_palette(STREAM s)
995 {
996 COLOURENTRY *entry;
997 COLOURMAP map;
998 HCOLOURMAP hmap;
999 int i;
1000
1001 in_uint8s(s, 2); /* pad */
1002 in_uint16_le(s, map.ncolours);
1003 in_uint8s(s, 2); /* pad */
1004
1005 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1006
1007 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1008
1009 for (i = 0; i < map.ncolours; i++)
1010 {
1011 entry = &map.colours[i];
1012 in_uint8(s, entry->red);
1013 in_uint8(s, entry->green);
1014 in_uint8(s, entry->blue);
1015 }
1016
1017 hmap = ui_create_colourmap(&map);
1018 ui_set_colourmap(hmap);
1019
1020 xfree(map.colours);
1021 }
1022
1023 /* Process an update PDU */
1024 static void
1025 process_update_pdu(STREAM s)
1026 {
1027 uint16 update_type, count;
1028
1029 in_uint16_le(s, update_type);
1030
1031 ui_begin_update();
1032 switch (update_type)
1033 {
1034 case RDP_UPDATE_ORDERS:
1035 in_uint8s(s, 2); /* pad */
1036 in_uint16_le(s, count);
1037 in_uint8s(s, 2); /* pad */
1038 process_orders(s, count);
1039 break;
1040
1041 case RDP_UPDATE_BITMAP:
1042 process_bitmap_updates(s);
1043 break;
1044
1045 case RDP_UPDATE_PALETTE:
1046 process_palette(s);
1047 break;
1048
1049 case RDP_UPDATE_SYNCHRONIZE:
1050 break;
1051
1052 default:
1053 unimpl("update %d\n", update_type);
1054 }
1055 ui_end_update();
1056 }
1057
1058 /* Process a disconnect PDU */
1059 void
1060 process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1061 {
1062 in_uint32_le(s, *ext_disc_reason);
1063
1064 DEBUG(("Received disconnect PDU\n"));
1065 }
1066
1067 /* Process data PDU */
1068 static BOOL
1069 process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1070 {
1071 uint8 data_pdu_type;
1072 uint8 ctype;
1073 uint16 clen;
1074 uint32 len;
1075
1076 uint32 roff, rlen;
1077
1078 struct stream *ns = &(g_mppc_dict.ns);
1079
1080 in_uint8s(s, 6); /* shareid, pad, streamid */
1081 in_uint16(s, len);
1082 in_uint8(s, data_pdu_type);
1083 in_uint8(s, ctype);
1084 in_uint16(s, clen);
1085 clen -= 18;
1086
1087 if (ctype & RDP_MPPC_COMPRESSED)
1088 {
1089
1090 if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1091 error("error while decompressing packet\n");
1092
1093 //len -= 18;
1094
1095 /* allocate memory and copy the uncompressed data into the temporary stream */
1096 ns->data = (uint8 *) xrealloc(ns->data, rlen);
1097
1098 memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1099
1100 ns->size = rlen;
1101 ns->end = (ns->data + ns->size);
1102 ns->p = ns->data;
1103 ns->rdp_hdr = ns->p;
1104
1105 s = ns;
1106 }
1107
1108 switch (data_pdu_type)
1109 {
1110 case RDP_DATA_PDU_UPDATE:
1111 process_update_pdu(s);
1112 break;
1113
1114 case RDP_DATA_PDU_CONTROL:
1115 DEBUG(("Received Control PDU\n"));
1116 break;
1117
1118 case RDP_DATA_PDU_SYNCHRONISE:
1119 DEBUG(("Received Sync PDU\n"));
1120 break;
1121
1122 case RDP_DATA_PDU_POINTER:
1123 process_pointer_pdu(s);
1124 break;
1125
1126 case RDP_DATA_PDU_BELL:
1127 ui_bell();
1128 break;
1129
1130 case RDP_DATA_PDU_LOGON:
1131 DEBUG(("Received Logon PDU\n"));
1132 /* User logged on */
1133 break;
1134
1135 case RDP_DATA_PDU_DISCONNECT:
1136 process_disconnect_pdu(s, ext_disc_reason);
1137 return True;
1138
1139 default:
1140 unimpl("data PDU %d\n", data_pdu_type);
1141 }
1142 return False;
1143 }
1144
1145 /* Process incoming packets */
1146 /* nevers gets out of here till app is done */
1147 void
1148 rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1149 {
1150 while (rdp_loop(deactivated, ext_disc_reason))
1151 ;
1152 }
1153
1154 /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1155 BOOL
1156 rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1157 {
1158 uint8 type;
1159 BOOL disc = False; /* True when a disconnect PDU was received */
1160 BOOL cont = True;
1161 STREAM s;
1162
1163 while (cont)
1164 {
1165 s = rdp_recv(&type);
1166 if (s == NULL)
1167 return False;
1168 switch (type)
1169 {
1170 case RDP_PDU_DEMAND_ACTIVE:
1171 process_demand_active(s);
1172 *deactivated = False;
1173 break;
1174 case RDP_PDU_DEACTIVATE:
1175 DEBUG(("RDP_PDU_DEACTIVATE\n"));
1176 *deactivated = True;
1177 break;
1178 case RDP_PDU_DATA:
1179 disc = process_data_pdu(s, ext_disc_reason);
1180 break;
1181 case 0:
1182 break;
1183 default:
1184 unimpl("PDU %d\n", type);
1185 }
1186 if (disc)
1187 return False;
1188 cont = g_next_packet < s->end;
1189 }
1190 return True;
1191 }
1192
1193 /* Establish a connection up to the RDP layer */
1194 BOOL
1195 rdp_connect(char *server, uint32 flags, char *domain, char *password,
1196 char *command, char *directory)
1197 {
1198 if (!sec_connect(server, g_username))
1199 return False;
1200
1201 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1202 return True;
1203 }
1204
1205 /* Disconnect from the RDP layer */
1206 void
1207 rdp_disconnect(void)
1208 {
1209 sec_disconnect();
1210 }

  ViewVC Help
Powered by ViewVC 1.1.26