Fixed (?) and enabled RDP5 encryption.
[rdpsrv] / rdp.c
diff --git a/rdp.c b/rdp.c
index 52ea009..4ea3698 100644 (file)
--- a/rdp.c
+++ b/rdp.c
@@ -72,7 +72,7 @@ rdp_recv(uint8 * type)
 
 #if WITH_DEBUG
        DEBUG(("RDP packet #%d, (type %x, length %u)\n", ++g_packetno, *type, length));
-       hexdump(g_next_packet, length);
+       //hexdump(g_next_packet, length);
 #endif /*  */
 
        g_next_packet += length;
@@ -148,78 +148,142 @@ rdp_in_unistr(STREAM s, char *string, int len)
        s->p += len;
 }
 
-void rdp_send_bitmap_update(void)
+void rdp_send_bitmap_update(unsigned x, unsigned y, unsigned width, unsigned height, unsigned char *data)
 {
        STREAM s;
 
-       s = rdp_init_data(11*2 + 2*2*3);
-       out_uint16_le(s, RDP_UPDATE_BITMAP);
-       out_uint16_le(s, 1); // one update
-       out_uint16_le(s, 1); // left, top, right, bottom
-       out_uint16_le(s, 2);
-       out_uint16_le(s, 3);
-       out_uint16_le(s, 4);
-       out_uint16_le(s, 2); // width, height
-       out_uint16_le(s, 2);
-       out_uint16_le(s, 24); // bpp
-       out_uint16_le(s, 0); // no compression
-       out_uint16_le(s, 2*2*3); // bufsize
+       int length = 10*2 + width*height*3 + 5;
 
-       out_uint8(s, 255);
-       out_uint8(s, 0);
-       out_uint8(s, 0);
+       s = rdp5_init(length, 1);
 
-       out_uint8(s, 0);
-       out_uint8(s, 255);
-       out_uint8(s, 0);
+       out_uint8(s, 1); // process bitmap update
+       out_uint16_le(s, 10*2 + width*height*3 + 2); // RDP5 chunk length
+       out_uint16_le(s, 10*2 + width*height*3);     // part length
 
-       out_uint8(s, 0);
-       out_uint8(s, 0);
-       out_uint8(s, 255);
-
-       out_uint8(s, 255);
-       out_uint8(s, 255);
-       out_uint8(s, 255);
+       out_uint16_le(s, 1); // one update
+       out_uint16_le(s, x); // left, top, right, bottom
+       out_uint16_le(s, y);
+       out_uint16_le(s, x+width);
+       out_uint16_le(s, y+height);
+       out_uint16_le(s, width); // width, height
+       out_uint16_le(s, height);
+       out_uint16_le(s, 24); // bpp
+       out_uint16_le(s, 0); // no compression
+       out_uint16_le(s, width*height*3); // bufsize
 
+       out_uint8p(s, data, width*height*3);
+       
        s_mark_end(s);
-       rdp_send_data(s, RDP_DATA_PDU_UPDATE);
+       rdp5_send(s, 1);
 }
 
