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

  ViewVC Help
Powered by ViewVC 1.1.26