/[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 879 - (show annotations)
Sun Apr 3 18:08:05 2005 UTC (19 years, 1 month ago) by astrand
File MIME type: text/plain
File size: 30713 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26