/[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 855 - (show annotations)
Sun Mar 13 13:18:48 2005 UTC (19 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 30383 byte(s)
unicode support from Andy Igoshin <ai@vsu.ru>
Currently disabled, need HAVE_ICONV and HAVE_ICONV_H defined to be
used. This should be done with a new configure test.

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

  ViewVC Help
Powered by ViewVC 1.1.26