Send different logon packets based on if we try to support RDP5 or not. The
order of the data is slightly different in RDP5. Moved pointer PDU handling to their own functions, since RDP5 no longer encapsulates ColorPointer and CachedPointer in a PDU with a type field. Made debug output when doing Bitmap updates clearer. Also added debug printout when bitmap compression failed. Added code that checks for a new way of sending the size of the compressed bitmaps. Code imported from Matt's RDP5 adventures :). Debug output when doing Palette updates in order to make it easier to follow packets. Fetch the number of orders here instead of in process_orders and send it along to that function as an argument. Send the username to sec_connect. git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@350 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
parent
fcfd8d4b90
commit
a20dd37798
250
rdp.c
250
rdp.c
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/* -*- c-basic-offset: 8 -*-
|
||||
rdesktop: A Remote Desktop Protocol client.
|
||||
Protocol services - RDP layer
|
||||
Copyright (C) Matthew Chapman 1999-2002
|
||||
@ -26,6 +26,8 @@ extern BOOL bitmap_compression;
|
||||
extern BOOL orders;
|
||||
extern BOOL encryption;
|
||||
extern BOOL desktop_save;
|
||||
extern BOOL use_rdp5;
|
||||
extern uint16 server_rdp_version;
|
||||
|
||||
uint8 *next_packet;
|
||||
uint32 rdp_shareid;
|
||||
@ -34,34 +36,6 @@ uint32 rdp_shareid;
|
||||
static uint32 packetno;
|
||||
#endif
|
||||
|
||||
/* Initialise an RDP packet */
|
||||
static STREAM
|
||||
rdp_init(int maxlen)
|
||||
{
|
||||
STREAM s;
|
||||
|
||||
s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 6);
|
||||
s_push_layer(s, rdp_hdr, 6);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Send an RDP packet */
|
||||
static void
|
||||
rdp_send(STREAM s, uint8 pdu_type)
|
||||
{
|
||||
uint16 length;
|
||||
|
||||
s_pop_layer(s, rdp_hdr);
|
||||
length = s->end - s->p;
|
||||
|
||||
out_uint16_le(s, length);
|
||||
out_uint16_le(s, (pdu_type | 0x10)); /* Version 1 */
|
||||
out_uint16_le(s, (mcs_userid + 1001));
|
||||
|
||||
sec_send(s, encryption ? SEC_ENCRYPT : 0);
|
||||
}
|
||||
|
||||
/* Receive an RDP packet */
|
||||
static STREAM
|
||||
rdp_recv(uint8 * type)
|
||||
@ -95,8 +69,8 @@ rdp_recv(uint8 * type)
|
||||
*type = pdu_type & 0xf;
|
||||
|
||||
#if WITH_DEBUG
|
||||
DEBUG(("RDP packet #%d, (type %x):\n", ++packetno, *type));
|
||||
hexdump(next_packet, length);
|
||||
DEBUG(("RDP packet #%d, (type %x)\n", ++packetno, *type));
|
||||
// hexdump(next_packet, length);
|
||||
#endif /* */
|
||||
|
||||
next_packet += length;
|
||||
@ -169,22 +143,86 @@ rdp_send_logon_info(uint32 flags, char *domain, char *user,
|
||||
uint32 sec_flags = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
|
||||
STREAM s;
|
||||
|
||||
s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
|
||||
+ len_program + len_directory + 10);
|
||||
if (1 == server_rdp_version)
|
||||
{
|
||||
DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
|
||||
|
||||
out_uint32(s, 0);
|
||||
out_uint32_le(s, flags);
|
||||
out_uint16_le(s, len_domain);
|
||||
out_uint16_le(s, len_user);
|
||||
out_uint16_le(s, len_password);
|
||||
out_uint16_le(s, len_program);
|
||||
out_uint16_le(s, len_directory);
|
||||
rdp_out_unistr(s, domain, len_domain);
|
||||
rdp_out_unistr(s, user, len_user);
|
||||
rdp_out_unistr(s, password, len_password);
|
||||
rdp_out_unistr(s, program, len_program);
|
||||
rdp_out_unistr(s, directory, len_directory);
|
||||
s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
|
||||
+ len_program + len_directory + 10);
|
||||
|
||||
out_uint32(s, 0);
|
||||
out_uint32_le(s, flags);
|
||||
out_uint16_le(s, len_domain);
|
||||
out_uint16_le(s, len_user);
|
||||
out_uint16_le(s, len_password);
|
||||
out_uint16_le(s, len_program);
|
||||
out_uint16_le(s, len_directory);
|
||||
rdp_out_unistr(s, domain, len_domain);
|
||||
rdp_out_unistr(s, user, len_user);
|
||||
rdp_out_unistr(s, password, len_password);
|
||||
rdp_out_unistr(s, program, len_program);
|
||||
rdp_out_unistr(s, directory, len_directory);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
|
||||
s = sec_init(sec_flags, 12 + (flags & RDP_LOGON_AUTO ? 2 : 0) + 6 + (flags & RDP_LOGON_AUTO ? len_password : 0) + len_domain + len_user + 4 + len_program + len_directory + 30 + 2 + 60 + 32 + 20 + 32 + 20); /* Phew! */
|
||||
|
||||
out_uint32(s, 0);
|
||||
out_uint32_le(s, flags);
|
||||
out_uint16_le(s, len_domain);
|
||||
out_uint16_le(s, len_user);
|
||||
if (flags & RDP_LOGON_AUTO)
|
||||
{
|
||||
out_uint16_le(s, len_password);
|
||||
}
|
||||
out_uint16_le(s, 0); /* Seems to be length of a 512 byte blob with
|
||||
completely unknown data, but hopefully we'll do
|
||||
with a 0 length block as well */
|
||||
out_uint16_le(s, len_program);
|
||||
out_uint16_le(s, len_directory);
|
||||
if (flags & RDP_LOGON_AUTO)
|
||||
{
|
||||
rdp_out_unistr(s, password, len_password);
|
||||
}
|
||||
rdp_out_unistr(s, domain, len_domain);
|
||||
rdp_out_unistr(s, user, len_user);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
if (0 < len_program)
|
||||
rdp_out_unistr(s, program, len_program);
|
||||
if (0 < len_directory)
|
||||
rdp_out_unistr(s, directory, len_directory);
|
||||
out_uint8s(s, 30); /* Some kind of client data - let's see if the server
|
||||
handles zeros well.. */
|
||||
out_uint16_le(s, 60);
|
||||
rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", 58);
|
||||
out_uint32_be(s, 0x88ffffff);
|
||||
rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid") - 2);
|
||||
out_uint8s(s, 30 - 2 * strlen("GTP, normaltid"));
|
||||
|
||||
out_uint32_le(s, 0x0a0000);
|
||||
out_uint32_le(s, 0x050000);
|
||||
out_uint32_le(s, 2);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0xffffffc4);
|
||||
out_uint32_le(s, 0xfffffffe);
|
||||
out_uint32_le(s, 0x0f);
|
||||
out_uint32_le(s, 0);
|
||||
|
||||
rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid") - 1);
|
||||
out_uint8s(s, 30 - 2 * strlen("GTP, sommartid"));
|
||||
|
||||
out_uint32_le(s, 0x030000);
|
||||
out_uint32_le(s, 0x050000);
|
||||
out_uint32_le(s, 2);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0xffffffc4);
|
||||
out_uint32_le(s, 0xfffffffe);
|
||||
out_uint32_le(s, 0x0f);
|
||||
out_uint32_le(s, 0);
|
||||
|
||||
}
|
||||
s_mark_end(s);
|
||||
sec_send(s, sec_flags);
|
||||
}
|
||||
@ -270,7 +308,14 @@ rdp_out_general_caps(STREAM s)
|
||||
out_uint16_le(s, 0x200); /* Protocol version */
|
||||
out_uint16(s, 0); /* Pad */
|
||||
out_uint16(s, 0); /* Compression types */
|
||||
out_uint16(s, 0); /* Pad */
|
||||
out_uint16(s, use_rdp5 ? 0x40d : 0);
|
||||
/* Pad, according to T.128. 0x40d seems to
|
||||
trigger
|
||||
the server to start sending RDP5 packets.
|
||||
However, the value is 0x1d04 with W2KTSK and
|
||||
NT4MS. Hmm.. Anyway, thankyou, Microsoft,
|
||||
for sending such information in a padding
|
||||
field.. */
|
||||
out_uint16(s, 0); /* Update capability */
|
||||
out_uint16(s, 0); /* Remote unshare capability */
|
||||
out_uint16(s, 0); /* Compression level */
|
||||
@ -433,7 +478,7 @@ static uint8 canned_caps[] = {
|
||||
0x02, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Output unknown capability set */
|
||||
/* Output unknown capability sets (number 13, 12, 14 and 16) */
|
||||
static void
|
||||
rdp_out_unknown_caps(STREAM s)
|
||||
{
|
||||
@ -443,18 +488,24 @@ rdp_out_unknown_caps(STREAM s)
|
||||
out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
|
||||
}
|
||||
|
||||
#define RDP5_FLAG 0x0030
|
||||
/* Send a confirm active PDU */
|
||||
static void
|
||||
rdp_send_confirm_active(void)
|
||||
{
|
||||
STREAM s;
|
||||
uint32 sec_flags = encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
|
||||
uint16 caplen =
|
||||
RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
|
||||
RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
|
||||
RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
|
||||
RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
|
||||
|
||||
s = rdp_init(14 + caplen + sizeof(RDP_SOURCE));
|
||||
s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
|
||||
|
||||
out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
|
||||
out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
|
||||
out_uint16_le(s, (mcs_userid + 1001));
|
||||
|
||||
out_uint32_le(s, rdp_shareid);
|
||||
out_uint16_le(s, 0x3ea); /* userid */
|
||||
@ -477,7 +528,7 @@ rdp_send_confirm_active(void)
|
||||
rdp_out_unknown_caps(s);
|
||||
|
||||
s_mark_end(s);
|
||||
rdp_send(s, RDP_PDU_CONFIRM_ACTIVE);
|
||||
sec_send(s, sec_flags);
|
||||
}
|
||||
|
||||
/* Respond to a demand active PDU */
|
||||
@ -504,14 +555,54 @@ process_demand_active(STREAM s)
|
||||
reset_order_state();
|
||||
}
|
||||
|
||||
/* Process a null system pointer PDU */
|
||||
void
|
||||
process_null_system_pointer_pdu(STREAM s)
|
||||
{
|
||||
// FIXME: We should probably set another cursor here,
|
||||
// like the X window system base cursor or something.
|
||||
ui_set_cursor(cache_get_cursor(0));
|
||||
}
|
||||
|
||||
/* Process a colour pointer PDU */
|
||||
void
|
||||
process_colour_pointer_pdu(STREAM s)
|
||||
{
|
||||
uint16 x, y, width, height, cache_idx, masklen, datalen;
|
||||
uint8 *mask, *data;
|
||||
HCURSOR cursor;
|
||||
|
||||
in_uint16_le(s, cache_idx);
|
||||
in_uint16_le(s, x);
|
||||
in_uint16_le(s, y);
|
||||
in_uint16_le(s, width);
|
||||
in_uint16_le(s, height);
|
||||
in_uint16_le(s, masklen);
|
||||
in_uint16_le(s, datalen);
|
||||
in_uint8p(s, data, datalen);
|
||||
in_uint8p(s, mask, masklen);
|
||||
cursor = ui_create_cursor(x, y, width, height, mask, data);
|
||||
ui_set_cursor(cursor);
|
||||
cache_put_cursor(cache_idx, cursor);
|
||||
}
|
||||
|
||||
/* Process a cached pointer PDU */
|
||||
void
|
||||
process_cached_pointer_pdu(STREAM s)
|
||||
{
|
||||
uint16 cache_idx;
|
||||
|
||||
in_uint16_le(s, cache_idx);
|
||||
ui_set_cursor(cache_get_cursor(cache_idx));
|
||||
}
|
||||
|
||||
|
||||
/* Process a pointer PDU */
|
||||
static void
|
||||
process_pointer_pdu(STREAM s)
|
||||
{
|
||||
uint16 message_type;
|
||||
uint16 x, y, width, height, cache_idx, masklen, datalen;
|
||||
uint8 *mask, *data;
|
||||
HCURSOR cursor;
|
||||
uint16 x, y;
|
||||
|
||||
in_uint16_le(s, message_type);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
@ -526,23 +617,11 @@ process_pointer_pdu(STREAM s)
|
||||
break;
|
||||
|
||||
case RDP_POINTER_COLOR:
|
||||
in_uint16_le(s, cache_idx);
|
||||
in_uint16_le(s, x);
|
||||
in_uint16_le(s, y);
|
||||
in_uint16_le(s, width);
|
||||
in_uint16_le(s, height);
|
||||
in_uint16_le(s, masklen);
|
||||
in_uint16_le(s, datalen);
|
||||
in_uint8p(s, data, datalen);
|
||||
in_uint8p(s, mask, masklen);
|
||||
cursor = ui_create_cursor(x, y, width, height, mask, data);
|
||||
ui_set_cursor(cursor);
|
||||
cache_put_cursor(cache_idx, cursor);
|
||||
process_colour_pointer_pdu(s);
|
||||
break;
|
||||
|
||||
case RDP_POINTER_CACHED:
|
||||
in_uint16_le(s, cache_idx);
|
||||
ui_set_cursor(cache_get_cursor(cache_idx));
|
||||
process_cached_pointer_pdu(s);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -551,7 +630,7 @@ process_pointer_pdu(STREAM s)
|
||||
}
|
||||
|
||||
/* Process bitmap updates */
|
||||
static void
|
||||
void
|
||||
process_bitmap_updates(STREAM s)
|
||||
{
|
||||
uint16 num_updates;
|
||||
@ -578,8 +657,8 @@ process_bitmap_updates(STREAM s)
|
||||
cx = right - left + 1;
|
||||
cy = bottom - top + 1;
|
||||
|
||||
DEBUG(("UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,cmp=%d)\n",
|
||||
left, top, right, bottom, width, height, compress));
|
||||
DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
|
||||
left, top, right, bottom, width, height, Bpp, compress));
|
||||
|
||||
if (!compress)
|
||||
{
|
||||
@ -595,21 +674,34 @@ process_bitmap_updates(STREAM s)
|
||||
continue;
|
||||
}
|
||||
|
||||
in_uint8s(s, 2); /* pad */
|
||||
in_uint16_le(s, size);
|
||||
in_uint8s(s, 4); /* line_size, final_size */
|
||||
|
||||
if (compress & 0x400)
|
||||
{
|
||||
size = bufsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_uint8s(s, 2); /* pad */
|
||||
in_uint16_le(s, size);
|
||||
in_uint8s(s, 4); /* line_size, final_size */
|
||||
}
|
||||
in_uint8p(s, data, size);
|
||||
bmpdata = xmalloc(width * height * Bpp);
|
||||
if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
|
||||
{
|
||||
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_RDP5(("Failed to decompress data\n"));
|
||||
}
|
||||
|
||||
xfree(bmpdata);
|
||||
}
|
||||
}
|
||||
|
||||
/* Process a palette update */
|
||||
static void
|
||||
void
|
||||
process_palette(STREAM s)
|
||||
{
|
||||
COLOURENTRY *entry;
|
||||
@ -623,6 +715,8 @@ process_palette(STREAM s)
|
||||
|
||||
map.colours = xmalloc(3 * map.ncolours);
|
||||
|
||||
DEBUG(("PALETTE(c=%d)\n", map.ncolours));
|
||||
|
||||
for (i = 0; i < map.ncolours; i++)
|
||||
{
|
||||
entry = &map.colours[i];
|
||||
@ -641,14 +735,17 @@ process_palette(STREAM s)
|
||||
static void
|
||||
process_update_pdu(STREAM s)
|
||||
{
|
||||
uint16 update_type;
|
||||
uint16 update_type, count;
|
||||
|
||||
in_uint16_le(s, update_type);
|
||||
|
||||
switch (update_type)
|
||||
{
|
||||
case RDP_UPDATE_ORDERS:
|
||||
process_orders(s);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
in_uint16_le(s, count);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
process_orders(s, count);
|
||||
break;
|
||||
|
||||
case RDP_UPDATE_BITMAP:
|
||||
@ -693,6 +790,7 @@ process_data_pdu(STREAM s)
|
||||
break;
|
||||
|
||||
case RDP_DATA_PDU_LOGON:
|
||||
DEBUG(("Received Logon PDU\n"));
|
||||
/* User logged on */
|
||||
break;
|
||||
|
||||
@ -737,7 +835,7 @@ BOOL
|
||||
rdp_connect(char *server, uint32 flags, char *domain, char *password,
|
||||
char *command, char *directory)
|
||||
{
|
||||
if (!sec_connect(server))
|
||||
if (!sec_connect(server, username))
|
||||
return False;
|
||||
|
||||
rdp_send_logon_info(flags, domain, username, password, command, directory);
|
||||
|
Loading…
Reference in New Issue
Block a user