1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman 1999-2005
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.
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.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 extern uint16 g_mcs_userid
;
24 extern char g_username
[];
25 extern char g_codepage
[];
26 extern BOOL g_bitmap_compression
;
28 extern BOOL g_encryption
;
29 extern BOOL g_desktop_save
;
30 extern BOOL g_polygon_ellipse_orders
;
31 extern BOOL g_use_rdp5
;
32 extern uint16 g_server_rdp_version
;
33 extern uint32 g_rdp5_performanceflags
;
34 extern int g_server_depth
;
37 extern BOOL g_bitmap_cache
;
38 extern BOOL g_bitmap_cache_persist_enable
;
43 extern RDPCOMP g_mppc_dict
;
45 /* Session Directory support */
46 extern BOOL g_redirect
;
47 extern char g_redirect_server
[64];
48 extern char g_redirect_domain
[16];
49 extern char g_redirect_password
[64];
50 extern char g_redirect_username
[64];
51 extern char g_redirect_cookie
[128];
52 extern uint32 g_redirect_flags
;
53 /* END Session Directory support */
56 static uint32 g_packetno
;
60 static BOOL g_iconv_works
= True
;
63 /* Receive an RDP packet */
65 rdp_recv(uint8
* type
)
68 uint16 length
, pdu_type
;
71 if ((rdp_s
== NULL
) || (g_next_packet
>= rdp_s
->end
) || (g_next_packet
== NULL
))
73 rdp_s
= sec_recv(&rdpver
);
78 g_next_packet
= rdp_s
->end
;
84 /* rdp5_process should move g_next_packet ok */
90 g_next_packet
= rdp_s
->p
;
94 rdp_s
->p
= g_next_packet
;
97 in_uint16_le(rdp_s
, length
);
98 /* 32k packets are really 8, keepalive fix */
105 in_uint16_le(rdp_s
, pdu_type
);
106 in_uint8s(rdp_s
, 2); /* userid */
107 *type
= pdu_type
& 0xf;
110 DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno
, *type
));
111 hexdump(g_next_packet
, length
);
114 g_next_packet
+= length
;
118 /* Initialise an RDP data packet */
120 rdp_init_data(int maxlen
)
124 s
= sec_init(g_encryption
? SEC_ENCRYPT
: 0, maxlen
+ 18);
125 s_push_layer(s
, rdp_hdr
, 18);
130 /* Send an RDP data packet */
132 rdp_send_data(STREAM s
, uint8 data_pdu_type
)
136 s_pop_layer(s
, rdp_hdr
);
137 length
= s
->end
- s
->p
;
139 out_uint16_le(s
, length
);
140 out_uint16_le(s
, (RDP_PDU_DATA
| 0x10));
141 out_uint16_le(s
, (g_mcs_userid
+ 1001));
143 out_uint32_le(s
, g_rdp_shareid
);
144 out_uint8(s
, 0); /* pad */
145 out_uint8(s
, 1); /* streamid */
146 out_uint16_le(s
, (length
- 14));
147 out_uint8(s
, data_pdu_type
);
148 out_uint8(s
, 0); /* compress_type */
149 out_uint16(s
, 0); /* compress_len */
151 sec_send(s
, g_encryption
? SEC_ENCRYPT
: 0);
154 /* Output a string in Unicode */
156 rdp_out_unistr(STREAM s
, char *string
, int len
)
159 size_t ibl
= strlen(string
), obl
= len
+ 2;
160 static iconv_t iconv_h
= (iconv_t
) - 1;
161 char *pin
= string
, *pout
= (char *) s
->p
;
163 memset(pout
, 0, len
+ 4);
167 if (iconv_h
== (iconv_t
) - 1)
170 if ((iconv_h
= iconv_open(WINDOWS_CODEPAGE
, g_codepage
)) == (iconv_t
) - 1)
172 warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
173 g_codepage
, WINDOWS_CODEPAGE
, (int) iconv_h
);
175 g_iconv_works
= False
;
176 rdp_out_unistr(s
, string
, len
);
179 if (iconv(iconv_h
, (ICONV_CONST
char **) &pin
, &i
, &pout
, &o
) ==
182 iconv_close(iconv_h
);
183 iconv_h
= (iconv_t
) - 1;
184 warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno
);
186 g_iconv_works
= False
;
187 rdp_out_unistr(s
, string
, len
);
191 pout
= (char *) s
->p
;
194 if (iconv(iconv_h
, (ICONV_CONST
char **) &pin
, &ibl
, &pout
, &obl
) == (size_t) - 1)
196 iconv_close(iconv_h
);
197 iconv_h
= (iconv_t
) - 1;
198 warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno
);
200 g_iconv_works
= False
;
201 rdp_out_unistr(s
, string
, len
);
217 s
->p
[i
++] = string
[j
++];
225 /* Input a string in Unicode
227 * Returns str_len of string
230 rdp_in_unistr(STREAM s
, char *string
, int uni_len
)
233 size_t ibl
= uni_len
, obl
= uni_len
;
234 char *pin
= (char *) s
->p
, *pout
= string
;
235 static iconv_t iconv_h
= (iconv_t
) - 1;
239 if (iconv_h
== (iconv_t
) - 1)
241 if ((iconv_h
= iconv_open(g_codepage
, WINDOWS_CODEPAGE
)) == (iconv_t
) - 1)
243 warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
244 WINDOWS_CODEPAGE
, g_codepage
, (int) iconv_h
);
246 g_iconv_works
= False
;
247 return rdp_in_unistr(s
, string
, uni_len
);
251 if (iconv(iconv_h
, (ICONV_CONST
char **) &pin
, &ibl
, &pout
, &obl
) == (size_t) - 1)
253 iconv_close(iconv_h
);
254 iconv_h
= (iconv_t
) - 1;
255 warning("rdp_in_unistr: iconv fail, errno %d\n", errno
);
257 g_iconv_works
= False
;
258 return rdp_in_unistr(s
, string
, uni_len
);
261 /* we must update the location of the current STREAM for future reads of s->p */
264 return pout
- string
;
271 while (i
< uni_len
/ 2)
273 in_uint8a(s
, &string
[i
++], 1);
282 /* Parse a logon info packet */
284 rdp_send_logon_info(uint32 flags
, char *domain
, char *user
,
285 char *password
, char *program
, char *directory
)
287 //char *ipaddr = tcp_get_address();
288 int len_domain
= 2 * strlen(domain
);
289 int len_user
= 2 * strlen(user
);
290 int len_password
= 2 * strlen(password
);
291 int len_program
= 2 * strlen(program
);
292 int len_directory
= 2 * strlen(directory
);
293 //int len_ip = 2 * strlen(ipaddr);
294 //int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
296 uint32 sec_flags
= g_encryption
? (SEC_LOGON_INFO
| SEC_ENCRYPT
) : SEC_LOGON_INFO
;
298 //time_t t = time(NULL);
301 if (!g_use_rdp5
|| 1 == g_server_rdp_version
)
303 DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
305 s
= sec_init(sec_flags
, 18 + len_domain
+ len_user
+ len_password
306 + len_program
+ len_directory
+ 10);
309 out_uint32_le(s
, flags
);
310 out_uint16_le(s
, len_domain
);
311 out_uint16_le(s
, len_user
);
312 out_uint16_le(s
, len_password
);
313 out_uint16_le(s
, len_program
);
314 out_uint16_le(s
, len_directory
);
315 rdp_out_unistr(s
, domain
, len_domain
);
316 rdp_out_unistr(s
, user
, len_user
);
317 rdp_out_unistr(s
, password
, len_password
);
318 rdp_out_unistr(s
, program
, len_program
);
319 rdp_out_unistr(s
, directory
, len_directory
);
324 flags
|= RDP_LOGON_BLOB
;
325 DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
326 packetlen
= 4 + /* Unknown uint32 */
330 (flags
& RDP_LOGON_AUTO
? 2 : 0) + /* len_password */
331 (flags
& RDP_LOGON_BLOB
? 2 : 0) + /* Length of BLOB */
332 2 + /* len_program */
333 2 + /* len_directory */
334 (0 < len_domain
? len_domain
: 2) + /* domain */
335 len_user
+ (flags
& RDP_LOGON_AUTO
? len_password
: 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */
336 (flags
& RDP_LOGON_BLOB
&& !(flags
& RDP_LOGON_AUTO
) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
337 (0 < len_program
? len_program
: 2) + (0 < len_directory
? len_directory
: 2) + 2 + /* Unknown (2) */
338 2 + /* Client ip length */
339 len_ip
+ /* Client ip */
340 2 + /* DLL string length */
341 len_dll
+ /* DLL string */
344 64 + /* Time zone #0 */
346 64 + /* Time zone #1 */
349 s
= sec_init(sec_flags
, packetlen
);
350 DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen
));
352 out_uint32(s
, 0); /* Unknown */
353 out_uint32_le(s
, flags
);
354 out_uint16_le(s
, len_domain
);
355 out_uint16_le(s
, len_user
);
356 if (flags
& RDP_LOGON_AUTO
)
358 out_uint16_le(s
, len_password
);
361 if (flags
& RDP_LOGON_BLOB
&& !(flags
& RDP_LOGON_AUTO
))
365 out_uint16_le(s
, len_program
);
366 out_uint16_le(s
, len_directory
);
368 rdp_out_unistr(s
, domain
, len_domain
);
371 rdp_out_unistr(s
, user
, len_user
);
372 if (flags
& RDP_LOGON_AUTO
)
374 rdp_out_unistr(s
, password
, len_password
);
376 if (flags
& RDP_LOGON_BLOB
&& !(flags
& RDP_LOGON_AUTO
))
382 rdp_out_unistr(s
, program
, len_program
);
389 if (0 < len_directory
)
391 rdp_out_unistr(s
, directory
, len_directory
);
398 out_uint16_le(s
, len_ip
+ 2); /* Length of client ip */
399 rdp_out_unistr(s
, ipaddr
, len_ip
);
400 out_uint16_le(s
, len_dll
+ 2);
401 rdp_out_unistr(s
, "C:\\WINNT\\System32\\mstscax.dll", len_dll
);
403 tzone
= (mktime(gmtime(&t
)) - mktime(localtime(&t
))) / 60;
404 out_uint32_le(s
, tzone
);
406 rdp_out_unistr(s
, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
407 out_uint8s(s
, 62 - 2 * strlen("GTB, normaltid"));
409 out_uint32_le(s
, 0x0a0000);
410 out_uint32_le(s
, 0x050000);
415 rdp_out_unistr(s
, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
416 out_uint8s(s
, 62 - 2 * strlen("GTB, sommartid"));
418 out_uint32_le(s
, 0x30000);
419 out_uint32_le(s
, 0x050000);
422 out_uint32_le(s
, 0xffffffc4);
423 out_uint32_le(s
, 0xfffffffe);
424 out_uint32_le(s
, g_rdp5_performanceflags
);
430 sec_send(s
, sec_flags
);
433 /* Send a control PDU */
435 rdp_send_control(uint16 action
)
439 s
= rdp_init_data(8);
441 out_uint16_le(s
, action
);
442 out_uint16(s
, 0); /* userid */
443 out_uint32(s
, 0); /* control id */
446 rdp_send_data(s
, RDP_DATA_PDU_CONTROL
);
449 /* Send a synchronisation PDU */
451 rdp_send_synchronise(void)
455 s
= rdp_init_data(4);
457 out_uint16_le(s
, 1); /* type */
458 out_uint16_le(s
, 1002);
461 rdp_send_data(s
, RDP_DATA_PDU_SYNCHRONISE
);
464 /* Send a single input event */
466 rdp_send_input(uint32 time
, uint16 message_type
, uint16 device_flags
, uint16 param1
, uint16 param2
)
470 s
= rdp_init_data(16);
472 out_uint16_le(s
, 1); /* number of events */
473 out_uint16(s
, 0); /* pad */
475 out_uint32_le(s
, time
);
476 out_uint16_le(s
, message_type
);
477 out_uint16_le(s
, device_flags
);
478 out_uint16_le(s
, param1
);
479 out_uint16_le(s
, param2
);
482 rdp_send_data(s
, RDP_DATA_PDU_INPUT
);
485 /* Send a client window information PDU */
487 rdp_send_client_window_status(int status
)
490 static int current_status
= 1;
492 if (current_status
== status
)
495 s
= rdp_init_data(12);
497 out_uint32_le(s
, status
);
501 case 0: /* shut the server up */
504 case 1: /* receive data again */
505 out_uint32_le(s
, 0); /* unknown */
506 out_uint16_le(s
, g_width
);
507 out_uint16_le(s
, g_height
);
512 rdp_send_data(s
, RDP_DATA_PDU_CLIENT_WINDOW_STATUS
);
513 current_status
= status
;
516 /* Send persistent bitmap cache enumeration PDU's */
518 rdp_enum_bmpcache2(void)
521 HASH_KEY keylist
[BMPCACHE2_NUM_PSTCELLS
];
522 uint32 num_keys
, offset
, count
, flags
;
525 num_keys
= pstcache_enumerate(2, keylist
);
527 while (offset
< num_keys
)
529 count
= MIN(num_keys
- offset
, 169);
531 s
= rdp_init_data(24 + count
* sizeof(HASH_KEY
));
535 flags
|= PDU_FLAG_FIRST
;
536 if (num_keys
- offset
<= 169)
537 flags
|= PDU_FLAG_LAST
;
541 out_uint16_le(s
, count
);
546 out_uint16_le(s
, num_keys
);
548 out_uint32_le(s
, flags
);
551 out_uint8a(s
, keylist
[offset
], count
* sizeof(HASH_KEY
));
554 rdp_send_data(s
, 0x2b);
560 /* Send an (empty) font information PDU */
562 rdp_send_fonts(uint16 seq
)
566 s
= rdp_init_data(8);
568 out_uint16(s
, 0); /* number of fonts */
569 out_uint16_le(s
, 0); /* pad? */
570 out_uint16_le(s
, seq
); /* unknown */
571 out_uint16_le(s
, 0x32); /* entry size */
574 rdp_send_data(s
, RDP_DATA_PDU_FONT2
);
577 /* Output general capability set */
579 rdp_out_general_caps(STREAM s
)
581 out_uint16_le(s
, RDP_CAPSET_GENERAL
);
582 out_uint16_le(s
, RDP_CAPLEN_GENERAL
);
584 out_uint16_le(s
, 1); /* OS major type */
585 out_uint16_le(s
, 3); /* OS minor type */
586 out_uint16_le(s
, 0x200); /* Protocol version */
587 out_uint16(s
, 0); /* Pad */
588 out_uint16(s
, 0); /* Compression types */
589 out_uint16_le(s
, g_use_rdp5
? 0x40d : 0);
590 /* Pad, according to T.128. 0x40d seems to
592 the server to start sending RDP5 packets.
593 However, the value is 0x1d04 with W2KTSK and
594 NT4MS. Hmm.. Anyway, thankyou, Microsoft,
595 for sending such information in a padding
597 out_uint16(s
, 0); /* Update capability */
598 out_uint16(s
, 0); /* Remote unshare capability */
599 out_uint16(s
, 0); /* Compression level */
600 out_uint16(s
, 0); /* Pad */
603 /* Output bitmap capability set */
605 rdp_out_bitmap_caps(STREAM s
)
607 out_uint16_le(s
, RDP_CAPSET_BITMAP
);
608 out_uint16_le(s
, RDP_CAPLEN_BITMAP
);
610 out_uint16_le(s
, g_server_depth
); /* Preferred colour depth */
611 out_uint16_le(s
, 1); /* Receive 1 BPP */
612 out_uint16_le(s
, 1); /* Receive 4 BPP */
613 out_uint16_le(s
, 1); /* Receive 8 BPP */
614 out_uint16_le(s
, 800); /* Desktop width */
615 out_uint16_le(s
, 600); /* Desktop height */
616 out_uint16(s
, 0); /* Pad */
617 out_uint16(s
, 1); /* Allow resize */
618 out_uint16_le(s
, g_bitmap_compression
? 1 : 0); /* Support compression */
619 out_uint16(s
, 0); /* Unknown */
620 out_uint16_le(s
, 1); /* Unknown */
621 out_uint16(s
, 0); /* Pad */
624 /* Output order capability set */
626 rdp_out_order_caps(STREAM s
)
628 uint8 order_caps
[32];
630 memset(order_caps
, 0, 32);
631 order_caps
[0] = 1; /* dest blt */
632 order_caps
[1] = 1; /* pat blt */
633 order_caps
[2] = 1; /* screen blt */
634 order_caps
[3] = (g_bitmap_cache
? 1 : 0); /* memblt */
635 order_caps
[4] = 0; /* triblt */
636 order_caps
[8] = 1; /* line */
637 order_caps
[9] = 1; /* line */
638 order_caps
[10] = 1; /* rect */
639 order_caps
[11] = (g_desktop_save
? 1 : 0); /* desksave */
640 order_caps
[13] = 1; /* memblt */
641 order_caps
[14] = 1; /* triblt */
642 order_caps
[20] = (g_polygon_ellipse_orders
? 1 : 0); /* polygon */
643 order_caps
[21] = (g_polygon_ellipse_orders
? 1 : 0); /* polygon2 */
644 order_caps
[22] = 1; /* polyline */
645 order_caps
[25] = (g_polygon_ellipse_orders
? 1 : 0); /* ellipse */
646 order_caps
[26] = (g_polygon_ellipse_orders
? 1 : 0); /* ellipse2 */
647 order_caps
[27] = 1; /* text2 */
648 out_uint16_le(s
, RDP_CAPSET_ORDER
);
649 out_uint16_le(s
, RDP_CAPLEN_ORDER
);
651 out_uint8s(s
, 20); /* Terminal desc, pad */
652 out_uint16_le(s
, 1); /* Cache X granularity */
653 out_uint16_le(s
, 20); /* Cache Y granularity */
654 out_uint16(s
, 0); /* Pad */
655 out_uint16_le(s
, 1); /* Max order level */
656 out_uint16_le(s
, 0x147); /* Number of fonts */
657 out_uint16_le(s
, 0x2a); /* Capability flags */
658 out_uint8p(s
, order_caps
, 32); /* Orders supported */
659 out_uint16_le(s
, 0x6a1); /* Text capability flags */
660 out_uint8s(s
, 6); /* Pad */
661 out_uint32_le(s
, g_desktop_save
== False
? 0 : 0x38400); /* Desktop cache size */
662 out_uint32(s
, 0); /* Unknown */
663 out_uint32_le(s
, 0x4e4); /* Unknown */
666 /* Output bitmap cache capability set */
668 rdp_out_bmpcache_caps(STREAM s
)
671 out_uint16_le(s
, RDP_CAPSET_BMPCACHE
);
672 out_uint16_le(s
, RDP_CAPLEN_BMPCACHE
);
674 Bpp
= (g_server_depth
+ 7) / 8; /* bytes per pixel */
675 out_uint8s(s
, 24); /* unused */
676 out_uint16_le(s
, 0x258); /* entries */
677 out_uint16_le(s
, 0x100 * Bpp
); /* max cell size */
678 out_uint16_le(s
, 0x12c); /* entries */
679 out_uint16_le(s
, 0x400 * Bpp
); /* max cell size */
680 out_uint16_le(s
, 0x106); /* entries */
681 out_uint16_le(s
, 0x1000 * Bpp
); /* max cell size */
684 /* Output bitmap cache v2 capability set */
686 rdp_out_bmpcache2_caps(STREAM s
)
688 out_uint16_le(s
, RDP_CAPSET_BMPCACHE2
);
689 out_uint16_le(s
, RDP_CAPLEN_BMPCACHE2
);
691 out_uint16_le(s
, g_bitmap_cache_persist_enable
? 2 : 0); /* version */
693 out_uint16_be(s
, 3); /* number of caches in this set */
695 /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
696 out_uint32_le(s
, BMPCACHE2_C0_CELLS
);
697 out_uint32_le(s
, BMPCACHE2_C1_CELLS
);
698 if (pstcache_init(2))
700 out_uint32_le(s
, BMPCACHE2_NUM_PSTCELLS
| BMPCACHE2_FLAG_PERSIST
);
704 out_uint32_le(s
, BMPCACHE2_C2_CELLS
);
706 out_uint8s(s
, 20); /* other bitmap caches not used */
709 /* Output control capability set */
711 rdp_out_control_caps(STREAM s
)
713 out_uint16_le(s
, RDP_CAPSET_CONTROL
);
714 out_uint16_le(s
, RDP_CAPLEN_CONTROL
);
716 out_uint16(s
, 0); /* Control capabilities */
717 out_uint16(s
, 0); /* Remote detach */
718 out_uint16_le(s
, 2); /* Control interest */
719 out_uint16_le(s
, 2); /* Detach interest */
722 /* Output activation capability set */
724 rdp_out_activate_caps(STREAM s
)
726 out_uint16_le(s
, RDP_CAPSET_ACTIVATE
);
727 out_uint16_le(s
, RDP_CAPLEN_ACTIVATE
);
729 out_uint16(s
, 0); /* Help key */
730 out_uint16(s
, 0); /* Help index key */
731 out_uint16(s
, 0); /* Extended help key */
732 out_uint16(s
, 0); /* Window activate */
735 /* Output pointer capability set */
737 rdp_out_pointer_caps(STREAM s
)
739 out_uint16_le(s
, RDP_CAPSET_POINTER
);
740 out_uint16_le(s
, RDP_CAPLEN_POINTER
);
742 out_uint16(s
, 0); /* Colour pointer */
743 out_uint16_le(s
, 20); /* Cache size */
746 /* Output share capability set */
748 rdp_out_share_caps(STREAM s
)
750 out_uint16_le(s
, RDP_CAPSET_SHARE
);
751 out_uint16_le(s
, RDP_CAPLEN_SHARE
);
753 out_uint16(s
, 0); /* userid */
754 out_uint16(s
, 0); /* pad */
757 /* Output colour cache capability set */
759 rdp_out_colcache_caps(STREAM s
)
761 out_uint16_le(s
, RDP_CAPSET_COLCACHE
);
762 out_uint16_le(s
, RDP_CAPLEN_COLCACHE
);
764 out_uint16_le(s
, 6); /* cache size */
765 out_uint16(s
, 0); /* pad */
768 static uint8 caps_0x0d
[] = {
769 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
770 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
779 0x00, 0x00, 0x00, 0x00
782 static uint8 caps_0x0c
[] = { 0x01, 0x00, 0x00, 0x00 };
784 static uint8 caps_0x0e
[] = { 0x01, 0x00, 0x00, 0x00 };
786 static uint8 caps_0x10
[] = {
787 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
788 0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
789 0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
790 0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
791 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
792 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
795 /* Output unknown capability sets */
797 rdp_out_unknown_caps(STREAM s
, uint16 id
, uint16 length
, uint8
* caps
)
799 out_uint16_le(s
, id
);
800 out_uint16_le(s
, length
);
802 out_uint8p(s
, caps
, length
- 4);
805 #define RDP5_FLAG 0x0030
806 /* Send a confirm active PDU */
808 rdp_send_confirm_active(void)
811 uint32 sec_flags
= g_encryption
? (RDP5_FLAG
| SEC_ENCRYPT
) : RDP5_FLAG
;
813 RDP_CAPLEN_GENERAL
+ RDP_CAPLEN_BITMAP
+ RDP_CAPLEN_ORDER
+
814 RDP_CAPLEN_BMPCACHE
+ RDP_CAPLEN_COLCACHE
+
815 RDP_CAPLEN_ACTIVATE
+ RDP_CAPLEN_CONTROL
+
816 RDP_CAPLEN_POINTER
+ RDP_CAPLEN_SHARE
+
817 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
818 4 /* w2k fix, why? */ ;
820 s
= sec_init(sec_flags
, 6 + 14 + caplen
+ sizeof(RDP_SOURCE
));
822 out_uint16_le(s
, 2 + 14 + caplen
+ sizeof(RDP_SOURCE
));
823 out_uint16_le(s
, (RDP_PDU_CONFIRM_ACTIVE
| 0x10)); /* Version 1 */
824 out_uint16_le(s
, (g_mcs_userid
+ 1001));
826 out_uint32_le(s
, g_rdp_shareid
);
827 out_uint16_le(s
, 0x3ea); /* userid */
828 out_uint16_le(s
, sizeof(RDP_SOURCE
));
829 out_uint16_le(s
, caplen
);
831 out_uint8p(s
, RDP_SOURCE
, sizeof(RDP_SOURCE
));
832 out_uint16_le(s
, 0xd); /* num_caps */
833 out_uint8s(s
, 2); /* pad */
835 rdp_out_general_caps(s
);
836 rdp_out_bitmap_caps(s
);
837 rdp_out_order_caps(s
);
838 g_use_rdp5
? rdp_out_bmpcache2_caps(s
) : rdp_out_bmpcache_caps(s
);
839 rdp_out_colcache_caps(s
);
840 rdp_out_activate_caps(s
);
841 rdp_out_control_caps(s
);
842 rdp_out_pointer_caps(s
);
843 rdp_out_share_caps(s
);
845 rdp_out_unknown_caps(s
, 0x0d, 0x58, caps_0x0d
); /* international? */
846 rdp_out_unknown_caps(s
, 0x0c, 0x08, caps_0x0c
);
847 rdp_out_unknown_caps(s
, 0x0e, 0x08, caps_0x0e
);
848 rdp_out_unknown_caps(s
, 0x10, 0x34, caps_0x10
); /* glyph cache? */
851 sec_send(s
, sec_flags
);
854 /* Process a general capability set */
856 rdp_process_general_caps(STREAM s
)
858 uint16 pad2octetsB
; /* rdp5 flags? */
861 in_uint16_le(s
, pad2octetsB
);
867 /* Process a bitmap capability set */
869 rdp_process_bitmap_caps(STREAM s
)
871 uint16 width
, height
, depth
;
873 in_uint16_le(s
, depth
);
876 in_uint16_le(s
, width
);
877 in_uint16_le(s
, height
);
879 DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width
, height
, depth
));
882 * The server may limit depth and change the size of the desktop (for
883 * example when shadowing another session).
885 if (g_server_depth
!= depth
)
887 warning("Remote desktop does not support colour depth %d; falling back to %d\n",
888 g_server_depth
, depth
);
889 g_server_depth
= depth
;
891 if (g_width
!= width
|| g_height
!= height
)
893 warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width
, g_height
,
901 /* Process server capabilities */
903 rdp_process_server_caps(STREAM s
, uint16 length
)
907 uint16 ncapsets
, capset_type
, capset_length
;
911 in_uint16_le(s
, ncapsets
);
912 in_uint8s(s
, 2); /* pad */
914 for (n
= 0; n
< ncapsets
; n
++)
916 if (s
->p
> start
+ length
)
919 in_uint16_le(s
, capset_type
);
920 in_uint16_le(s
, capset_length
);
922 next
= s
->p
+ capset_length
- 4;
926 case RDP_CAPSET_GENERAL
:
927 rdp_process_general_caps(s
);
930 case RDP_CAPSET_BITMAP
:
931 rdp_process_bitmap_caps(s
);
939 /* Respond to a demand active PDU */
941 process_demand_active(STREAM s
)
944 uint16 len_src_descriptor
, len_combined_caps
;
946 in_uint32_le(s
, g_rdp_shareid
);
947 in_uint16_le(s
, len_src_descriptor
);
948 in_uint16_le(s
, len_combined_caps
);
949 in_uint8s(s
, len_src_descriptor
);
951 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid
));
952 rdp_process_server_caps(s
, len_combined_caps
);
954 rdp_send_confirm_active();
955 rdp_send_synchronise();
956 rdp_send_control(RDP_CTL_COOPERATE
);
957 rdp_send_control(RDP_CTL_REQUEST_CONTROL
);
958 rdp_recv(&type
); /* RDP_PDU_SYNCHRONIZE */
959 rdp_recv(&type
); /* RDP_CTL_COOPERATE */
960 rdp_recv(&type
); /* RDP_CTL_GRANT_CONTROL */
961 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE
, 0, ui_get_numlock_state(read_keyboard_state()), 0);
965 rdp_enum_bmpcache2();
974 rdp_recv(&type
); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
978 /* Process a colour pointer PDU */
980 process_colour_pointer_pdu(STREAM s
)
982 uint16 x
, y
, width
, height
, cache_idx
, masklen
, datalen
;
986 in_uint16_le(s
, cache_idx
);
989 in_uint16_le(s
, width
);
990 in_uint16_le(s
, height
);
991 in_uint16_le(s
, masklen
);
992 in_uint16_le(s
, datalen
);
993 in_uint8p(s
, data
, datalen
);
994 in_uint8p(s
, mask
, masklen
);
995 cursor
= ui_create_cursor(x
, y
, width
, height
, mask
, data
);
996 ui_set_cursor(cursor
);
997 cache_put_cursor(cache_idx
, cursor
);
1000 /* Process a cached pointer PDU */
1002 process_cached_pointer_pdu(STREAM s
)
1006 in_uint16_le(s
, cache_idx
);
1007 ui_set_cursor(cache_get_cursor(cache_idx
));
1010 /* Process a system pointer PDU */
1012 process_system_pointer_pdu(STREAM s
)
1014 uint16 system_pointer_type
;
1016 in_uint16(s
, system_pointer_type
);
1017 switch (system_pointer_type
)
1019 case RDP_NULL_POINTER
:
1020 ui_set_null_cursor();
1024 unimpl("System pointer message 0x%x\n", system_pointer_type
);
1028 /* Process a pointer PDU */
1030 process_pointer_pdu(STREAM s
)
1032 uint16 message_type
;
1035 in_uint16_le(s
, message_type
);
1036 in_uint8s(s
, 2); /* pad */
1038 switch (message_type
)
1040 case RDP_POINTER_MOVE
:
1044 ui_move_pointer(x
, y
);
1047 case RDP_POINTER_COLOR
:
1048 process_colour_pointer_pdu(s
);
1051 case RDP_POINTER_CACHED
:
1052 process_cached_pointer_pdu(s
);
1055 case RDP_POINTER_SYSTEM
:
1056 process_system_pointer_pdu(s
);
1060 unimpl("Pointer message 0x%x\n", message_type
);
1064 /* Process bitmap updates */
1066 process_bitmap_updates(STREAM s
)
1069 uint16 left
, top
, right
, bottom
, width
, height
;
1070 uint16 cx
, cy
, bpp
, Bpp
, compress
, bufsize
, size
;
1071 uint8
*data
, *bmpdata
;
1074 in_uint16_le(s
, num_updates
);
1076 for (i
= 0; i
< num_updates
; i
++)
1078 in_uint16_le(s
, left
);
1079 in_uint16_le(s
, top
);
1080 in_uint16_le(s
, right
);
1081 in_uint16_le(s
, bottom
);
1082 in_uint16_le(s
, width
);
1083 in_uint16_le(s
, height
);
1084 in_uint16_le(s
, bpp
);
1085 Bpp
= (bpp
+ 7) / 8;
1086 in_uint16_le(s
, compress
);
1087 in_uint16_le(s
, bufsize
);
1089 cx
= right
- left
+ 1;
1090 cy
= bottom
- top
+ 1;
1092 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1093 left
, top
, right
, bottom
, width
, height
, Bpp
, compress
));
1098 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
1099 for (y
= 0; y
< height
; y
++)
1101 in_uint8a(s
, &bmpdata
[(height
- y
- 1) * (width
* Bpp
)],
1104 ui_paint_bitmap(left
, top
, cx
, cy
, width
, height
, bmpdata
);
1110 if (compress
& 0x400)
1116 in_uint8s(s
, 2); /* pad */
1117 in_uint16_le(s
, size
);
1118 in_uint8s(s
, 4); /* line_size, final_size */
1120 in_uint8p(s
, data
, size
);
1121 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
1122 if (bitmap_decompress(bmpdata
, width
, height
, data
, size
, Bpp
))
1124 ui_paint_bitmap(left
, top
, cx
, cy
, width
, height
, bmpdata
);
1128 DEBUG_RDP5(("Failed to decompress data\n"));
1135 /* Process a palette update */
1137 process_palette(STREAM s
)
1144 in_uint8s(s
, 2); /* pad */
1145 in_uint16_le(s
, map
.ncolours
);
1146 in_uint8s(s
, 2); /* pad */
1148 map
.colours
= (COLOURENTRY
*) xmalloc(sizeof(COLOURENTRY
) * map
.ncolours
);
1150 DEBUG(("PALETTE(c=%d)\n", map
.ncolours
));
1152 for (i
= 0; i
< map
.ncolours
; i
++)
1154 entry
= &map
.colours
[i
];
1155 in_uint8(s
, entry
->red
);
1156 in_uint8(s
, entry
->green
);
1157 in_uint8(s
, entry
->blue
);
1160 hmap
= ui_create_colourmap(&map
);
1161 ui_set_colourmap(hmap
);
1166 /* Process an update PDU */
1168 process_update_pdu(STREAM s
)
1170 uint16 update_type
, count
;
1172 in_uint16_le(s
, update_type
);
1175 switch (update_type
)
1177 case RDP_UPDATE_ORDERS
:
1178 in_uint8s(s
, 2); /* pad */
1179 in_uint16_le(s
, count
);
1180 in_uint8s(s
, 2); /* pad */
1181 process_orders(s
, count
);
1184 case RDP_UPDATE_BITMAP
:
1185 process_bitmap_updates(s
);
1188 case RDP_UPDATE_PALETTE
:
1192 case RDP_UPDATE_SYNCHRONIZE
:
1196 unimpl("update %d\n", update_type
);
1201 /* Process a disconnect PDU */
1203 process_disconnect_pdu(STREAM s
, uint32
* ext_disc_reason
)
1205 in_uint32_le(s
, *ext_disc_reason
);
1207 DEBUG(("Received disconnect PDU\n"));
1210 /* Process data PDU */
1212 process_data_pdu(STREAM s
, uint32
* ext_disc_reason
)
1214 uint8 data_pdu_type
;
1221 struct stream
*ns
= &(g_mppc_dict
.ns
);
1223 in_uint8s(s
, 6); /* shareid, pad, streamid */
1225 in_uint8(s
, data_pdu_type
);
1230 if (ctype
& RDP_MPPC_COMPRESSED
)
1232 if (len
> RDP_MPPC_DICT_SIZE
)
1233 error("error decompressed packet size exceeds max\n");
1234 if (mppc_expand(s
->p
, clen
, ctype
, &roff
, &rlen
) == -1)
1235 error("error while decompressing packet\n");
1239 /* allocate memory and copy the uncompressed data into the temporary stream */
1240 ns
->data
= (uint8
*) xrealloc(ns
->data
, rlen
);
1242 memcpy((ns
->data
), (unsigned char *) (g_mppc_dict
.hist
+ roff
), rlen
);
1245 ns
->end
= (ns
->data
+ ns
->size
);
1247 ns
->rdp_hdr
= ns
->p
;
1252 switch (data_pdu_type
)
1254 case RDP_DATA_PDU_UPDATE
:
1255 process_update_pdu(s
);
1258 case RDP_DATA_PDU_CONTROL
:
1259 DEBUG(("Received Control PDU\n"));
1262 case RDP_DATA_PDU_SYNCHRONISE
:
1263 DEBUG(("Received Sync PDU\n"));
1266 case RDP_DATA_PDU_POINTER
:
1267 process_pointer_pdu(s
);
1270 case RDP_DATA_PDU_BELL
:
1274 case RDP_DATA_PDU_LOGON
:
1275 DEBUG(("Received Logon PDU\n"));
1276 /* User logged on */
1279 case RDP_DATA_PDU_DISCONNECT
:
1280 process_disconnect_pdu(s
, ext_disc_reason
);
1284 unimpl("data PDU %d\n", data_pdu_type
);
1289 /* Process redirect PDU from Session Directory */
1291 process_redirect_pdu(STREAM s
/*, uint32 * ext_disc_reason */ )
1295 /* these 2 bytes are unknown, seem to be zeros */
1298 /* read connection flags */
1299 in_uint32_le(s
, g_redirect_flags
);
1301 /* read length of ip string */
1302 in_uint32_le(s
, len
);
1304 /* read ip string */
1305 rdp_in_unistr(s
, g_redirect_server
, len
);
1307 /* read length of cookie string */
1308 in_uint32_le(s
, len
);
1310 /* read cookie string (plain ASCII) */
1311 in_uint8a(s
, g_redirect_cookie
, len
);
1312 g_redirect_cookie
[len
] = 0;
1314 /* read length of username string */
1315 in_uint32_le(s
, len
);
1317 /* read username string */
1318 rdp_in_unistr(s
, g_redirect_username
, len
);
1320 /* read length of domain string */
1321 in_uint32_le(s
, len
);
1323 /* read domain string */
1324 rdp_in_unistr(s
, g_redirect_domain
, len
);
1326 /* read length of password string */
1327 in_uint32_le(s
, len
);
1329 /* read password string */
1330 rdp_in_unistr(s
, g_redirect_password
, len
);
1337 /* Process incoming packets */
1338 /* nevers gets out of here till app is done */
1340 rdp_main_loop(BOOL
* deactivated
, uint32
* ext_disc_reason
)
1342 while (rdp_loop(deactivated
, ext_disc_reason
))
1346 /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1348 rdp_loop(BOOL
* deactivated
, uint32
* ext_disc_reason
)
1351 BOOL disc
= False
; /* True when a disconnect PDU was received */
1357 s
= rdp_recv(&type
);
1362 case RDP_PDU_DEMAND_ACTIVE
:
1363 process_demand_active(s
);
1364 *deactivated
= False
;
1366 case RDP_PDU_DEACTIVATE
:
1367 DEBUG(("RDP_PDU_DEACTIVATE\n"));
1368 *deactivated
= True
;
1370 case RDP_PDU_REDIRECT
:
1371 return process_redirect_pdu(s
);
1374 disc
= process_data_pdu(s
, ext_disc_reason
);
1379 unimpl("PDU %d\n", type
);
1383 cont
= g_next_packet
< s
->end
;
1388 /* Establish a connection up to the RDP layer */
1390 rdp_connect(char *server
, uint32 flags
, char *domain
, char *password
,
1391 char *command
, char *directory
)
1393 if (!sec_connect(server
, g_username
))
1396 rdp_send_logon_info(flags
, domain
, g_username
, password
, command
, directory
);
1400 /* Establish a reconnection up to the RDP layer */
1402 rdp_reconnect(char *server
, uint32 flags
, char *domain
, char *password
,
1403 char *command
, char *directory
, char *cookie
)
1405 if (!sec_reconnect(server
))
1408 rdp_send_logon_info(flags
, domain
, g_username
, password
, command
, directory
);
1412 /* Called during redirection to reset the state to support redirection */
1414 rdp_reset_state(void)
1416 g_next_packet
= NULL
; /* reset the packet information */
1421 /* Disconnect from the RDP layer */
1423 rdp_disconnect(void)