/[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 730 - (show annotations)
Tue Jun 29 16:22:41 2004 UTC (19 years, 10 months ago) by jsorg71
File MIME type: text/plain
File size: 28213 byte(s)
a few fixes for PBC from Jeroen

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

  ViewVC Help
Powered by ViewVC 1.1.26