/[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 1475 - (show annotations)
Fri Jul 11 03:51:23 2008 UTC (15 years, 10 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/rdp.c
File MIME type: text/plain
File size: 34796 byte(s)
update the copyright year

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

  ViewVC Help
Powered by ViewVC 1.1.26