1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman 1999-2002
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
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern uint16 g_mcs_userid;
25 extern char g_username[16];
26 extern BOOL g_bitmap_compression;
28 BOOL g_encryption = 0;
29 extern BOOL g_desktop_save;
30 extern BOOL g_use_rdp5;
31 extern uint16 g_server_rdp_version;
32 extern int g_server_bpp;
38 static uint32 g_packetno;
41 /* Receive an RDP packet */
43 rdp_recv(uint8 * type)
46 uint16 length, pdu_type;
48 if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
54 g_next_packet = rdp_s->p;
58 rdp_s->p = g_next_packet;
61 in_uint16_le(rdp_s, length);
62 /* 32k packets are really 8, keepalive fix */
69 in_uint16_le(rdp_s, pdu_type);
70 in_uint8s(rdp_s, 2); /* userid */
71 *type = pdu_type & 0xf;
74 DEBUG(("RDP packet #%d, (type %x, length %u)\n", ++g_packetno, *type, length));
75 //hexdump(g_next_packet, length);
78 g_next_packet += length;
82 /* Initialise an RDP data packet */
84 rdp_init_data(int maxlen)
88 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
89 s_push_layer(s, rdp_hdr, 18);
94 /* Send an RDP data packet */
96 rdp_send_data(STREAM s, uint8 data_pdu_type)
100 s_pop_layer(s, rdp_hdr);
101 length = s->end - s->p;
103 out_uint16_le(s, length);
104 out_uint16_le(s, (RDP_PDU_DATA | 0x10));
105 out_uint16_le(s, (g_mcs_userid + 1001));
107 out_uint32_le(s, g_rdp_shareid);
108 out_uint8(s, 0); /* pad */
109 out_uint8(s, 1); /* streamid */
110 out_uint16_le(s, (length - 14));
111 out_uint8(s, data_pdu_type);
112 out_uint8(s, 0); /* compress_type */
113 out_uint16(s, 0); /* compress_len */
115 sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
118 /* Output a string in Unicode */
120 rdp_out_unistr(STREAM s, char *string, int len)
128 s->p[i++] = string[j++];
135 /* Input a string in Unicode (uuuuuuugly, use iconv later) */
137 rdp_in_unistr(STREAM s, char *string, int len)
144 string[j++] = s->p[i];
151 void rdp_send_bitmap_update(unsigned x, unsigned y, unsigned width, unsigned height, unsigned char *data)
155 int length = 10*2 + width*height*3 + 8;
157 printf("RDP5 chunk length: %u\n", 10*2 + width*height*3 + 2);
159 s = tcp_init(length);
160 out_uint8(s, 0); // version (RDP5)
161 out_uint8(s, 0x80 | (length >> 8));
162 out_uint8(s, length & 0xff);
164 out_uint8(s, 1); // process bitmap update
165 out_uint16_le(s, 10*2 + width*height*3 + 2); // RDP5 chunk length
166 out_uint16_le(s, 10*2 + width*height*3); // part length
168 out_uint16_le(s, 1); // one update
169 out_uint16_le(s, x); // left, top, right, bottom
171 out_uint16_le(s, x+width);
172 out_uint16_le(s, y+height);
173 out_uint16_le(s, width); // width, height
174 out_uint16_le(s, height);
175 out_uint16_le(s, 24); // bpp
176 out_uint16_le(s, 0); // no compression
177 out_uint16_le(s, width*height*3); // bufsize
179 out_uint8p(s, data, width*height*3);
185 #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); }
186 #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); }
189 rdp_get_logon_info(STREAM s)
191 uint32 flags, unknown;
192 uint16 tzone_major, tzone_minor;
193 int len_domain, len_user, len_password, len_program, len_directory, len_ip, len_dll;
194 char domain[256], user[256], password[256], program[256], directory[256], ip[256], dll[256], tz1[256], tz2[256]; // FIXME
196 in_uint32_le(s, unknown);
197 in_uint32_le(s, flags);
199 printf("logon flags: %x\n", flags);
201 if (flags & RDP_LOGON_BLOB) {
202 printf("RDP5-style logon packet\n");
204 in_uint16_le(s, len_domain);
205 in_uint16_le(s, len_user);
207 if (flags & RDP_LOGON_AUTO) {
208 in_uint16_le(s, len_password);
210 strcpy(password, "<none>");
212 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO)) {
213 // is this too some kind of length?
216 in_uint16_le(s, len_program);
217 in_uint16_le(s, len_directory);
219 rdp_in_unistr(s, domain, len_domain);
220 rdp_in_unistr(s, user, len_user);
222 if (flags & RDP_LOGON_AUTO)
223 rdp_in_unistr(s, password, len_password);
225 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
228 rdp_in_unistr(s, program, len_program);
229 rdp_in_unistr(s, directory, len_directory);
233 in_uint16_le(s, len_ip);
234 rdp_in_unistr(s, ip, len_ip - 2);
236 in_uint16_le(s, len_dll);
237 rdp_in_unistr(s, dll, len_dll - 2);
239 in_uint16_le(s, tzone_major);
240 in_uint16_le(s, tzone_minor);
243 rdp_in_unistr(s, tz1, 62);
250 rdp_in_unistr(s, tz2, 62);
255 EXPECT32(0xffffffc4);
256 EXPECT32(0xfffffffe);
260 printf("domain='%s'\n", domain);
261 printf("user='%s'\n", user);
262 printf("password='%s'\n", password);
263 printf("program='%s'\n", program);
264 printf("directory='%s'\n", directory);
265 printf("ip='%s'\n", ip);
266 printf("dll='%s'\n", dll);
267 printf("timezone=%d:%02d\n", tzone_major, tzone_minor);
268 printf("tz1='%64s'\n", tz1);
269 printf("tz2='%64s'\n", tz2);
271 in_uint16_le(s, len_domain);
272 in_uint16_le(s, len_user);
273 in_uint16_le(s, len_password);
274 in_uint16_le(s, len_program);
275 in_uint16_le(s, len_directory);
276 rdp_in_unistr(s, domain, len_domain);
277 rdp_in_unistr(s, user, len_user);
278 rdp_in_unistr(s, password, len_password);
279 rdp_in_unistr(s, program, len_program);
280 rdp_in_unistr(s, directory, len_directory);
282 printf("domain='%s'\n", domain);
283 printf("user='%s'\n", user);
284 printf("password='%s'\n", password);
285 printf("program='%s'\n", program);
286 printf("directory='%s'\n", directory);
289 if (!s_check_end(s)) {
290 printf("Unknown data at end of logon packet!\n");
294 /* Send a control PDU */
296 rdp_send_control(uint16 action)
300 s = rdp_init_data(8);
302 out_uint16_le(s, action);
303 out_uint16(s, 0); /* userid */
304 out_uint32(s, 0); /* control id */
307 rdp_send_data(s, RDP_DATA_PDU_CONTROL);
310 /* Send a synchronisation PDU */
312 rdp_send_synchronise(void)
316 s = rdp_init_data(4);
318 out_uint16_le(s, 1); /* type */
319 out_uint16_le(s, 1002);
322 rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
325 /* Receive a single input event */
327 rdp_recv_input(STREAM s, uint32 *time, uint16 *message_type, uint16 *device_flags, uint16 *param1, uint16 *param2)
329 in_uint32_le(s, *time);
330 in_uint16_le(s, *message_type);
331 in_uint16_le(s, *device_flags);
332 in_uint16_le(s, *param1);
333 in_uint16_le(s, *param2);
336 /* Disconnect from the RDP layer */