1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
5 Copyright 2003-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
6 Copyright 2011-2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 extern uint16 g_mcs_userid
;
25 extern char g_username
[256];
26 extern char g_password
[256];
28 extern RD_BOOL g_bitmap_compression
;
29 extern RD_BOOL g_orders
;
30 extern RD_BOOL g_encryption
;
31 extern RD_BOOL g_desktop_save
;
32 extern RD_BOOL g_polygon_ellipse_orders
;
33 extern RDP_VERSION g_rdp_version
;
34 extern uint16 g_server_rdp_version
;
35 extern uint32 g_rdp5_performanceflags
;
36 extern int g_server_depth
;
39 extern RD_BOOL g_bitmap_cache
;
40 extern RD_BOOL g_bitmap_cache_persist_enable
;
41 extern RD_BOOL g_numlock_sync
;
42 extern RD_BOOL g_pending_resize
;
43 extern RD_BOOL g_network_error
;
48 extern RDPCOMP g_mppc_dict
;
50 /* Session Directory support */
51 extern RD_BOOL g_redirect
;
52 extern char *g_redirect_server
;
53 extern uint32 g_redirect_server_len
;
54 extern char *g_redirect_domain
;
55 extern uint32 g_redirect_domain_len
;
56 extern char *g_redirect_username
;
57 extern uint32 g_redirect_username_len
;
58 extern uint8
*g_redirect_lb_info
;
59 extern uint32 g_redirect_lb_info_len
;
60 extern uint8
*g_redirect_cookie
;
61 extern uint32 g_redirect_cookie_len
;
62 extern uint32 g_redirect_flags
;
63 extern uint32 g_redirect_session_id
;
65 /* END Session Directory support */
67 extern uint32 g_reconnect_logonid
;
68 extern char g_reconnect_random
[16];
69 extern time_t g_reconnect_random_ts
;
70 extern RD_BOOL g_has_reconnect_random
;
71 extern uint8 g_client_random
[SEC_RANDOM_SIZE
];
73 void rdssl_hmac_md5(char* key
, int keylen
, char* data
, int len
, char* output
);
76 static uint32 g_packetno
;
80 static RD_BOOL g_iconv_works
= True
;
83 /* Receive an RDP packet */
85 rdp_recv(uint8
* type
)
88 uint16 length
, pdu_type
;
91 if ((rdp_s
== NULL
) || (g_next_packet
>= rdp_s
->end
) || (g_next_packet
== NULL
))
93 rdp_s
= sec_recv(&rdpver
);
98 g_next_packet
= rdp_s
->end
;
102 else if (rdpver
!= 3)
104 /* rdp5_process should move g_next_packet ok */
110 g_next_packet
= rdp_s
->p
;
114 rdp_s
->p
= g_next_packet
;
117 in_uint16_le(rdp_s
, length
);
118 /* 32k packets are really 8, keepalive fix */
119 if (length
== 0x8000)
125 in_uint16_le(rdp_s
, pdu_type
);
126 in_uint8s(rdp_s
, 2); /* userid */
127 *type
= pdu_type
& 0xf;
130 DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno
, *type
));
131 hexdump(g_next_packet
, length
);
134 g_next_packet
+= length
;
138 /* Initialise an RDP data packet */
140 rdp_init_data(int maxlen
)
144 s
= sec_init(g_encryption
? SEC_ENCRYPT
: 0, maxlen
+ 18);
145 s_push_layer(s
, rdp_hdr
, 18);
150 /* Send an RDP data packet */
152 rdp_send_data(STREAM s
, uint8 data_pdu_type
)
156 s_pop_layer(s
, rdp_hdr
);
157 length
= s
->end
- s
->p
;
159 out_uint16_le(s
, length
);
160 out_uint16_le(s
, (RDP_PDU_DATA
| 0x10));
161 out_uint16_le(s
, (g_mcs_userid
+ 1001));
163 out_uint32_le(s
, g_rdp_shareid
);
164 out_uint8(s
, 0); /* pad */
165 out_uint8(s
, 1); /* streamid */
166 out_uint16_le(s
, (length
- 14));
167 out_uint8(s
, data_pdu_type
);
168 out_uint8(s
, 0); /* compress_type */
169 out_uint16(s
, 0); /* compress_len */
171 sec_send(s
, g_encryption
? SEC_ENCRYPT
: 0);
174 /* Output a string in Unicode with mandatory null termination. If
175 string is NULL or len is 0, write an unicode null termination to
178 rdp_out_unistr_mandatory_null(STREAM s
, char *string
, int len
)
180 if (string
&& len
> 0)
181 rdp_out_unistr(s
, string
, len
);
186 /* Output a string in Unicode */
188 rdp_out_unistr(STREAM s
, char *string
, int len
)
190 if (string
== NULL
|| len
== 0)
194 size_t ibl
= strlen(string
), obl
= len
+ 2;
195 static iconv_t iconv_h
= (iconv_t
) - 1;
196 char *pin
= string
, *pout
= (char *) s
->p
;
198 memset(pout
, 0, len
+ 4);
202 if (iconv_h
== (iconv_t
) - 1)
205 if ((iconv_h
= iconv_open(WINDOWS_CODEPAGE
, g_codepage
)) == (iconv_t
) - 1)
207 warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
208 g_codepage
, WINDOWS_CODEPAGE
, (int) iconv_h
);
210 g_iconv_works
= False
;
211 rdp_out_unistr(s
, string
, len
);
214 if (iconv(iconv_h
, (ICONV_CONST
char **) &pin
, &i
, &pout
, &o
) ==
217 iconv_close(iconv_h
);
218 iconv_h
= (iconv_t
) - 1;
219 warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno
);
221 g_iconv_works
= False
;
222 rdp_out_unistr(s
, string
, len
);
226 pout
= (char *) s
->p
;
229 if (iconv(iconv_h
, (ICONV_CONST
char **) &pin
, &ibl
, &pout
, &obl
) == (size_t) - 1)
231 iconv_close(iconv_h
);
232 iconv_h
= (iconv_t
) - 1;
233 warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno
);
235 g_iconv_works
= False
;
236 rdp_out_unistr(s
, string
, len
);
252 s
->p
[i
++] = string
[j
++];
260 /* Input a string in Unicode
262 * Returns str_len of string
265 rdp_in_unistr(STREAM s
, int in_len
, char **string
, uint32
* str_size
)
267 /* Dynamic allocate of destination string if not provided */
268 *string
= xmalloc(in_len
* 2);
269 *str_size
= in_len
* 2;
272 size_t ibl
= in_len
, obl
= *str_size
- 1;
273 char *pin
= (char *) s
->p
, *pout
= *string
;
274 static iconv_t iconv_h
= (iconv_t
) - 1;
278 if (iconv_h
== (iconv_t
) - 1)
280 if ((iconv_h
= iconv_open(g_codepage
, WINDOWS_CODEPAGE
)) == (iconv_t
) - 1)
282 warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
283 WINDOWS_CODEPAGE
, g_codepage
, (int) iconv_h
);
285 g_iconv_works
= False
;
286 return rdp_in_unistr(s
, in_len
, string
, str_size
);
290 if (iconv(iconv_h
, (ICONV_CONST
char **) &pin
, &ibl
, &pout
, &obl
) == (size_t) - 1)
294 warning("server sent an unexpectedly long string, truncating\n");
298 warning("rdp_in_unistr: iconv fail, errno %d\n", errno
);
306 /* we must update the location of the current STREAM for future reads of s->p */
312 *str_size
= pout
- *string
;
319 uint32 len
= in_len
/ 2;
321 if (len
> *str_size
- 1)
323 warning("server sent an unexpectedly long string, truncating\n");
325 rem
= in_len
- 2 * len
;
330 in_uint8a(s
, &string
[i
++], 1);
341 /* Parse a logon info packet */
343 rdp_send_logon_info(uint32 flags
, char *domain
, char *user
,
344 char *password
, char *program
, char *directory
)
346 char *ipaddr
= tcp_get_address();
347 /* length of string in TS_INFO_PACKET excludes null terminator */
348 int len_domain
= 2 * strlen(domain
);
349 int len_user
= 2 * strlen(user
);
350 int len_password
= 2 * strlen(password
);
351 int len_program
= 2 * strlen(program
);
352 int len_directory
= 2 * strlen(directory
);
354 /* length of strings in TS_EXTENDED_PACKET includes null terminator */
355 char dllName
[MAX_PATH
];
356 int len_ip
= 2 * strlen(ipaddr
) + 2;
360 uint32 sec_flags
= g_encryption
? (SEC_INFO_PKT
| SEC_ENCRYPT
) : SEC_INFO_PKT
;
362 time_t t
= time(NULL
);
364 uint8 security_verifier
[16];
366 GetModuleFileNameA(NULL
, dllName
, ARRAYSIZE(dllName
));
367 len_dll
= 2 * strlen(dllName
) + 2;
369 if (g_rdp_version
== RDP_V4
|| 1 == g_server_rdp_version
)
372 s
= sec_init(sec_flags
, 18 + len_domain
+ len_user
+ len_password
373 + len_program
+ len_directory
+ 10);
376 out_uint32_le(s
, flags
);
377 out_uint16_le(s
, len_domain
);
378 out_uint16_le(s
, len_user
);
379 out_uint16_le(s
, len_password
);
380 out_uint16_le(s
, len_program
);
381 out_uint16_le(s
, len_directory
);
383 rdp_out_unistr_mandatory_null(s
, domain
, len_domain
);
384 rdp_out_unistr_mandatory_null(s
, user
, len_user
);
385 rdp_out_unistr_mandatory_null(s
, password
, len_password
);
386 rdp_out_unistr_mandatory_null(s
, program
, len_program
);
387 rdp_out_unistr_mandatory_null(s
, directory
, len_directory
);
391 DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
393 if (g_redirect
== True
&& g_redirect_cookie_len
> 0)
395 flags
|= RDP_INFO_AUTOLOGON
;
396 len_password
= g_redirect_cookie_len
;
397 len_password
-= 2; /* substract 2 bytes which is added below */
401 /* size of TS_INFO_PACKET */
407 2 + /* cbAlternateShell */
408 2 + /* cbWorkingDir */
409 2 + len_domain
+ /* Domain */
410 2 + len_user
+ /* UserName */
411 2 + len_password
+ /* Password */
412 2 + len_program
+ /* AlternateShell */
413 2 + len_directory
+ /* WorkingDir */
414 /* size of TS_EXTENDED_INFO_PACKET */
415 2 + /* clientAddressFamily */
416 2 + /* cbClientAddress */
417 len_ip
+ /* clientAddress */
418 2 + /* cbClientDir */
419 len_dll
+ /* clientDir */
420 /* size of TS_TIME_ZONE_INFORMATION */
421 4 + /* Bias, (UTC = local time + bias */
422 64 + /* StandardName, 32 unicode char array, Descriptive standard time on client */
423 16 + /* StandardDate */
424 4 + /* StandardBias */
425 64 + /* DaylightName, 32 unicode char array */
426 16 + /* DaylightDate */
427 4 + /* DaylightBias */
428 4 + /* clientSessionId */
429 4 + /* performanceFlags */
430 2 + /* cbAutoReconnectCookie, either 0 or 0x001c */
431 /* size of ARC_CS_PRIVATE_PACKET */
432 28; /* autoReconnectCookie */
435 s
= sec_init(sec_flags
, packetlen
);
436 DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen
));
439 out_uint32(s
, 0); /* Code Page */
440 out_uint32_le(s
, flags
);
441 out_uint16_le(s
, len_domain
);
442 out_uint16_le(s
, len_user
);
443 out_uint16_le(s
, len_password
);
444 out_uint16_le(s
, len_program
);
445 out_uint16_le(s
, len_directory
);
447 rdp_out_unistr_mandatory_null(s
, domain
, len_domain
);
448 rdp_out_unistr_mandatory_null(s
, user
, len_user
);
450 if (g_redirect
== True
&& 0 < g_redirect_cookie_len
)
452 out_uint8p(s
, g_redirect_cookie
, g_redirect_cookie_len
);
456 rdp_out_unistr_mandatory_null(s
, password
, len_password
);
460 rdp_out_unistr_mandatory_null(s
, program
, len_program
);
461 rdp_out_unistr_mandatory_null(s
, directory
, len_directory
);
463 /* TS_EXTENDED_INFO_PACKET */
464 out_uint16_le(s
, 2); /* clientAddressFamily = AF_INET */
465 out_uint16_le(s
, len_ip
); /* cbClientAddress */
466 rdp_out_unistr_mandatory_null(s
, ipaddr
, len_ip
- 2); /* clientAddress */
467 out_uint16_le(s
, len_dll
); /* cbClientDir */
468 rdp_out_unistr(s
, dllName
, len_dll
- 2); /* clientDir */
470 /* TS_TIME_ZONE_INFORMATION */
471 tzone
= (mktime(gmtime(&t
)) - mktime(localtime(&t
))) / 60;
472 out_uint32_le(s
, tzone
);
473 rdp_out_unistr(s
, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
474 out_uint8s(s
, 62 - 2 * strlen("GTB, normaltid"));
475 out_uint32_le(s
, 0x0a0000);
476 out_uint32_le(s
, 0x050000);
480 rdp_out_unistr(s
, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
481 out_uint8s(s
, 62 - 2 * strlen("GTB, sommartid"));
482 out_uint32_le(s
, 0x30000);
483 out_uint32_le(s
, 0x050000);
486 out_uint32_le(s
, 0xffffffc4); /* DaylightBias */
488 /* Rest of TS_EXTENDED_INFO_PACKET */
489 out_uint32_le(s
, 0); /* clientSessionId (Ignored by server MUST be 0) */
490 out_uint32_le(s
, g_rdp5_performanceflags
);
492 /* Client Auto-Reconnect */
493 if (g_has_reconnect_random
)
495 out_uint16_le(s
, 28); /* cbAutoReconnectLen */
496 /* ARC_CS_PRIVATE_PACKET */
497 out_uint32_le(s
, 28); /* cbLen */
498 out_uint32_le(s
, 1); /* Version */
499 out_uint32_le(s
, g_reconnect_logonid
); /* LogonId */
500 rdssl_hmac_md5(g_reconnect_random
, sizeof(g_reconnect_random
),
501 (char *)g_client_random
, SEC_RANDOM_SIZE
, (char *)security_verifier
);
502 out_uint8a(s
, security_verifier
, sizeof(security_verifier
));
506 out_uint16_le(s
, 0); /* cbAutoReconnectLen */
511 /* clear the redirect flag */
514 sec_send(s
, sec_flags
);
517 /* Send a control PDU */
519 rdp_send_control(uint16 action
)
523 s
= rdp_init_data(8);
525 out_uint16_le(s
, action
);
526 out_uint16(s
, 0); /* userid */
527 out_uint32(s
, 0); /* control id */
530 rdp_send_data(s
, RDP_DATA_PDU_CONTROL
);
533 /* Send a synchronisation PDU */
535 rdp_send_synchronise(void)
539 s
= rdp_init_data(4);
541 out_uint16_le(s
, 1); /* type */
542 out_uint16_le(s
, 1002);
545 rdp_send_data(s
, RDP_DATA_PDU_SYNCHRONISE
);
548 /* Send a single input event */
550 rdp_send_input(uint32 time
, uint16 message_type
, uint16 device_flags
, uint16 param1
, uint16 param2
)
554 s
= rdp_init_data(16);
556 out_uint16_le(s
, 1); /* number of events */
557 out_uint16(s
, 0); /* pad */
559 out_uint32_le(s
, time
);
560 out_uint16_le(s
, message_type
);
561 out_uint16_le(s
, device_flags
);
562 out_uint16_le(s
, param1
);
563 out_uint16_le(s
, param2
);
566 rdp_send_data(s
, RDP_DATA_PDU_INPUT
);
569 /* Send a client window information PDU */
571 rdp_send_client_window_status(int status
)
574 static int current_status
= 1;
576 if (current_status
== status
)
579 s
= rdp_init_data(12);
581 out_uint32_le(s
, status
);
585 case 0: /* shut the server up */
588 case 1: /* receive data again */
589 out_uint32_le(s
, 0); /* unknown */
590 out_uint16_le(s
, g_width
);
591 out_uint16_le(s
, g_height
);
596 rdp_send_data(s
, RDP_DATA_PDU_CLIENT_WINDOW_STATUS
);
597 current_status
= status
;
600 /* Send persistent bitmap cache enumeration PDU's */
602 rdp_enum_bmpcache2(void)
605 HASH_KEY keylist
[BMPCACHE2_NUM_PSTCELLS
];
606 uint32 num_keys
, offset
, count
, flags
;
609 num_keys
= pstcache_enumerate(2, keylist
);
611 while (offset
< num_keys
)
613 count
= MIN(num_keys
- offset
, 169);
615 s
= rdp_init_data(24 + count
* sizeof(HASH_KEY
));
619 flags
|= PDU_FLAG_FIRST
;
620 if (num_keys
- offset
<= 169)
621 flags
|= PDU_FLAG_LAST
;
625 out_uint16_le(s
, count
);
630 out_uint16_le(s
, num_keys
);
632 out_uint32_le(s
, flags
);
635 out_uint8a(s
, keylist
[offset
], count
* sizeof(HASH_KEY
));
638 rdp_send_data(s
, 0x2b);
644 /* Send an (empty) font information PDU */
646 rdp_send_fonts(uint16 seq
)
650 s
= rdp_init_data(8);
652 out_uint16(s
, 0); /* number of fonts */
653 out_uint16_le(s
, 0); /* pad? */
654 out_uint16_le(s
, seq
); /* unknown */
655 out_uint16_le(s
, 0x32); /* entry size */
658 rdp_send_data(s
, RDP_DATA_PDU_FONT2
);
661 /* Output general capability set */
663 rdp_out_general_caps(STREAM s
)
665 out_uint16_le(s
, RDP_CAPSET_GENERAL
);
666 out_uint16_le(s
, RDP_CAPLEN_GENERAL
);
668 out_uint16_le(s
, 1); /* OS major type */
669 out_uint16_le(s
, 3); /* OS minor type */
670 out_uint16_le(s
, 0x200); /* Protocol version */
671 out_uint16(s
, 0); /* Pad */
672 out_uint16(s
, 0); /* Compression types */
673 out_uint16_le(s
, (g_rdp_version
>= RDP_V5
) ? 0x40d : 0);
674 /* Pad, according to T.128. 0x40d seems to
676 the server to start sending RDP5 packets.
677 However, the value is 0x1d04 with W2KTSK and
678 NT4MS. Hmm.. Anyway, thankyou, Microsoft,
679 for sending such information in a padding
681 out_uint16(s
, 0); /* Update capability */
682 out_uint16(s
, 0); /* Remote unshare capability */
683 out_uint16(s
, 0); /* Compression level */
684 out_uint16(s
, 0); /* Pad */
687 /* Output bitmap capability set */
689 rdp_out_bitmap_caps(STREAM s
)
691 out_uint16_le(s
, RDP_CAPSET_BITMAP
);
692 out_uint16_le(s
, RDP_CAPLEN_BITMAP
);
694 out_uint16_le(s
, g_server_depth
); /* Preferred colour depth */
695 out_uint16_le(s
, 1); /* Receive 1 BPP */
696 out_uint16_le(s
, 1); /* Receive 4 BPP */
697 out_uint16_le(s
, 1); /* Receive 8 BPP */
698 out_uint16_le(s
, 800); /* Desktop width */
699 out_uint16_le(s
, 600); /* Desktop height */
700 out_uint16(s
, 0); /* Pad */
701 out_uint16(s
, 1); /* Allow resize */
702 out_uint16_le(s
, g_bitmap_compression
? 1 : 0); /* Support compression */
703 out_uint16(s
, 0); /* Unknown */
704 out_uint16_le(s
, 1); /* Unknown */
705 out_uint16(s
, 0); /* Pad */
708 /* Output order capability set */
710 rdp_out_order_caps(STREAM s
)
712 uint8 order_caps
[32];
714 memset(order_caps
, 0, 32);
715 order_caps
[0] = 1; /* dest blt */
716 order_caps
[1] = 1; /* pat blt */
717 order_caps
[2] = 1; /* screen blt */
718 order_caps
[3] = (g_bitmap_cache
? 1 : 0); /* memblt */
719 order_caps
[4] = 0; /* triblt */
720 order_caps
[8] = 1; /* line */
721 order_caps
[9] = 1; /* line */
722 order_caps
[10] = 1; /* rect */
723 order_caps
[11] = (g_desktop_save
? 1 : 0); /* desksave */
724 order_caps
[13] = 1; /* memblt */
725 order_caps
[14] = 1; /* triblt */
726 order_caps
[20] = (g_polygon_ellipse_orders
? 1 : 0); /* polygon */
727 order_caps
[21] = (g_polygon_ellipse_orders
? 1 : 0); /* polygon2 */
728 order_caps
[22] = 1; /* polyline */
729 order_caps
[25] = (g_polygon_ellipse_orders
? 1 : 0); /* ellipse */
730 order_caps
[26] = (g_polygon_ellipse_orders
? 1 : 0); /* ellipse2 */
731 order_caps
[27] = 1; /* text2 */
732 out_uint16_le(s
, RDP_CAPSET_ORDER
);
733 out_uint16_le(s
, RDP_CAPLEN_ORDER
);
735 out_uint8s(s
, 20); /* Terminal desc, pad */
736 out_uint16_le(s
, 1); /* Cache X granularity */
737 out_uint16_le(s
, 20); /* Cache Y granularity */
738 out_uint16(s
, 0); /* Pad */
739 out_uint16_le(s
, 1); /* Max order level */
740 out_uint16_le(s
, 0x147); /* Number of fonts */
741 out_uint16_le(s
, 0x2a); /* Capability flags */
742 out_uint8p(s
, order_caps
, 32); /* Orders supported */
743 out_uint16_le(s
, 0x6a1); /* Text capability flags */
744 out_uint8s(s
, 6); /* Pad */
745 out_uint32_le(s
, g_desktop_save
== False
? 0 : 0x38400); /* Desktop cache size */
746 out_uint32(s
, 0); /* Unknown */
747 out_uint32_le(s
, 0x4e4); /* Unknown */
750 /* Output bitmap cache capability set */
752 rdp_out_bmpcache_caps(STREAM s
)
755 out_uint16_le(s
, RDP_CAPSET_BMPCACHE
);
756 out_uint16_le(s
, RDP_CAPLEN_BMPCACHE
);
758 Bpp
= (g_server_depth
+ 7) / 8; /* bytes per pixel */
759 out_uint8s(s
, 24); /* unused */
760 out_uint16_le(s
, 0x258); /* entries */
761 out_uint16_le(s
, 0x100 * Bpp
); /* max cell size */
762 out_uint16_le(s
, 0x12c); /* entries */
763 out_uint16_le(s
, 0x400 * Bpp
); /* max cell size */
764 out_uint16_le(s
, 0x106); /* entries */
765 out_uint16_le(s
, 0x1000 * Bpp
); /* max cell size */
768 /* Output bitmap cache v2 capability set */
770 rdp_out_bmpcache2_caps(STREAM s
)
772 out_uint16_le(s
, RDP_CAPSET_BMPCACHE2
);
773 out_uint16_le(s
, RDP_CAPLEN_BMPCACHE2
);
775 out_uint16_le(s
, g_bitmap_cache_persist_enable
? 2 : 0); /* version */
777 out_uint16_be(s
, 3); /* number of caches in this set */
779 /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
780 out_uint32_le(s
, BMPCACHE2_C0_CELLS
);
781 out_uint32_le(s
, BMPCACHE2_C1_CELLS
);
782 if (pstcache_init(2))
784 out_uint32_le(s
, BMPCACHE2_NUM_PSTCELLS
| BMPCACHE2_FLAG_PERSIST
);
788 out_uint32_le(s
, BMPCACHE2_C2_CELLS
);
790 out_uint8s(s
, 20); /* other bitmap caches not used */
793 /* Output control capability set */
795 rdp_out_control_caps(STREAM s
)
797 out_uint16_le(s
, RDP_CAPSET_CONTROL
);
798 out_uint16_le(s
, RDP_CAPLEN_CONTROL
);
800 out_uint16(s
, 0); /* Control capabilities */
801 out_uint16(s
, 0); /* Remote detach */
802 out_uint16_le(s
, 2); /* Control interest */
803 out_uint16_le(s
, 2); /* Detach interest */
806 /* Output activation capability set */
808 rdp_out_activate_caps(STREAM s
)
810 out_uint16_le(s
, RDP_CAPSET_ACTIVATE
);
811 out_uint16_le(s
, RDP_CAPLEN_ACTIVATE
);
813 out_uint16(s
, 0); /* Help key */
814 out_uint16(s
, 0); /* Help index key */
815 out_uint16(s
, 0); /* Extended help key */
816 out_uint16(s
, 0); /* Window activate */
819 /* Output pointer capability set */
821 rdp_out_pointer_caps(STREAM s
)
823 out_uint16_le(s
, RDP_CAPSET_POINTER
);
824 out_uint16_le(s
, RDP_CAPLEN_POINTER
);
826 out_uint16(s
, 0); /* Colour pointer */
827 out_uint16_le(s
, 20); /* Cache size */
830 /* Output new pointer capability set */
832 rdp_out_newpointer_caps(STREAM s
)
834 out_uint16_le(s
, RDP_CAPSET_POINTER
);
835 out_uint16_le(s
, RDP_CAPLEN_NEWPOINTER
);
837 out_uint16_le(s
, 1); /* Colour pointer */
838 out_uint16_le(s
, 20); /* Cache size */
839 out_uint16_le(s
, 20); /* Cache size for new pointers */
842 /* Output share capability set */
844 rdp_out_share_caps(STREAM s
)
846 out_uint16_le(s
, RDP_CAPSET_SHARE
);
847 out_uint16_le(s
, RDP_CAPLEN_SHARE
);
849 out_uint16(s
, 0); /* userid */
850 out_uint16(s
, 0); /* pad */
853 /* Output colour cache capability set */
855 rdp_out_colcache_caps(STREAM s
)
857 out_uint16_le(s
, RDP_CAPSET_COLCACHE
);
858 out_uint16_le(s
, RDP_CAPLEN_COLCACHE
);
860 out_uint16_le(s
, 6); /* cache size */
861 out_uint16(s
, 0); /* pad */
864 /* Output brush cache capability set */
866 rdp_out_brushcache_caps(STREAM s
)
868 out_uint16_le(s
, RDP_CAPSET_BRUSHCACHE
);
869 out_uint16_le(s
, RDP_CAPLEN_BRUSHCACHE
);
870 out_uint32_le(s
, 1); /* cache type */
873 static uint8 caps_0x0d
[] = {
874 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
875 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
876 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884 0x00, 0x00, 0x00, 0x00
887 static uint8 caps_0x0c
[] = { 0x01, 0x00, 0x00, 0x00 };
889 static uint8 caps_0x0e
[] = { 0x01, 0x00, 0x00, 0x00 };
891 static uint8 caps_0x10
[] = {
892 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
893 0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
894 0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
895 0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
896 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
897 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
900 /* Output unknown capability sets */
902 rdp_out_unknown_caps(STREAM s
, uint16 id
, uint16 length
, uint8
* caps
)
904 out_uint16_le(s
, id
);
905 out_uint16_le(s
, length
);
907 out_uint8p(s
, caps
, length
- 4);
910 #define RDP5_FLAG 0x0030
911 /* Send a confirm active PDU */
913 rdp_send_confirm_active(void)
916 uint32 sec_flags
= g_encryption
? (RDP5_FLAG
| SEC_ENCRYPT
) : RDP5_FLAG
;
918 RDP_CAPLEN_GENERAL
+ RDP_CAPLEN_BITMAP
+ RDP_CAPLEN_ORDER
+
919 RDP_CAPLEN_COLCACHE
+
920 RDP_CAPLEN_ACTIVATE
+ RDP_CAPLEN_CONTROL
+
922 RDP_CAPLEN_BRUSHCACHE
+ 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
923 4 /* w2k fix, sessionid */ ;
925 if (g_rdp_version
>= RDP_V5
)
927 caplen
+= RDP_CAPLEN_BMPCACHE2
;
928 caplen
+= RDP_CAPLEN_NEWPOINTER
;
932 caplen
+= RDP_CAPLEN_BMPCACHE
;
933 caplen
+= RDP_CAPLEN_POINTER
;
936 s
= sec_init(sec_flags
, 6 + 14 + caplen
+ sizeof(RDP_SOURCE
));
938 out_uint16_le(s
, 2 + 14 + caplen
+ sizeof(RDP_SOURCE
));
939 out_uint16_le(s
, (RDP_PDU_CONFIRM_ACTIVE
| 0x10)); /* Version 1 */
940 out_uint16_le(s
, (g_mcs_userid
+ 1001));
942 out_uint32_le(s
, g_rdp_shareid
);
943 out_uint16_le(s
, 0x3ea); /* userid */
944 out_uint16_le(s
, sizeof(RDP_SOURCE
));
945 out_uint16_le(s
, caplen
);
947 out_uint8p(s
, RDP_SOURCE
, sizeof(RDP_SOURCE
));
948 out_uint16_le(s
, 0xe); /* num_caps */
949 out_uint8s(s
, 2); /* pad */
951 rdp_out_general_caps(s
);
952 rdp_out_bitmap_caps(s
);
953 rdp_out_order_caps(s
);
954 if (g_rdp_version
>= RDP_V5
)
956 rdp_out_bmpcache2_caps(s
);
957 rdp_out_newpointer_caps(s
);
961 rdp_out_bmpcache_caps(s
);
962 rdp_out_pointer_caps(s
);
964 rdp_out_colcache_caps(s
);
965 rdp_out_activate_caps(s
);
966 rdp_out_control_caps(s
);
967 rdp_out_share_caps(s
);
968 rdp_out_brushcache_caps(s
);
970 rdp_out_unknown_caps(s
, 0x0d, 0x58, caps_0x0d
); /* CAPSTYPE_INPUT */
971 rdp_out_unknown_caps(s
, 0x0c, 0x08, caps_0x0c
); /* CAPSTYPE_SOUND */
972 rdp_out_unknown_caps(s
, 0x0e, 0x08, caps_0x0e
); /* CAPSTYPE_FONT */
973 rdp_out_unknown_caps(s
, 0x10, 0x34, caps_0x10
); /* CAPSTYPE_GLYPHCACHE */
976 sec_send(s
, sec_flags
);
979 /* Process a general capability set */
981 rdp_process_general_caps(STREAM s
)
983 uint16 pad2octetsB
; /* rdp5 flags? */
986 in_uint16_le(s
, pad2octetsB
);
989 g_rdp_version
= RDP_V4
;
992 /* Process a bitmap capability set */
994 rdp_process_bitmap_caps(STREAM s
)
996 uint16 width
, height
, depth
;
998 in_uint16_le(s
, depth
);
1001 in_uint16_le(s
, width
);
1002 in_uint16_le(s
, height
);
1004 DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width
, height
, depth
));
1007 * The server may limit depth and change the size of the desktop (for
1008 * example when shadowing another session).
1010 if (g_server_depth
!= depth
)
1012 warning("Remote desktop does not support colour depth %d; falling back to %d\n",
1013 g_server_depth
, depth
);
1014 g_server_depth
= depth
;
1016 if (g_width
!= width
|| g_height
!= height
)
1018 warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width
, g_height
,
1026 /* Process server capabilities */
1028 rdp_process_server_caps(STREAM s
, uint16 length
)
1031 uint8
*next
, *start
;
1032 uint16 ncapsets
, capset_type
, capset_length
;
1036 in_uint16_le(s
, ncapsets
);
1037 in_uint8s(s
, 2); /* pad */
1039 for (n
= 0; n
< ncapsets
; n
++)
1041 if (s
->p
> start
+ length
)
1044 in_uint16_le(s
, capset_type
);
1045 in_uint16_le(s
, capset_length
);
1047 next
= s
->p
+ capset_length
- 4;
1049 switch (capset_type
)
1051 case RDP_CAPSET_GENERAL
:
1052 rdp_process_general_caps(s
);
1055 case RDP_CAPSET_BITMAP
:
1056 rdp_process_bitmap_caps(s
);
1064 /* Respond to a demand active PDU */
1066 process_demand_active(STREAM s
)
1069 uint16 len_src_descriptor
, len_combined_caps
;
1071 in_uint32_le(s
, g_rdp_shareid
);
1072 in_uint16_le(s
, len_src_descriptor
);
1073 in_uint16_le(s
, len_combined_caps
);
1074 in_uint8s(s
, len_src_descriptor
);
1076 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid
));
1077 rdp_process_server_caps(s
, len_combined_caps
);
1079 rdp_send_confirm_active();
1080 rdp_send_synchronise();
1081 rdp_send_control(RDP_CTL_COOPERATE
);
1082 rdp_send_control(RDP_CTL_REQUEST_CONTROL
);
1083 rdp_recv(&type
); /* RDP_PDU_SYNCHRONIZE */
1084 rdp_recv(&type
); /* RDP_CTL_COOPERATE */
1085 rdp_recv(&type
); /* RDP_CTL_GRANT_CONTROL */
1086 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE
, 0,
1087 g_numlock_sync
? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
1089 if (g_rdp_version
>= RDP_V5
)
1091 rdp_enum_bmpcache2();
1100 rdp_recv(&type
); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
1101 reset_order_state();
1104 /* Process a colour pointer PDU */
1106 process_colour_pointer_common(STREAM s
, int bpp
)
1108 uint16 width
, height
, cache_idx
, masklen
, datalen
;
1114 in_uint16_le(s
, cache_idx
);
1117 in_uint16_le(s
, width
);
1118 in_uint16_le(s
, height
);
1119 in_uint16_le(s
, masklen
);
1120 in_uint16_le(s
, datalen
);
1121 in_uint8p(s
, data
, datalen
);
1122 in_uint8p(s
, mask
, masklen
);
1123 if ((width
!= 32) || (height
!= 32))
1125 warning("process_colour_pointer_common: " "width %d height %d\n", width
, height
);
1128 /* keep hotspot within cursor bounding box */
1129 x
= MIN(x
, width
- 1);
1130 y
= MIN(y
, height
- 1);
1131 cursor
= ui_create_cursor(x
, y
, width
, height
, mask
, data
, bpp
);
1132 ui_set_cursor(cursor
);
1133 cache_put_cursor(cache_idx
, cursor
);
1136 /* Process a colour pointer PDU */
1138 process_colour_pointer_pdu(STREAM s
)
1140 process_colour_pointer_common(s
, 24);
1143 /* Process a New Pointer PDU - these pointers have variable bit depth */
1145 process_new_pointer_pdu(STREAM s
)
1149 in_uint16_le(s
, xor_bpp
);
1150 process_colour_pointer_common(s
, xor_bpp
);
1153 /* Process a cached pointer PDU */
1155 process_cached_pointer_pdu(STREAM s
)
1159 in_uint16_le(s
, cache_idx
);
1160 ui_set_cursor(cache_get_cursor(cache_idx
));
1163 /* Process a system pointer PDU */
1165 process_system_pointer_pdu(STREAM s
)
1167 uint16 system_pointer_type
;
1169 in_uint16_le(s
, system_pointer_type
);
1170 switch (system_pointer_type
)
1172 case RDP_NULL_POINTER
:
1173 ui_set_null_cursor();
1177 unimpl("System pointer message 0x%x\n", system_pointer_type
);
1181 /* Process a pointer PDU */
1183 process_pointer_pdu(STREAM s
)
1185 uint16 message_type
;
1188 in_uint16_le(s
, message_type
);
1189 in_uint8s(s
, 2); /* pad */
1191 switch (message_type
)
1193 case RDP_POINTER_MOVE
:
1197 ui_move_pointer(x
, y
);
1200 case RDP_POINTER_COLOR
:
1201 process_colour_pointer_pdu(s
);
1204 case RDP_POINTER_CACHED
:
1205 process_cached_pointer_pdu(s
);
1208 case RDP_POINTER_SYSTEM
:
1209 process_system_pointer_pdu(s
);
1212 case RDP_POINTER_NEW
:
1213 process_new_pointer_pdu(s
);
1217 unimpl("Pointer message 0x%x\n", message_type
);
1221 /* Process bitmap updates */
1223 process_bitmap_updates(STREAM s
)
1226 uint16 left
, top
, right
, bottom
, width
, height
;
1227 uint16 cx
, cy
, bpp
, Bpp
, compress
, bufsize
, size
;
1228 uint8
*data
, *bmpdata
;
1231 in_uint16_le(s
, num_updates
);
1233 for (i
= 0; i
< num_updates
; i
++)
1235 in_uint16_le(s
, left
);
1236 in_uint16_le(s
, top
);
1237 in_uint16_le(s
, right
);
1238 in_uint16_le(s
, bottom
);
1239 in_uint16_le(s
, width
);
1240 in_uint16_le(s
, height
);
1241 in_uint16_le(s
, bpp
);
1242 Bpp
= (bpp
+ 7) / 8;
1243 in_uint16_le(s
, compress
);
1244 in_uint16_le(s
, bufsize
);
1246 cx
= right
- left
+ 1;
1247 cy
= bottom
- top
+ 1;
1249 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1250 left
, top
, right
, bottom
, width
, height
, Bpp
, compress
));
1255 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
1256 for (y
= 0; y
< height
; y
++)
1258 in_uint8a(s
, &bmpdata
[(height
- y
- 1) * (width
* Bpp
)],
1261 ui_paint_bitmap(left
, top
, cx
, cy
, width
, height
, bmpdata
);
1267 if (compress
& 0x400)
1273 in_uint8s(s
, 2); /* pad */
1274 in_uint16_le(s
, size
);
1275 in_uint8s(s
, 4); /* line_size, final_size */
1277 in_uint8p(s
, data
, size
);
1278 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
1279 if (bitmap_decompress(bmpdata
, width
, height
, data
, size
, Bpp
))
1281 ui_paint_bitmap(left
, top
, cx
, cy
, width
, height
, bmpdata
);
1285 DEBUG_RDP5(("Failed to decompress data\n"));
1292 /* Process a palette update */
1294 process_palette(STREAM s
)
1301 in_uint8s(s
, 2); /* pad */
1302 in_uint16_le(s
, map
.ncolours
);
1303 in_uint8s(s
, 2); /* pad */
1305 map
.colours
= (COLOURENTRY
*) xmalloc(sizeof(COLOURENTRY
) * map
.ncolours
);
1307 DEBUG(("PALETTE(c=%d)\n", map
.ncolours
));
1309 for (i
= 0; i
< map
.ncolours
; i
++)
1311 entry
= &map
.colours
[i
];
1312 in_uint8(s
, entry
->red
);
1313 in_uint8(s
, entry
->green
);
1314 in_uint8(s
, entry
->blue
);
1317 hmap
= ui_create_colourmap(&map
);
1318 ui_set_colourmap(hmap
);
1323 /* Process an update PDU */
1325 process_update_pdu(STREAM s
)
1327 uint16 update_type
, count
;
1329 in_uint16_le(s
, update_type
);
1332 switch (update_type
)
1334 case RDP_UPDATE_ORDERS
:
1335 in_uint8s(s
, 2); /* pad */
1336 in_uint16_le(s
, count
);
1337 in_uint8s(s
, 2); /* pad */
1338 process_orders(s
, count
);
1341 case RDP_UPDATE_BITMAP
:
1342 process_bitmap_updates(s
);
1345 case RDP_UPDATE_PALETTE
:
1349 case RDP_UPDATE_SYNCHRONIZE
:
1353 unimpl("update %d\n", update_type
);
1359 /* Process a Save Session Info PDU */
1361 process_pdu_logon(STREAM s
)
1364 in_uint32_le(s
, infotype
);
1365 if (infotype
== INFOTYPE_LOGON_EXTENDED_INF
)
1367 uint32 fieldspresent
;
1369 in_uint8s(s
, 2); /* Length */
1370 in_uint32_le(s
, fieldspresent
);
1371 if (fieldspresent
& LOGON_EX_AUTORECONNECTCOOKIE
)
1376 /* TS_LOGON_INFO_FIELD */
1377 in_uint8s(s
, 4); /* cbFieldData */
1379 /* ARC_SC_PRIVATE_PACKET */
1380 in_uint32_le(s
, len
);
1383 warning("Invalid length in Auto-Reconnect packet\n");
1387 in_uint32_le(s
, version
);
1390 warning("Unsupported version of Auto-Reconnect packet\n");
1394 in_uint32_le(s
, g_reconnect_logonid
);
1395 in_uint8a(s
, g_reconnect_random
, 16);
1396 g_has_reconnect_random
= True
;
1397 g_reconnect_random_ts
= time(NULL
);
1398 DEBUG(("Saving auto-reconnect cookie, id=%u\n", g_reconnect_logonid
));
1404 /* Process a disconnect PDU */
1406 process_disconnect_pdu(STREAM s
, uint32
* ext_disc_reason
)
1408 in_uint32_le(s
, *ext_disc_reason
);
1410 DEBUG(("Received disconnect PDU\n"));
1413 /* Process data PDU */
1415 process_data_pdu(STREAM s
, uint32
* ext_disc_reason
)
1417 uint8 data_pdu_type
;
1424 struct stream
*ns
= &(g_mppc_dict
.ns
);
1426 in_uint8s(s
, 6); /* shareid, pad, streamid */
1427 in_uint16_le(s
, len
);
1428 in_uint8(s
, data_pdu_type
);
1430 in_uint16_le(s
, clen
);
1433 if (ctype
& RDP_MPPC_COMPRESSED
)
1435 if (len
> RDP_MPPC_DICT_SIZE
)
1436 error("error decompressed packet size exceeds max\n");
1437 if (mppc_expand(s
->p
, clen
, ctype
, &roff
, &rlen
) == -1)
1438 error("error while decompressing packet\n");
1442 /* allocate memory and copy the uncompressed data into the temporary stream */
1443 ns
->data
= (uint8
*) xrealloc(ns
->data
, rlen
);
1445 memcpy((ns
->data
), (unsigned char *) (g_mppc_dict
.hist
+ roff
), rlen
);
1448 ns
->end
= (ns
->data
+ ns
->size
);
1450 ns
->rdp_hdr
= ns
->p
;
1455 switch (data_pdu_type
)
1457 case RDP_DATA_PDU_UPDATE
:
1458 process_update_pdu(s
);
1461 case RDP_DATA_PDU_CONTROL
:
1462 DEBUG(("Received Control PDU\n"));
1465 case RDP_DATA_PDU_SYNCHRONISE
:
1466 DEBUG(("Received Sync PDU\n"));
1469 case RDP_DATA_PDU_POINTER
:
1470 process_pointer_pdu(s
);
1473 case RDP_DATA_PDU_BELL
:
1477 case RDP_DATA_PDU_LOGON
:
1478 DEBUG(("Received Logon PDU\n"));
1479 /* User logged on */
1480 process_pdu_logon(s
);
1483 case RDP_DATA_PDU_DISCONNECT
:
1484 process_disconnect_pdu(s
, ext_disc_reason
);
1486 /* We used to return true and disconnect immediately here, but
1487 * Windows Vista sends a disconnect PDU with reason 0 when
1488 * reconnecting to a disconnected session, and MSTSC doesn't
1489 * drop the connection. I think we should just save the status.
1493 case RDP_DATA_PDU_AUTORECONNECT_STATUS
:
1494 warning("Automatic reconnect using cookie, failed.\n");
1498 unimpl("data PDU %d\n", data_pdu_type
);
1503 /* Process redirect PDU from Session Directory */
1505 process_redirect_pdu(STREAM s
, RD_BOOL enhanced_redirect
/*, uint32 * ext_disc_reason */ )
1508 uint16 redirect_identifier
;
1510 /* reset any previous redirection information */
1512 free(g_redirect_server
);
1513 free(g_redirect_username
);
1514 free(g_redirect_domain
);
1515 free(g_redirect_lb_info
);
1516 free(g_redirect_cookie
);
1518 g_redirect_server
= NULL
;
1519 g_redirect_username
= NULL
;
1520 g_redirect_domain
= NULL
;
1521 g_redirect_lb_info
= NULL
;
1522 g_redirect_cookie
= NULL
;
1524 /* these 2 bytes are unknown, seem to be zeros */
1527 /* FIXME: Previous implementation only reads 4 bytes which has been working
1528 but todays spec says something different. Investigate and retest
1529 server redirection using WTS 2003 cluster.
1532 if (enhanced_redirect
)
1534 /* read identifier */
1535 in_uint16_le(s
, redirect_identifier
);
1536 if (redirect_identifier
!= 0x0400)
1537 error("Protocol error in server redirection, unexpected data.");
1539 /* FIXME: skip total length */
1542 /* read session_id */
1543 in_uint32_le(s
, g_redirect_session_id
);
1546 /* read connection flags */
1547 in_uint32_le(s
, g_redirect_flags
);
1549 if (g_redirect_flags
& LB_TARGET_NET_ADDRESS
)
1551 /* read length of ip string */
1552 in_uint32_le(s
, len
);
1554 /* read ip string */
1555 rdp_in_unistr(s
, len
, &g_redirect_server
, &g_redirect_server_len
);
1558 if (g_redirect_flags
& LB_LOAD_BALANCE_INFO
)
1560 /* read length of load balance info blob */
1561 in_uint32_le(s
, g_redirect_lb_info_len
);
1563 /* reallocate a loadbalance info blob */
1564 if (g_redirect_lb_info
!= NULL
)
1565 free(g_redirect_lb_info
);
1567 g_redirect_lb_info
= xmalloc(g_redirect_lb_info_len
);
1569 /* read load balance info blob */
1570 in_uint8p(s
, g_redirect_lb_info
, g_redirect_lb_info_len
);
1573 if (g_redirect_flags
& LB_USERNAME
)
1575 /* read length of username string */
1576 in_uint32_le(s
, len
);
1578 /* read username string */
1579 rdp_in_unistr(s
, len
, &g_redirect_username
, &g_redirect_username_len
);
1582 if (g_redirect_flags
& LB_DOMAIN
)
1584 /* read length of domain string */
1585 in_uint32_le(s
, len
);
1587 /* read domain string */
1588 rdp_in_unistr(s
, len
, &g_redirect_domain
, &g_redirect_domain_len
);
1591 if (g_redirect_flags
& LB_PASSWORD
)
1593 /* the information in this blob is either a password or a cookie that
1594 should be passed though as blob and not parsed as a unicode string */
1596 /* read blob length */
1597 in_uint32_le(s
, g_redirect_cookie_len
);
1599 /* reallocate cookie blob */
1600 if (g_redirect_cookie
!= NULL
)
1601 free(g_redirect_cookie
);
1603 g_redirect_cookie
= xmalloc(g_redirect_cookie_len
);
1605 /* read cookie as is */
1606 in_uint8p(s
, g_redirect_cookie
, g_redirect_cookie_len
);
1609 if (g_redirect_flags
& LB_DONTSTOREUSERNAME
)
1611 warning("LB_DONTSTOREUSERNAME set\n");
1614 if (g_redirect_flags
& LB_SMARTCARD_LOGON
)
1616 warning("LB_SMARTCARD_LOGON set\n");
1619 if (g_redirect_flags
& LB_NOREDIRECT
)
1621 /* By spec this is only for information and doesn't mean that an actual
1622 redirect should be performed. How it should be used is not mentioned. */
1626 if (g_redirect_flags
& LB_TARGET_FQDN
)
1628 in_uint32_le(s
, len
);
1630 /* Let target fqdn replace target ip address */
1631 if (g_redirect_server
)
1633 free(g_redirect_server
);
1634 g_redirect_server
= NULL
;
1637 /* read fqdn string */
1638 rdp_in_unistr(s
, len
, &g_redirect_server
, &g_redirect_server_len
);
1641 if (g_redirect_flags
& LB_TARGET_NETBIOS
)
1643 warning("LB_TARGET_NETBIOS set\n");
1646 if (g_redirect_flags
& LB_TARGET_NET_ADDRESSES
)
1648 warning("LB_TARGET_NET_ADDRESSES set\n");
1651 if (g_redirect_flags
& LB_CLIENT_TSV_URL
)
1653 warning("LB_CLIENT_TSV_URL set\n");
1656 if (g_redirect_flags
& LB_SERVER_TSV_CAPABLE
)
1658 warning("LB_SERVER_TSV_CAPABLE set\n");
1661 if (g_redirect_flags
& LB_PASSWORD_IS_PK_ENCRYPTED
)
1663 warning("LB_PASSWORD_IS_PK_ENCRYPTED set\n");
1666 if (g_redirect_flags
& LB_REDIRECTION_GUID
)
1668 warning("LB_REDIRECTION_GUID set\n");
1671 if (g_redirect_flags
& LB_TARGET_CERTIFICATE
)
1673 warning("LB_TARGET_CERTIFICATE set\n");
1679 /* Process incoming packets */
1681 rdp_main_loop(RD_BOOL
* deactivated
, uint32
* ext_disc_reason
)
1683 while (rdp_loop(deactivated
, ext_disc_reason
))
1685 if (g_pending_resize
|| g_redirect
)
1692 /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1694 rdp_loop(RD_BOOL
* deactivated
, uint32
* ext_disc_reason
)
1697 RD_BOOL cont
= True
;
1702 s
= rdp_recv(&type
);
1707 case RDP_PDU_DEMAND_ACTIVE
:
1708 process_demand_active(s
);
1709 *deactivated
= False
;
1711 case RDP_PDU_DEACTIVATE
:
1712 DEBUG(("RDP_PDU_DEACTIVATE\n"));
1713 *deactivated
= True
;
1715 case RDP_PDU_REDIRECT
:
1716 return process_redirect_pdu(s
, False
);
1718 case RDP_PDU_ENHANCED_REDIRECT
:
1719 return process_redirect_pdu(s
, True
);
1722 /* If we got a data PDU, we don't need to keep the password in memory
1723 anymore and therefor we should clear it for security reasons. */
1724 if (g_password
[0] != '\0')
1725 memset(g_password
, 0, sizeof(g_password
));
1727 process_data_pdu(s
, ext_disc_reason
);
1732 unimpl("PDU %d\n", type
);
1734 cont
= g_next_packet
< s
->end
;
1739 /* Establish a connection up to the RDP layer */
1741 rdp_connect(char *server
, uint32 flags
, char *domain
, char *password
,
1742 char *command
, char *directory
, RD_BOOL reconnect
)
1744 RD_BOOL deactivated
= False
;
1745 uint32 ext_disc_reason
= 0;
1747 if (!sec_connect(server
, g_username
, domain
, password
, reconnect
))
1750 rdp_send_logon_info(flags
, domain
, g_username
, password
, command
, directory
);
1752 /* run RDP loop until first licence demand active PDU */
1753 while (!g_rdp_shareid
)
1755 if (g_network_error
)
1758 if (!rdp_loop(&deactivated
, &ext_disc_reason
))
1767 /* Called during redirection to reset the state to support redirection */
1769 rdp_reset_state(void)
1771 g_next_packet
= NULL
; /* reset the packet information */
1776 /* Disconnect from the RDP layer */
1778 rdp_disconnect(void)