+#define EXPECT16(value) { in_uint16_le(s, unknown); if (unknown != (value)) printf("Unknown value on code line %u; expected 0x%x, got 0x%x\n", __LINE__, (value), unknown); }
+#define EXPECT32(value) { in_uint32_le(s, unknown); if (unknown != (value)) printf("Unknown value on code line %u; expected 0x%x, got 0x%x\n", __LINE__, (value), unknown); }
 
 void
 rdp_get_logon_info(STREAM s)
 {
-       uint32 flags;
-       int len_domain, len_user, len_password, len_program, len_directory;
-       char domain[256], user[256], password[256], program[256], directory[256]; // FIXME
+       uint32 flags, unknown;
+       uint16 tzone_major, tzone_minor;
+       int len_domain, len_user, len_password, len_program, len_directory, len_ip, len_dll;
+       char domain[256], user[256], password[256], program[256], directory[256], ip[256], dll[256], tz1[256], tz2[256]; // FIXME
        
-       in_uint32_le(s, flags);  // unknown
+       in_uint32_le(s, unknown);
        in_uint32_le(s, flags);
-
-       if (flags & RDP_LOGON_BLOB) 
-               error("got RDP5-style logon packet, can't handle this yet");
-
+       
        printf("logon flags: %x\n", flags);
 
-       in_uint16_le(s, len_domain);
-       in_uint16_le(s, len_user);
-       in_uint16_le(s, len_password);
-       in_uint16_le(s, len_program);
-       in_uint16_le(s, len_directory);
-       rdp_in_unistr(s, domain, len_domain);
-       rdp_in_unistr(s, user, len_user);
-       rdp_in_unistr(s, password, len_password);
-       rdp_in_unistr(s, program, len_program);
-       rdp_in_unistr(s, directory, len_directory);
-
-       printf("domain='%s'\n", domain);
-       printf("user='%s'\n", user);
-       printf("password='%s'\n", password);
-       printf("program='%s'\n", program);
-       printf("directory='%s'\n", directory);
-
-       if (!s_check_end(s))
-               error("Unknown data at end of logon packet!");
+       if (flags & RDP_LOGON_BLOB) { 
+               printf("RDP5-style logon packet\n");
+
+               in_uint16_le(s, len_domain);
+               in_uint16_le(s, len_user);
+
+               if (flags & RDP_LOGON_AUTO) {
+                       in_uint16_le(s, len_password);
+               } else {
+                       strcpy(password, "<none>");
+               }
+               if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO)) {
+                       // is this too some kind of length?
+                       EXPECT16(0);
+               }
+               in_uint16_le(s, len_program);
+               in_uint16_le(s, len_directory);
+               
+               rdp_in_unistr(s, domain, len_domain);
+               rdp_in_unistr(s, user, len_user);
+
+               if (flags & RDP_LOGON_AUTO)
+                       rdp_in_unistr(s, password, len_password);
+               
+               if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
+                       EXPECT16(0);
+                       
+               rdp_in_unistr(s, program, len_program);
+               rdp_in_unistr(s, directory, len_directory);
+
+               EXPECT16(2);
+
+               in_uint16_le(s, len_ip);
+               rdp_in_unistr(s, ip, len_ip - 2);
+
+               in_uint16_le(s, len_dll);
+               rdp_in_unistr(s, dll, len_dll - 2);
+
+               in_uint16_le(s, tzone_major);
+               in_uint16_le(s, tzone_minor);
+
+               // time zone names?
+               rdp_in_unistr(s, tz1, 62);
+               EXPECT32(0x0a0000);
+               EXPECT32(0x050000);
+               EXPECT32(3);
+               EXPECT32(0);
+               EXPECT32(0);
+
+               rdp_in_unistr(s, tz2, 62);
+               EXPECT32(0x030000);
+               EXPECT32(0x050000);
+               EXPECT32(2);
+               EXPECT32(0);
+               EXPECT32(0xffffffc4);
+               EXPECT32(0xfffffffe);
+               EXPECT32(0x0f);
+               EXPECT32(0);
+
+               printf("domain='%s'\n", domain);
+               printf("user='%s'\n", user);
+               printf("password='%s'\n", password);
+               printf("program='%s'\n", program);
+               printf("directory='%s'\n", directory);
+               printf("ip='%s'\n", ip);
+               printf("dll='%s'\n", dll);
+               printf("timezone=%d:%02d\n", tzone_major, tzone_minor);
+               printf("tz1='%64s'\n", tz1);
+               printf("tz2='%64s'\n", tz2);
+       } else {
+               in_uint16_le(s, len_domain);
+               in_uint16_le(s, len_user);
+               in_uint16_le(s, len_password);
+               in_uint16_le(s, len_program);
+               in_uint16_le(s, len_directory);
+               rdp_in_unistr(s, domain, len_domain);
+               rdp_in_unistr(s, user, len_user);
+               rdp_in_unistr(s, password, len_password);
+               rdp_in_unistr(s, program, len_program);
+               rdp_in_unistr(s, directory, len_directory);
+
+               printf("domain='%s'\n", domain);
+               printf("user='%s'\n", user);
+               printf("password='%s'\n", password);
+               printf("program='%s'\n", program);
+               printf("directory='%s'\n", directory);
+       }
+
+       if (!s_check_end(s)) {
+               printf("Unknown data at end of logon packet!\n");
+       }
 }
 
 /* Send a control PDU */
@@ -253,25 +317,15 @@ rdp_send_synchronise(void)
        rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
 }
 
-/* Send a single input event */
+/* Receive a single input event */
 void
-rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
+rdp_recv_input(STREAM s, uint32 *time, uint16 *message_type, uint16 *device_flags, uint16 *param1, uint16 *param2)
 {
-       STREAM s;
-
-       s = rdp_init_data(16);
-
-       out_uint16_le(s, 1);    /* number of events */
-       out_uint16(s, 0);       /* pad */
-
-       out_uint32_le(s, time);
-       out_uint16_le(s, message_type);
-       out_uint16_le(s, device_flags);
-       out_uint16_le(s, param1);
-       out_uint16_le(s, param2);
-
-       s_mark_end(s);
-       rdp_send_data(s, RDP_DATA_PDU_INPUT);
+       in_uint32_le(s, *time);
+       in_uint16_le(s, *message_type);
+       in_uint16_le(s, *device_flags);
+       in_uint16_le(s, *param1);
+       in_uint16_le(s, *param2);
 }
 
 /* Disconnect from the RDP layer */