/[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 779 - (show annotations)
Mon Oct 4 03:21:58 2004 UTC (19 years, 7 months ago) by jsorg71
File MIME type: text/plain
File size: 28114 byte(s)
bring the channel packets through rdp_loop so the uiports can enjoy the channel data

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

  ViewVC Help
Powered by ViewVC 1.1.26