/[rdesktop]/jpeg/rdesktop/trunk/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

Contents of /jpeg/rdesktop/trunk/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 857 - (show annotations)
Sun Mar 13 13:36:04 2005 UTC (19 years, 2 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdp.c
File MIME type: text/plain
File size: 30408 byte(s)
configure test for HAVE_ICONV_H, HAVE_LOCALE_H and HAVE_LANGINFO_H
still no test for HAVE_ICONV

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman 1999-2005
5
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.
10
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.
15
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.
19 */
20
21 #include <time.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include "rdesktop.h"
25
26 #ifdef HAVE_ICONV
27 #ifdef HAVE_ICONV_H
28 #include <iconv.h>
29 #endif
30 #endif
31
32 extern uint16 g_mcs_userid;
33 extern char g_username[64];
34 extern char g_codepage[16];
35 extern BOOL g_bitmap_compression;
36 extern BOOL g_orders;
37 extern BOOL g_encryption;
38 extern BOOL g_desktop_save;
39 extern BOOL g_polygon_ellipse_orders;
40 extern BOOL g_use_rdp5;
41 extern uint16 g_server_rdp_version;
42 extern uint32 g_rdp5_performanceflags;
43 extern int g_server_bpp;
44 extern int g_width;
45 extern int g_height;
46 extern BOOL g_bitmap_cache;
47 extern BOOL g_bitmap_cache_persist_enable;
48
49 uint8 *g_next_packet;
50 uint32 g_rdp_shareid;
51
52 extern RDPCOMP g_mppc_dict;
53
54 #if WITH_DEBUG
55 static uint32 g_packetno;
56 #endif
57
58 /* Receive an RDP packet */
59 static STREAM
60 rdp_recv(uint8 * type)
61 {
62 static STREAM rdp_s;
63 uint16 length, pdu_type;
64 uint8 rdpver;
65
66 if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
67 {
68 rdp_s = sec_recv(&rdpver);
69 if (rdp_s == NULL)
70 return NULL;
71 if (rdpver == 0xff)
72 {
73 g_next_packet = rdp_s->end;
74 *type = 0;
75 return rdp_s;
76 }
77 else if (rdpver != 3)
78 {
79 /* rdp5_process should move g_next_packet ok */
80 rdp5_process(rdp_s);
81 *type = 0;
82 return rdp_s;
83 }
84
85 g_next_packet = rdp_s->p;
86 }
87 else
88 {
89 rdp_s->p = g_next_packet;
90 }
91
92 in_uint16_le(rdp_s, length);
93 /* 32k packets are really 8, keepalive fix */
94 if (length == 0x8000)
95 {
96 g_next_packet += 8;
97 *type = 0;
98 return rdp_s;
99 }
100 in_uint16_le(rdp_s, pdu_type);
101 in_uint8s(rdp_s, 2); /* userid */
102 *type = pdu_type & 0xf;
103
104 #if WITH_DEBUG
105 DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
106 hexdump(g_next_packet, length);
107 #endif /* */
108
109 g_next_packet += length;
110 return rdp_s;
111 }
112
113 /* Initialise an RDP data packet */
114 static STREAM
115 rdp_init_data(int maxlen)
116 {
117 STREAM s;
118
119 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
120 s_push_layer(s, rdp_hdr, 18);
121
122 return s;
123 }
124
125 /* Send an RDP data packet */
126 static void
127 rdp_send_data(STREAM s, uint8 data_pdu_type)
128 {
129 uint16 length;
130
131 s_pop_layer(s, rdp_hdr);
132 length = s->end - s->p;
133
134 out_uint16_le(s, length);
135 out_uint16_le(s, (RDP_PDU_DATA | 0x10));
136 out_uint16_le(s, (g_mcs_userid + 1001));
137
138 out_uint32_le(s, g_rdp_shareid);
139 out_uint8(s, 0); /* pad */
140 out_uint8(s, 1); /* streamid */
141 out_uint16_le(s, (length - 14));
142 out_uint8(s, data_pdu_type);
143 out_uint8(s, 0); /* compress_type */
144 out_uint16(s, 0); /* compress_len */
145
146 sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
147 }
148
149 /* Output a string in Unicode */
150 void
151 rdp_out_unistr(STREAM s, char *string, int len)
152 {
153 #ifdef HAVE_ICONV
154 size_t ibl = strlen(string), obl = len + 2;
155 static iconv_t iconv_h = (iconv_t)-1;
156 char *pin = string, *pout;
157 #ifdef B_ENDIAN
158 char ss[4096]; // FIXME: global MAX_BUF_SIZE macro need
159
160 pout = ss;
161 #else
162 pout = s->p;
163 #endif
164
165 memset(pout, 0, len + 4);
166
167 if (iconv_h == (iconv_t)-1)
168 {
169 size_t i = 1, o = 4;
170 if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t)-1)
171 {
172 printf("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
173 g_codepage, WINDOWS_CODEPAGE, (int)iconv_h);
174 return;
175 }
176 if (iconv(iconv_h, (const char**)&pin, &i, &pout, &o) == (size_t)-1)
177 {
178 iconv_close(iconv_h);
179 iconv_h = (iconv_t)-1;
180 printf("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
181 return;
182 }
183 pin = string; pout = s->p;
184 }
185
186 if (iconv(iconv_h, (const char**)&pin, &ibl, &pout, &obl) == (size_t)-1)
187 {
188 iconv_close(iconv_h);
189 iconv_h = (iconv_t)-1;
190 printf("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
191 return;
192 }
193
194 #ifdef B_ENDIAN
195 swab(ss, s->p, len + 4);
196 #endif
197
198 s->p += len + 2;
199
200 #else /*HAVE_ICONV undef*/
201 int i = 0, j = 0;
202
203 len += 2;
204
205 while (i < len)
206 {
207 s->p[i++] = string[j++];
208 s->p[i++] = 0;
209 }
210
211 s->p += len;
212 #endif
213 }
214
215 /* Input a string in Unicode
216 *
217 * Returns str_len of string
218 */
219 int
220 rdp_in_unistr(STREAM s, char *string, int uni_len)
221 {
222 #ifdef HAVE_ICONV
223 size_t ibl = uni_len, obl = uni_len;
224 char *pin, *pout = string;
225 static iconv_t iconv_h = (iconv_t)-1;
226 #ifdef B_ENDIAN
227 char ss[4096]; // FIXME: global MAX_BUF_SIZE macro need
228
229 swab(s->p, ss, uni_len);
230 pin = ss;
231 #else
232 pin = s->p;
233 #endif
234
235 if (iconv_h == (iconv_t)-1)
236 {
237 if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t)-1)
238 {
239 printf("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
240 WINDOWS_CODEPAGE, g_codepage, (int)iconv_h);
241 return 0;
242 }
243 }
244
245 if (iconv(iconv_h, (const char**)&pin, &ibl, &pout, &obl) == (size_t)-1)
246 {
247 iconv_close(iconv_h);
248 iconv_h = (iconv_t)-1;
249 printf("rdp_in_unistr: iconv fail, errno %d\n", errno);
250 return 0;
251 }
252 return pout - string;
253 #else /* HAVE_ICONV undef */
254 int i = 0;
255
256 while (i < uni_len / 2)
257 {
258 in_uint8a(s, &string[i++], 1);
259 in_uint8s(s, 1);
260 }
261
262 return i - 1;
263 #endif
264 }
265
266
267 /* Parse a logon info packet */
268 static void
269 rdp_send_logon_info(uint32 flags, char *domain, char *user,
270 char *password, char *program, char *directory)
271 {
272 char *ipaddr = tcp_get_address();
273 int len_domain = 2 * strlen(domain);
274 int len_user = 2 * strlen(user);
275 int len_password = 2 * strlen(password);
276 int len_program = 2 * strlen(program);
277 int len_directory = 2 * strlen(directory);
278 int len_ip = 2 * strlen(ipaddr);
279 int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
280 int packetlen = 0;
281 uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
282 STREAM s;
283 time_t t = time(NULL);
284 time_t tzone;
285
286 #if 0
287 /* enable rdp compression */
288 /* some problems still exist with rdp5 */
289 flags |= RDP_COMPRESSION;
290 #endif
291
292 if (!g_use_rdp5 || 1 == g_server_rdp_version)
293 {
294 DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
295
296 s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
297 + len_program + len_directory + 10);
298
299 out_uint32(s, 0);
300 out_uint32_le(s, flags);
301 out_uint16_le(s, len_domain);
302 out_uint16_le(s, len_user);
303 out_uint16_le(s, len_password);
304 out_uint16_le(s, len_program);
305 out_uint16_le(s, len_directory);
306 rdp_out_unistr(s, domain, len_domain);
307 rdp_out_unistr(s, user, len_user);
308 rdp_out_unistr(s, password, len_password);
309 rdp_out_unistr(s, program, len_program);
310 rdp_out_unistr(s, directory, len_directory);
311 }
312 else
313 {
314
315 flags |= RDP_LOGON_BLOB;
316 DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
317 packetlen = 4 + /* Unknown uint32 */
318 4 + /* flags */
319 2 + /* len_domain */
320 2 + /* len_user */
321 (flags & RDP_LOGON_AUTO ? 2 : 0) + /* len_password */
322 (flags & RDP_LOGON_BLOB ? 2 : 0) + /* Length of BLOB */
323 2 + /* len_program */
324 2 + /* len_directory */
325 (0 < len_domain ? len_domain : 2) + /* domain */
326 len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */
327 (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
328 (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */
329 2 + /* Client ip length */
330 len_ip + /* Client ip */
331 2 + /* DLL string length */
332 len_dll + /* DLL string */
333 2 + /* Unknown */
334 2 + /* Unknown */
335 64 + /* Time zone #0 */
336 2 + /* Unknown */
337 64 + /* Time zone #1 */
338 32; /* Unknown */
339
340 s = sec_init(sec_flags, packetlen);
341 DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
342
343 out_uint32(s, 0); /* Unknown */
344 out_uint32_le(s, flags);
345 out_uint16_le(s, len_domain);
346 out_uint16_le(s, len_user);
347 if (flags & RDP_LOGON_AUTO)
348 {
349 out_uint16_le(s, len_password);
350
351 }
352 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
353 {
354 out_uint16_le(s, 0);
355 }
356 out_uint16_le(s, len_program);
357 out_uint16_le(s, len_directory);
358 if (0 < len_domain)
359 rdp_out_unistr(s, domain, len_domain);
360 else
361 out_uint16_le(s, 0);
362 rdp_out_unistr(s, user, len_user);
363 if (flags & RDP_LOGON_AUTO)
364 {
365 rdp_out_unistr(s, password, len_password);
366 }
367 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
368 {
369 out_uint16_le(s, 0);
370 }
371 if (0 < len_program)
372 {
373 rdp_out_unistr(s, program, len_program);
374
375 }
376 else
377 {
378 out_uint16_le(s, 0);
379 }
380 if (0 < len_directory)
381 {
382 rdp_out_unistr(s, directory, len_directory);
383 }
384 else
385 {
386 out_uint16_le(s, 0);
387 }
388 out_uint16_le(s, 2);
389 out_uint16_le(s, len_ip + 2); /* Length of client ip */
390 rdp_out_unistr(s, ipaddr, len_ip);
391 out_uint16_le(s, len_dll + 2);
392 rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
393
394 tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
395 out_uint32_le(s, tzone);
396
397 rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
398 out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
399
400 out_uint32_le(s, 0x0a0000);
401 out_uint32_le(s, 0x050000);
402 out_uint32_le(s, 3);
403 out_uint32_le(s, 0);
404 out_uint32_le(s, 0);
405
406 rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
407 out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
408
409 out_uint32_le(s, 0x30000);
410 out_uint32_le(s, 0x050000);
411 out_uint32_le(s, 2);
412 out_uint32(s, 0);
413 out_uint32_le(s, 0xffffffc4);
414 out_uint32_le(s, 0xfffffffe);
415 out_uint32_le(s, g_rdp5_performanceflags);
416 out_uint32(s, 0);
417
418
419 }
420 s_mark_end(s);
421 sec_send(s, sec_flags);
422 }
423
424 /* Send a control PDU */
425 static void
426 rdp_send_control(uint16 action)
427 {
428 STREAM s;
429
430 s = rdp_init_data(8);
431
432 out_uint16_le(s, action);
433 out_uint16(s, 0); /* userid */
434 out_uint32(s, 0); /* control id */
435
436 s_mark_end(s);
437 rdp_send_data(s, RDP_DATA_PDU_CONTROL);
438 }
439
440 /* Send a synchronisation PDU */
441 static void
442 rdp_send_synchronise(void)
443 {
444 STREAM s;
445
446 s = rdp_init_data(4);
447
448 out_uint16_le(s, 1); /* type */
449 out_uint16_le(s, 1002);
450
451 s_mark_end(s);
452 rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
453 }
454
455 /* Send a single input event */
456 void
457 rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
458 {
459 STREAM s;
460
461 s = rdp_init_data(16);
462
463 out_uint16_le(s, 1); /* number of events */
464 out_uint16(s, 0); /* pad */
465
466 out_uint32_le(s, time);
467 out_uint16_le(s, message_type);
468 out_uint16_le(s, device_flags);
469 out_uint16_le(s, param1);
470 out_uint16_le(s, param2);
471
472 s_mark_end(s);
473 rdp_send_data(s, RDP_DATA_PDU_INPUT);
474 }
475
476 /* Inform the server on the contents of the persistent bitmap cache */
477 static void
478 rdp_enum_bmpcache2(void)
479 {
480 STREAM s;
481 HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
482 uint32 num_keys, offset, count, flags;
483
484 offset = 0;
485 num_keys = pstcache_enumerate(2, keylist);
486
487 while (offset < num_keys)
488 {
489 count = MIN(num_keys - offset, 169);
490
491 s = rdp_init_data(24 + count * sizeof(HASH_KEY));
492
493 flags = 0;
494 if (offset == 0)
495 flags |= PDU_FLAG_FIRST;
496 if (num_keys - offset <= 169)
497 flags |= PDU_FLAG_LAST;
498
499 /* header */
500 out_uint32_le(s, 0);
501 out_uint16_le(s, count);
502 out_uint16_le(s, 0);
503 out_uint16_le(s, 0);
504 out_uint16_le(s, 0);
505 out_uint16_le(s, 0);
506 out_uint16_le(s, num_keys);
507 out_uint32_le(s, 0);
508 out_uint32_le(s, flags);
509
510 /* list */
511 out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
512
513 s_mark_end(s);
514 rdp_send_data(s, 0x2b);
515
516 offset += 169;
517 }
518 }
519
520 /* Send an (empty) font information PDU */
521 static void
522 rdp_send_fonts(uint16 seq)
523 {
524 STREAM s;
525
526 s = rdp_init_data(8);
527
528 out_uint16(s, 0); /* number of fonts */
529 out_uint16_le(s, 0); /* pad? */
530 out_uint16_le(s, seq); /* unknown */
531 out_uint16_le(s, 0x32); /* entry size */
532
533 s_mark_end(s);
534 rdp_send_data(s, RDP_DATA_PDU_FONT2);
535 }
536
537 /* Output general capability set */
538 static void
539 rdp_out_general_caps(STREAM s)
540 {
541 out_uint16_le(s, RDP_CAPSET_GENERAL);
542 out_uint16_le(s, RDP_CAPLEN_GENERAL);
543
544 out_uint16_le(s, 1); /* OS major type */
545 out_uint16_le(s, 3); /* OS minor type */
546 out_uint16_le(s, 0x200); /* Protocol version */
547 out_uint16(s, 0); /* Pad */
548 out_uint16(s, 0); /* Compression types */
549 out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
550 /* Pad, according to T.128. 0x40d seems to
551 trigger
552 the server to start sending RDP5 packets.
553 However, the value is 0x1d04 with W2KTSK and
554 NT4MS. Hmm.. Anyway, thankyou, Microsoft,
555 for sending such information in a padding
556 field.. */
557 out_uint16(s, 0); /* Update capability */
558 out_uint16(s, 0); /* Remote unshare capability */
559 out_uint16(s, 0); /* Compression level */
560 out_uint16(s, 0); /* Pad */
561 }
562
563 /* Output bitmap capability set */
564 static void
565 rdp_out_bitmap_caps(STREAM s)
566 {
567 out_uint16_le(s, RDP_CAPSET_BITMAP);
568 out_uint16_le(s, RDP_CAPLEN_BITMAP);
569
570 out_uint16_le(s, g_server_bpp); /* Preferred BPP */
571 out_uint16_le(s, 1); /* Receive 1 BPP */
572 out_uint16_le(s, 1); /* Receive 4 BPP */
573 out_uint16_le(s, 1); /* Receive 8 BPP */
574 out_uint16_le(s, 800); /* Desktop width */
575 out_uint16_le(s, 600); /* Desktop height */
576 out_uint16(s, 0); /* Pad */
577 out_uint16(s, 1); /* Allow resize */
578 out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
579 out_uint16(s, 0); /* Unknown */
580 out_uint16_le(s, 1); /* Unknown */
581 out_uint16(s, 0); /* Pad */
582 }
583
584 /* Output order capability set */
585 static void
586 rdp_out_order_caps(STREAM s)
587 {
588 uint8 order_caps[32];
589
590 memset(order_caps, 0, 32);
591 order_caps[0] = 1; /* dest blt */
592 order_caps[1] = 1; /* pat blt */
593 order_caps[2] = 1; /* screen blt */
594 order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */
595 order_caps[4] = 0; /* triblt */
596 order_caps[8] = 1; /* line */
597 order_caps[9] = 1; /* line */
598 order_caps[10] = 1; /* rect */
599 order_caps[11] = (g_desktop_save ? 1 : 0); /* desksave */
600 order_caps[13] = 1; /* memblt */
601 order_caps[14] = 1; /* triblt */
602 order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon */
603 order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon2 */
604 order_caps[22] = 1; /* polyline */
605 order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse */
606 order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse2 */
607 order_caps[27] = 1; /* text2 */
608 out_uint16_le(s, RDP_CAPSET_ORDER);
609 out_uint16_le(s, RDP_CAPLEN_ORDER);
610
611 out_uint8s(s, 20); /* Terminal desc, pad */
612 out_uint16_le(s, 1); /* Cache X granularity */
613 out_uint16_le(s, 20); /* Cache Y granularity */
614 out_uint16(s, 0); /* Pad */
615 out_uint16_le(s, 1); /* Max order level */
616 out_uint16_le(s, 0x147); /* Number of fonts */
617 out_uint16_le(s, 0x2a); /* Capability flags */
618 out_uint8p(s, order_caps, 32); /* Orders supported */
619 out_uint16_le(s, 0x6a1); /* Text capability flags */
620 out_uint8s(s, 6); /* Pad */
621 out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */
622 out_uint32(s, 0); /* Unknown */
623 out_uint32_le(s, 0x4e4); /* Unknown */
624 }
625
626 /* Output bitmap cache capability set */
627 static void
628 rdp_out_bmpcache_caps(STREAM s)
629 {
630 int Bpp;
631 out_uint16_le(s, RDP_CAPSET_BMPCACHE);
632 out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
633
634 Bpp = (g_server_bpp + 7) / 8;
635 out_uint8s(s, 24); /* unused */
636 out_uint16_le(s, 0x258); /* entries */
637 out_uint16_le(s, 0x100 * Bpp); /* max cell size */
638 out_uint16_le(s, 0x12c); /* entries */
639 out_uint16_le(s, 0x400 * Bpp); /* max cell size */
640 out_uint16_le(s, 0x106); /* entries */
641 out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
642 }
643
644 /* Output bitmap cache v2 capability set */
645 static void
646 rdp_out_bmpcache2_caps(STREAM s)
647 {
648 out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
649 out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
650
651 out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0); /* version */
652
653 out_uint16_le(s, 0x0300); /* flags? number of caches? */
654
655 out_uint32_le(s, BMPCACHE2_C0_CELLS);
656 out_uint32_le(s, BMPCACHE2_C1_CELLS);
657 if (pstcache_init(2))
658 {
659 out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
660 }
661 else
662 {
663 out_uint32_le(s, BMPCACHE2_C2_CELLS);
664 }
665 out_uint8s(s, 20); /* other bitmap caches not used */
666 }
667
668 /* Output control capability set */
669 static void
670 rdp_out_control_caps(STREAM s)
671 {
672 out_uint16_le(s, RDP_CAPSET_CONTROL);
673 out_uint16_le(s, RDP_CAPLEN_CONTROL);
674
675 out_uint16(s, 0); /* Control capabilities */
676 out_uint16(s, 0); /* Remote detach */
677 out_uint16_le(s, 2); /* Control interest */
678 out_uint16_le(s, 2); /* Detach interest */
679 }
680
681 /* Output activation capability set */
682 static void
683 rdp_out_activate_caps(STREAM s)
684 {
685 out_uint16_le(s, RDP_CAPSET_ACTIVATE);
686 out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
687
688 out_uint16(s, 0); /* Help key */
689 out_uint16(s, 0); /* Help index key */
690 out_uint16(s, 0); /* Extended help key */
691 out_uint16(s, 0); /* Window activate */
692 }
693
694 /* Output pointer capability set */
695 static void
696 rdp_out_pointer_caps(STREAM s)
697 {
698 out_uint16_le(s, RDP_CAPSET_POINTER);
699 out_uint16_le(s, RDP_CAPLEN_POINTER);
700
701 out_uint16(s, 0); /* Colour pointer */
702 out_uint16_le(s, 20); /* Cache size */
703 }
704
705 /* Output share capability set */
706 static void
707 rdp_out_share_caps(STREAM s)
708 {
709 out_uint16_le(s, RDP_CAPSET_SHARE);
710 out_uint16_le(s, RDP_CAPLEN_SHARE);
711
712 out_uint16(s, 0); /* userid */
713 out_uint16(s, 0); /* pad */
714 }
715
716 /* Output colour cache capability set */
717 static void
718 rdp_out_colcache_caps(STREAM s)
719 {
720 out_uint16_le(s, RDP_CAPSET_COLCACHE);
721 out_uint16_le(s, RDP_CAPLEN_COLCACHE);
722
723 out_uint16_le(s, 6); /* cache size */
724 out_uint16(s, 0); /* pad */
725 }
726
727 static uint8 caps_0x0d[] = {
728 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
729 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738 0x00, 0x00, 0x00, 0x00
739 };
740
741 static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
742
743 static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
744
745 static uint8 caps_0x10[] = {
746 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
747 0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
748 0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
749 0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
750 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
751 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
752 };
753
754 /* Output unknown capability sets */
755 static void
756 rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
757 {
758 out_uint16_le(s, id);
759 out_uint16_le(s, length);
760
761 out_uint8p(s, caps, length - 4);
762 }
763
764 #define RDP5_FLAG 0x0030
765 /* Send a confirm active PDU */
766 static void
767 rdp_send_confirm_active(void)
768 {
769 STREAM s;
770 uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
771 uint16 caplen =
772 RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
773 RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
774 RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
775 RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
776 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
777 4 /* w2k fix, why? */ ;
778
779 s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
780
781 out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
782 out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
783 out_uint16_le(s, (g_mcs_userid + 1001));
784
785 out_uint32_le(s, g_rdp_shareid);
786 out_uint16_le(s, 0x3ea); /* userid */
787 out_uint16_le(s, sizeof(RDP_SOURCE));
788 out_uint16_le(s, caplen);
789
790 out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
791 out_uint16_le(s, 0xd); /* num_caps */
792 out_uint8s(s, 2); /* pad */
793
794 rdp_out_general_caps(s);
795 rdp_out_bitmap_caps(s);
796 rdp_out_order_caps(s);
797 g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
798 rdp_out_colcache_caps(s);
799 rdp_out_activate_caps(s);
800 rdp_out_control_caps(s);
801 rdp_out_pointer_caps(s);
802 rdp_out_share_caps(s);
803
804 rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
805 rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
806 rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
807 rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
808
809 s_mark_end(s);
810 sec_send(s, sec_flags);
811 }
812
813 /* Process a general capability set */
814 static void
815 rdp_process_general_caps(STREAM s)
816 {
817 uint16 pad2octetsB; /* rdp5 flags? */
818
819 in_uint8s(s, 10);
820 in_uint16_le(s, pad2octetsB);
821
822 if (!pad2octetsB)
823 g_use_rdp5 = False;
824 }
825
826 /* Process a bitmap capability set */
827 static void
828 rdp_process_bitmap_caps(STREAM s)
829 {
830 uint16 width, height, bpp;
831
832 in_uint16_le(s, bpp);
833 in_uint8s(s, 6);
834
835 in_uint16_le(s, width);
836 in_uint16_le(s, height);
837
838 DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
839
840 /*
841 * The server may limit bpp and change the size of the desktop (for
842 * example when shadowing another session).
843 */
844 if (g_server_bpp != bpp)
845 {
846 warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
847 g_server_bpp = bpp;
848 }
849 if (g_width != width || g_height != height)
850 {
851 warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
852 width, height);
853 g_width = width;
854 g_height = height;
855 ui_resize_window();
856 }
857 }
858
859 /* Process server capabilities */
860 void
861 rdp_process_server_caps(STREAM s, uint16 length)
862 {
863 int n;
864 uint8 *next, *start;
865 uint16 ncapsets, capset_type, capset_length;
866
867 start = s->p;
868
869 in_uint16_le(s, ncapsets);
870 in_uint8s(s, 2); /* pad */
871
872 for (n = 0; n < ncapsets; n++)
873 {
874 if (s->p > start + length)
875 return;
876
877 in_uint16_le(s, capset_type);
878 in_uint16_le(s, capset_length);
879
880 next = s->p + capset_length - 4;
881
882 switch (capset_type)
883 {
884 case RDP_CAPSET_GENERAL:
885 rdp_process_general_caps(s);
886 break;
887
888 case RDP_CAPSET_BITMAP:
889 rdp_process_bitmap_caps(s);
890 break;
891 }
892
893 s->p = next;
894 }
895 }
896
897 /* Respond to a demand active PDU */
898 static void
899 process_demand_active(STREAM s)
900 {
901 uint8 type;
902 uint16 len_src_descriptor, len_combined_caps;
903
904 in_uint32_le(s, g_rdp_shareid);
905 in_uint16_le(s, len_src_descriptor);
906 in_uint16_le(s, len_combined_caps);
907 in_uint8s(s, len_src_descriptor);
908
909 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
910 rdp_process_server_caps(s, len_combined_caps);
911
912 rdp_send_confirm_active();
913 rdp_send_synchronise();
914 rdp_send_control(RDP_CTL_COOPERATE);
915 rdp_send_control(RDP_CTL_REQUEST_CONTROL);
916 rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
917 rdp_recv(&type); /* RDP_CTL_COOPERATE */
918 rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
919 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
920
921 if (g_use_rdp5)
922 {
923 rdp_enum_bmpcache2();
924 rdp_send_fonts(3);
925 }
926 else
927 {
928 rdp_send_fonts(1);
929 rdp_send_fonts(2);
930 }
931
932 rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
933 reset_order_state();
934 }
935
936 /* Process a colour pointer PDU */
937 void
938 process_colour_pointer_pdu(STREAM s)
939 {
940 uint16 x, y, width, height, cache_idx, masklen, datalen;
941 uint8 *mask, *data;
942 HCURSOR cursor;
943
944 in_uint16_le(s, cache_idx);
945 in_uint16_le(s, x);
946 in_uint16_le(s, y);
947 in_uint16_le(s, width);
948 in_uint16_le(s, height);
949 in_uint16_le(s, masklen);
950 in_uint16_le(s, datalen);
951 in_uint8p(s, data, datalen);
952 in_uint8p(s, mask, masklen);
953 cursor = ui_create_cursor(x, y, width, height, mask, data);
954 ui_set_cursor(cursor);
955 cache_put_cursor(cache_idx, cursor);
956 }
957
958 /* Process a cached pointer PDU */
959 void
960 process_cached_pointer_pdu(STREAM s)
961 {
962 uint16 cache_idx;
963
964 in_uint16_le(s, cache_idx);
965 ui_set_cursor(cache_get_cursor(cache_idx));
966 }
967
968 /* Process a system pointer PDU */
969 void
970 process_system_pointer_pdu(STREAM s)
971 {
972 uint16 system_pointer_type;
973
974 in_uint16(s, system_pointer_type);
975 switch (system_pointer_type)
976 {
977 case RDP_NULL_POINTER:
978 ui_set_null_cursor();
979 break;
980
981 default:
982 unimpl("System pointer message 0x%x\n", system_pointer_type);
983 }
984 }
985
986 /* Process a pointer PDU */
987 static void
988 process_pointer_pdu(STREAM s)
989 {
990 uint16 message_type;
991 uint16 x, y;
992
993 in_uint16_le(s, message_type);
994 in_uint8s(s, 2); /* pad */
995
996 switch (message_type)
997 {
998 case RDP_POINTER_MOVE:
999 in_uint16_le(s, x);
1000 in_uint16_le(s, y);
1001 if (s_check(s))
1002 ui_move_pointer(x, y);
1003 break;
1004
1005 case RDP_POINTER_COLOR:
1006 process_colour_pointer_pdu(s);
1007 break;
1008
1009 case RDP_POINTER_CACHED:
1010 process_cached_pointer_pdu(s);
1011 break;
1012
1013 case RDP_POINTER_SYSTEM:
1014 process_system_pointer_pdu(s);
1015 break;
1016
1017 default:
1018 unimpl("Pointer message 0x%x\n", message_type);
1019 }
1020 }
1021
1022 /* Process bitmap updates */
1023 void
1024 process_bitmap_updates(STREAM s)
1025 {
1026 uint16 num_updates;
1027 uint16 left, top, right, bottom, width, height;
1028 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1029 uint8 *data, *bmpdata;
1030 int i;
1031
1032 in_uint16_le(s, num_updates);
1033
1034 for (i = 0; i < num_updates; i++)
1035 {
1036 in_uint16_le(s, left);
1037 in_uint16_le(s, top);
1038 in_uint16_le(s, right);
1039 in_uint16_le(s, bottom);
1040 in_uint16_le(s, width);
1041 in_uint16_le(s, height);
1042 in_uint16_le(s, bpp);
1043 Bpp = (bpp + 7) / 8;
1044 in_uint16_le(s, compress);
1045 in_uint16_le(s, bufsize);
1046
1047 cx = right - left + 1;
1048 cy = bottom - top + 1;
1049
1050 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1051 left, top, right, bottom, width, height, Bpp, compress));
1052
1053 if (!compress)
1054 {
1055 int y;
1056 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1057 for (y = 0; y < height; y++)
1058 {
1059 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1060 width * Bpp);
1061 }
1062 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1063 xfree(bmpdata);
1064 continue;
1065 }
1066
1067
1068 if (compress & 0x400)
1069 {
1070 size = bufsize;
1071 }
1072 else
1073 {
1074 in_uint8s(s, 2); /* pad */
1075 in_uint16_le(s, size);
1076 in_uint8s(s, 4); /* line_size, final_size */
1077 }
1078 in_uint8p(s, data, size);
1079 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1080 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1081 {
1082 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1083 }
1084 else
1085 {
1086 DEBUG_RDP5(("Failed to decompress data\n"));
1087 }
1088
1089 xfree(bmpdata);
1090 }
1091 }
1092
1093 /* Process a palette update */
1094 void
1095 process_palette(STREAM s)
1096 {
1097 COLOURENTRY *entry;
1098 COLOURMAP map;
1099 HCOLOURMAP hmap;
1100 int i;
1101
1102 in_uint8s(s, 2); /* pad */
1103 in_uint16_le(s, map.ncolours);
1104 in_uint8s(s, 2); /* pad */
1105
1106 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1107
1108 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1109
1110 for (i = 0; i < map.ncolours; i++)
1111 {
1112 entry = &map.colours[i];
1113 in_uint8(s, entry->red);
1114 in_uint8(s, entry->green);
1115 in_uint8(s, entry->blue);
1116 }
1117
1118 hmap = ui_create_colourmap(&map);
1119 ui_set_colourmap(hmap);
1120
1121 xfree(map.colours);
1122 }
1123
1124 /* Process an update PDU */
1125 static void
1126 process_update_pdu(STREAM s)
1127 {
1128 uint16 update_type, count;
1129
1130 in_uint16_le(s, update_type);
1131
1132 ui_begin_update();
1133 switch (update_type)
1134 {
1135 case RDP_UPDATE_ORDERS:
1136 in_uint8s(s, 2); /* pad */
1137 in_uint16_le(s, count);
1138 in_uint8s(s, 2); /* pad */
1139 process_orders(s, count);
1140 break;
1141
1142 case RDP_UPDATE_BITMAP:
1143 process_bitmap_updates(s);
1144 break;
1145
1146 case RDP_UPDATE_PALETTE:
1147 process_palette(s);
1148 break;
1149
1150 case RDP_UPDATE_SYNCHRONIZE:
1151 break;
1152
1153 default:
1154 unimpl("update %d\n", update_type);
1155 }
1156 ui_end_update();
1157 }
1158
1159 /* Process a disconnect PDU */
1160 void
1161 process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1162 {
1163 in_uint32_le(s, *ext_disc_reason);
1164
1165 DEBUG(("Received disconnect PDU\n"));
1166 }
1167
1168 /* Process data PDU */
1169 static BOOL
1170 process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1171 {
1172 uint8 data_pdu_type;
1173 uint8 ctype;
1174 uint16 clen;
1175 uint32 len;
1176
1177 uint32 roff, rlen;
1178
1179 struct stream *ns = &(g_mppc_dict.ns);
1180
1181 in_uint8s(s, 6); /* shareid, pad, streamid */
1182 in_uint16(s, len);
1183 in_uint8(s, data_pdu_type);
1184 in_uint8(s, ctype);
1185 in_uint16(s, clen);
1186 clen -= 18;
1187
1188 if (ctype & RDP_MPPC_COMPRESSED)
1189 {
1190 if (len > RDP_MPPC_DICT_SIZE)
1191 error("error decompressed packet size exceeds max\n");
1192 if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1193 error("error while decompressing packet\n");
1194
1195 //len -= 18;
1196
1197 /* allocate memory and copy the uncompressed data into the temporary stream */
1198 ns->data = (uint8 *) xrealloc(ns->data, rlen);
1199
1200 memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1201
1202 ns->size = rlen;
1203 ns->end = (ns->data + ns->size);
1204 ns->p = ns->data;
1205 ns->rdp_hdr = ns->p;
1206
1207 s = ns;
1208 }
1209
1210 switch (data_pdu_type)
1211 {
1212 case RDP_DATA_PDU_UPDATE:
1213 process_update_pdu(s);
1214 break;
1215
1216 case RDP_DATA_PDU_CONTROL:
1217 DEBUG(("Received Control PDU\n"));
1218 break;
1219
1220 case RDP_DATA_PDU_SYNCHRONISE:
1221 DEBUG(("Received Sync PDU\n"));
1222 break;
1223
1224 case RDP_DATA_PDU_POINTER:
1225 process_pointer_pdu(s);
1226 break;
1227
1228 case RDP_DATA_PDU_BELL:
1229 ui_bell();
1230 break;
1231
1232 case RDP_DATA_PDU_LOGON:
1233 DEBUG(("Received Logon PDU\n"));
1234 /* User logged on */
1235 break;
1236
1237 case RDP_DATA_PDU_DISCONNECT:
1238 process_disconnect_pdu(s, ext_disc_reason);
1239 return True;
1240
1241 default:
1242 unimpl("data PDU %d\n", data_pdu_type);
1243 }
1244 return False;
1245 }
1246
1247 /* Process incoming packets */
1248 /* nevers gets out of here till app is done */
1249 void
1250 rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1251 {
1252 while (rdp_loop(deactivated, ext_disc_reason))
1253 ;
1254 }
1255
1256 /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1257 BOOL
1258 rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1259 {
1260 uint8 type;
1261 BOOL disc = False; /* True when a disconnect PDU was received */
1262 BOOL cont = True;
1263 STREAM s;
1264
1265 while (cont)
1266 {
1267 s = rdp_recv(&type);
1268 if (s == NULL)
1269 return False;
1270 switch (type)
1271 {
1272 case RDP_PDU_DEMAND_ACTIVE:
1273 process_demand_active(s);
1274 *deactivated = False;
1275 break;
1276 case RDP_PDU_DEACTIVATE:
1277 DEBUG(("RDP_PDU_DEACTIVATE\n"));
1278 *deactivated = True;
1279 break;
1280 case RDP_PDU_DATA:
1281 disc = process_data_pdu(s, ext_disc_reason);
1282 break;
1283 case 0:
1284 break;
1285 default:
1286 unimpl("PDU %d\n", type);
1287 }
1288 if (disc)
1289 return False;
1290 cont = g_next_packet < s->end;
1291 }
1292 return True;
1293 }
1294
1295 /* Establish a connection up to the RDP layer */
1296 BOOL
1297 rdp_connect(char *server, uint32 flags, char *domain, char *password,
1298 char *command, char *directory)
1299 {
1300 if (!sec_connect(server, g_username))
1301 return False;
1302
1303 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1304 return True;
1305 }
1306
1307 /* Disconnect from the RDP layer */
1308 void
1309 rdp_disconnect(void)
1310 {
1311 sec_disconnect();
1312 }

  ViewVC Help
Powered by ViewVC 1.1.26