/[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 863 - (show annotations)
Mon Mar 14 17:47:46 2005 UTC (19 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 30245 byte(s)
use UTF-16LE instead of UTF-16 => let iconv swab the bytes for us

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

  ViewVC Help
Powered by ViewVC 1.1.26