/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 858 - (show annotations)
Sun Mar 13 13:58:23 2005 UTC (19 years, 1 month ago) by stargo
File MIME type: text/plain
File size: 30477 byte(s)
HAVE_ICONV configure test

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

  ViewVC Help
Powered by ViewVC 1.1.26