~ubuntu-branches/ubuntu/edgy/rdesktop/edgy-security

« back to all changes in this revision

Viewing changes to rdp.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Johnston
  • Date: 2004-02-04 17:52:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040204175226-87kz4bzs1nimji68
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

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