/[rdesktop]/sourceforge.net/trunk/rdesktop/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/rdesktop/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 554 - (hide annotations)
Tue Dec 9 09:57:44 2003 UTC (20 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 22575 byte(s)
Timezone patch by Mark Roach

1 forsberg 351 /* -*- c-basic-offset: 8 -*-
2 matty 3 rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP layer
4 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
5 jsorg71 433
6 matty 3 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.
10 jsorg71 433
11 matty 3 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.
15 jsorg71 433
16 matty 3 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.
19     */
20    
21 stargo 554 #include <time.h>
22 matty 10 #include "rdesktop.h"
23 matty 3
24 jsorg71 381 extern uint16 g_mcs_userid;
25 jsorg71 437 extern char g_username[16];
26     extern BOOL g_bitmap_compression;
27     extern BOOL g_orders;
28     extern BOOL g_encryption;
29 jsorg71 438 extern BOOL g_desktop_save;
30     extern BOOL g_use_rdp5;
31     extern uint16 g_server_rdp_version;
32     extern int g_server_bpp;
33 stargo 554 extern time_t timezone;
34 matty 3
35 jsorg71 438 uint8 *g_next_packet;
36     uint32 g_rdp_shareid;
37 matty 3
38 forsberg 340 #if WITH_DEBUG
39 jsorg71 438 static uint32 g_packetno;
40 forsberg 351 #endif
41 forsberg 340
42 matty 10 /* Receive an RDP packet */
43 matty 25 static STREAM
44 astrand 64 rdp_recv(uint8 * type)
45 matty 3 {
46 matty 10 static STREAM rdp_s;
47     uint16 length, pdu_type;
48 matty 3
49 jsorg71 438 if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
50 matty 10 {
51     rdp_s = sec_recv();
52     if (rdp_s == NULL)
53     return NULL;
54 matty 3
55 jsorg71 438 g_next_packet = rdp_s->p;
56 matty 10 }
57     else
58 matty 7 {
59 jsorg71 438 rdp_s->p = g_next_packet;
60 matty 7 }
61    
62 matty 10 in_uint16_le(rdp_s, length);
63 jsorg71 283 /* 32k packets are really 8, keepalive fix */
64     if (length == 0x8000)
65     {
66 jsorg71 438 g_next_packet += 8;
67 jsorg71 283 *type = 0;
68     return rdp_s;
69     }
70 matty 10 in_uint16_le(rdp_s, pdu_type);
71 matty 24 in_uint8s(rdp_s, 2); /* userid */
72 matty 10 *type = pdu_type & 0xf;
73 matty 7
74 matty 30 #if WITH_DEBUG
75 jsorg71 438 DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
76 matthewc 513 hexdump(g_next_packet, length);
77 matty 28 #endif /* */
78 matty 7
79 jsorg71 438 g_next_packet += length;
80 matty 10 return rdp_s;
81 matty 3 }
82    
83 matty 10 /* Initialise an RDP data packet */
84 matty 25 static STREAM
85     rdp_init_data(int maxlen)
86 matty 3 {
87 matty 10 STREAM s;
88 matty 3
89 jsorg71 437 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
90 matty 10 s_push_layer(s, rdp_hdr, 18);
91    
92     return s;
93 matty 3 }
94    
95 matty 10 /* Send an RDP data packet */
96 matty 25 static void
97     rdp_send_data(STREAM s, uint8 data_pdu_type)
98 matty 9 {
99 matty 10 uint16 length;
100 matty 9
101 matty 10 s_pop_layer(s, rdp_hdr);
102     length = s->end - s->p;
103 matty 9
104 matty 10 out_uint16_le(s, length);
105     out_uint16_le(s, (RDP_PDU_DATA | 0x10));
106 jsorg71 381 out_uint16_le(s, (g_mcs_userid + 1001));
107 matty 9
108 jsorg71 438 out_uint32_le(s, g_rdp_shareid);
109 matty 24 out_uint8(s, 0); /* pad */
110     out_uint8(s, 1); /* streamid */
111 n-ki 176 out_uint16_le(s, (length - 14));
112 matty 10 out_uint8(s, data_pdu_type);
113 matty 24 out_uint8(s, 0); /* compress_type */
114     out_uint16(s, 0); /* compress_len */
115 matty 3
116 jsorg71 437 sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
117 matty 3 }
118    
119 matty 10 /* Output a string in Unicode */
120 matty 25 void
121     rdp_out_unistr(STREAM s, char *string, int len)
122 matty 3 {
123 matty 10 int i = 0, j = 0;
124 matty 9
125 matty 10 len += 2;
126 matty 9
127 matty 10 while (i < len)
128 matty 9 {
129 matty 10 s->p[i++] = string[j++];
130     s->p[i++] = 0;
131 matty 9 }
132    
133 matty 10 s->p += len;
134 matty 3 }
135    
136 matty 10 /* Parse a logon info packet */
137 matty 25 static void
138     rdp_send_logon_info(uint32 flags, char *domain, char *user,
139     char *password, char *program, char *directory)
140 matty 3 {
141 matty 24 int len_domain = 2 * strlen(domain);
142     int len_user = 2 * strlen(user);
143     int len_password = 2 * strlen(password);
144     int len_program = 2 * strlen(program);
145 matty 10 int len_directory = 2 * strlen(directory);
146 forsberg 371 int len_ip = 2 * strlen("127.0.0.1");
147     int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
148     int packetlen = 0;
149 jsorg71 437 uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
150 matty 10 STREAM s;
151 stargo 554 tzset();
152 matty 3
153 jsorg71 438 if (!g_use_rdp5 || 1 == g_server_rdp_version)
154 forsberg 351 {
155     DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
156 matty 3
157 forsberg 351 s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
158     + len_program + len_directory + 10);
159 matty 3
160 forsberg 351 out_uint32(s, 0);
161     out_uint32_le(s, flags);
162     out_uint16_le(s, len_domain);
163     out_uint16_le(s, len_user);
164     out_uint16_le(s, len_password);
165     out_uint16_le(s, len_program);
166     out_uint16_le(s, len_directory);
167     rdp_out_unistr(s, domain, len_domain);
168     rdp_out_unistr(s, user, len_user);
169     rdp_out_unistr(s, password, len_password);
170     rdp_out_unistr(s, program, len_program);
171     rdp_out_unistr(s, directory, len_directory);
172     }
173     else
174     {
175 forsberg 371 flags |= RDP_LOGON_BLOB;
176 forsberg 351 DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
177 astrand 540 packetlen = 4 + /* Unknown uint32 */
178     4 + /* flags */
179     2 + /* len_domain */
180     2 + /* len_user */
181     (flags & RDP_LOGON_AUTO ? 2 : 0) + /* len_password */
182     (flags & RDP_LOGON_BLOB ? 2 : 0) + /* Length of BLOB */
183     2 + /* len_program */
184     2 + /* len_directory */
185     (0 < len_domain ? len_domain : 2) + /* domain */
186     len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */
187     (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
188     (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */
189     2 + /* Client ip length */
190     len_ip + /* Client ip */
191     2 + /* DLL string length */
192     len_dll + /* DLL string */
193     2 + /* Unknown */
194     2 + /* Unknown */
195     64 + /* Time zone #0 */
196     2 + /* Unknown */
197     64 + /* Time zone #1 */
198     32; /* Unknown */
199 forsberg 410
200     s = sec_init(sec_flags, packetlen);
201 forsberg 371 DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
202 forsberg 351
203 astrand 540 out_uint32(s, 0); /* Unknown */
204 forsberg 351 out_uint32_le(s, flags);
205     out_uint16_le(s, len_domain);
206     out_uint16_le(s, len_user);
207     if (flags & RDP_LOGON_AUTO)
208     {
209     out_uint16_le(s, len_password);
210 forsberg 371
211 forsberg 351 }
212 forsberg 410 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
213     {
214 forsberg 371 out_uint16_le(s, 0);
215     }
216 forsberg 351 out_uint16_le(s, len_program);
217     out_uint16_le(s, len_directory);
218 forsberg 371 if (0 < len_domain)
219     rdp_out_unistr(s, domain, len_domain);
220 forsberg 410 else
221 forsberg 371 out_uint16_le(s, 0);
222     rdp_out_unistr(s, user, len_user);
223 forsberg 351 if (flags & RDP_LOGON_AUTO)
224     {
225     rdp_out_unistr(s, password, len_password);
226     }
227 forsberg 410 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
228     {
229 forsberg 371 out_uint16_le(s, 0);
230     }
231 forsberg 410 if (0 < len_program)
232     {
233 forsberg 351 rdp_out_unistr(s, program, len_program);
234 forsberg 410
235     }
236     else
237     {
238 forsberg 371 out_uint16_le(s, 0);
239     }
240 forsberg 410 if (0 < len_directory)
241     {
242 forsberg 351 rdp_out_unistr(s, directory, len_directory);
243 forsberg 410 }
244     else
245     {
246 forsberg 371 out_uint16_le(s, 0);
247 jsorg71 376 }
248 forsberg 371 out_uint16_le(s, 2);
249 astrand 540 out_uint16_le(s, len_ip + 2); /* Length of client ip */
250 forsberg 371 rdp_out_unistr(s, "127.0.0.1", len_ip);
251 forsberg 410 out_uint16_le(s, len_dll + 2);
252 forsberg 371 rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
253 stargo 554 out_uint16_le(s, timezone/60);
254     out_uint16_le(s, 0x0000);
255 forsberg 410 rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
256     out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
257 forsberg 351
258 forsberg 410
259 forsberg 351 out_uint32_le(s, 0x0a0000);
260     out_uint32_le(s, 0x050000);
261 forsberg 371 out_uint32_le(s, 3);
262     out_uint32_le(s, 0);
263     out_uint32_le(s, 0);
264 forsberg 351
265 forsberg 410 rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
266     out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
267    
268 forsberg 371 out_uint32_le(s, 0x30000);
269 forsberg 351 out_uint32_le(s, 0x050000);
270     out_uint32_le(s, 2);
271 matthewc 365 out_uint32(s, 0);
272 forsberg 351 out_uint32_le(s, 0xffffffc4);
273     out_uint32_le(s, 0xfffffffe);
274     out_uint32_le(s, 0x0f);
275 matthewc 365 out_uint32(s, 0);
276 forsberg 351
277 forsberg 371
278 forsberg 351 }
279 matty 10 s_mark_end(s);
280     sec_send(s, sec_flags);
281 matty 3 }
282    
283 matty 10 /* Send a control PDU */
284 matty 25 static void
285     rdp_send_control(uint16 action)
286 matty 3 {
287 matty 10 STREAM s;
288 matty 9
289 matty 10 s = rdp_init_data(8);
290 matty 9
291 matty 10 out_uint16_le(s, action);
292 matty 24 out_uint16(s, 0); /* userid */
293     out_uint32(s, 0); /* control id */
294 matty 9
295 matty 10 s_mark_end(s);
296     rdp_send_data(s, RDP_DATA_PDU_CONTROL);
297 matty 3 }
298    
299 matty 10 /* Send a synchronisation PDU */
300 matty 25 static void
301 matthewc 192 rdp_send_synchronise(void)
302 matty 3 {
303 matty 10 STREAM s;
304 matty 9
305 matty 10 s = rdp_init_data(4);
306 matty 9
307 matty 24 out_uint16_le(s, 1); /* type */
308 matty 10 out_uint16_le(s, 1002);
309 matty 9
310 matty 10 s_mark_end(s);
311     rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
312 matty 3 }
313    
314 matty 10 /* Send a single input event */
315 matty 25 void
316 astrand 82 rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
317 matty 3 {
318 matty 10 STREAM s;
319 matty 9
320 matty 10 s = rdp_init_data(16);
321 matty 9
322 matty 24 out_uint16_le(s, 1); /* number of events */
323     out_uint16(s, 0); /* pad */
324 matty 9
325 matty 10 out_uint32_le(s, time);
326     out_uint16_le(s, message_type);
327     out_uint16_le(s, device_flags);
328     out_uint16_le(s, param1);
329     out_uint16_le(s, param2);
330 matty 9
331 matty 10 s_mark_end(s);
332     rdp_send_data(s, RDP_DATA_PDU_INPUT);
333 matty 3 }
334    
335 matty 10 /* Send an (empty) font information PDU */
336 matty 25 static void
337     rdp_send_fonts(uint16 seq)
338 matty 3 {
339 matty 10 STREAM s;
340 matty 3
341 matty 10 s = rdp_init_data(8);
342 matty 9
343 matty 10 out_uint16(s, 0); /* number of fonts */
344     out_uint16_le(s, 0x3e); /* unknown */
345     out_uint16_le(s, seq); /* unknown */
346     out_uint16_le(s, 0x32); /* entry size */
347 matty 9
348 matty 10 s_mark_end(s);
349     rdp_send_data(s, RDP_DATA_PDU_FONT2);
350 matty 3 }
351    
352 matty 10 /* Output general capability set */
353 matty 25 static void
354     rdp_out_general_caps(STREAM s)
355 matty 3 {
356 matty 10 out_uint16_le(s, RDP_CAPSET_GENERAL);
357     out_uint16_le(s, RDP_CAPLEN_GENERAL);
358 matty 3
359 matty 10 out_uint16_le(s, 1); /* OS major type */
360     out_uint16_le(s, 3); /* OS minor type */
361 matty 24 out_uint16_le(s, 0x200); /* Protocol version */
362 matty 10 out_uint16(s, 0); /* Pad */
363     out_uint16(s, 0); /* Compression types */
364 jsorg71 438 out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
365 forsberg 351 /* Pad, according to T.128. 0x40d seems to
366     trigger
367     the server to start sending RDP5 packets.
368     However, the value is 0x1d04 with W2KTSK and
369     NT4MS. Hmm.. Anyway, thankyou, Microsoft,
370     for sending such information in a padding
371     field.. */
372 matty 10 out_uint16(s, 0); /* Update capability */
373     out_uint16(s, 0); /* Remote unshare capability */
374     out_uint16(s, 0); /* Compression level */
375     out_uint16(s, 0); /* Pad */
376 matty 3 }
377    
378 matty 10 /* Output bitmap capability set */
379 matty 25 static void
380     rdp_out_bitmap_caps(STREAM s)
381 matty 9 {
382 matty 10 out_uint16_le(s, RDP_CAPSET_BITMAP);
383     out_uint16_le(s, RDP_CAPLEN_BITMAP);
384 matty 9
385 matty 10 out_uint16_le(s, 8); /* Preferred BPP */
386 n-ki 176 out_uint16_le(s, 1); /* Receive 1 BPP */
387     out_uint16_le(s, 1); /* Receive 4 BPP */
388 matty 10 out_uint16_le(s, 1); /* Receive 8 BPP */
389     out_uint16_le(s, 800); /* Desktop width */
390     out_uint16_le(s, 600); /* Desktop height */
391     out_uint16(s, 0); /* Pad */
392     out_uint16(s, 0); /* Allow resize */
393 jsorg71 437 out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
394 matty 10 out_uint16(s, 0); /* Unknown */
395     out_uint16_le(s, 1); /* Unknown */
396     out_uint16(s, 0); /* Pad */
397 matty 9 }
398    
399 matty 10 /* Output order capability set */
400 matty 25 static void
401     rdp_out_order_caps(STREAM s)
402 matty 3 {
403 matty 10 uint8 order_caps[32];
404 matty 3
405 matty 9
406 matty 28 memset(order_caps, 0, 32);
407     order_caps[0] = 1; /* dest blt */
408     order_caps[1] = 1; /* pat blt */
409     order_caps[2] = 1; /* screen blt */
410 matthewc 161 order_caps[3] = 1; /* required for memblt? */
411 matty 28 order_caps[8] = 1; /* line */
412     order_caps[9] = 1; /* line */
413     order_caps[10] = 1; /* rect */
414 jsorg71 438 order_caps[11] = (g_desktop_save == False ? 0 : 1); /* desksave */
415 matty 28 order_caps[13] = 1; /* memblt */
416     order_caps[14] = 1; /* triblt */
417     order_caps[22] = 1; /* polyline */
418     order_caps[27] = 1; /* text2 */
419 matty 10 out_uint16_le(s, RDP_CAPSET_ORDER);
420     out_uint16_le(s, RDP_CAPLEN_ORDER);
421 matty 9
422 matty 10 out_uint8s(s, 20); /* Terminal desc, pad */
423     out_uint16_le(s, 1); /* Cache X granularity */
424     out_uint16_le(s, 20); /* Cache Y granularity */
425     out_uint16(s, 0); /* Pad */
426     out_uint16_le(s, 1); /* Max order level */
427     out_uint16_le(s, 0x147); /* Number of fonts */
428 matty 24 out_uint16_le(s, 0x2a); /* Capability flags */
429 matty 10 out_uint8p(s, order_caps, 32); /* Orders supported */
430     out_uint16_le(s, 0x6a1); /* Text capability flags */
431     out_uint8s(s, 6); /* Pad */
432 jsorg71 438 out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */
433 matty 10 out_uint32(s, 0); /* Unknown */
434 n-ki 176 out_uint32_le(s, 0x4e4); /* Unknown */
435 matty 9 }
436    
437 matty 10 /* Output bitmap cache capability set */
438 matty 25 static void
439     rdp_out_bmpcache_caps(STREAM s)
440 matty 9 {
441 jsorg71 433 int Bpp;
442 matty 10 out_uint16_le(s, RDP_CAPSET_BMPCACHE);
443     out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
444 matty 3
445 jsorg71 438 Bpp = (g_server_bpp + 7) / 8;
446 matty 24 out_uint8s(s, 24); /* unused */
447     out_uint16_le(s, 0x258); /* entries */
448 jsorg71 433 out_uint16_le(s, 0x100 * Bpp); /* max cell size */
449 matty 24 out_uint16_le(s, 0x12c); /* entries */
450 jsorg71 433 out_uint16_le(s, 0x400 * Bpp); /* max cell size */
451 matty 24 out_uint16_le(s, 0x106); /* entries */
452 jsorg71 433 out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
453 matty 9 }
454    
455 matty 10 /* Output control capability set */
456 matty 25 static void
457     rdp_out_control_caps(STREAM s)
458 matty 9 {
459 matty 10 out_uint16_le(s, RDP_CAPSET_CONTROL);
460     out_uint16_le(s, RDP_CAPLEN_CONTROL);
461 matty 9
462 matty 10 out_uint16(s, 0); /* Control capabilities */
463     out_uint16(s, 0); /* Remote detach */
464     out_uint16_le(s, 2); /* Control interest */
465     out_uint16_le(s, 2); /* Detach interest */
466 matty 9 }
467    
468 matty 10 /* Output activation capability set */
469 matty 25 static void
470     rdp_out_activate_caps(STREAM s)
471 matty 9 {
472 matty 10 out_uint16_le(s, RDP_CAPSET_ACTIVATE);
473     out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
474 matty 9
475 matty 10 out_uint16(s, 0); /* Help key */
476     out_uint16(s, 0); /* Help index key */
477     out_uint16(s, 0); /* Extended help key */
478     out_uint16(s, 0); /* Window activate */
479 matty 9 }
480    
481 matty 10 /* Output pointer capability set */
482 matty 25 static void
483     rdp_out_pointer_caps(STREAM s)
484 matty 9 {
485 matty 10 out_uint16_le(s, RDP_CAPSET_POINTER);
486     out_uint16_le(s, RDP_CAPLEN_POINTER);
487 matty 9
488 matty 10 out_uint16(s, 0); /* Colour pointer */
489     out_uint16_le(s, 20); /* Cache size */
490 matty 9 }
491    
492 matty 10 /* Output share capability set */
493 matty 25 static void
494     rdp_out_share_caps(STREAM s)
495 matty 3 {
496 matty 10 out_uint16_le(s, RDP_CAPSET_SHARE);
497     out_uint16_le(s, RDP_CAPLEN_SHARE);
498 matty 3
499 matty 10 out_uint16(s, 0); /* userid */
500     out_uint16(s, 0); /* pad */
501 matty 9 }
502 matty 3
503 matty 10 /* Output colour cache capability set */
504 matty 25 static void
505     rdp_out_colcache_caps(STREAM s)
506 matty 9 {
507 matty 10 out_uint16_le(s, RDP_CAPSET_COLCACHE);
508     out_uint16_le(s, RDP_CAPLEN_COLCACHE);
509 matty 3
510 matty 10 out_uint16_le(s, 6); /* cache size */
511     out_uint16(s, 0); /* pad */
512 matty 3 }
513    
514 matty 10 static uint8 canned_caps[] = {
515 matty 24 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
516     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
517 matty 25 0x00, 0x00, 0x00, 0x00, 0x00,
518 matty 24 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 matty 25 0x00, 0x00, 0x00, 0x00, 0x00,
520 matty 24 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 matty 25 0x00, 0x00, 0x00, 0x00, 0x00,
522 matty 24 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 matty 25 0x00, 0x00, 0x00, 0x00, 0x00,
524 matty 24 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 matty 25 0x0C, 0x00, 0x08, 0x00, 0x01,
526 matty 24 0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
527 matty 25 0x10, 0x00, 0x34, 0x00, 0xFE,
528 matty 24 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
529 matty 25 0xFE, 0x00, 0x08, 0x00, 0xFE,
530 matty 24 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
531 matty 25 0xFE, 0x00, 0x80, 0x00, 0xFE,
532 matty 24 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
533 matty 25 0x02, 0x00, 0x00, 0x00
534 matty 10 };
535 matty 3
536 forsberg 351 /* Output unknown capability sets (number 13, 12, 14 and 16) */
537 matty 25 static void
538     rdp_out_unknown_caps(STREAM s)
539 matty 3 {
540 matty 10 out_uint16_le(s, RDP_CAPSET_UNKNOWN);
541     out_uint16_le(s, 0x58);
542 matty 24
543     out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
544 matty 3 }
545    
546 forsberg 351 #define RDP5_FLAG 0x0030
547 matty 10 /* Send a confirm active PDU */
548 matty 25 static void
549 matthewc 192 rdp_send_confirm_active(void)
550 matty 7 {
551 matty 10 STREAM s;
552 jsorg71 437 uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
553 matty 24 uint16 caplen =
554     RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
555     RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
556     RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
557 astrand 82 RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
558 matty 7
559 forsberg 351 s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
560 matty 9
561 forsberg 351 out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
562     out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
563 jsorg71 381 out_uint16_le(s, (g_mcs_userid + 1001));
564 forsberg 351
565 jsorg71 438 out_uint32_le(s, g_rdp_shareid);
566 matty 24 out_uint16_le(s, 0x3ea); /* userid */
567 matty 10 out_uint16_le(s, sizeof(RDP_SOURCE));
568     out_uint16_le(s, caplen);
569 matty 9
570 matty 10 out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
571 matty 24 out_uint16_le(s, 0xd); /* num_caps */
572     out_uint8s(s, 2); /* pad */
573 matty 9
574 matty 10 rdp_out_general_caps(s);
575     rdp_out_bitmap_caps(s);
576     rdp_out_order_caps(s);
577     rdp_out_bmpcache_caps(s);
578     rdp_out_colcache_caps(s);
579     rdp_out_activate_caps(s);
580     rdp_out_control_caps(s);
581     rdp_out_pointer_caps(s);
582     rdp_out_share_caps(s);
583     rdp_out_unknown_caps(s);
584 matty 9
585 matty 10 s_mark_end(s);
586 forsberg 351 sec_send(s, sec_flags);
587 matty 9 }
588    
589 matty 10 /* Respond to a demand active PDU */
590 matty 25 static void
591     process_demand_active(STREAM s)
592 matty 9 {
593 matty 10 uint8 type;
594 matty 9
595 jsorg71 438 in_uint32_le(s, g_rdp_shareid);
596 matty 9
597 jsorg71 438 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
598 matty 9
599 matty 10 rdp_send_confirm_active();
600     rdp_send_synchronise();
601     rdp_send_control(RDP_CTL_COOPERATE);
602     rdp_send_control(RDP_CTL_REQUEST_CONTROL);
603 matty 28 rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
604     rdp_recv(&type); /* RDP_CTL_COOPERATE */
605     rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
606 astrand 543 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
607 matty 10 rdp_send_fonts(1);
608     rdp_send_fonts(2);
609 matty 28 rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 */
610 matty 10 reset_order_state();
611 matty 9 }
612    
613 forsberg 351 /* Process a colour pointer PDU */
614     void
615     process_colour_pointer_pdu(STREAM s)
616     {
617     uint16 x, y, width, height, cache_idx, masklen, datalen;
618     uint8 *mask, *data;
619     HCURSOR cursor;
620    
621     in_uint16_le(s, cache_idx);
622     in_uint16_le(s, x);
623     in_uint16_le(s, y);
624     in_uint16_le(s, width);
625     in_uint16_le(s, height);
626     in_uint16_le(s, masklen);
627     in_uint16_le(s, datalen);
628     in_uint8p(s, data, datalen);
629     in_uint8p(s, mask, masklen);
630     cursor = ui_create_cursor(x, y, width, height, mask, data);
631     ui_set_cursor(cursor);
632     cache_put_cursor(cache_idx, cursor);
633     }
634    
635     /* Process a cached pointer PDU */
636     void
637     process_cached_pointer_pdu(STREAM s)
638     {
639     uint16 cache_idx;
640    
641     in_uint16_le(s, cache_idx);
642     ui_set_cursor(cache_get_cursor(cache_idx));
643     }
644    
645 astrand 508 /* Process a system pointer PDU */
646     void
647     process_system_pointer_pdu(STREAM s)
648     {
649     uint16 system_pointer_type;
650 forsberg 351
651 astrand 508 in_uint16(s, system_pointer_type);
652     switch (system_pointer_type)
653     {
654     case RDP_NULL_POINTER:
655     ui_set_null_cursor();
656     break;
657    
658     default:
659     unimpl("System pointer message 0x%x\n", system_pointer_type);
660     }
661     }
662    
663 matty 10 /* Process a pointer PDU */
664 matty 25 static void
665     process_pointer_pdu(STREAM s)
666 matty 9 {
667 matty 10 uint16 message_type;
668 forsberg 351 uint16 x, y;
669 matty 9
670 matty 10 in_uint16_le(s, message_type);
671 matty 24 in_uint8s(s, 2); /* pad */
672 matty 9
673 matty 10 switch (message_type)
674 matty 7 {
675 matty 10 case RDP_POINTER_MOVE:
676     in_uint16_le(s, x);
677     in_uint16_le(s, y);
678     if (s_check(s))
679     ui_move_pointer(x, y);
680     break;
681 matty 9
682 matty 28 case RDP_POINTER_COLOR:
683 forsberg 351 process_colour_pointer_pdu(s);
684 matty 28 break;
685    
686     case RDP_POINTER_CACHED:
687 forsberg 351 process_cached_pointer_pdu(s);
688 matty 28 break;
689    
690 astrand 508 case RDP_POINTER_SYSTEM:
691     process_system_pointer_pdu(s);
692     break;
693    
694 matty 10 default:
695 astrand 508 unimpl("Pointer message 0x%x\n", message_type);
696 matty 7 }
697 matty 9 }
698    
699 matty 10 /* Process bitmap updates */
700 forsberg 351 void
701 matty 25 process_bitmap_updates(STREAM s)
702 matty 9 {
703 matty 10 uint16 num_updates;
704     uint16 left, top, right, bottom, width, height;
705 jsorg71 314 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
706 matty 28 uint8 *data, *bmpdata;
707 matty 9 int i;
708    
709 matty 10 in_uint16_le(s, num_updates);
710 matty 9
711 matty 10 for (i = 0; i < num_updates; i++)
712 matty 9 {
713 matty 10 in_uint16_le(s, left);
714     in_uint16_le(s, top);
715     in_uint16_le(s, right);
716     in_uint16_le(s, bottom);
717     in_uint16_le(s, width);
718     in_uint16_le(s, height);
719     in_uint16_le(s, bpp);
720 jsorg71 314 Bpp = (bpp + 7) / 8;
721 matty 10 in_uint16_le(s, compress);
722     in_uint16_le(s, bufsize);
723 matty 9
724 matty 10 cx = right - left + 1;
725     cy = bottom - top + 1;
726 matty 7
727 forsberg 351 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
728     left, top, right, bottom, width, height, Bpp, compress));
729 matty 9
730 matthewc 518 /* Server may limit bpp - this is how we find out */
731 astrand 532 if (g_server_bpp != bpp)
732     {
733 matthewc 518 warning("Server limited colour depth to %d bits\n", bpp);
734     g_server_bpp = bpp;
735     }
736    
737 matty 10 if (!compress)
738     {
739 matty 28 int y;
740 forsberg 410 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
741 matty 28 for (y = 0; y < height; y++)
742     {
743 astrand 318 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
744     width * Bpp);
745 matty 28 }
746 astrand 82 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
747 matty 28 xfree(bmpdata);
748     continue;
749 matty 10 }
750 matty 9
751 forsberg 351
752     if (compress & 0x400)
753     {
754     size = bufsize;
755     }
756     else
757     {
758     in_uint8s(s, 2); /* pad */
759     in_uint16_le(s, size);
760     in_uint8s(s, 4); /* line_size, final_size */
761     }
762 matty 10 in_uint8p(s, data, size);
763 forsberg 410 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
764 jsorg71 314 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
765 matty 9 {
766 astrand 82 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
767 matty 9 }
768 forsberg 351 else
769     {
770     DEBUG_RDP5(("Failed to decompress data\n"));
771     }
772    
773 matty 28 xfree(bmpdata);
774 matty 10 }
775 matty 9 }
776    
777 matty 10 /* Process a palette update */
778 forsberg 351 void
779 matty 25 process_palette(STREAM s)
780 matty 9 {
781 matthewc 254 COLOURENTRY *entry;
782     COLOURMAP map;
783 matty 10 HCOLOURMAP hmap;
784 matthewc 254 int i;
785 matty 9
786 matty 24 in_uint8s(s, 2); /* pad */
787     in_uint16_le(s, map.ncolours);
788     in_uint8s(s, 2); /* pad */
789 matty 3
790 jsorg71 436 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
791 matthewc 254
792 forsberg 351 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
793    
794 matthewc 254 for (i = 0; i < map.ncolours; i++)
795     {
796     entry = &map.colours[i];
797     in_uint8(s, entry->red);
798     in_uint8(s, entry->green);
799     in_uint8(s, entry->blue);
800 astrand 260 }
801 matthewc 254
802 matty 10 hmap = ui_create_colourmap(&map);
803     ui_set_colourmap(hmap);
804 matthewc 254
805     xfree(map.colours);
806 matty 3 }
807    
808 matty 10 /* Process an update PDU */
809 matty 25 static void
810     process_update_pdu(STREAM s)
811 matty 9 {
812 forsberg 351 uint16 update_type, count;
813 matty 9
814 matty 10 in_uint16_le(s, update_type);
815 matty 3
816 matty 10 switch (update_type)
817 matty 3 {
818 matty 10 case RDP_UPDATE_ORDERS:
819 forsberg 351 in_uint8s(s, 2); /* pad */
820     in_uint16_le(s, count);
821     in_uint8s(s, 2); /* pad */
822     process_orders(s, count);
823 matty 10 break;
824 matty 3
825 matty 10 case RDP_UPDATE_BITMAP:
826     process_bitmap_updates(s);
827     break;
828 matty 3
829 matty 10 case RDP_UPDATE_PALETTE:
830     process_palette(s);
831     break;
832 matty 3
833 matty 10 case RDP_UPDATE_SYNCHRONIZE:
834     break;
835 matty 9
836 matty 10 default:
837 matty 30 unimpl("update %d\n", update_type);
838 matty 3 }
839    
840     }
841    
842 matty 10 /* Process data PDU */
843 matty 25 static void
844     process_data_pdu(STREAM s)
845 matty 9 {
846 matty 10 uint8 data_pdu_type;
847 matty 9
848 matty 24 in_uint8s(s, 8); /* shareid, pad, streamid, length */
849 matty 10 in_uint8(s, data_pdu_type);
850 matty 24 in_uint8s(s, 3); /* compress_type, compress_len */
851 matty 3
852 matty 10 switch (data_pdu_type)
853 matty 3 {
854 matty 10 case RDP_DATA_PDU_UPDATE:
855     process_update_pdu(s);
856     break;
857 matty 3
858 matty 10 case RDP_DATA_PDU_POINTER:
859     process_pointer_pdu(s);
860     break;
861 matty 3
862 matty 10 case RDP_DATA_PDU_BELL:
863     ui_bell();
864     break;
865 matty 3
866 matty 10 case RDP_DATA_PDU_LOGON:
867 forsberg 351 DEBUG(("Received Logon PDU\n"));
868 matty 10 /* User logged on */
869     break;
870 matty 3
871 matthewc 522 case RDP_DATA_PDU_DISCONNECT:
872     /* Normally received when user logs out or disconnects from a
873     console session on Windows XP and 2003 Server */
874     DEBUG(("Received disconnect PDU\n"));
875     break;
876    
877 matty 10 default:
878 matty 30 unimpl("data PDU %d\n", data_pdu_type);
879 matty 3 }
880     }
881    
882 matty 10 /* Process incoming packets */
883 forsberg 424 BOOL
884 matthewc 192 rdp_main_loop(void)
885 matty 9 {
886 matty 10 uint8 type;
887     STREAM s;
888 matty 9
889 matty 10 while ((s = rdp_recv(&type)) != NULL)
890 matty 3 {
891 matty 10 switch (type)
892     {
893     case RDP_PDU_DEMAND_ACTIVE:
894     process_demand_active(s);
895     break;
896 matty 3
897 matty 10 case RDP_PDU_DEACTIVATE:
898 forsberg 424 DEBUG(("RDP_PDU_DEACTIVATE\n"));
899 forsberg 426 /* We thought we could detect a clean
900     shutdown of the session by this
901     packet, but it seems Windows 2003
902     is sending us one of these when we
903     reconnect to a disconnected session
904     return True; */
905 matty 10 break;
906 matty 3
907 matty 10 case RDP_PDU_DATA:
908     process_data_pdu(s);
909     break;
910 matty 3
911 jsorg71 283 case 0:
912     break;
913    
914 matty 10 default:
915 matty 30 unimpl("PDU %d\n", type);
916 matty 10 }
917 matty 3 }
918 forsberg 426 return True;
919     /* We want to detect if we got a clean shutdown, but we
920 astrand 435 can't. Se above.
921     return False; */
922 matty 3 }
923    
924 matty 10 /* Establish a connection up to the RDP layer */
925 matty 25 BOOL
926     rdp_connect(char *server, uint32 flags, char *domain, char *password,
927     char *command, char *directory)
928 matty 9 {
929 jsorg71 437 if (!sec_connect(server, g_username))
930 matty 3 return False;
931    
932 jsorg71 437 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
933 matty 10 return True;
934 matty 3 }
935    
936 matty 10 /* Disconnect from the RDP layer */
937 matty 25 void
938 matthewc 192 rdp_disconnect(void)
939 matty 9 {
940 matty 10 sec_disconnect();
941 matty 9 }

  ViewVC Help
Powered by ViewVC 1.1.26