--- sourceforge.net/trunk/rdesktop/rdp.c 2003/04/16 08:19:15 365 +++ sourceforge.net/trunk/rdesktop/rdp.c 2003/07/28 18:13:30 436 @@ -2,17 +2,17 @@ rdesktop: A Remote Desktop Protocol client. Protocol services - RDP layer Copyright (C) Matthew Chapman 1999-2002 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -20,7 +20,7 @@ #include "rdesktop.h" -extern uint16 mcs_userid; +extern uint16 g_mcs_userid; extern char username[16]; extern BOOL bitmap_compression; extern BOOL orders; @@ -28,6 +28,7 @@ extern BOOL desktop_save; extern BOOL use_rdp5; extern uint16 server_rdp_version; +extern int server_bpp; uint8 *next_packet; uint32 rdp_shareid; @@ -100,7 +101,7 @@ out_uint16_le(s, length); out_uint16_le(s, (RDP_PDU_DATA | 0x10)); - out_uint16_le(s, (mcs_userid + 1001)); + out_uint16_le(s, (g_mcs_userid + 1001)); out_uint32_le(s, rdp_shareid); out_uint8(s, 0); /* pad */ @@ -140,10 +141,13 @@ int len_password = 2 * strlen(password); int len_program = 2 * strlen(program); int len_directory = 2 * strlen(directory); + int len_ip = 2 * strlen("127.0.0.1"); + int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll"); + int packetlen = 0; uint32 sec_flags = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO; STREAM s; - if (1 == server_rdp_version) + if (!use_rdp5 || 1 == server_rdp_version) { DEBUG_RDP5(("Sending RDP4-style Logon packet\n")); @@ -165,55 +169,100 @@ } else { + flags |= RDP_LOGON_BLOB; 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! */ + packetlen = 4 + // Unknown uint32 + 4 + // flags + 2 + // len_domain + 2 + // len_user + (flags & RDP_LOGON_AUTO ? 2 : 0) + // len_password + (flags & RDP_LOGON_BLOB ? 2 : 0) + // Length of BLOB + 2 + // len_program + 2 + // len_directory + (0 < len_domain ? len_domain : 2) + // domain + len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + // We have no 512 byte BLOB. Perhaps we must? + (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + // After the BLOB is a unknown int16. If there is a BLOB, that is. + (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + // Unknown (2) + 2 + // Client ip length + len_ip + // Client ip + 2 + // DLL string length + len_dll + // DLL string + 2 + // Unknown + 2 + // Unknown + 64 + // Time zone #0 + 2 + // Unknown + 64 + // Time zone #1 + 32; // Unknown - out_uint32(s, 0); + s = sec_init(sec_flags, packetlen); + DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen)); + + out_uint32(s, 0); // Unknown 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); + + } + if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO)) + { + out_uint16_le(s, 0); } - out_uint16(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 (0 < len_domain) + rdp_out_unistr(s, domain, len_domain); + else + out_uint16_le(s, 0); + rdp_out_unistr(s, user, len_user); 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(s, 0); - out_uint16(s, 0); + if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO)) + { + out_uint16_le(s, 0); + } if (0 < len_program) + { rdp_out_unistr(s, program, len_program); + + } + else + { + out_uint16_le(s, 0); + } 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")); + } + else + { + out_uint16_le(s, 0); + } + out_uint16_le(s, 2); + out_uint16_le(s, len_ip + 2); // Length of client ip + rdp_out_unistr(s, "127.0.0.1", len_ip); + out_uint16_le(s, len_dll + 2); + rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll); + out_uint16_le(s, 0xffc4); + out_uint16_le(s, 0xffff); + rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid")); + out_uint8s(s, 62 - 2 * strlen("GTB, normaltid")); + out_uint32_le(s, 0x0a0000); out_uint32_le(s, 0x050000); - out_uint32_le(s, 2); - out_uint32(s, 0); - out_uint32_le(s, 0xffffffc4); - out_uint32_le(s, 0xfffffffe); - out_uint32_le(s, 0x0f); - out_uint32(s, 0); + out_uint32_le(s, 3); + out_uint32_le(s, 0); + out_uint32_le(s, 0); - rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid") - 1); - out_uint8s(s, 30 - 2 * strlen("GTP, sommartid")); + rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid")); + out_uint8s(s, 62 - 2 * strlen("GTB, sommartid")); - out_uint32_le(s, 0x030000); + out_uint32_le(s, 0x30000); out_uint32_le(s, 0x050000); out_uint32_le(s, 2); out_uint32(s, 0); @@ -222,6 +271,7 @@ out_uint32_le(s, 0x0f); out_uint32(s, 0); + } s_mark_end(s); sec_send(s, sec_flags); @@ -385,16 +435,18 @@ static void rdp_out_bmpcache_caps(STREAM s) { + int Bpp; out_uint16_le(s, RDP_CAPSET_BMPCACHE); out_uint16_le(s, RDP_CAPLEN_BMPCACHE); + Bpp = (server_bpp + 7) / 8; out_uint8s(s, 24); /* unused */ out_uint16_le(s, 0x258); /* entries */ - out_uint16_le(s, 0x100); /* max cell size */ + out_uint16_le(s, 0x100 * Bpp); /* max cell size */ out_uint16_le(s, 0x12c); /* entries */ - out_uint16_le(s, 0x400); /* max cell size */ + out_uint16_le(s, 0x400 * Bpp); /* max cell size */ out_uint16_le(s, 0x106); /* entries */ - out_uint16_le(s, 0x1000); /* max cell size */ + out_uint16_le(s, 0x1000 * Bpp); /* max cell size */ } /* Output control capability set */ @@ -505,7 +557,7 @@ 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_uint16_le(s, (g_mcs_userid + 1001)); out_uint32_le(s, rdp_shareid); out_uint16_le(s, 0x3ea); /* userid */ @@ -663,7 +715,7 @@ if (!compress) { int y; - bmpdata = xmalloc(width * height * Bpp); + bmpdata = (uint8 *) xmalloc(width * height * Bpp); for (y = 0; y < height; y++) { in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)], @@ -686,7 +738,7 @@ in_uint8s(s, 4); /* line_size, final_size */ } in_uint8p(s, data, size); - bmpdata = xmalloc(width * height * Bpp); + bmpdata = (uint8 *) xmalloc(width * height * Bpp); if (bitmap_decompress(bmpdata, width, height, data, size, Bpp)) { ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata); @@ -713,7 +765,7 @@ in_uint16_le(s, map.ncolours); in_uint8s(s, 2); /* pad */ - map.colours = xmalloc(3 * map.ncolours); + map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours); DEBUG(("PALETTE(c=%d)\n", map.ncolours)); @@ -800,7 +852,7 @@ } /* Process incoming packets */ -void +BOOL rdp_main_loop(void) { uint8 type; @@ -815,6 +867,13 @@ break; case RDP_PDU_DEACTIVATE: + DEBUG(("RDP_PDU_DEACTIVATE\n")); + /* We thought we could detect a clean + shutdown of the session by this + packet, but it seems Windows 2003 + is sending us one of these when we + reconnect to a disconnected session + return True; */ break; case RDP_PDU_DATA: @@ -828,6 +887,10 @@ unimpl("PDU %d\n", type); } } + return True; + /* We want to detect if we got a clean shutdown, but we + can't. Se above. + return False; */ } /* Establish a connection up to the RDP layer */