Update MSTSC with latest (1.8.3) rdesktop version.
Patch by 'hater', for more details see CORE-9013 #resolve #comment Committed, thanks!

svn path=/trunk/; revision=66502
This commit is contained in:
Hermès Bélusca-Maïto 2015-02-28 20:28:09 +00:00
parent 014d37e58e
commit 38ecef1f2b
26 changed files with 2747 additions and 1334 deletions

View file

@ -1,5 +1,6 @@
list(APPEND SOURCE list(APPEND SOURCE
asn.c
bitmap.c bitmap.c
bsops.c bsops.c
cache.c cache.c
@ -19,6 +20,14 @@ list(APPEND SOURCE
tcp.c tcp.c
uimain.c uimain.c
win32.c win32.c
bsops.h
constants.h
orders.h
proto.h
rdesktop.h
resource.h
types.h
uimain.h
precomp.h) precomp.h)
add_executable(mstsc ${SOURCE} rdc.rc) add_executable(mstsc ${SOURCE} rdc.rc)

View file

@ -0,0 +1,109 @@
/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
ASN.1 utility functions
Copyright 2012 Henrik Andersson <hean01@cendio.se> for Cendio AB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precomp.h"
/* Parse an ASN.1 BER header */
RD_BOOL
ber_parse_header(STREAM s, int tagval, int *length)
{
int tag, len;
if (tagval > 0xff)
{
in_uint16_be(s, tag);
}
else
{
in_uint8(s, tag);
}
if (tag != tagval)
{
error("expected tag %d, got %d\n", tagval, tag);
return False;
}
in_uint8(s, len);
if (len & 0x80)
{
len &= ~0x80;
*length = 0;
while (len--)
next_be(s, *length);
}
else
*length = len;
return s_check(s);
}
/* Output an ASN.1 BER header */
void
ber_out_header(STREAM s, int tagval, int length)
{
if (tagval > 0xff)
{
out_uint16_be(s, tagval);
}
else
{
out_uint8(s, tagval);
}
if (length >= 0x80)
{
out_uint8(s, 0x82);
out_uint16_be(s, length);
}
else
out_uint8(s, length);
}
/* Output an ASN.1 BER integer */
void
ber_out_integer(STREAM s, int value)
{
ber_out_header(s, BER_TAG_INTEGER, 2);
out_uint16_be(s, value);
}
RD_BOOL
ber_in_header(STREAM s, int *tagval, int *decoded_len)
{
in_uint8(s, *tagval);
in_uint8(s, *decoded_len);
if (*decoded_len < 0x80)
return True;
else if (*decoded_len == 0x81)
{
in_uint8(s, *decoded_len);
return True;
}
else if (*decoded_len == 0x82)
{
in_uint16_be(s, *decoded_len);
return True;
}
return False;
}

View file

@ -1,11 +1,11 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Bitmap decompression routines Bitmap decompression routines
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,23 +13,19 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
/* three seperate function for speed when decompressing the bitmaps */ /* three seperate function for speed when decompressing the bitmaps
/* when modifing one function make the change in the others */ when modifing one function make the change in the others
/* comment out #define BITMAP_SPEED_OVER_SIZE below for one slower function */ jay.sorg@gmail.com */
/* j@american-data.com */
/* indent is confused by this file */ /* indent is confused by this file */
/* *INDENT-OFF* */ /* *INDENT-OFF* */
#include "precomp.h" #include "precomp.h"
#define BITMAP_SPEED_OVER_SIZE
#define CVAL(p) (*(p++)) #define CVAL(p) (*(p++))
#ifdef NEED_ALIGN #ifdef NEED_ALIGN
#ifdef L_ENDIAN #ifdef L_ENDIAN
@ -66,10 +62,8 @@
} \ } \
} }
#ifdef BITMAP_SPEED_OVER_SIZE
/* 1 byte bitmap decompress */ /* 1 byte bitmap decompress */
static BOOL static RD_BOOL
bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size) bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
{ {
uint8 *end = input + size; uint8 *end = input + size;
@ -267,7 +261,7 @@ bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int siz
} }
/* 2 byte bitmap decompress */ /* 2 byte bitmap decompress */
static BOOL static RD_BOOL
bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size) bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
{ {
uint8 *end = input + size; uint8 *end = input + size;
@ -466,7 +460,7 @@ bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int siz
} }
/* 3 byte bitmap decompress */ /* 3 byte bitmap decompress */
static BOOL static RD_BOOL
bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size) bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
{ {
uint8 *end = input + size; uint8 *end = input + size;
@ -751,254 +745,146 @@ bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int siz
return True; return True;
} }
#else /* decompress a colour plane */
static int
static uint32 process_plane(uint8 * in, int width, int height, uint8 * out, int size)
cvalx(uint8 **input, int Bpp)
{ {
uint32 rv = 0; int indexw;
memcpy(&rv, *input, Bpp); int indexh;
*input += Bpp; int code;
return rv; int collen;
} int replen;
int color;
int x;
int revcode;
uint8 * last_line;
uint8 * this_line;
uint8 * org_in;
uint8 * org_out;
static void org_in = in;
setli(uint8 *input, int offset, uint32 value, int Bpp) org_out = out;
{ last_line = 0;
input += offset * Bpp; indexh = 0;
memcpy(input, &value, Bpp); while (indexh < height)
}
static uint32
getli(uint8 *input, int offset, int Bpp)
{
uint32 rv = 0;
input += offset * Bpp;
memcpy(&rv, input, Bpp);
return rv;
}
static BOOL
bitmap_decompressx(uint8 *output, int width, int height, uint8 *input, int size, int Bpp)
{
uint8 *end = input + size;
uint8 *prevline = NULL, *line = NULL;
int opcode, count, offset, isfillormix, x = width;
int lastopcode = -1, insertmix = False, bicolour = False;
uint8 code;
uint32 colour1 = 0, colour2 = 0;
uint8 mixmask, mask = 0;
uint32 mix = 0xffffffff;
int fom_mask = 0;
while (input < end)
{ {
fom_mask = 0; out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
code = CVAL(input); color = 0;
opcode = code >> 4; this_line = out;
indexw = 0;
/* Handle different opcode forms */ if (last_line == 0)
switch (opcode)
{ {
case 0xc: while (indexw < width)
case 0xd: {
case 0xe: code = CVAL(in);
opcode -= 6; replen = code & 0xf;
count = code & 0xf; collen = (code >> 4) & 0xf;
offset = 16; revcode = (replen << 4) | collen;
break; if ((revcode <= 47) && (revcode >= 16))
case 0xf:
opcode = code & 0xf;
if (opcode < 9)
{ {
count = CVAL(input); replen = revcode;
count |= CVAL(input) << 8; collen = 0;
} }
else while (collen > 0)
{ {
count = (opcode < 0xb) ? 8 : 1; color = CVAL(in);
*out = color;
out += 4;
indexw++;
collen--;
}
while (replen > 0)
{
*out = color;
out += 4;
indexw++;
replen--;
} }
offset = 0;
break;
default:
opcode >>= 1;
count = code & 0x1f;
offset = 32;
break;
}
/* Handle strange cases for counts */
if (offset != 0)
{
isfillormix = ((opcode == 2) || (opcode == 7));
if (count == 0)
{
if (isfillormix)
count = CVAL(input) + 1;
else
count = CVAL(input) + offset;
}
else if (isfillormix)
{
count <<= 3;
} }
} }
else
/* Read preliminary data */
switch (opcode)
{ {
case 0: /* Fill */ while (indexw < width)
if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
insertmix = True;
break;
case 8: /* Bicolour */
colour1 = cvalx(&input, Bpp);
case 3: /* Colour */
colour2 = cvalx(&input, Bpp);
break;
case 6: /* SetMix/Mix */
case 7: /* SetMix/FillOrMix */
mix = cvalx(&input, Bpp);
opcode -= 5;
break;
case 9: /* FillOrMix_1 */
mask = 0x03;
opcode = 0x02;
fom_mask = 3;
break;
case 0x0a: /* FillOrMix_2 */
mask = 0x05;
opcode = 0x02;
fom_mask = 5;
break;
}
lastopcode = opcode;
mixmask = 0;
/* Output body */
while (count > 0)
{
if (x >= width)
{ {
if (height <= 0) code = CVAL(in);
return False; replen = code & 0xf;
collen = (code >> 4) & 0xf;
x = 0; revcode = (replen << 4) | collen;
height--; if ((revcode <= 47) && (revcode >= 16))
{
prevline = line; replen = revcode;
line = output + height * width * Bpp; collen = 0;
} }
while (collen > 0)
switch (opcode) {
{ x = CVAL(in);
case 0: /* Fill */ if (x & 1)
if (insertmix)
{ {
if (prevline == NULL) x = x >> 1;
setli(line, x, mix, Bpp); x = x + 1;
else color = -x;
setli(line, x,
getli(prevline, x, Bpp) ^ mix, Bpp);
insertmix = False;
count--;
x++;
}
if (prevline == NULL)
{
REPEAT(setli(line, x, 0, Bpp))}
else
{
REPEAT(setli
(line, x, getli(prevline, x, Bpp), Bpp));
}
break;
case 1: /* Mix */
if (prevline == NULL)
{
REPEAT(setli(line, x, mix, Bpp));
} }
else else
{ {
REPEAT(setli x = x >> 1;
(line, x, getli(prevline, x, Bpp) ^ mix, color = x;
Bpp));
} }
break; x = last_line[indexw * 4] + color;
*out = x;
case 2: /* Fill or Mix */ out += 4;
if (prevline == NULL) indexw++;
{ collen--;
REPEAT(MASK_UPDATE(); }
if (mask & mixmask) setli(line, x, mix, Bpp); while (replen > 0)
else {
setli(line, x, 0, Bpp);); x = last_line[indexw * 4] + color;
} *out = x;
else out += 4;
{ indexw++;
REPEAT(MASK_UPDATE(); replen--;
if (mask & mixmask) }
setli(line, x, getli(prevline, x, Bpp) ^ mix,
Bpp);
else
setli(line, x, getli(prevline, x, Bpp),
Bpp););
}
break;
case 3: /* Colour */
REPEAT(setli(line, x, colour2, Bpp));
break;
case 4: /* Copy */
REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));
break;
case 8: /* Bicolour */
REPEAT(if (bicolour)
{
setli(line, x, colour2, Bpp); bicolour = False;}
else
{
setli(line, x, colour1, Bpp); bicolour = True;
count++;}
);
break;
case 0xd: /* White */
REPEAT(setli(line, x, 0xffffffff, Bpp));
break;
case 0xe: /* Black */
REPEAT(setli(line, x, 0, Bpp));
break;
default:
unimpl("bitmap opcode 0x%x\n", opcode);
return False;
} }
} }
indexh++;
last_line = this_line;
} }
return (int) (in - org_in);
return True;
} }
#endif /* 4 byte bitmap decompress */
static RD_BOOL
bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size)
{
int code;
int bytes_pro;
int total_pro;
code = CVAL(input);
if (code != 0x10)
{
return False;
}
total_pro = 1;
bytes_pro = process_plane(input, width, height, output + 3, size - total_pro);
total_pro += bytes_pro;
input += bytes_pro;
bytes_pro = process_plane(input, width, height, output + 2, size - total_pro);
total_pro += bytes_pro;
input += bytes_pro;
bytes_pro = process_plane(input, width, height, output + 1, size - total_pro);
total_pro += bytes_pro;
input += bytes_pro;
bytes_pro = process_plane(input, width, height, output + 0, size - total_pro);
total_pro += bytes_pro;
return size == total_pro;
}
/* main decompress function */ /* main decompress function */
BOOL RD_BOOL
bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp) bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
{ {
#ifdef BITMAP_SPEED_OVER_SIZE RD_BOOL rv = False;
BOOL rv = False;
switch (Bpp) switch (Bpp)
{ {
case 1: case 1:
@ -1010,11 +896,13 @@ bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size
case 3: case 3:
rv = bitmap_decompress3(output, width, height, input, size); rv = bitmap_decompress3(output, width, height, input, size);
break; break;
case 4:
rv = bitmap_decompress4(output, width, height, input, size);
break;
default:
unimpl("Bpp %d\n", Bpp);
break;
} }
#else
BOOL rv;
rv = bitmap_decompressx(output, width, height, input, size, Bpp);
#endif
return rv; return rv;
} }

View file

@ -223,12 +223,24 @@ bs_is_pixel_on(char * data, int x, int y, int width, int bpp)
{ {
return data[y * width + x] != 0; return data[y * width + x] != 0;
} }
else if (bpp == 15 || bpp == 16)
{
return data[(y * 2) * width + (x * 2)] != 0 ||
data[(y * 2) * width + (x * 2) + 1] != 0;
}
else if (bpp == 24) else if (bpp == 24)
{ {
return data[(y * 3) * width + (x * 3)] != 0 && return data[(y * 3) * width + (x * 3)] != 0 ||
data[(y * 3) * width + (x * 3) + 1] != 0 && data[(y * 3) * width + (x * 3) + 1] != 0 ||
data[(y * 3) * width + (x * 3) + 2] != 0; data[(y * 3) * width + (x * 3) + 2] != 0;
} }
else if (bpp == 32)
{
return data[(y * 4) * width + (x * 4)] != 0 ||
data[(y * 4) * width + (x * 4) + 1] != 0 ||
data[(y * 4) * width + (x * 4) + 2] != 0 ||
data[(y * 4) * width + (x * 4) + 3] != 0;
}
else else
{ {
return 0; return 0;

View file

@ -1,12 +1,13 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Cache routines Cache routines
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright (C) Jeroen Meijer 2005 Copyright (C) Jeroen Meijer <jeroen@oldambt7.com> 2005
Copyright 2003-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -14,9 +15,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
@ -50,6 +50,7 @@ static RD_HBITMAP g_volatile_bc[3];
static int g_bmpcache_lru[3] = { NOT_SET, NOT_SET, NOT_SET }; static int g_bmpcache_lru[3] = { NOT_SET, NOT_SET, NOT_SET };
static int g_bmpcache_mru[3] = { NOT_SET, NOT_SET, NOT_SET }; static int g_bmpcache_mru[3] = { NOT_SET, NOT_SET, NOT_SET };
static int g_bmpcache_count[3]; static int g_bmpcache_count[3];
/* Setup the bitmap cache lru/mru linked list */ /* Setup the bitmap cache lru/mru linked list */
@ -94,7 +95,7 @@ cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count)
{ {
error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c, error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c,
g_bmpcache_count[id]); g_bmpcache_count[id]);
exit(1); exit(EX_SOFTWARE);
} }
} }
@ -176,7 +177,7 @@ cache_evict_bitmap(uint8 id)
idx = g_bmpcache_lru[id]; idx = g_bmpcache_lru[id];
n_idx = g_bmpcache[id][idx].next; n_idx = g_bmpcache[id][idx].next;
DEBUG_RDP5(("evict bitmap: id=%d idx=%d n_idx=%d bmp=0x%x\n", id, idx, n_idx, DEBUG_RDP5(("evict bitmap: id=%d idx=%d n_idx=%d bmp=%p\n", id, idx, n_idx,
g_bmpcache[id][idx].bitmap)); g_bmpcache[id][idx].bitmap));
ui_destroy_bitmap(g_bmpcache[id][idx].bitmap); ui_destroy_bitmap(g_bmpcache[id][idx].bitmap);
@ -262,7 +263,7 @@ cache_save_state(void)
idx = g_bmpcache_lru[id]; idx = g_bmpcache_lru[id];
while (idx >= 0) while (idx >= 0)
{ {
pstcache_touch_bitmap((uint8) id, (uint16) idx, ++t); pstcache_touch_bitmap(id, idx, ++t);
idx = g_bmpcache[id][idx].next; idx = g_bmpcache[id][idx].next;
} }
DEBUG_RDP5((" %d stamps written.\n", t)); DEBUG_RDP5((" %d stamps written.\n", t));
@ -430,3 +431,43 @@ cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor)
error("put cursor %d\n", cache_idx); error("put cursor %d\n", cache_idx);
} }
} }
/* BRUSH CACHE */
/* index 0 is 2 colour brush, index 1 is muti colour brush */
static BRUSHDATA g_brushcache[2][64];
/* Retrieve brush from cache */
BRUSHDATA *
cache_get_brush_data(uint8 colour_code, uint8 idx)
{
colour_code = colour_code == 1 ? 0 : 1;
if (idx < NUM_ELEMENTS(g_brushcache[0]))
{
return &g_brushcache[colour_code][idx];
}
error("get brush %d %d\n", colour_code, idx);
return NULL;
}
/* Store brush in cache */
/* this function takes over the data pointer in struct, eg, caller gives it up */
void
cache_put_brush_data(uint8 colour_code, uint8 idx, BRUSHDATA * brush_data)
{
BRUSHDATA *bd;
colour_code = colour_code == 1 ? 0 : 1;
if (idx < NUM_ELEMENTS(g_brushcache[0]))
{
bd = &g_brushcache[colour_code][idx];
if (bd->data != 0)
{
xfree(bd->data);
}
memcpy(bd, brush_data, sizeof(BRUSHDATA));
}
else
{
error("put brush %d %d\n", colour_code, idx);
}
}

View file

@ -1,12 +1,12 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Protocol services - Virtual channels Protocol services - Virtual channels
Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003 Copyright 2003 Erik Forsberg <forsberg@cendio.se> for Cendio AB
Copyright (C) Matthew Chapman 2003-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -14,9 +14,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
@ -27,8 +26,8 @@
#define CHANNEL_FLAG_LAST 0x02 #define CHANNEL_FLAG_LAST 0x02
#define CHANNEL_FLAG_SHOW_PROTOCOL 0x10 #define CHANNEL_FLAG_SHOW_PROTOCOL 0x10
extern BOOL g_use_rdp5; extern RDP_VERSION g_rdp_version;
extern BOOL g_encryption; extern RD_BOOL g_encryption;
VCHANNEL g_channels[MAX_CHANNELS]; VCHANNEL g_channels[MAX_CHANNELS];
unsigned int g_num_channels; unsigned int g_num_channels;
@ -48,7 +47,7 @@ channel_register(char *name, uint32 flags, void (*callback) (STREAM))
{ {
VCHANNEL *channel; VCHANNEL *channel;
if (!g_use_rdp5) if (g_rdp_version < RDP_V5)
return NULL; return NULL;
if (g_num_channels >= MAX_CHANNELS) if (g_num_channels >= MAX_CHANNELS)
@ -83,6 +82,10 @@ channel_send(STREAM s, VCHANNEL * channel)
uint32 thislength, remaining; uint32 thislength, remaining;
uint8 *data; uint8 *data;
#ifdef WITH_SCARD
scard_lock(SCARD_LOCK_CHANNEL);
#endif
/* first fragment sent in-place */ /* first fragment sent in-place */
s_pop_layer(s, channel_hdr); s_pop_layer(s, channel_hdr);
length = s->end - s->p - 8; length = s->end - s->p - 8;
@ -125,6 +128,10 @@ channel_send(STREAM s, VCHANNEL * channel)
data += thislength; data += thislength;
} }
#ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_CHANNEL);
#endif
} }
void void

View file

@ -1,11 +1,11 @@
/* /*
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Miscellaneous protocol constants Miscellaneous protocol constants
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman 1999-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -14,8 +14,7 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program. If not, see <http://www.gnu.org/licenses/>.
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* TCP port for Remote Desktop Protocol */ /* TCP port for Remote Desktop Protocol */
@ -34,6 +33,31 @@ enum ISO_PDU_CODE
ISO_PDU_ER = 0x70 /* Error */ ISO_PDU_ER = 0x70 /* Error */
}; };
/* RDP protocol negotiating constants */
enum RDP_NEG_TYPE_CODE
{
RDP_NEG_REQ = 1,
RDP_NEG_RSP = 2,
RDP_NEG_FAILURE = 3
};
enum RDP_NEG_REQ_CODE
{
PROTOCOL_RDP = 0,
PROTOCOL_SSL = 1,
PROTOCOL_HYBRID = 2
};
enum RDP_NEG_FAILURE_CODE
{
SSL_REQUIRED_BY_SERVER = 1,
SSL_NOT_ALLOWED_BY_SERVER = 2,
SSL_CERT_NOT_ON_SERVER = 3,
INCONSISTENT_FLAGS = 4,
HYBRID_REQUIRED_BY_SERVER = 5,
SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 6
};
/* MCS PDU codes */ /* MCS PDU codes */
enum MCS_PDU_TYPE enum MCS_PDU_TYPE
{ {
@ -54,17 +78,21 @@ enum MCS_PDU_TYPE
#define BER_TAG_INTEGER 2 #define BER_TAG_INTEGER 2
#define BER_TAG_OCTET_STRING 4 #define BER_TAG_OCTET_STRING 4
#define BER_TAG_RESULT 10 #define BER_TAG_RESULT 10
#define BER_TAG_SEQUENCE 16
#define BER_TAG_CONSTRUCTED 0x20
#define BER_TAG_CTXT_SPECIFIC 0x80
#define MCS_TAG_DOMAIN_PARAMS 0x30 #define MCS_TAG_DOMAIN_PARAMS 0x30
#define MCS_GLOBAL_CHANNEL 1003 #define MCS_GLOBAL_CHANNEL 1003
#define MCS_USERCHANNEL_BASE 1001 #define MCS_USERCHANNEL_BASE 1001
/* RDP secure transport constants */ /* RDP secure transport constants */
#define SEC_RANDOM_SIZE 32 #define SEC_RANDOM_SIZE 32
#define SEC_MODULUS_SIZE 64 #define SEC_MODULUS_SIZE 64
#define SEC_MAX_MODULUS_SIZE 256 #define SEC_MAX_MODULUS_SIZE 256
#define SEC_PADDING_SIZE 8 #define SEC_PADDING_SIZE 8
#define SEC_EXPONENT_SIZE 4 #define SEC_EXPONENT_SIZE 4
#define SEC_CLIENT_RANDOM 0x0001 #define SEC_CLIENT_RANDOM 0x0001
#define SEC_ENCRYPT 0x0008 #define SEC_ENCRYPT 0x0008
@ -79,38 +107,50 @@ enum MCS_PDU_TYPE
#define SEC_TAG_CLI_INFO 0xc001 #define SEC_TAG_CLI_INFO 0xc001
#define SEC_TAG_CLI_CRYPT 0xc002 #define SEC_TAG_CLI_CRYPT 0xc002
#define SEC_TAG_CLI_CHANNELS 0xc003 #define SEC_TAG_CLI_CHANNELS 0xc003
#define SEC_TAG_CLI_4 0xc004 #define SEC_TAG_CLI_CLUSTER 0xc004
#define SEC_TAG_PUBKEY 0x0006 #define SEC_TAG_PUBKEY 0x0006
#define SEC_TAG_KEYSIG 0x0008 #define SEC_TAG_KEYSIG 0x0008
#define SEC_RSA_MAGIC 0x31415352 /* RSA1 */ #define SEC_RSA_MAGIC 0x31415352 /* RSA1 */
/* Client cluster constants */
#define SEC_CC_REDIRECTION_SUPPORTED 0x00000001
#define SEC_CC_REDIRECT_SESSIONID_FIELD_VALID 0x00000002
#define SEC_CC_REDIRECTED_SMARTCARD 0x00000040
#define SEC_CC_REDIRECT_VERSION_MASK 0x0000003c
#define SEC_CC_REDIRECT_VERSION_3 0x02
#define SEC_CC_REDIRECT_VERSION_4 0x03
#define SEC_CC_REDIRECT_VERSION_5 0x04
#define SEC_CC_REDIRECT_VERSION_6 0x05
/* RDP licensing constants */ /* RDP licensing constants */
#define LICENCE_TOKEN_SIZE 10 #define LICENCE_TOKEN_SIZE 10
#define LICENCE_HWID_SIZE 20 #define LICENCE_HWID_SIZE 20
#define LICENCE_SIGNATURE_SIZE 16 #define LICENCE_SIGNATURE_SIZE 16
#define LICENCE_TAG_DEMAND 0x01 #define LICENCE_TAG_REQUEST 0x01
#define LICENCE_TAG_AUTHREQ 0x02 #define LICENCE_TAG_PLATFORM_CHALLANGE 0x02
#define LICENCE_TAG_ISSUE 0x03 #define LICENCE_TAG_NEW_LICENCE 0x03
#define LICENCE_TAG_REISSUE 0x04 #define LICENCE_TAG_UPGRADE_LICENCE 0x04
#define LICENCE_TAG_PRESENT 0x12 #define LICENCE_TAG_LICENCE_INFO 0x12
#define LICENCE_TAG_REQUEST 0x13 #define LICENCE_TAG_NEW_LICENCE_REQUEST 0x13
#define LICENCE_TAG_AUTHRESP 0x15 #define LICENCE_TAG_PLATFORM_CHALLANGE_RESPONSE 0x15
#define LICENCE_TAG_RESULT 0xff #define LICENCE_TAG_ERROR_ALERT 0xff
#define LICENCE_TAG_USER 0x000f #define BB_CLIENT_USER_NAME_BLOB 0x000f
#define LICENCE_TAG_HOST 0x0010 #define BB_CLIENT_MACHINE_NAME_BLOB 0x0010
/* RDP PDU codes */ /* RDP PDU codes */
enum RDP_PDU_TYPE enum RDP_PDU_TYPE
{ {
RDP_PDU_DEMAND_ACTIVE = 1, RDP_PDU_DEMAND_ACTIVE = 1,
RDP_PDU_CONFIRM_ACTIVE = 3, RDP_PDU_CONFIRM_ACTIVE = 3,
RDP_PDU_REDIRECT = 4, /* MS Server 2003 Session Redirect */ RDP_PDU_REDIRECT = 4, /* Standard Server Redirect */
RDP_PDU_DEACTIVATE = 6, RDP_PDU_DEACTIVATE = 6,
RDP_PDU_DATA = 7 RDP_PDU_DATA = 7,
RDP_PDU_ENHANCED_REDIRECT = 10 /* Enhanced Server Redirect */
}; };
enum RDP_DATA_PDU_TYPE enum RDP_DATA_PDU_TYPE
@ -122,10 +162,25 @@ enum RDP_DATA_PDU_TYPE
RDP_DATA_PDU_SYNCHRONISE = 31, RDP_DATA_PDU_SYNCHRONISE = 31,
RDP_DATA_PDU_BELL = 34, RDP_DATA_PDU_BELL = 34,
RDP_DATA_PDU_CLIENT_WINDOW_STATUS = 35, RDP_DATA_PDU_CLIENT_WINDOW_STATUS = 35,
RDP_DATA_PDU_LOGON = 38, RDP_DATA_PDU_LOGON = 38, /* PDUTYPE2_SAVE_SESSION_INFO */
RDP_DATA_PDU_FONT2 = 39, RDP_DATA_PDU_FONT2 = 39,
RDP_DATA_PDU_KEYBOARD_INDICATORS = 41, RDP_DATA_PDU_KEYBOARD_INDICATORS = 41,
RDP_DATA_PDU_DISCONNECT = 47 RDP_DATA_PDU_DISCONNECT = 47,
RDP_DATA_PDU_AUTORECONNECT_STATUS = 50
};
enum RDP_SAVE_SESSION_PDU_TYPE
{
INFOTYPE_LOGON = 0,
INFOTYPE_LOGON_LONG = 1,
INFOTYPE_LOGON_PLAINNOTIFY = 2,
INFOTYPE_LOGON_EXTENDED_INF = 3
};
enum RDP_LOGON_INFO_EXTENDED_TYPE
{
LOGON_EX_AUTORECONNECTCOOKIE = 1,
LOGON_EX_LOGONERRORS = 2
}; };
enum RDP_CONTROL_PDU_TYPE enum RDP_CONTROL_PDU_TYPE
@ -149,7 +204,8 @@ enum RDP_POINTER_PDU_TYPE
RDP_POINTER_SYSTEM = 1, RDP_POINTER_SYSTEM = 1,
RDP_POINTER_MOVE = 3, RDP_POINTER_MOVE = 3,
RDP_POINTER_COLOR = 6, RDP_POINTER_COLOR = 6,
RDP_POINTER_CACHED = 7 RDP_POINTER_CACHED = 7,
RDP_POINTER_NEW = 8
}; };
enum RDP_SYSTEM_POINTER_TYPE enum RDP_SYSTEM_POINTER_TYPE
@ -192,9 +248,8 @@ enum RDP_INPUT_DEVICE
#define MOUSE_FLAG_DOWN 0x8000 #define MOUSE_FLAG_DOWN 0x8000
/* Raster operation masks */ /* Raster operation masks */
#define ROP2_S(rop3) ((uint8) (rop3 & 0xf)) #define ROP2_S(rop3) (rop3 & 0xf)
#define ROP2_P(rop3) ((uint8) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2))) #define ROP2_P(rop3) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2))
#define ROP_MINUS_1(rop) ((uint8) (rop - 1))
#define ROP2_COPY 0xc #define ROP2_COPY 0xc
#define ROP2_XOR 0x6 #define ROP2_XOR 0x6
@ -245,6 +300,7 @@ enum RDP_INPUT_DEVICE
#define RDP_CAPSET_POINTER 8 #define RDP_CAPSET_POINTER 8
#define RDP_CAPLEN_POINTER 0x08 #define RDP_CAPLEN_POINTER 0x08
#define RDP_CAPLEN_NEWPOINTER 0x0a
#define RDP_CAPSET_SHARE 9 #define RDP_CAPSET_SHARE 9
#define RDP_CAPLEN_SHARE 0x08 #define RDP_CAPLEN_SHARE 0x08
@ -252,6 +308,9 @@ enum RDP_INPUT_DEVICE
#define RDP_CAPSET_COLCACHE 10 #define RDP_CAPSET_COLCACHE 10
#define RDP_CAPLEN_COLCACHE 0x08 #define RDP_CAPLEN_COLCACHE 0x08
#define RDP_CAPSET_BRUSHCACHE 15
#define RDP_CAPLEN_BRUSHCACHE 0x08
#define RDP_CAPSET_BMPCACHE2 19 #define RDP_CAPSET_BMPCACHE2 19
#define RDP_CAPLEN_BMPCACHE2 0x28 #define RDP_CAPLEN_BMPCACHE2 0x28
#define BMPCACHE2_FLAG_PERSIST ((uint32)1<<31) #define BMPCACHE2_FLAG_PERSIST ((uint32)1<<31)
@ -259,12 +318,16 @@ enum RDP_INPUT_DEVICE
#define RDP_SOURCE "MSTSC" #define RDP_SOURCE "MSTSC"
/* Logon flags */ /* Logon flags */
#define RDP_LOGON_AUTO 0x0008 #define RDP_INFO_MOUSE 0x00000001
#define RDP_LOGON_NORMAL 0x0033 #define RDP_INFO_DISABLECTRLALTDEL 0x00000002
#define RDP_LOGON_COMPRESSION 0x0080 /* mppc compression with 8kB histroy buffer */ #define RDP_INFO_AUTOLOGON 0x00000008
#define RDP_LOGON_BLOB 0x0100 #define RDP_INFO_UNICODE 0x00000010
#define RDP_LOGON_COMPRESSION2 0x0200 /* rdp5 mppc compression with 64kB history buffer */ #define RDP_INFO_MAXIMIZESHELL 0x00000020
#define RDP_LOGON_LEAVE_AUDIO 0x2000 #define RDP_INFO_COMPRESSION 0x00000080 /* mppc compression with 8kB histroy buffer */
#define RDP_INFO_ENABLEWINDOWSKEY 0x00000100
#define RDP_INFO_COMPRESSION2 0x00000200 /* rdp5 mppc compression with 64kB history buffer */
#define RDP_INFO_REMOTE_CONSOLE_AUDIO 0x00002000
#define RDP_INFO_PASSWORD_IS_SC_PIN 0x00040000
#define RDP5_DISABLE_NOTHING 0x00 #define RDP5_DISABLE_NOTHING 0x00
#define RDP5_NO_WALLPAPER 0x01 #define RDP5_NO_WALLPAPER 0x01
@ -313,7 +376,8 @@ enum RDP_INPUT_DEVICE
#define MASK_CHANGE_BIT(var, mask, active) (var = ((var & ~mask) | (active ? mask : 0))) #define MASK_CHANGE_BIT(var, mask, active) (var = ((var & ~mask) | (active ? mask : 0)))
/* Clipboard constants, "borrowed" from GCC system headers in /* Clipboard constants, "borrowed" from GCC system headers in
the w32 cross compiler */ the w32 cross compiler
this is the CF_ set when WINVER is 0x0400 */
#ifndef CF_TEXT #ifndef CF_TEXT
#define CF_TEXT 1 #define CF_TEXT 1
@ -357,37 +421,53 @@ enum RDP_INPUT_DEVICE
#define CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 #define CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000
/* NT status codes for RDPDR */ /* NT status codes for RDPDR */
#undef STATUS_SUCCESS #define RD_STATUS_SUCCESS 0x00000000
#define STATUS_SUCCESS 0x00000000 #define RD_STATUS_NOT_IMPLEMENTED 0x00000001
#undef STATUS_NOT_IMPLEMENTED #define RD_STATUS_PENDING 0x00000103
#define STATUS_NOT_IMPLEMENTED 0x00000001
#undef STATUS_PENDING
#define STATUS_PENDING 0x00000103
#ifndef STATUS_NO_MORE_FILES #define RD_STATUS_NO_MORE_FILES 0x80000006
#define STATUS_NO_MORE_FILES 0x80000006 #define RD_STATUS_DEVICE_PAPER_EMPTY 0x8000000e
#define STATUS_DEVICE_PAPER_EMPTY 0x8000000e #define RD_STATUS_DEVICE_POWERED_OFF 0x8000000f
#define STATUS_DEVICE_POWERED_OFF 0x8000000f #define RD_STATUS_DEVICE_OFF_LINE 0x80000010
#define STATUS_DEVICE_OFF_LINE 0x80000010 #define RD_STATUS_DEVICE_BUSY 0x80000011
#define STATUS_DEVICE_BUSY 0x80000011
#endif
#ifndef STATUS_INVALID_HANDLE #define RD_STATUS_INVALID_HANDLE 0xc0000008
#define STATUS_INVALID_HANDLE 0xc0000008 #define RD_STATUS_INVALID_PARAMETER 0xc000000d
#define STATUS_INVALID_PARAMETER 0xc000000d #define RD_STATUS_NO_SUCH_FILE 0xc000000f
#define STATUS_NO_SUCH_FILE 0xc000000f #define RD_STATUS_INVALID_DEVICE_REQUEST 0xc0000010
#define STATUS_INVALID_DEVICE_REQUEST 0xc0000010 #define RD_STATUS_ACCESS_DENIED 0xc0000022
#define STATUS_ACCESS_DENIED 0xc0000022 #define RD_STATUS_OBJECT_NAME_COLLISION 0xc0000035
#define STATUS_OBJECT_NAME_COLLISION 0xc0000035 #define RD_STATUS_DISK_FULL 0xc000007f
#define STATUS_DISK_FULL 0xc000007f #define RD_STATUS_FILE_IS_A_DIRECTORY 0xc00000ba
#define STATUS_FILE_IS_A_DIRECTORY 0xc00000ba #define RD_STATUS_NOT_SUPPORTED 0xc00000bb
#define STATUS_NOT_SUPPORTED 0xc00000bb #define RD_STATUS_TIMEOUT 0xc0000102
#define STATUS_TIMEOUT 0xc0000102 #define RD_STATUS_NOTIFY_ENUM_DIR 0xc000010c
#define STATUS_NOTIFY_ENUM_DIR 0xc000010c #define RD_STATUS_CANCELLED 0xc0000120
#define STATUS_CANCELLED 0xc0000120 #define RD_STATUS_DIRECTORY_NOT_EMPTY 0xc0000101
#endif
/* RDPSND constants */
#define TSSNDCAPS_ALIVE 0x00000001
#define TSSNDCAPS_VOLUME 0x00000002
/* RDPDR constants */ /* RDPDR constants */
#define RDPDR_CTYP_CORE 0x4472
#define RDPDR_CTYP_PRN 0x5052
#define PAKID_CORE_SERVER_ANNOUNCE 0x496e
#define PAKID_CORE_CLIENTID_CONFIRM 0x4343
#define PAKID_CORE_CLIENT_NAME 0x434e
#define PAKID_CORE_DEVICE_LIST_ANNOUNCE 0x4441
#define PAKID_CORE_DEVICE_REPLY 0x6472
#define PAKID_CORE_DEVICE_IOREQUEST 0x4952
#define PAKID_CORE_DEVICE_IOCOMPLETION 0x4943
#define PAKID_CORE_SERVER_CAPABILITY 0x5350
#define PAKID_CORE_CLIENT_CAPABILITY 0x4350
#define PAKID_CORE_DEVICELIST_REMOVE 0x444d
#define PAKID_PRN_CACHE_DATA 0x5043
#define PAKID_CORE_USER_LOGGEDON 0x554c
#define PAKID_PRN_USING_XPS 0x5543
#define RDPDR_MAX_DEVICES 0x10 #define RDPDR_MAX_DEVICES 0x10
#define DEVICE_TYPE_SERIAL 0x01 #define DEVICE_TYPE_SERIAL 0x01
#define DEVICE_TYPE_PARALLEL 0x02 #define DEVICE_TYPE_PARALLEL 0x02
@ -411,6 +491,10 @@ enum RDP_INPUT_DEVICE
#define exDiscReasonOutOfMemory 0x0006 #define exDiscReasonOutOfMemory 0x0006
#define exDiscReasonServerDeniedConnection 0x0007 #define exDiscReasonServerDeniedConnection 0x0007
#define exDiscReasonServerDeniedConnectionFips 0x0008 #define exDiscReasonServerDeniedConnectionFips 0x0008
#define exDiscReasonServerInsufficientPrivileges 0x0009
#define exDiscReasonServerFreshCredentialsRequired 0x000a
#define exDiscReasonRPCInitiatedDisconnectByUser 0x000b
#define exDiscReasonByUser 0x000c
#define exDiscReasonLicenseInternal 0x0100 #define exDiscReasonLicenseInternal 0x0100
#define exDiscReasonLicenseNoLicenseServer 0x0101 #define exDiscReasonLicenseNoLicenseServer 0x0101
#define exDiscReasonLicenseNoLicense 0x0102 #define exDiscReasonLicenseNoLicense 0x0102
@ -431,6 +515,31 @@ enum RDP_INPUT_DEVICE
#define SEAMLESSRDP_POSITION_TIMER 200000 #define SEAMLESSRDP_POSITION_TIMER 200000
#define SEAMLESSRDP_CREATE_MODAL 0x0001 #define SEAMLESSRDP_CREATE_MODAL 0x0001
#define SEAMLESSRDP_CREATE_TOPMOST 0x0002
#define SEAMLESSRDP_HELLO_RECONNECT 0x0001 #define SEAMLESSRDP_HELLO_RECONNECT 0x0001
#define SEAMLESSRDP_HELLO_HIDDEN 0x0002 #define SEAMLESSRDP_HELLO_HIDDEN 0x0002
/* Smartcard constants */
#define SCARD_LOCK_TCP 0
#define SCARD_LOCK_SEC 1
#define SCARD_LOCK_CHANNEL 2
#define SCARD_LOCK_RDPDR 3
#define SCARD_LOCK_LAST 4
/* redirect flags, from [MS-RDPBCGR] 2.2.13.1 */
enum RDP_PDU_REDIRECT_FLAGS
{
PDU_REDIRECT_HAS_IP = 0x1,
PDU_REDIRECT_HAS_LOAD_BALANCE_INFO = 0x2,
PDU_REDIRECT_HAS_USERNAME = 0x4,
PDU_REDIRECT_HAS_DOMAIN = 0x8,
PDU_REDIRECT_HAS_PASSWORD = 0x10,
PDU_REDIRECT_DONT_STORE_USERNAME = 0x20,
PDU_REDIRECT_USE_SMARTCARD = 0x40,
PDU_REDIRECT_INFORMATIONAL = 0x80,
PDU_REDIRECT_HAS_TARGET_FQDN = 0x100,
PDU_REDIRECT_HAS_TARGET_NETBIOS = 0x200,
PDU_REDIRECT_HAS_TARGET_IP_ARRAY = 0x800
};

View file

@ -1,11 +1,13 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Protocol services - ISO layer Protocol services - ISO layer
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
Copyright 2012 Henrik Andersson <hean01@cendio.se> for Cendio AB
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,13 +15,25 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
extern RD_BOOL g_encryption;
extern RD_BOOL g_encryption_initial;
extern RDP_VERSION g_rdp_version;
extern RD_BOOL g_use_password_as_pin;
static RD_BOOL g_negotiate_rdp_protocol = True;
extern char *g_sc_csp_name;
extern char *g_sc_reader_name;
extern char *g_sc_card_name;
extern char *g_sc_container_name;
/* Send a self-contained ISO PDU */ /* Send a self-contained ISO PDU */
static void static void
iso_send_msg(uint8 code) iso_send_msg(uint8 code)
@ -43,11 +57,14 @@ iso_send_msg(uint8 code)
} }
static void static void
iso_send_connection_request(char *username) iso_send_connection_request(char *username, uint32 neg_proto)
{ {
STREAM s; STREAM s;
int length = 30 + strlen(username); int length = 30 + strlen(username);
if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol)
length += 8;
s = tcp_init(length); s = tcp_init(length);
out_uint8(s, 3); /* version */ out_uint8(s, 3); /* version */
@ -63,8 +80,17 @@ iso_send_connection_request(char *username)
out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash=")); out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
out_uint8p(s, username, strlen(username)); out_uint8p(s, username, strlen(username));
out_uint8(s, 0x0d); /* Unknown */ out_uint8(s, 0x0d); /* cookie termination string: CR+LF */
out_uint8(s, 0x0a); /* Unknown */ out_uint8(s, 0x0a);
if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol)
{
/* optional rdp protocol negotiation request for RDPv5 */
out_uint8(s, RDP_NEG_REQ);
out_uint8(s, 0);
out_uint16(s, 8);
out_uint32(s, neg_proto);
}
s_mark_end(s); s_mark_end(s);
tcp_send(s); tcp_send(s);
@ -98,6 +124,11 @@ iso_recv_msg(uint8 * code, uint8 * rdpver)
next_be(s, length); next_be(s, length);
} }
} }
if (length < 4)
{
error("Bad packet header\n");
return NULL;
}
s = tcp_recv(s, length - 4); s = tcp_recv(s, length - 4);
if (s == NULL) if (s == NULL)
return NULL; return NULL;
@ -168,17 +199,38 @@ iso_recv(uint8 * rdpver)
} }
/* Establish a connection up to the ISO layer */ /* Establish a connection up to the ISO layer */
BOOL RD_BOOL
iso_connect(char *server, char *username) iso_connect(char *server, char *username, char *domain, char *password,
RD_BOOL reconnect, uint32 * selected_protocol)
{ {
uint8 code = 0; STREAM s;
uint8 code;
uint32 neg_proto;
g_negotiate_rdp_protocol = True;
neg_proto = PROTOCOL_SSL;
#ifdef WITH_CREDSSP
if (!g_use_password_as_pin)
neg_proto |= PROTOCOL_HYBRID;
else if (g_sc_csp_name || g_sc_reader_name || g_sc_card_name || g_sc_container_name)
neg_proto |= PROTOCOL_HYBRID;
else
warning("Disables CredSSP due to missing smartcard information for SSO.\n");
#endif
retry:
*selected_protocol = PROTOCOL_RDP;
code = 0;
if (!tcp_connect(server)) if (!tcp_connect(server))
return False; return False;
iso_send_connection_request(username); iso_send_connection_request(username, neg_proto);
if (iso_recv_msg(&code, NULL) == NULL) s = iso_recv_msg(&code, NULL);
if (s == NULL)
return False; return False;
if (code != ISO_PDU_CC) if (code != ISO_PDU_CC)
@ -188,30 +240,120 @@ iso_connect(char *server, char *username)
return False; return False;
} }
return True; if (g_rdp_version >= RDP_V5 && s_check_rem(s, 8))
}
/* Establish a reconnection up to the ISO layer */
BOOL
iso_reconnect(char *server)
{
uint8 code = 0;
if (!tcp_connect(server))
return False;
iso_send_msg(ISO_PDU_CR);
if (iso_recv_msg(&code, NULL) == NULL)
return False;
if (code != ISO_PDU_CC)
{ {
error("expected CC, got 0x%x\n", code); /* handle RDP_NEG_REQ response */
tcp_disconnect(); const char *reason = NULL;
return False;
}
uint8 type = 0, flags = 0;
uint16 length = 0;
uint32 data = 0;
in_uint8(s, type);
in_uint8(s, flags);
in_uint16(s, length);
in_uint32(s, data);
if (type == RDP_NEG_FAILURE)
{
RD_BOOL retry_without_neg = False;
switch (data)
{
case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
reason = "SSL with user authentication required by server";
break;
case SSL_NOT_ALLOWED_BY_SERVER:
reason = "SSL not allowed by server";
retry_without_neg = True;
break;
case SSL_CERT_NOT_ON_SERVER:
reason = "no valid authentication certificate on server";
retry_without_neg = True;
break;
case INCONSISTENT_FLAGS:
reason = "inconsistent negotiation flags";
break;
case SSL_REQUIRED_BY_SERVER:
reason = "SSL required by server";
break;
case HYBRID_REQUIRED_BY_SERVER:
reason = "CredSSP required by server";
break;
default:
reason = "unknown reason";
}
tcp_disconnect();
if (retry_without_neg)
{
fprintf(stderr,
"Failed to negotiate protocol, retrying with plain RDP.\n");
g_negotiate_rdp_protocol = False;
goto retry;
}
fprintf(stderr, "Failed to connect, %s.\n", reason);
return False;
}
if (type != RDP_NEG_RSP)
{
tcp_disconnect();
error("Expected RDP_NEG_RSP, got type = 0x%x\n", type);
return False;
}
/* handle negotiation response */
if (data == PROTOCOL_SSL)
{
#ifdef WITH_SSL
if (!tcp_tls_connect())
{
/* failed to connect using cssp, let retry with plain TLS */
tcp_disconnect();
neg_proto = PROTOCOL_RDP;
goto retry;
}
/* do not use encryption when using TLS */
g_encryption = False;
fprintf(stderr, "Connection established using SSL.\n");
#else /* WITH_SSL */
fprintf(stderr, "SSL not compiled in.\n");
#endif /* WITH_SSL */
}
#ifdef WITH_CREDSSP
else if (data == PROTOCOL_HYBRID)
{
if (!cssp_connect(server, username, domain, password, s))
{
/* failed to connect using cssp, let retry with plain TLS */
tcp_disconnect();
neg_proto = PROTOCOL_SSL;
goto retry;
}
/* do not use encryption when using TLS */
fprintf(stderr, "Connection established using CredSSP.\n");
g_encryption = False;
}
#endif
else if (data == PROTOCOL_RDP)
{
fprintf(stderr, "Connection established using plain RDP.\n");
}
else if (data != PROTOCOL_RDP)
{
tcp_disconnect();
error("Unexpected protocol in negotiation response, got data = 0x%x.\n",
data);
return False;
}
if (length || flags) {}
*selected_protocol = data;
}
return True; return True;
} }
@ -227,5 +369,6 @@ iso_disconnect(void)
void void
iso_reset_state(void) iso_reset_state(void)
{ {
g_encryption = g_encryption_initial;
tcp_reset_state(); tcp_reset_state();
} }

View file

@ -1,11 +1,14 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
RDP licensing negotiation RDP licensing negotiation
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright (C) Thomas Uhle <thomas.uhle@mailbox.tu-dresden.de> 2011
Copyright (C) Henrik Andersson <henrik.andersson@cendio.com> 2014
This program is free software; you can redistribute it and/or modify
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,9 +16,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
@ -32,13 +34,15 @@ int
ssl_mod_exp(char* out, int out_len, char* in, int in_len, ssl_mod_exp(char* out, int out_len, char* in, int in_len,
char* mod, int mod_len, char* exp, int exp_len); char* mod, int mod_len, char* exp, int exp_len);
extern char g_username[]; extern char g_username[256];
extern char g_hostname[]; extern char g_hostname[256];
extern RDP_VERSION g_rdp_version;
static uint8 g_licence_key[16]; static uint8 g_licence_key[16];
static uint8 g_licence_sign_key[16]; static uint8 g_licence_sign_key[16];
BOOL g_licence_issued = False; RD_BOOL g_licence_issued = False;
RD_BOOL g_licence_error_result = False;
/* Generate a session key and RC4 keys, given client and server randoms */ /* Generate a session key and RC4 keys, given client and server randoms */
static void static void
@ -65,21 +69,21 @@ licence_generate_hwid(uint8 * hwid)
strncpy((char *) (hwid + 4), g_hostname, LICENCE_HWID_SIZE - 4); strncpy((char *) (hwid + 4), g_hostname, LICENCE_HWID_SIZE - 4);
} }
/* Present an existing licence to the server */ /* Send a lincece info packet to server */
static void static void
licence_present(uint8 * client_random, uint8 * rsa_data, licence_info(uint8 * client_random, uint8 * rsa_data,
uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature) uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
{ {
uint32 sec_flags = SEC_LICENCE_NEG; uint32 sec_flags = SEC_LICENCE_NEG;
uint16 length = uint16 length =
16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + 24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE; licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
STREAM s; STREAM s;
s = sec_init(sec_flags, length + 4); s = sec_init(sec_flags, length + 2);
out_uint8(s, LICENCE_TAG_PRESENT); out_uint8(s, LICENCE_TAG_LICENCE_INFO);
out_uint8(s, 2); /* version */ out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
out_uint16_le(s, length); out_uint16_le(s, length);
out_uint32_le(s, 1); out_uint32_le(s, 1);
@ -87,7 +91,7 @@ licence_present(uint8 * client_random, uint8 * rsa_data,
out_uint16_le(s, 0x0201); out_uint16_le(s, 0x0201);
out_uint8p(s, client_random, SEC_RANDOM_SIZE); out_uint8p(s, client_random, SEC_RANDOM_SIZE);
out_uint16(s, 0); out_uint16_le(s, 2);
out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE)); out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
out_uint8p(s, rsa_data, SEC_MODULUS_SIZE); out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
out_uint8s(s, SEC_PADDING_SIZE); out_uint8s(s, SEC_PADDING_SIZE);
@ -106,37 +110,40 @@ licence_present(uint8 * client_random, uint8 * rsa_data,
sec_send(s, sec_flags); sec_send(s, sec_flags);
} }
/* Send a licence request packet */ /* Send a new licence request packet */
static void static void
licence_send_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host) licence_send_new_licence_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
{ {
uint32 sec_flags = SEC_LICENCE_NEG; uint32 sec_flags = SEC_LICENCE_NEG;
uint16 userlen = strlen(user) + 1; uint16 userlen = strlen(user) + 1;
uint16 hostlen = strlen(host) + 1; uint16 hostlen = strlen(host) + 1;
uint16 length = 128 + userlen + hostlen; uint16 length =
24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + userlen + hostlen;
STREAM s; STREAM s;
s = sec_init(sec_flags, length + 2); s = sec_init(sec_flags, length + 2);
out_uint8(s, LICENCE_TAG_REQUEST); out_uint8(s, LICENCE_TAG_NEW_LICENCE_REQUEST);
out_uint8(s, 2); /* version */ out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
out_uint16_le(s, length); out_uint16_le(s, length);
out_uint32_le(s, 1); out_uint32_le(s, 1); // KEY_EXCHANGE_ALG_RSA
out_uint16(s, 0); out_uint16(s, 0);
out_uint16_le(s, 0xff01); out_uint16_le(s, 0xff01);
out_uint8p(s, client_random, SEC_RANDOM_SIZE); out_uint8p(s, client_random, SEC_RANDOM_SIZE);
out_uint16(s, 0); out_uint16_le(s, 2);
out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE)); out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
out_uint8p(s, rsa_data, SEC_MODULUS_SIZE); out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
out_uint8s(s, SEC_PADDING_SIZE); out_uint8s(s, SEC_PADDING_SIZE);
out_uint16_le(s, LICENCE_TAG_USER); /* Username LICENSE_BINARY_BLOB */
out_uint16_le(s, BB_CLIENT_USER_NAME_BLOB);
out_uint16_le(s, userlen); out_uint16_le(s, userlen);
out_uint8p(s, user, userlen); out_uint8p(s, user, userlen);
out_uint16_le(s, LICENCE_TAG_HOST); /* Machinename LICENSE_BINARY_BLOB */
out_uint16_le(s, BB_CLIENT_MACHINE_NAME_BLOB);
out_uint16_le(s, hostlen); out_uint16_le(s, hostlen);
out_uint8p(s, host, hostlen); out_uint8p(s, host, hostlen);
@ -144,9 +151,9 @@ licence_send_request(uint8 * client_random, uint8 * rsa_data, char *user, char *
sec_send(s, sec_flags); sec_send(s, sec_flags);
} }
/* Process a licence demand packet */ /* Process a licence request packet */
static void static void
licence_process_demand(STREAM s) licence_process_request(STREAM s)
{ {
uint8 null_data[SEC_MODULUS_SIZE]; uint8 null_data[SEC_MODULUS_SIZE];
uint8 *server_random; uint8 *server_random;
@ -177,17 +184,24 @@ licence_process_demand(STREAM s)
ssl_rc4_crypt(crypt_key, (char *)hwid, (char *)hwid, sizeof(hwid)); ssl_rc4_crypt(crypt_key, (char *)hwid, (char *)hwid, sizeof(hwid));
ssl_rc4_info_delete(crypt_key); ssl_rc4_info_delete(crypt_key);
licence_present(null_data, null_data, licence_data, licence_size, hwid, signature); #if WITH_DEBUG
DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_LICENCE_INFO));
#endif
licence_info(null_data, null_data, licence_data, licence_size, hwid, signature);
xfree(licence_data); xfree(licence_data);
return; return;
} }
licence_send_request(null_data, null_data, g_username, g_hostname); #if WITH_DEBUG
DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_NEW_LICENCE_REQUEST));
#endif
licence_send_new_licence_request(null_data, null_data, g_username, g_hostname);
} }
/* Send an authentication response packet */ /* Send a platform challange response packet */
static void static void
licence_send_authresp(uint8 * token, uint8 * crypt_hwid, uint8 * signature) licence_send_platform_challange_response(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
{ {
uint32 sec_flags = SEC_LICENCE_NEG; uint32 sec_flags = SEC_LICENCE_NEG;
uint16 length = 58; uint16 length = 58;
@ -195,8 +209,8 @@ licence_send_authresp(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
s = sec_init(sec_flags, length + 2); s = sec_init(sec_flags, length + 2);
out_uint8(s, LICENCE_TAG_AUTHRESP); out_uint8(s, LICENCE_TAG_PLATFORM_CHALLANGE_RESPONSE);
out_uint8(s, 2); /* version */ out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
out_uint16_le(s, length); out_uint16_le(s, length);
out_uint16_le(s, 1); out_uint16_le(s, 1);
@ -213,9 +227,9 @@ licence_send_authresp(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
sec_send(s, sec_flags); sec_send(s, sec_flags);
} }
/* Parse an authentication request packet */ /* Parse an platform challange request packet */
static BOOL static RD_BOOL
licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature) licence_parse_platform_challange(STREAM s, uint8 ** token, uint8 ** signature)
{ {
uint16 tokenlen; uint16 tokenlen;
@ -234,9 +248,9 @@ licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature)
return s_check_end(s); return s_check_end(s);
} }
/* Process an authentication request packet */ /* Process a platform challange packet */
static void static void
licence_process_authreq(STREAM s) licence_process_platform_challange(STREAM s)
{ {
uint8 *in_token = NULL, *in_sig; uint8 *in_token = NULL, *in_sig;
uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE]; uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
@ -246,7 +260,7 @@ licence_process_authreq(STREAM s)
void * crypt_key; void * crypt_key;
/* Parse incoming packet and save the encrypted token */ /* Parse incoming packet and save the encrypted token */
licence_parse_authreq(s, &in_token, &in_sig); licence_parse_platform_challange(s, &in_token, &in_sig);
memcpy(out_token, in_token, LICENCE_TOKEN_SIZE); memcpy(out_token, in_token, LICENCE_TOKEN_SIZE);
/* Decrypt the token. It should read TEST in Unicode. */ /* Decrypt the token. It should read TEST in Unicode. */
@ -267,19 +281,18 @@ licence_process_authreq(STREAM s)
ssl_rc4_crypt(crypt_key, (char *)hwid, (char *)crypt_hwid, LICENCE_HWID_SIZE); ssl_rc4_crypt(crypt_key, (char *)hwid, (char *)crypt_hwid, LICENCE_HWID_SIZE);
ssl_rc4_info_delete(crypt_key); ssl_rc4_info_delete(crypt_key);
licence_send_authresp(out_token, crypt_hwid, out_sig); licence_send_platform_challange_response(out_token, crypt_hwid, out_sig);
} }
/* Process an licence issue packet */ /* Process a new licence packet */
static void static void
licence_process_issue(STREAM s) licence_process_new_license(STREAM s)
{ {
void * crypt_key; void * crypt_key;
uint32 length; uint32 length;
uint16 check;
int i; int i;
in_uint8s(s, 2); /* 3d 45 - unknown */ in_uint8s(s, 2); // Skip license binary blob type
in_uint16_le(s, length); in_uint16_le(s, length);
if (!s_check_rem(s, length)) if (!s_check_rem(s, length))
return; return;
@ -289,15 +302,11 @@ licence_process_issue(STREAM s)
ssl_rc4_crypt(crypt_key, (char *)s->p, (char *)s->p, length); ssl_rc4_crypt(crypt_key, (char *)s->p, (char *)s->p, length);
ssl_rc4_info_delete(crypt_key); ssl_rc4_info_delete(crypt_key);
in_uint16(s, check); /* Parse NEW_LICENSE_INFO block */
if (check != 0) in_uint8s(s, 4); // skip dwVersion
return;
g_licence_issued = True; /* Skip strings, Scope, CompanyName and ProductId to get
to the LicenseInfo which we store in license blob. */
in_uint8s(s, 2); /* pad */
/* advance to fourth string */
length = 0; length = 0;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
@ -311,6 +320,60 @@ licence_process_issue(STREAM s)
save_licence(s->p, length); save_licence(s->p, length);
} }
/* process a licence error alert packet */
void
licence_process_error_alert(STREAM s)
{
uint32 error_code;
uint32 state_transition;
uint32 error_info;
in_uint32(s, error_code);
in_uint32(s, state_transition);
in_uint32(s, error_info);
/* There is a special case in the error alert handling, when licensing is all good
and the server is not sending a license to client, a "Server License Error PDU -
Valid Client" packet is sent which means, every thing is ok.
Therefor we should flag that everything is ok with license here.
*/
if (error_code == 0x07)
{
g_licence_issued = True;
return;
}
/* handle error codes, for now, jsut report them */
switch (error_code)
{
case 0x6: // ERR_NO_LICENSE_SERVER
warning("License error alert from server: No license server\n");
break;
case 0x8: // ERR_INVALID_CLIENT
warning("License error alert from server: Invalid client\n");
break;
case 0x4: // ERR_INVALID_SCOPE
case 0xb: // ERR_INVALID_PRODUCTID
case 0xc: // ERR_INVALID_MESSAGE_LENGTH
default:
warning("License error alert from server: code %u, state transition %u\n",
error_code, state_transition);
break;
}
/* handle error codes, for now, jsut report them */
switch (error_info)
{
default:
break;
}
g_licence_error_result = True;
}
/* Process a licence packet */ /* Process a licence packet */
void void
licence_process(STREAM s) licence_process(STREAM s)
@ -320,25 +383,31 @@ licence_process(STREAM s)
in_uint8(s, tag); in_uint8(s, tag);
in_uint8s(s, 3); /* version, length */ in_uint8s(s, 3); /* version, length */
#if WITH_DEBUG
DEBUG(("Received licensing PDU (message type 0x%02x)\n", tag));
#endif
switch (tag) switch (tag)
{ {
case LICENCE_TAG_DEMAND: case LICENCE_TAG_REQUEST:
licence_process_demand(s); licence_process_request(s);
break; break;
case LICENCE_TAG_AUTHREQ: case LICENCE_TAG_PLATFORM_CHALLANGE:
licence_process_authreq(s); licence_process_platform_challange(s);
break; break;
case LICENCE_TAG_ISSUE: case LICENCE_TAG_NEW_LICENCE:
licence_process_issue(s); case LICENCE_TAG_UPGRADE_LICENCE:
/* we can handle new and upgrades of licences the same way. */
licence_process_new_license(s);
break; break;
case LICENCE_TAG_REISSUE: case LICENCE_TAG_ERROR_ALERT:
case LICENCE_TAG_RESULT: licence_process_error_alert(s);
break; break;
default: default:
unimpl("licence tag 0x%x\n", tag); unimpl("licence tag 0x%02x\n", tag);
} }
} }

View file

@ -1,11 +1,12 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Protocol services - Multipoint Communications Service Protocol services - Multipoint Communications Service
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,9 +14,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
@ -24,70 +24,6 @@ uint16 g_mcs_userid;
extern VCHANNEL g_channels[]; extern VCHANNEL g_channels[];
extern unsigned int g_num_channels; extern unsigned int g_num_channels;
/* Parse an ASN.1 BER header */
static BOOL
ber_parse_header(STREAM s, int tagval, int *length)
{
int tag, len;
if (tagval > 0xff)
{
in_uint16_be(s, tag);
}
else
{
in_uint8(s, tag)}
if (tag != tagval)
{
error("expected tag %d, got %d\n", tagval, tag);
return False;
}
in_uint8(s, len);
if (len & 0x80)
{
len &= ~0x80;
*length = 0;
while (len--)
next_be(s, *length);
}
else
*length = len;
return s_check(s);
}
/* Output an ASN.1 BER header */
static void
ber_out_header(STREAM s, int tagval, int length)
{
if (tagval > 0xff)
{
out_uint16_be(s, tagval);
}
else
{
out_uint8(s, tagval);
}
if (length >= 0x80)
{
out_uint8(s, 0x82);
out_uint16_be(s, length);
}
else
out_uint8(s, length);
}
/* Output an ASN.1 BER integer */
static void
ber_out_integer(STREAM s, int value)
{
ber_out_header(s, BER_TAG_INTEGER, 2);
out_uint16_be(s, value);
}
/* Output a DOMAIN_PARAMS structure (ASN.1 BER) */ /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
static void static void
@ -105,7 +41,7 @@ mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens,
} }
/* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */ /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
static BOOL static RD_BOOL
mcs_parse_domain_params(STREAM s) mcs_parse_domain_params(STREAM s)
{ {
int length; int length;
@ -147,7 +83,7 @@ mcs_send_connect_initial(STREAM mcs_data)
} }
/* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */ /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
static BOOL static RD_BOOL
mcs_recv_connect_response(STREAM mcs_data) mcs_recv_connect_response(STREAM mcs_data)
{ {
uint8 result; uint8 result;
@ -221,7 +157,7 @@ mcs_send_aurq(void)
} }
/* Expect a AUcf message (ASN.1 PER) */ /* Expect a AUcf message (ASN.1 PER) */
static BOOL static RD_BOOL
mcs_recv_aucf(uint16 * mcs_userid) mcs_recv_aucf(uint16 * mcs_userid)
{ {
uint8 opcode, result; uint8 opcode, result;
@ -270,7 +206,7 @@ mcs_send_cjrq(uint16 chanid)
} }
/* Expect a CJcf message (ASN.1 PER) */ /* Expect a CJcf message (ASN.1 PER) */
static BOOL static RD_BOOL
mcs_recv_cjcf(void) mcs_recv_cjcf(void)
{ {
uint8 opcode, result; uint8 opcode, result;
@ -371,56 +307,18 @@ mcs_recv(uint16 * channel, uint8 * rdpver)
return s; return s;
} }
/* Establish a connection up to the MCS layer */ RD_BOOL
BOOL mcs_connect_start(char *server, char *username, char *domain, char *password,
mcs_connect(char *server, STREAM mcs_data, char *username) RD_BOOL reconnect, uint32 * selected_protocol)
{ {
unsigned int i; return iso_connect(server, username, domain, password, reconnect, selected_protocol);
if (!iso_connect(server, username))
return False;
mcs_send_connect_initial(mcs_data);
if (!mcs_recv_connect_response(mcs_data))
goto error;
mcs_send_edrq();
mcs_send_aurq();
if (!mcs_recv_aucf(&g_mcs_userid))
goto error;
mcs_send_cjrq((uint16) (g_mcs_userid + MCS_USERCHANNEL_BASE));
if (!mcs_recv_cjcf())
goto error;
mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
if (!mcs_recv_cjcf())
goto error;
for (i = 0; i < g_num_channels; i++)
{
mcs_send_cjrq(g_channels[i].mcs_id);
if (!mcs_recv_cjcf())
goto error;
}
return True;
error:
iso_disconnect();
return False;
} }
/* Establish a connection up to the MCS layer */ RD_BOOL
BOOL mcs_connect_finalize(STREAM mcs_data)
mcs_reconnect(char *server, STREAM mcs_data)
{ {
unsigned int i; unsigned int i;
if (!iso_reconnect(server))
return False;
mcs_send_connect_initial(mcs_data); mcs_send_connect_initial(mcs_data);
if (!mcs_recv_connect_response(mcs_data)) if (!mcs_recv_connect_response(mcs_data))
goto error; goto error;
@ -431,7 +329,7 @@ mcs_reconnect(char *server, STREAM mcs_data)
if (!mcs_recv_aucf(&g_mcs_userid)) if (!mcs_recv_aucf(&g_mcs_userid))
goto error; goto error;
mcs_send_cjrq((uint16) (g_mcs_userid + MCS_USERCHANNEL_BASE)); mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);
if (!mcs_recv_cjcf()) if (!mcs_recv_cjcf())
goto error; goto error;

View file

@ -1,11 +1,11 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Protocol services - RDP decompression Protocol services - RDP decompression
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,11 +13,13 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <stdio.h>
#include <string.h>
#include "precomp.h" #include "precomp.h"
/* mppc decompression */ /* mppc decompression */
@ -60,7 +62,7 @@ mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen
int next_offset, match_off; int next_offset, match_off;
int match_len; int match_len;
int old_offset, match_bits; int old_offset, match_bits;
BOOL big = ctype & RDP_MPPC_BIG ? True : False; RD_BOOL big = ctype & RDP_MPPC_BIG ? True : False;
uint8 *dict = g_mppc_dict.hist; uint8 *dict = g_mppc_dict.hist;

View file

@ -1,11 +1,11 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
RDP order processing RDP order processing
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,18 +13,16 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
#include "orders.h" #include "orders.h"
extern uint8 *g_next_packet; extern uint8 *g_next_packet;
static RDP_ORDER_STATE g_order_state; static RDP_ORDER_STATE g_order_state;
extern BOOL g_use_rdp5; extern RDP_VERSION g_rdp_version;
/* Read field indicating which parameters are present */ /* Read field indicating which parameters are present */
static void static void
@ -56,7 +54,7 @@ rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size)
/* Read a co-ordinate (16-bit, or 8-bit delta) */ /* Read a co-ordinate (16-bit, or 8-bit delta) */
static void static void
rdp_in_coord(STREAM s, sint16 * coord, BOOL delta) rdp_in_coord(STREAM s, sint16 * coord, RD_BOOL delta)
{ {
sint8 change; sint8 change;
@ -103,7 +101,7 @@ rdp_in_colour(STREAM s, uint32 * colour)
} }
/* Parse bounds information */ /* Parse bounds information */
static BOOL static RD_BOOL
rdp_parse_bounds(STREAM s, BOUNDS * bounds) rdp_parse_bounds(STREAM s, BOUNDS * bounds)
{ {
uint8 present; uint8 present;
@ -134,7 +132,7 @@ rdp_parse_bounds(STREAM s, BOUNDS * bounds)
} }
/* Parse a pen */ /* Parse a pen */
static BOOL static RD_BOOL
rdp_parse_pen(STREAM s, PEN * pen, uint32 present) rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
{ {
if (present & 1) if (present & 1)
@ -149,8 +147,35 @@ rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
return s_check(s); return s_check(s);
} }
static void
setup_brush(BRUSH * out_brush, BRUSH * in_brush)
{
BRUSHDATA *brush_data;
uint8 cache_idx;
uint8 colour_code;
memcpy(out_brush, in_brush, sizeof(BRUSH));
if (out_brush->style & 0x80)
{
colour_code = out_brush->style & 0x0f;
cache_idx = out_brush->pattern[0];
brush_data = cache_get_brush_data(colour_code, cache_idx);
if ((brush_data == NULL) || (brush_data->data == NULL))
{
error("error getting brush data, style %x\n", out_brush->style);
out_brush->bd = NULL;
memset(out_brush->pattern, 0, 8);
}
else
{
out_brush->bd = brush_data;
}
out_brush->style = 3;
}
}
/* Parse a brush */ /* Parse a brush */
static BOOL static RD_BOOL
rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present) rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
{ {
if (present & 1) if (present & 1)
@ -173,7 +198,7 @@ rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
/* Process a destination blt order */ /* Process a destination blt order */
static void static void
process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta) process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, RD_BOOL delta)
{ {
if (present & 0x01) if (present & 0x01)
rdp_in_coord(s, &os->x, delta); rdp_in_coord(s, &os->x, delta);
@ -198,8 +223,10 @@ process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta)
/* Process a pattern blt order */ /* Process a pattern blt order */
static void static void
process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta) process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, RD_BOOL delta)
{ {
BRUSH brush;
if (present & 0x0001) if (present & 0x0001)
rdp_in_coord(s, &os->x, delta); rdp_in_coord(s, &os->x, delta);
@ -226,13 +253,15 @@ process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta)
DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os->opcode, os->x, DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os->opcode, os->x,
os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour)); os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour));
setup_brush(&brush, &os->brush);
ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy, ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
&os->brush, os->bgcolour, os->fgcolour); &brush, os->bgcolour, os->fgcolour);
} }
/* Process a screen blt order */ /* Process a screen blt order */
static void static void
process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta) process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, RD_BOOL delta)
{ {
if (present & 0x0001) if (present & 0x0001)
rdp_in_coord(s, &os->x, delta); rdp_in_coord(s, &os->x, delta);
@ -263,7 +292,7 @@ process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta)
/* Process a line order */ /* Process a line order */
static void static void
process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta) process_line(STREAM s, LINE_ORDER * os, uint32 present, RD_BOOL delta)
{ {
if (present & 0x0001) if (present & 0x0001)
in_uint16_le(s, os->mixmode); in_uint16_le(s, os->mixmode);
@ -297,12 +326,12 @@ process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta)
return; return;
} }
ui_line(ROP_MINUS_1(os->opcode), os->startx, os->starty, os->endx, os->endy, &os->pen); ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen);
} }
/* Process an opaque rectangle order */ /* Process an opaque rectangle order */
static void static void
process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta) process_rect(STREAM s, RECT_ORDER * os, uint32 present, RD_BOOL delta)
{ {
uint32 i; uint32 i;
if (present & 0x01) if (present & 0x01)
@ -342,7 +371,7 @@ process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta)
/* Process a desktop save order */ /* Process a desktop save order */
static void static void
process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta) process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, RD_BOOL delta)
{ {
int width, height; int width, height;
@ -378,9 +407,9 @@ process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta)
/* Process a memory blt order */ /* Process a memory blt order */
static void static void
process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta) process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, RD_BOOL delta)
{ {
HBITMAP bitmap; RD_HBITMAP bitmap;
if (present & 0x0001) if (present & 0x0001)
{ {
@ -424,9 +453,10 @@ process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta)
/* Process a 3-way blt order */ /* Process a 3-way blt order */
static void static void
process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta) process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, RD_BOOL delta)
{ {
HBITMAP bitmap; RD_HBITMAP bitmap;
BRUSH brush;
if (present & 0x000001) if (present & 0x000001)
{ {
@ -477,17 +507,19 @@ process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta)
if (bitmap == NULL) if (bitmap == NULL)
return; return;
setup_brush(&brush, &os->brush);
ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy, ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour); bitmap, os->srcx, os->srcy, &brush, os->bgcolour, os->fgcolour);
} }
/* Process a polygon order */ /* Process a polygon order */
static void static void
process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, BOOL delta) process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, RD_BOOL delta)
{ {
int index, data, next; int index, data, next;
uint8 flags = 0; uint8 flags = 0;
POINT *points; RD_POINT *points;
if (present & 0x01) if (present & 0x01)
rdp_in_coord(s, &os->x, delta); rdp_in_coord(s, &os->x, delta);
@ -529,8 +561,8 @@ process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, BOOL delta)
return; return;
} }
points = (POINT *) xmalloc((os->npoints + 1) * sizeof(POINT)); points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT));
memset(points, 0, (os->npoints + 1) * sizeof(POINT)); memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT));
points[0].x = os->x; points[0].x = os->x;
points[0].y = os->y; points[0].y = os->y;
@ -552,7 +584,7 @@ process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, BOOL delta)
} }
if (next - 1 == os->npoints) if (next - 1 == os->npoints)
ui_polygon(ROP_MINUS_1(os->opcode), os->fillmode, points, os->npoints + 1, NULL, 0, ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1, NULL, 0,
os->fgcolour); os->fgcolour);
else else
error("polygon parse error\n"); error("polygon parse error\n");
@ -562,11 +594,12 @@ process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, BOOL delta)
/* Process a polygon2 order */ /* Process a polygon2 order */
static void static void
process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, BOOL delta) process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, RD_BOOL delta)
{ {
int index, data, next; int index, data, next;
uint8 flags = 0; uint8 flags = 0;
POINT *points; RD_POINT *points;
BRUSH brush;
if (present & 0x0001) if (present & 0x0001)
rdp_in_coord(s, &os->x, delta); rdp_in_coord(s, &os->x, delta);
@ -614,8 +647,10 @@ process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, BOOL delta)
return; return;
} }
points = (POINT *) xmalloc((os->npoints + 1) * sizeof(POINT)); setup_brush(&brush, &os->brush);
memset(points, 0, (os->npoints + 1) * sizeof(POINT));
points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT));
memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT));
points[0].x = os->x; points[0].x = os->x;
points[0].y = os->y; points[0].y = os->y;
@ -637,8 +672,8 @@ process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, BOOL delta)
} }
if (next - 1 == os->npoints) if (next - 1 == os->npoints)
ui_polygon(ROP_MINUS_1(os->opcode), os->fillmode, points, os->npoints + 1, ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1,
&os->brush, os->bgcolour, os->fgcolour); &brush, os->bgcolour, os->fgcolour);
else else
error("polygon2 parse error\n"); error("polygon2 parse error\n");
@ -647,12 +682,12 @@ process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, BOOL delta)
/* Process a polyline order */ /* Process a polyline order */
static void static void
process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta) process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, RD_BOOL delta)
{ {
int index, next, data; int index, next, data;
uint8 flags = 0; uint8 flags = 0;
PEN pen; PEN pen;
POINT *points; RD_POINT *points;
if (present & 0x01) if (present & 0x01)
rdp_in_coord(s, &os->x, delta); rdp_in_coord(s, &os->x, delta);
@ -691,8 +726,8 @@ process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
return; return;
} }
points = (POINT *) xmalloc((os->lines + 1) * sizeof(POINT)); points = (RD_POINT *) xmalloc((os->lines + 1) * sizeof(RD_POINT));
memset(points, 0, (os->lines + 1) * sizeof(POINT)); memset(points, 0, (os->lines + 1) * sizeof(RD_POINT));
points[0].x = os->x; points[0].x = os->x;
points[0].y = os->y; points[0].y = os->y;
@ -716,7 +751,7 @@ process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
} }
if (next - 1 == os->lines) if (next - 1 == os->lines)
ui_polyline(ROP_MINUS_1(os->opcode), points, os->lines + 1, &pen); ui_polyline(os->opcode - 1, points, os->lines + 1, &pen);
else else
error("polyline parse error\n"); error("polyline parse error\n");
@ -725,7 +760,7 @@ process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
/* Process an ellipse order */ /* Process an ellipse order */
static void static void
process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, BOOL delta) process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, RD_BOOL delta)
{ {
if (present & 0x01) if (present & 0x01)
rdp_in_coord(s, &os->left, delta); rdp_in_coord(s, &os->left, delta);
@ -751,14 +786,16 @@ process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, BOOL delta)
DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os->left, os->top, DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os->left, os->top,
os->right, os->bottom, os->opcode, os->fillmode, os->fgcolour)); os->right, os->bottom, os->opcode, os->fillmode, os->fgcolour));
ui_ellipse(ROP_MINUS_1(os->opcode), os->fillmode, os->left, os->top, os->right - os->left, ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
os->bottom - os->top, NULL, 0, os->fgcolour); os->bottom - os->top, NULL, 0, os->fgcolour);
} }
/* Process an ellipse2 order */ /* Process an ellipse2 order */
static void static void
process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, BOOL delta) process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, RD_BOOL delta)
{ {
BRUSH brush;
if (present & 0x0001) if (present & 0x0001)
rdp_in_coord(s, &os->left, delta); rdp_in_coord(s, &os->left, delta);
@ -789,15 +826,18 @@ process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, BOOL delta)
os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style, os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style,
os->bgcolour, os->fgcolour)); os->bgcolour, os->fgcolour));
ui_ellipse(ROP_MINUS_1(os->opcode), os->fillmode, os->left, os->top, os->right - os->left, setup_brush(&brush, &os->brush);
os->bottom - os->top, &os->brush, os->bgcolour, os->fgcolour);
ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
os->bottom - os->top, &brush, os->bgcolour, os->fgcolour);
} }
/* Process a text order */ /* Process a text order */
static void static void
process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta) process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, RD_BOOL delta)
{ {
int i; int i;
BRUSH brush;
if (present & 0x000001) if (present & 0x000001)
in_uint8(s, os->font); in_uint8(s, os->font);
@ -864,18 +904,20 @@ process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta)
DEBUG(("\n")); DEBUG(("\n"));
ui_draw_text(os->font, os->flags, ROP_MINUS_1(os->opcode), os->mixmode, os->x, os->y, setup_brush(&brush, &os->brush);
ui_draw_text(os->font, os->flags, os->opcode - 1, os->mixmode, os->x, os->y,
os->clipleft, os->cliptop, os->clipright - os->clipleft, os->clipleft, os->cliptop, os->clipright - os->clipleft,
os->clipbottom - os->cliptop, os->boxleft, os->boxtop, os->clipbottom - os->cliptop, os->boxleft, os->boxtop,
os->boxright - os->boxleft, os->boxbottom - os->boxtop, os->boxright - os->boxleft, os->boxbottom - os->boxtop,
&os->brush, os->bgcolour, os->fgcolour, os->text, os->length); &brush, os->bgcolour, os->fgcolour, os->text, os->length);
} }
/* Process a raw bitmap cache order */ /* Process a raw bitmap cache order */
static void static void
process_raw_bmpcache(STREAM s) process_raw_bmpcache(STREAM s)
{ {
HBITMAP bitmap; RD_HBITMAP bitmap;
uint16 cache_idx, bufsize; uint16 cache_idx, bufsize;
uint8 cache_id, width, height, bpp, Bpp; uint8 cache_id, width, height, bpp, Bpp;
uint8 *data, *inverted; uint8 *data, *inverted;
@ -908,7 +950,7 @@ process_raw_bmpcache(STREAM s)
static void static void
process_bmpcache(STREAM s) process_bmpcache(STREAM s)
{ {
HBITMAP bitmap; RD_HBITMAP bitmap;
uint16 cache_idx, size; uint16 cache_idx, size;
uint8 cache_id, width, height, bpp, Bpp; uint8 cache_id, width, height, bpp, Bpp;
uint8 *data, *bmpdata; uint8 *data, *bmpdata;
@ -926,7 +968,7 @@ process_bmpcache(STREAM s)
in_uint16_le(s, bufsize); /* bufsize */ in_uint16_le(s, bufsize); /* bufsize */
in_uint16_le(s, cache_idx); in_uint16_le(s, cache_idx);
if (g_use_rdp5) if (g_rdp_version >= RDP_V5)
{ {
size = bufsize; size = bufsize;
} }
@ -944,7 +986,6 @@ process_bmpcache(STREAM s)
in_uint8p(s, data, size); in_uint8p(s, data, size);
DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d,bpp=%d,size=%d,pad1=%d,bufsize=%d,pad2=%d,rs=%d,fs=%d)\n", width, height, cache_id, cache_idx, bpp, size, pad1, bufsize, pad2, row_size, final_size)); DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d,bpp=%d,size=%d,pad1=%d,bufsize=%d,pad2=%d,rs=%d,fs=%d)\n", width, height, cache_id, cache_idx, bpp, size, pad1, bufsize, pad2, row_size, final_size));
(void)pad1; (void)pad2;
bmpdata = (uint8 *) xmalloc(width * height * Bpp); bmpdata = (uint8 *) xmalloc(width * height * Bpp);
@ -957,15 +998,16 @@ process_bmpcache(STREAM s)
{ {
DEBUG(("Failed to decompress bitmap data\n")); DEBUG(("Failed to decompress bitmap data\n"));
} }
if (pad1 || pad2) {}
xfree(bmpdata); xfree(bmpdata);
} }
/* Process a bitmap cache v2 order */ /* Process a bitmap cache v2 order */
static void static void
process_bmpcache2(STREAM s, uint16 flags, BOOL compressed) process_bmpcache2(STREAM s, uint16 flags, RD_BOOL compressed)
{ {
HBITMAP bitmap; RD_HBITMAP bitmap;
int y; int y;
uint8 cache_id, cache_idx_low, width, height, Bpp; uint8 cache_id, cache_idx_low, width, height, Bpp;
uint16 cache_idx, bufsize; uint16 cache_idx, bufsize;
@ -1031,7 +1073,7 @@ process_bmpcache2(STREAM s, uint16 flags, BOOL compressed)
cache_put_bitmap(cache_id, cache_idx, bitmap); cache_put_bitmap(cache_id, cache_idx, bitmap);
if (flags & PERSIST) if (flags & PERSIST)
pstcache_save_bitmap(cache_id, cache_idx, bitmap_id, width, height, pstcache_save_bitmap(cache_id, cache_idx, bitmap_id, width, height,
(uint16) (width * height * Bpp), bmpdata); width * height * Bpp, bmpdata);
} }
else else
{ {
@ -1106,6 +1148,109 @@ process_fontcache(STREAM s)
} }
} }
static void
process_compressed_8x8_brush_data(uint8 * in, uint8 * out, int Bpp)
{
int x, y, pal_index, in_index, shift, do2, i;
uint8 *pal;
in_index = 0;
pal = in + 16;
/* read it bottom up */
for (y = 7; y >= 0; y--)
{
/* 2 bytes per row */
x = 0;
for (do2 = 0; do2 < 2; do2++)
{
/* 4 pixels per byte */
shift = 6;
while (shift >= 0)
{
pal_index = (in[in_index] >> shift) & 3;
/* size of palette entries depends on Bpp */
for (i = 0; i < Bpp; i++)
{
out[(y * 8 + x) * Bpp + i] = pal[pal_index * Bpp + i];
}
x++;
shift -= 2;
}
in_index++;
}
}
}
/* Process a brush cache order */
static void
process_brushcache(STREAM s, uint16 flags)
{
BRUSHDATA brush_data;
uint8 cache_idx, colour_code, width, height, size, type;
uint8 *comp_brush;
int index;
int Bpp;
in_uint8(s, cache_idx);
in_uint8(s, colour_code);
in_uint8(s, width);
in_uint8(s, height);
in_uint8(s, type); /* type, 0x8x = cached */
in_uint8(s, size);
DEBUG(("BRUSHCACHE(idx=%d,wd=%d,ht=%d,sz=%d)\n", cache_idx, width, height, size));
if ((width == 8) && (height == 8))
{
if (colour_code == 1)
{
brush_data.colour_code = 1;
brush_data.data_size = 8;
brush_data.data = xmalloc(8);
if (size == 8)
{
/* read it bottom up */
for (index = 7; index >= 0; index--)
{
in_uint8(s, brush_data.data[index]);
}
}
else
{
warning("incompatible brush, colour_code %d size %d\n", colour_code,
size);
}
cache_put_brush_data(1, cache_idx, &brush_data);
}
else if ((colour_code >= 3) && (colour_code <= 6))
{
Bpp = colour_code - 2;
brush_data.colour_code = colour_code;
brush_data.data_size = 8 * 8 * Bpp;
brush_data.data = xmalloc(8 * 8 * Bpp);
if (size == 16 + 4 * Bpp)
{
in_uint8p(s, comp_brush, 16 + 4 * Bpp);
process_compressed_8x8_brush_data(comp_brush, brush_data.data, Bpp);
}
else
{
in_uint8a(s, brush_data.data, 8 * 8 * Bpp);
}
cache_put_brush_data(colour_code, cache_idx, &brush_data);
}
else
{
warning("incompatible brush, colour_code %d size %d\n", colour_code, size);
}
}
else
{
warning("incompatible brush, width height %d %d\n", width, height);
}
if (type) {}
}
/* Process a secondary order */ /* Process a secondary order */
static void static void
process_secondary_order(STREAM s) process_secondary_order(STREAM s)
@ -1150,6 +1295,10 @@ process_secondary_order(STREAM s)
process_bmpcache2(s, flags, True); /* compressed */ process_bmpcache2(s, flags, True); /* compressed */
break; break;
case RDP_ORDER_BRUSHCACHE:
process_brushcache(s, flags);
break;
default: default:
unimpl("secondary order %d\n", type); unimpl("secondary order %d\n", type);
} }
@ -1165,7 +1314,7 @@ process_orders(STREAM s, uint16 num_orders)
uint32 present; uint32 present;
uint8 order_flags; uint8 order_flags;
int size, processed = 0; int size, processed = 0;
BOOL delta; RD_BOOL delta;
while (processed < num_orders) while (processed < num_orders)
{ {

View file

@ -1,11 +1,11 @@
/* /*
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
RDP order processing RDP order processing
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman 1999-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,13 +13,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#pragma once
#define RDP_ORDER_STANDARD 0x01 #define RDP_ORDER_STANDARD 0x01
#define RDP_ORDER_SECONDARY 0x02 #define RDP_ORDER_SECONDARY 0x02
#define RDP_ORDER_BOUNDS 0x04 #define RDP_ORDER_BOUNDS 0x04

View file

@ -1,11 +1,12 @@
/* /*
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Parsing primitives Parsing primitives
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman 1999-2008
Copyright 2012 Henrik Andersson <hean01@cendio.se> for Cendio AB
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,9 +14,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
/* Parser state */ /* Parser state */
@ -42,6 +42,8 @@ typedef struct stream
#define s_check(s) ((s)->p <= (s)->end) #define s_check(s) ((s)->p <= (s)->end)
#define s_check_rem(s,n) ((s)->p + n <= (s)->end) #define s_check_rem(s,n) ((s)->p + n <= (s)->end)
#define s_check_end(s) ((s)->p == (s)->end) #define s_check_end(s) ((s)->p == (s)->end)
#define s_length(s) ((s)->end - (s)->data)
#define s_reset(s) ((s)->end = (s)->p = (s)->data)
#if defined(L_ENDIAN) && !defined(NEED_ALIGN) #if defined(L_ENDIAN) && !defined(NEED_ALIGN)
#define in_uint16_le(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; } #define in_uint16_le(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; }

View file

@ -20,6 +20,22 @@
#ifndef __TODO_MSTSC_H #ifndef __TODO_MSTSC_H
#define __TODO_MSTSC_H #define __TODO_MSTSC_H
#define RDP_INFO_MOUSE 0x00000001
#define RDP_INFO_DISABLECTRLALTDEL 0x00000002
#define RDP_INFO_AUTOLOGON 0x00000008
#define RDP_INFO_UNICODE 0x00000010
#define RDP_INFO_MAXIMIZESHELL 0x00000020
#define RDP_INFO_COMPRESSION 0x00000080 /* mppc compression with 8kB histroy buffer */
#define RDP_INFO_ENABLEWINDOWSKEY 0x00000100
#define RDP_INFO_COMPRESSION2 0x00000200 /* rdp5 mppc compression with 64kB history buffer */
#define RDP_INFO_REMOTE_CONSOLE_AUDIO 0x00002000
#define RDP_INFO_PASSWORD_IS_SC_PIN 0x00040000
#define RDP5_DISABLE_NOTHING 0x00
#define RDP5_NO_WALLPAPER 0x01
#define RDP_LOGON_NORMAL (RDP_INFO_MOUSE | RDP_INFO_DISABLECTRLALTDEL | RDP_INFO_UNICODE | RDP_INFO_MAXIMIZESHELL)
#define IS_PERSISTENT(id) (id < 8 && g_pstcache_fd[id] > 0) #define IS_PERSISTENT(id) (id < 8 && g_pstcache_fd[id] > 0)
#define MAXKEY 256 #define MAXKEY 256

View file

@ -1,10 +1,10 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman 1999-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -12,20 +12,26 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#pragma once #ifndef RDESKTOP_PROTO_H
#define RDESKTOP_PROTO_H
/* *INDENT-OFF* */ /* *INDENT-OFF* */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* *INDENT-ON* */ /* *INDENT-ON* */
/* utils.c */
char *utils_string_escape(const char *str);
char *utils_string_unescape(const char *str);
int utils_locale_to_utf8(const char *src, size_t is, char *dest, size_t os);
int utils_mkdir_safe(const char *path, int mask);
int utils_mkdir_p(const char *path, int mask);
/* bitmap.c */ /* bitmap.c */
BOOL bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp); RD_BOOL bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp);
/* cache.c */ /* cache.c */
void cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count); void cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count);
void cache_bump_bitmap(uint8 id, uint16 idx, int bump); void cache_bump_bitmap(uint8 id, uint16 idx, int bump);
@ -43,6 +49,8 @@ void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_pe
uint8 * data); uint8 * data);
RD_HCURSOR cache_get_cursor(uint16 cache_idx); RD_HCURSOR cache_get_cursor(uint16 cache_idx);
void cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor); void cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor);
BRUSHDATA *cache_get_brush_data(uint8 colour_code, uint8 idx);
void cache_put_brush_data(uint8 colour_code, uint8 idx, BRUSHDATA * brush_data);
/* channels.c */ /* channels.c */
VCHANNEL *channel_register(char *name, uint32 flags, void (*callback) (STREAM)); VCHANNEL *channel_register(char *name, uint32 flags, void (*callback) (STREAM));
STREAM channel_init(VCHANNEL * channel, uint32 length); STREAM channel_init(VCHANNEL * channel, uint32 length);
@ -54,7 +62,15 @@ void cliprdr_send_native_format_announce(uint8 * formats_data, uint32 formats_da
void cliprdr_send_data_request(uint32 format); void cliprdr_send_data_request(uint32 format);
void cliprdr_send_data(uint8 * data, uint32 length); void cliprdr_send_data(uint8 * data, uint32 length);
void cliprdr_set_mode(const char *optarg); void cliprdr_set_mode(const char *optarg);
BOOL cliprdr_init(void); RD_BOOL cliprdr_init(void);
/* ctrl.c */
int ctrl_init(const char *user, const char *domain, const char *host);
void ctrl_cleanup();
RD_BOOL ctrl_is_slave();
int ctrl_send_command(const char *cmd, const char *args);
void ctrl_add_fds(int *n, fd_set * rfds);
void ctrl_check_fds(fd_set * rfds, fd_set * wfds);
/* disk.c */ /* disk.c */
int disk_enum_devices(uint32 * id, char *optarg); int disk_enum_devices(uint32 * id, char *optarg);
RD_NTSTATUS disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out); RD_NTSTATUS disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out);
@ -72,10 +88,12 @@ void ewmh_init(void);
STREAM iso_init(int length); STREAM iso_init(int length);
void iso_send(STREAM s); void iso_send(STREAM s);
STREAM iso_recv(uint8 * rdpver); STREAM iso_recv(uint8 * rdpver);
BOOL iso_connect(char *server, char *username); RD_BOOL iso_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect,
BOOL iso_reconnect(char *server); uint32 * selected_protocol);
void iso_disconnect(void); void iso_disconnect(void);
void iso_reset_state(void); void iso_reset_state(void);
/* cssp.c */
RD_BOOL cssp_connect(char *server, char *user, char *domain, char *password, STREAM s);
/* licence.c */ /* licence.c */
void licence_process(STREAM s); void licence_process(STREAM s);
/* mcs.c */ /* mcs.c */
@ -83,8 +101,9 @@ STREAM mcs_init(int length);
void mcs_send_to_channel(STREAM s, uint16 channel); void mcs_send_to_channel(STREAM s, uint16 channel);
void mcs_send(STREAM s); void mcs_send(STREAM s);
STREAM mcs_recv(uint16 * channel, uint8 * rdpver); STREAM mcs_recv(uint16 * channel, uint8 * rdpver);
BOOL mcs_connect(char *server, STREAM mcs_data, char *username); RD_BOOL mcs_connect_start(char *server, char *username, char *domain, char *password,
BOOL mcs_reconnect(char *server, STREAM mcs_data); RD_BOOL reconnect, uint32 * selected_protocol);
RD_BOOL mcs_connect_finalize(STREAM s);
void mcs_disconnect(void); void mcs_disconnect(void);
void mcs_reset_state(void); void mcs_reset_state(void);
/* orders.c */ /* orders.c */
@ -99,17 +118,18 @@ int printercache_load_blob(char *printer_name, uint8 ** data);
void printercache_process(STREAM s); void printercache_process(STREAM s);
/* pstcache.c */ /* pstcache.c */
void pstcache_touch_bitmap(uint8 cache_id, uint16 cache_idx, uint32 stamp); void pstcache_touch_bitmap(uint8 cache_id, uint16 cache_idx, uint32 stamp);
BOOL pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx); RD_BOOL pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx);
BOOL pstcache_save_bitmap(uint8 cache_id, uint16 cache_idx, uint8 * key, uint8 width, RD_BOOL pstcache_save_bitmap(uint8 cache_id, uint16 cache_idx, uint8 * key, uint8 width,
uint8 height, uint16 length, uint8 * data); uint8 height, uint16 length, uint8 * data);
int pstcache_enumerate(uint8 id, HASH_KEY * keylist); int pstcache_enumerate(uint8 id, HASH_KEY * keylist);
BOOL pstcache_init(uint8 cache_id); RD_BOOL pstcache_init(uint8 cache_id);
/* rdesktop.c */ /* rdesktop.c */
int main(int argc, char *argv[]); int main(int argc, char *argv[]);
void generate_random(uint8 * random); void generate_random(uint8 * random);
void *xmalloc(int size); void *xmalloc(int size);
void exit_if_null(void *ptr);
char *xstrdup(const char *s); char *xstrdup(const char *s);
void *xrealloc(void *oldmem, int size); void *xrealloc(void *oldmem, size_t size);
void xfree(void *mem); void xfree(void *mem);
void error(char *format, ...); void error(char *format, ...);
void warning(char *format, ...); void warning(char *format, ...);
@ -117,62 +137,67 @@ void unimpl(char *format, ...);
void hexdump(unsigned char *p, unsigned int len); void hexdump(unsigned char *p, unsigned int len);
char *next_arg(char *src, char needle); char *next_arg(char *src, char needle);
void toupper_str(char *p); void toupper_str(char *p);
BOOL str_startswith(const char *s, const char *prefix); RD_BOOL str_startswith(const char *s, const char *prefix);
BOOL str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data); RD_BOOL str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler,
BOOL subprocess(char *const argv[], str_handle_lines_t linehandler, void *data); void *data);
RD_BOOL subprocess(char *const argv[], str_handle_lines_t linehandler, void *data);
char *l_to_a(long N, int base); char *l_to_a(long N, int base);
int load_licence(unsigned char **data); int load_licence(unsigned char **data);
void save_licence(unsigned char *data, int length); void save_licence(unsigned char *data, int length);
BOOL rd_pstcache_mkdir(void); void rd_create_ui(void);
RD_BOOL rd_pstcache_mkdir(void);
int rd_open_file(char *filename); int rd_open_file(char *filename);
void rd_close_file(int fd); void rd_close_file(int fd);
int rd_read_file(int fd, void *ptr, int len); int rd_read_file(int fd, void *ptr, int len);
int rd_write_file(int fd, void *ptr, int len); int rd_write_file(int fd, void *ptr, int len);
int rd_lseek_file(int fd, int offset); int rd_lseek_file(int fd, int offset);
BOOL rd_lock_file(int fd, int start, int len); RD_BOOL rd_lock_file(int fd, int start, int len);
/* rdp5.c */ /* rdp5.c */
void rdp5_process(STREAM s); void rdp5_process(STREAM s);
/* rdp.c */ /* rdp.c */
void rdp_out_unistr(STREAM s, char *string, int len); void rdp_out_unistr(STREAM s, char *string, int len);
int rdp_in_unistr(STREAM s, char *string, int uni_len); void rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size);
void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1,
uint16 param2); uint16 param2);
void rdp_send_client_window_status(int status); void rdp_send_client_window_status(int status);
void process_colour_pointer_pdu(STREAM s); void process_colour_pointer_pdu(STREAM s);
void process_new_pointer_pdu(STREAM s);
void process_cached_pointer_pdu(STREAM s); void process_cached_pointer_pdu(STREAM s);
void process_system_pointer_pdu(STREAM s); void process_system_pointer_pdu(STREAM s);
void process_bitmap_updates(STREAM s); void process_bitmap_updates(STREAM s);
void process_palette(STREAM s); void process_palette(STREAM s);
void process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason); void process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason);
void rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason); void rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason);
BOOL rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason); RD_BOOL rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason);
BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, char *command, RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, char *command,
char *directory); char *directory, RD_BOOL reconnect);
BOOL rdp_reconnect(char *server, uint32 flags, char *domain, char *password, char *command,
char *directory, char *cookie);
void rdp_reset_state(void); void rdp_reset_state(void);
void rdp_disconnect(void); void rdp_disconnect(void);
/* rdpdr.c */ /* rdpdr.c */
int get_device_index(RD_NTHANDLE handle); int get_device_index(RD_NTHANDLE handle);
void convert_to_unix_filename(char *filename); void convert_to_unix_filename(char *filename);
BOOL rdpdr_init(void); void rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
void rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout); uint32 length);
RD_BOOL rdpdr_init();
void rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, RD_BOOL * timeout);
struct async_iorequest *rdpdr_remove_iorequest(struct async_iorequest *prev, struct async_iorequest *rdpdr_remove_iorequest(struct async_iorequest *prev,
struct async_iorequest *iorq); struct async_iorequest *iorq);
void rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out); void rdpdr_check_fds(fd_set * rfds, fd_set * wfds, RD_BOOL timed_out);
BOOL rdpdr_abort_io(uint32 fd, uint32 major, RD_NTSTATUS status); RD_BOOL rdpdr_abort_io(uint32 fd, uint32 major, RD_NTSTATUS status);
/* rdpsnd.c */ /* rdpsnd.c */
void rdpsnd_send_completion(uint16 tick, uint8 packet_index); void rdpsnd_record(const void *data, unsigned int size);
BOOL rdpsnd_init(void); RD_BOOL rdpsnd_init(char *optarg);
/* rdpsnd_oss.c */ void rdpsnd_show_help(void);
BOOL wave_out_open(void); void rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv);
void wave_out_close(void); void rdpsnd_check_fds(fd_set * rfds, fd_set * wfds);
BOOL wave_out_format_supported(WAVEFORMATEX * pwfx); struct audio_packet *rdpsnd_queue_current_packet(void);
BOOL wave_out_set_format(WAVEFORMATEX * pwfx); RD_BOOL rdpsnd_queue_empty(void);
void wave_out_volume(uint16 left, uint16 right); void rdpsnd_queue_next(unsigned long completed_in_us);
void wave_out_write(STREAM s, uint16 tick, uint8 index); int rdpsnd_queue_next_tick(void);
void wave_out_play(void); void rdpsnd_reset_state(void);
/* secure.c */ /* secure.c */
void sec_hash_to_string(char *out, int out_size, uint8 * in, int in_size);
void sec_hash_sha1_16(uint8 * out, uint8 * in, uint8 * salt1);
void sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt); void sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt);
void sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2); void sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2);
void buf_out_uint32(uint8 * buffer, uint32 value); void buf_out_uint32(uint8 * buffer, uint32 value);
@ -184,22 +209,33 @@ void sec_send_to_channel(STREAM s, uint32 flags, uint16 channel);
void sec_send(STREAM s, uint32 flags); void sec_send(STREAM s, uint32 flags);
void sec_process_mcs_data(STREAM s); void sec_process_mcs_data(STREAM s);
STREAM sec_recv(uint8 * rdpver); STREAM sec_recv(uint8 * rdpver);
BOOL sec_connect(char *server, char *username); RD_BOOL sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect);
BOOL sec_reconnect(char *server);
void sec_disconnect(void); void sec_disconnect(void);
void sec_reset_state(void); void sec_reset_state(void);
/* serial.c */ /* serial.c */
int serial_enum_devices(uint32 * id, char *optarg); int serial_enum_devices(uint32 * id, char *optarg);
BOOL serial_get_event(RD_NTHANDLE handle, uint32 * result); RD_BOOL serial_get_event(RD_NTHANDLE handle, uint32 * result);
BOOL serial_get_timeout(RD_NTHANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout); RD_BOOL serial_get_timeout(RD_NTHANDLE handle, uint32 length, uint32 * timeout,
uint32 * itv_timeout);
/* tcp.c */ /* tcp.c */
STREAM tcp_init(uint32 maxlen); STREAM tcp_init(uint32 maxlen);
void tcp_send(STREAM s); void tcp_send(STREAM s);
STREAM tcp_recv(STREAM s, uint32 length); STREAM tcp_recv(STREAM s, uint32 length);
BOOL tcp_connect(char *server); RD_BOOL tcp_connect(char *server);
void tcp_disconnect(void); void tcp_disconnect(void);
char *tcp_get_address(void); char *tcp_get_address(void);
RD_BOOL tcp_is_connected(void);
void tcp_reset_state(void); void tcp_reset_state(void);
RD_BOOL tcp_tls_connect(void);
RD_BOOL tcp_tls_get_server_pubkey(STREAM s);
void tcp_run_ui(RD_BOOL run);
/* asn.c */
RD_BOOL ber_in_header(STREAM s, int *tagval, int *length);
void ber_out_header(STREAM s, int tagval, int length);
RD_BOOL ber_parse_header(STREAM s, int tagval, int *length);
void ber_out_integer(STREAM s, int value);
/* xclip.c */ /* xclip.c */
void ui_clip_format_announce(uint8 * data, uint32 length); void ui_clip_format_announce(uint8 * data, uint32 length);
void ui_clip_handle_data(uint8 * data, uint32 length); void ui_clip_handle_data(uint8 * data, uint32 length);
@ -208,14 +244,15 @@ void ui_clip_request_data(uint32 format);
void ui_clip_sync(void); void ui_clip_sync(void);
void ui_clip_set_mode(const char *optarg); void ui_clip_set_mode(const char *optarg);
void xclip_init(void); void xclip_init(void);
void xclip_deinit(void);
/* xkeymap.c */ /* xkeymap.c */
BOOL xkeymap_from_locale(const char *locale); RD_BOOL xkeymap_from_locale(const char *locale);
FILE *xkeymap_open(const char *filename); FILE *xkeymap_open(const char *filename);
void xkeymap_init(void); void xkeymap_init(void);
BOOL handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed); RD_BOOL handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, RD_BOOL pressed);
key_translation xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state); key_translation xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state);
void xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time, void xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
BOOL pressed, uint8 nesting); RD_BOOL pressed, uint8 nesting);
uint16 xkeymap_translate_button(unsigned int button); uint16 xkeymap_translate_button(unsigned int button);
char *get_ksname(uint32 keysym); char *get_ksname(uint32 keysym);
void save_remote_modifiers(uint8 scancode); void save_remote_modifiers(uint8 scancode);
@ -226,12 +263,14 @@ uint16 ui_get_numlock_state(unsigned int state);
void reset_modifier_keys(void); void reset_modifier_keys(void);
void rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode); void rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode);
/* xwin.c */ /* xwin.c */
BOOL get_key_state(unsigned int state, uint32 keysym); RD_BOOL get_key_state(unsigned int state, uint32 keysym);
BOOL ui_init(void); RD_BOOL ui_init(void);
void ui_init_connection(void);
void ui_deinit(void); void ui_deinit(void);
BOOL ui_create_window(void); RD_BOOL ui_create_window(void);
void ui_resize_window(void); void ui_resize_window(void);
void ui_destroy_window(void); void ui_destroy_window(void);
RD_BOOL ui_have_window(void);
void xwin_toggle_fullscreen(void); void xwin_toggle_fullscreen(void);
int ui_select(int rdp_socket); int ui_select(int rdp_socket);
void ui_move_pointer(int x, int y); void ui_move_pointer(int x, int y);
@ -241,7 +280,7 @@ void ui_destroy_bitmap(RD_HBITMAP bmp);
RD_HGLYPH ui_create_glyph(int width, int height, uint8 * data); RD_HGLYPH ui_create_glyph(int width, int height, uint8 * data);
void ui_destroy_glyph(RD_HGLYPH glyph); void ui_destroy_glyph(RD_HGLYPH glyph);
RD_HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask, RD_HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask,
uint8 * xormask); uint8 * xormask, int bpp);
void ui_set_cursor(RD_HCURSOR cursor); void ui_set_cursor(RD_HCURSOR cursor);
void ui_destroy_cursor(RD_HCURSOR cursor); void ui_destroy_cursor(RD_HCURSOR cursor);
void ui_set_null_cursor(void); void ui_set_null_cursor(void);
@ -260,9 +299,9 @@ void ui_triblt(uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int s
BRUSH * brush, int bgcolour, int fgcolour); BRUSH * brush, int bgcolour, int fgcolour);
void ui_line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen); void ui_line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen);
void ui_rect(int x, int y, int cx, int cy, int colour); void ui_rect(int x, int y, int cx, int cy, int colour);
void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints, BRUSH * brush, void ui_polygon(uint8 opcode, uint8 fillmode, RD_POINT * point, int npoints, BRUSH * brush,
int bgcolour, int fgcolour); int bgcolour, int fgcolour);
void ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen); void ui_polyline(uint8 opcode, RD_POINT * points, int npoints, PEN * pen);
void ui_ellipse(uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, BRUSH * brush, void ui_ellipse(uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, BRUSH * brush,
int bgcolour, int fgcolour); int bgcolour, int fgcolour);
void ui_draw_glyph(int mixmode, int x, int y, int cx, int cy, RD_HGLYPH glyph, int srcx, int srcy, void ui_draw_glyph(int mixmode, int x, int y, int cx, int cy, RD_HGLYPH glyph, int srcx, int srcy,
@ -274,13 +313,18 @@ void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy);
void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy); void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy);
void ui_begin_update(void); void ui_begin_update(void);
void ui_end_update(void); void ui_end_update(void);
void ui_seamless_begin(BOOL hidden); void ui_seamless_begin(RD_BOOL hidden);
void ui_seamless_end();
void ui_seamless_hide_desktop(void); void ui_seamless_hide_desktop(void);
void ui_seamless_unhide_desktop(void); void ui_seamless_unhide_desktop(void);
void ui_seamless_toggle(void); void ui_seamless_toggle(void);
void ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent, void ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
unsigned long flags); unsigned long flags);
void ui_seamless_destroy_window(unsigned long id, unsigned long flags); void ui_seamless_destroy_window(unsigned long id, unsigned long flags);
void ui_seamless_destroy_group(unsigned long id, unsigned long flags);
void ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
const char *data, int chunk_len);
void ui_seamless_delicon(unsigned long id, const char *format, int width, int height);
void ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, void ui_seamless_move_window(unsigned long id, int x, int y, int width, int height,
unsigned long flags); unsigned long flags);
void ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags); void ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags);
@ -289,9 +333,10 @@ void ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long fl
void ui_seamless_syncbegin(unsigned long flags); void ui_seamless_syncbegin(unsigned long flags);
void ui_seamless_ack(unsigned int serial); void ui_seamless_ack(unsigned int serial);
/* lspci.c */ /* lspci.c */
BOOL lspci_init(void); RD_BOOL lspci_init(void);
/* seamless.c */ /* seamless.c */
BOOL seamless_init(void); RD_BOOL seamless_init(void);
void seamless_reset_state(void);
unsigned int seamless_send_sync(void); unsigned int seamless_send_sync(void);
unsigned int seamless_send_state(unsigned long id, unsigned int state, unsigned long flags); unsigned int seamless_send_state(unsigned long id, unsigned int state, unsigned long flags);
unsigned int seamless_send_position(unsigned long id, int x, int y, int width, int height, unsigned int seamless_send_position(unsigned long id, int x, int y, int width, int height,
@ -299,9 +344,21 @@ unsigned int seamless_send_position(unsigned long id, int x, int y, int width, i
void seamless_select_timeout(struct timeval *tv); void seamless_select_timeout(struct timeval *tv);
unsigned int seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags); unsigned int seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags);
unsigned int seamless_send_focus(unsigned long id, unsigned long flags); unsigned int seamless_send_focus(unsigned long id, unsigned long flags);
unsigned int seamless_send_destroy(unsigned long id);
unsigned int seamless_send_spawn(char *cmd);
unsigned int seamless_send_persistent(RD_BOOL);
/* scard.c */
void scard_lock(int lock);
void scard_unlock(int lock);
int scard_enum_devices(uint32 * id, char *optarg);
void scardSetInfo(uint32 epoch, uint32 device, uint32 id, uint32 bytes_out);
void scard_reset_state();
/* *INDENT-OFF* */ /* *INDENT-OFF* */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/* *INDENT-ON* */ /* *INDENT-ON* */
#endif

View file

@ -1,11 +1,11 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Persistent Bitmap Cache routines Persistent Bitmap Cache routines
Copyright (C) Jeroen Meijer 2004-2005 Copyright (C) Jeroen Meijer <jeroen@oldambt7.com> 2004-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,23 +13,24 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
#define MAX_CELL_SIZE 0x1000 /* pixels */ #define MAX_CELL_SIZE 0x1000 /* pixels */
#define IS_PERSISTENT(id) (id < 8 && g_pstcache_fd[id] > 0)
extern int g_server_depth; extern int g_server_depth;
extern BOOL g_bitmap_cache; extern RD_BOOL g_bitmap_cache;
extern BOOL g_bitmap_cache_persist_enable; extern RD_BOOL g_bitmap_cache_persist_enable;
extern BOOL g_bitmap_cache_precache; extern RD_BOOL g_bitmap_cache_precache;
int g_pstcache_fd[8]; int g_pstcache_fd[8];
int g_pstcache_Bpp; int g_pstcache_Bpp;
BOOL g_pstcache_enumerated = False; RD_BOOL g_pstcache_enumerated = False;
uint8 zero_key[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8 zero_key[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
@ -48,13 +49,13 @@ pstcache_touch_bitmap(uint8 cache_id, uint16 cache_idx, uint32 stamp)
} }
/* Load a bitmap from the persistent cache */ /* Load a bitmap from the persistent cache */
BOOL RD_BOOL
pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx) pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx)
{ {
uint8 *celldata; uint8 *celldata;
int fd; int fd;
CELLHEADER cellhdr; CELLHEADER cellhdr;
HBITMAP bitmap; RD_HBITMAP bitmap;
if (!g_bitmap_cache_persist_enable) if (!g_bitmap_cache_persist_enable)
return False; return False;
@ -62,8 +63,6 @@ pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx)
if (!IS_PERSISTENT(cache_id) || cache_idx >= BMPCACHE2_NUM_PSTCELLS) if (!IS_PERSISTENT(cache_id) || cache_idx >= BMPCACHE2_NUM_PSTCELLS)
return False; return False;
memset(&cellhdr, 0, sizeof(CELLHEADER));
fd = g_pstcache_fd[cache_id]; fd = g_pstcache_fd[cache_id];
rd_lseek_file(fd, cache_idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER))); rd_lseek_file(fd, cache_idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
rd_read_file(fd, &cellhdr, sizeof(CELLHEADER)); rd_read_file(fd, &cellhdr, sizeof(CELLHEADER));
@ -71,7 +70,7 @@ pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx)
rd_read_file(fd, celldata, cellhdr.length); rd_read_file(fd, celldata, cellhdr.length);
bitmap = ui_create_bitmap(cellhdr.width, cellhdr.height, celldata); bitmap = ui_create_bitmap(cellhdr.width, cellhdr.height, celldata);
DEBUG(("Load bitmap from disk: id=%d, idx=%d, bmp=0x%x)\n", cache_id, cache_idx, bitmap)); DEBUG(("Load bitmap from disk: id=%d, idx=%d, bmp=%p)\n", cache_id, cache_idx, bitmap));
cache_put_bitmap(cache_id, cache_idx, bitmap); cache_put_bitmap(cache_id, cache_idx, bitmap);
xfree(celldata); xfree(celldata);
@ -79,7 +78,7 @@ pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx)
} }
/* Store a bitmap in the persistent cache */ /* Store a bitmap in the persistent cache */
BOOL RD_BOOL
pstcache_save_bitmap(uint8 cache_id, uint16 cache_idx, uint8 * key, pstcache_save_bitmap(uint8 cache_id, uint16 cache_idx, uint8 * key,
uint8 width, uint8 height, uint16 length, uint8 * data) uint8 width, uint8 height, uint16 length, uint8 * data)
{ {
@ -160,7 +159,7 @@ pstcache_enumerate(uint8 id, HASH_KEY * keylist)
} }
/* initialise the persistent bitmap cache */ /* initialise the persistent bitmap cache */
BOOL RD_BOOL
pstcache_init(uint8 cache_id) pstcache_init(uint8 cache_id)
{ {
int fd; int fd;

View file

@ -1,11 +1,11 @@
/* /*
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Master include file Master include file
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman 1999-2008
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,19 +13,22 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#pragma once #pragma once
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> /* winsock2.h first */ #include <winsock2.h> /* winsock2.h first */
#include <mmsystem.h> #include <mmsystem.h>
#include <time.h>
#define DIR int
#else /* WIN32 */ #else /* WIN32 */
#include <dirent.h> #include <dirent.h>
#include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> #include <sys/select.h>
@ -35,8 +38,90 @@
#endif /* HAVE_SYS_SELECT_H */ #endif /* HAVE_SYS_SELECT_H */
#endif /* WIN32 */ #endif /* WIN32 */
//#include <limits.h> /* PATH_MAX */ //#include <limits.h> /* PATH_MAX */
#ifdef HAVE_SYSEXITS_H
#include <sysexits.h>
#endif
#define VERSION "1.4.1" #define VERSION "1.8.3"
/* standard exit codes */
#ifndef EX_OK
#define EX_OK 0
#endif
#ifndef EX_USAGE
#define EX_USAGE 64
#endif
#ifndef EX_DATAERR
#define EX_DATAERR 65
#endif
#ifndef EX_NOINPUT
#define EX_NOINPUT 66
#endif
#ifndef EX_NOUSER
#define EX_NOUSER 67
#endif
#ifndef EX_NOHOST
#define EX_NOHOST 68
#endif
#ifndef EX_UNAVAILABLE
#define EX_UNAVAILABLE 69
#endif
#ifndef EX_SOFTWARE
#define EX_SOFTWARE 70
#endif
#ifndef EX_OSERR
#define EX_OSERR 71
#endif
#ifndef EX_OSFILE
#define EX_OSFILE 72
#endif
#ifndef EX_CANTCREAT
#define EX_CANTCREAT 73
#endif
#ifndef EX_IOERR
#define EX_IOERR 74
#endif
#ifndef EX_TEMPFAIL
#define EX_TEMPFAIL 75
#endif
#ifndef EX_PROTOCOL
#define EX_PROTOCOL 76
#endif
#ifndef EX_NOPERM
#define EX_NOPERM 77
#endif
#ifndef EX_CONFIG
#define EX_CONFIG 78
#endif
/* rdesktop specific exit codes, lined up with disconnect PDU reasons */
#define EXRD_API_DISCONNECT 1
#define EXRD_API_LOGOFF 2
#define EXRD_IDLE_TIMEOUT 3
#define EXRD_LOGON_TIMEOUT 4
#define EXRD_REPLACED 5
#define EXRD_OUT_OF_MEM 6
#define EXRD_DENIED 7
#define EXRD_DENIED_FIPS 8
#define EXRD_INSUFFICIENT_PRIVILEGES 9
#define EXRD_FRESH_CREDENTIALS_REQUIRED 10
#define EXRD_RPC_DISCONNECT_BY_USER 11
#define EXRD_DISCONNECT_BY_USER 12
#define EXRD_LIC_INTERNAL 16
#define EXRD_LIC_NOSERVER 17
#define EXRD_LIC_NOLICENSE 18
#define EXRD_LIC_MSG 19
#define EXRD_LIC_HWID 20
#define EXRD_LIC_CLIENT 21
#define EXRD_LIC_NET 22
#define EXRD_LIC_PROTO 23
#define EXRD_LIC_ENC 24
#define EXRD_LIC_UPGRADE 25
#define EXRD_LIC_NOREMOTE 26
/* other exit codes */
#define EXRD_WINDOW_CLOSED 62
#define EXRD_UNKNOWN 63
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
#define DEBUG(args) printf args; #define DEBUG(args) printf args;
@ -62,12 +147,24 @@
#define DEBUG_CLIPBOARD(args) #define DEBUG_CLIPBOARD(args)
#endif #endif
#ifdef WITH_DEBUG_SOUND
#define DEBUG_SOUND(args) printf args;
#else
#define DEBUG_SOUND(args)
#endif
#ifdef WITH_DEBUG_CHANNEL #ifdef WITH_DEBUG_CHANNEL
#define DEBUG_CHANNEL(args) printf args; #define DEBUG_CHANNEL(args) printf args;
#else #else
#define DEBUG_CHANNEL(args) #define DEBUG_CHANNEL(args)
#endif #endif
#ifdef WITH_DEBUG_SCARD
#define DEBUG_SCARD(args) printf args;
#else
#define DEBUG_SCARD(args)
#endif
#define STRNCPY(dst,src,n) { strncpy(dst,src,n-1); dst[n-1] = 0; } #define STRNCPY(dst,src,n) { strncpy(dst,src,n-1); dst[n-1] = 0; }
#ifndef MIN #ifndef MIN

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,12 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Protocol services - RDP5 short form PDU processing Protocol services - RDP5 short form PDU processing
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright (C) Erik Forsberg 2003 Copyright 2003-2008 Erik Forsberg <forsberg@cendio.se> for Cendio AB
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -14,9 +14,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
@ -111,6 +110,9 @@ rdp5_process(STREAM s)
case 10: /* cached pointer */ case 10: /* cached pointer */
process_cached_pointer_pdu(ts); process_cached_pointer_pdu(ts);
break; break;
case 11:
process_new_pointer_pdu(ts);
break;
default: default:
unimpl("RDP5 opcode %d\n", type); unimpl("RDP5 opcode %d\n", type);
} }

File diff suppressed because it is too large Load diff

View file

@ -713,6 +713,43 @@ ssl_md5_complete(void* md5_info, char* data)
PUT_UINT32(ctx->state[3], data, 12); PUT_UINT32(ctx->state[3], data, 12);
} }
void APP_CC ssl_hmac_md5(char* key, int keylen, char* data, int len, char* output)
{
int i;
char ipad[64];
char opad[64];
char sum[16];
void* ctx;
if( keylen > 64 )
{
ctx = ssl_md5_info_create();
ssl_md5_transform(ctx, key, keylen);
ssl_md5_complete(ctx, sum);
ssl_md5_info_delete(ctx);
keylen = 16;
key = sum;
}
memset( ipad, 0x36, sizeof(ipad) );
memset( opad, 0x5C, sizeof(opad) );
for( i = 0; i < keylen; i++ )
{
ipad[i] = ipad[i] ^ key[i];
opad[i] = opad[i] ^ key[i];
}
ctx = ssl_md5_info_create();
ssl_md5_transform(ctx, ipad, sizeof(ipad));
ssl_md5_transform(ctx, data, len);
ssl_md5_complete(ctx, sum);
ssl_md5_info_delete(ctx);
ctx = ssl_md5_info_create();
ssl_md5_transform(ctx, opad, sizeof(opad));
ssl_md5_complete(ctx, output);
ssl_md5_info_delete(ctx);
}
/*****************************************************************************/ /*****************************************************************************/
/*****************************************************************************/ /*****************************************************************************/
/* big number stuff */ /* big number stuff */

View file

@ -1,11 +1,13 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Protocol services - TCP layer Protocol services - TCP layer
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
Copyright 2012-2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,9 +15,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "precomp.h" #include "precomp.h"
@ -37,70 +38,150 @@
#define INADDR_NONE ((unsigned long) -1) #define INADDR_NONE ((unsigned long) -1)
#endif #endif
static int sock; #ifdef WITH_SCARD
static struct stream in; #define STREAM_COUNT 8
static struct stream out; #else
#define STREAM_COUNT 1
#endif
#ifdef WITH_SSL
static RD_BOOL g_ssl_initialized = False;
static SSL *g_ssl = NULL;
static SSL_CTX *g_ssl_ctx = NULL;
#endif /* WITH_SSL */
static int g_sock;
static struct stream g_in;
static struct stream g_out[STREAM_COUNT];
int g_tcp_port_rdp = TCP_PORT_RDP; int g_tcp_port_rdp = TCP_PORT_RDP;
extern RD_BOOL g_user_quit;
extern RD_BOOL g_network_error;
extern RD_BOOL g_reconnect_loop;
/* Initialise TCP transport data packet */ /* Initialise TCP transport data packet */
STREAM STREAM
tcp_init(uint32 maxlen) tcp_init(uint32 maxlen)
{ {
if (maxlen > out.size) static int cur_stream_id = 0;
STREAM result = NULL;
#ifdef WITH_SCARD
scard_lock(SCARD_LOCK_TCP);
#endif
result = &g_out[cur_stream_id];
cur_stream_id = (cur_stream_id + 1) % STREAM_COUNT;
if (maxlen > result->size)
{ {
out.data = (uint8 *) xrealloc(out.data, maxlen); result->data = (uint8 *) xrealloc(result->data, maxlen);
out.size = maxlen; result->size = maxlen;
} }
out.p = out.data; result->p = result->data;
out.end = out.data + out.size; result->end = result->data + result->size;
return &out; #ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_TCP);
#endif
return result;
} }
/* Send TCP transport data packet */ /* Send TCP transport data packet */
void void
tcp_send(STREAM s) tcp_send(STREAM s)
{ {
#ifdef WITH_SSL
int ssl_err;
#endif /* WITH_SSL */
int length = s->end - s->data; int length = s->end - s->data;
int sent, total = 0; int sent, total = 0;
if (g_network_error == True)
return;
#ifdef WITH_SCARD
scard_lock(SCARD_LOCK_TCP);
#endif
while (total < length) while (total < length)
{ {
sent = send(sock, (char *)s->data + total, length - total, 0); #ifdef WITH_SSL
if (sent <= 0) if (g_ssl)
{ {
if (sent == -1 && TCP_BLOCKS) sent = SSL_write(g_ssl, s->data + total, length - total);
if (sent <= 0)
{ {
TCP_SLEEP(0); ssl_err = SSL_get_error(g_ssl, sent);
sent = 0; if (sent < 0 && (ssl_err == SSL_ERROR_WANT_READ ||
} ssl_err == SSL_ERROR_WANT_WRITE))
else {
{ TCP_SLEEP(0);
error("send: %s\n", TCP_STRERROR); sent = 0;
return; }
else
{
#ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_TCP);
#endif
error("SSL_write: %d (%s)\n", ssl_err, TCP_STRERROR);
g_network_error = True;
return;
}
} }
} }
else
{
#endif /* WITH_SSL */
sent = send(g_sock, (const char *)s->data + total, length - total, 0);
if (sent <= 0)
{
if (sent == -1 && TCP_BLOCKS)
{
TCP_SLEEP(0);
sent = 0;
}
else
{
#ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_TCP);
#endif
error("send: %s\n", TCP_STRERROR);
g_network_error = True;
return;
}
}
#ifdef WITH_SSL
}
#endif /* WITH_SSL */
total += sent; total += sent;
} }
#ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_TCP);
#endif
} }
/* Receive a message on the TCP layer */ /* Receive a message on the TCP layer */
STREAM STREAM
tcp_recv(STREAM s, uint32 length) tcp_recv(STREAM s, uint32 length)
{ {
unsigned int new_length, end_offset, p_offset; uint32 new_length, end_offset, p_offset;
int rcvd = 0; int rcvd = 0;
#ifdef WITH_SSL
int ssl_err;
#endif /* WITH_SSL */
if (g_network_error == True)
return NULL;
if (s == NULL) if (s == NULL)
{ {
/* read into "new" stream */ /* read into "new" stream */
if (length > in.size) if (length > g_in.size)
{ {
in.data = (uint8 *) xrealloc(in.data, length); g_in.data = (uint8 *) xrealloc(g_in.data, length);
in.size = length; g_in.size = length;
} }
in.end = in.p = in.data; g_in.end = g_in.p = g_in.data;
s = &in; s = &g_in;
} }
else else
{ {
@ -119,29 +200,74 @@ tcp_recv(STREAM s, uint32 length)
while (length > 0) while (length > 0)
{ {
if (!ui_select(sock)) #ifdef WITH_SSL
/* User quit */ if (!g_ssl || SSL_pending(g_ssl) <= 0)
return NULL; #endif /* WITH_SSL */
rcvd = recv(sock, (char *)s->end, length, 0);
if (rcvd < 0)
{ {
if (rcvd == -1 && TCP_BLOCKS) if (!ui_select(g_sock))
{ {
TCP_SLEEP(0); /* User quit */
rcvd = 0; g_user_quit = True;
}
else
{
error("recv: %s\n", TCP_STRERROR);
return NULL; return NULL;
} }
} }
else if (rcvd == 0)
#ifdef WITH_SSL
if (g_ssl)
{ {
error("Connection closed\n"); rcvd = SSL_read(g_ssl, s->end, length);
return NULL; ssl_err = SSL_get_error(g_ssl, rcvd);
if (ssl_err == SSL_ERROR_SSL)
{
if (SSL_get_shutdown(g_ssl) & SSL_RECEIVED_SHUTDOWN)
{
error("Remote peer initiated ssl shutdown.\n");
return NULL;
}
ERR_print_errors_fp(stdout);
g_network_error = True;
return NULL;
}
if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE)
{
rcvd = 0;
}
else if (ssl_err != SSL_ERROR_NONE)
{
error("SSL_read: %d (%s)\n", ssl_err, TCP_STRERROR);
g_network_error = True;
return NULL;
}
} }
else
{
#endif /* WITH_SSL */
rcvd = recv(g_sock, (char *)s->end, length, 0);
if (rcvd < 0)
{
if (rcvd == -1 && TCP_BLOCKS)
{
rcvd = 0;
}
else
{
error("recv: %s\n", TCP_STRERROR);
g_network_error = True;
return NULL;
}
}
else if (rcvd == 0)
{
error("Connection closed\n");
return NULL;
}
#ifdef WITH_SSL
}
#endif /* WITH_SSL */
s->end += rcvd; s->end += rcvd;
length -= rcvd; length -= rcvd;
@ -150,11 +276,137 @@ tcp_recv(STREAM s, uint32 length)
return s; return s;
} }
#ifdef WITH_SSL
/* Establish a SSL/TLS 1.0 connection */
RD_BOOL
tcp_tls_connect(void)
{
int err;
long options;
if (!g_ssl_initialized)
{
SSL_load_error_strings();
SSL_library_init();
g_ssl_initialized = True;
}
/* create process context */
if (g_ssl_ctx == NULL)
{
g_ssl_ctx = SSL_CTX_new(TLSv1_client_method());
if (g_ssl_ctx == NULL)
{
error("tcp_tls_connect: SSL_CTX_new() failed to create TLS v1.0 context\n");
goto fail;
}
options = 0;
#ifdef SSL_OP_NO_COMPRESSION
options |= SSL_OP_NO_COMPRESSION;
#endif // __SSL_OP_NO_COMPRESSION
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
SSL_CTX_set_options(g_ssl_ctx, options);
}
/* free old connection */
if (g_ssl)
SSL_free(g_ssl);
/* create new ssl connection */
g_ssl = SSL_new(g_ssl_ctx);
if (g_ssl == NULL)
{
error("tcp_tls_connect: SSL_new() failed\n");
goto fail;
}
if (SSL_set_fd(g_ssl, g_sock) < 1)
{
error("tcp_tls_connect: SSL_set_fd() failed\n");
goto fail;
}
do
{
err = SSL_connect(g_ssl);
}
while (SSL_get_error(g_ssl, err) == SSL_ERROR_WANT_READ);
if (err < 0)
{
ERR_print_errors_fp(stdout);
goto fail;
}
return True;
fail:
if (g_ssl)
SSL_free(g_ssl);
if (g_ssl_ctx)
SSL_CTX_free(g_ssl_ctx);
g_ssl = NULL;
g_ssl_ctx = NULL;
return False;
}
/* Get public key from server of TLS 1.0 connection */
RD_BOOL
tcp_tls_get_server_pubkey(STREAM s)
{
X509 *cert = NULL;
EVP_PKEY *pkey = NULL;
s->data = s->p = NULL;
s->size = 0;
if (g_ssl == NULL)
goto out;
cert = SSL_get_peer_certificate(g_ssl);
if (cert == NULL)
{
error("tcp_tls_get_server_pubkey: SSL_get_peer_certificate() failed\n");
goto out;
}
pkey = X509_get_pubkey(cert);
if (pkey == NULL)
{
error("tcp_tls_get_server_pubkey: X509_get_pubkey() failed\n");
goto out;
}
s->size = i2d_PublicKey(pkey, NULL);
if (s->size < 1)
{
error("tcp_tls_get_server_pubkey: i2d_PublicKey() failed\n");
goto out;
}
s->data = s->p = xmalloc(s->size);
i2d_PublicKey(pkey, &s->p);
s->p = s->data;
s->end = s->p + s->size;
out:
if (cert)
X509_free(cert);
if (pkey)
EVP_PKEY_free(pkey);
return (s->size != 0);
}
#endif /* WITH_SSL */
/* Establish a connection on the TCP layer */ /* Establish a connection on the TCP layer */
BOOL RD_BOOL
tcp_connect(char *server) tcp_connect(char *server)
{ {
int true_value = 1; socklen_t option_len;
uint32 option_value;
int i;
#ifdef IPv6 #ifdef IPv6
@ -175,22 +427,22 @@ tcp_connect(char *server)
} }
ressave = res; ressave = res;
sock = -1; g_sock = -1;
while (res) while (res)
{ {
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); g_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (!(sock < 0)) if (!(g_sock < 0))
{ {
if (connect(sock, res->ai_addr, res->ai_addrlen) == 0) if (connect(g_sock, res->ai_addr, res->ai_addrlen) == 0)
break; break;
TCP_CLOSE(sock); TCP_CLOSE(g_sock);
sock = -1; g_sock = -1;
} }
res = res->ai_next; res = res->ai_next;
} }
freeaddrinfo(ressave); freeaddrinfo(ressave);
if (sock == -1) if (g_sock == -1)
{ {
error("%s: unable to connect\n", server); error("%s: unable to connect\n", server);
return False; return False;
@ -211,7 +463,7 @@ tcp_connect(char *server)
return False; return False;
} }
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((g_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{ {
error("socket: %s\n", TCP_STRERROR); error("socket: %s\n", TCP_STRERROR);
return False; return False;
@ -220,22 +472,41 @@ tcp_connect(char *server)
servaddr.sin_family = AF_INET; servaddr.sin_family = AF_INET;
servaddr.sin_port = htons((uint16) g_tcp_port_rdp); servaddr.sin_port = htons((uint16) g_tcp_port_rdp);
if (connect(sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0) if (connect(g_sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)
{ {
error("connect: %s\n", TCP_STRERROR); if (!g_reconnect_loop)
TCP_CLOSE(sock); error("connect: %s\n", TCP_STRERROR);
TCP_CLOSE(g_sock);
g_sock = -1;
return False; return False;
} }
#endif /* IPv6 */ #endif /* IPv6 */
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &true_value, sizeof(true_value)); option_value = 1;
option_len = sizeof(option_value);
setsockopt(g_sock, IPPROTO_TCP, TCP_NODELAY, (void *) &option_value, option_len);
/* receive buffer must be a least 16 K */
if (getsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value, &option_len) == 0)
{
if (option_value < (1024 * 16))
{
option_value = 1024 * 16;
option_len = sizeof(option_value);
setsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value,
option_len);
}
}
in.size = 4096; g_in.size = 4096;
in.data = (uint8 *) xmalloc(in.size); g_in.data = (uint8 *) xmalloc(g_in.size);
out.size = 4096; for (i = 0; i < STREAM_COUNT; i++)
out.data = (uint8 *) xmalloc(out.size); {
g_out[i].size = 4096;
g_out[i].data = (uint8 *) xmalloc(g_out[i].size);
}
return True; return True;
} }
@ -244,7 +515,19 @@ tcp_connect(char *server)
void void
tcp_disconnect(void) tcp_disconnect(void)
{ {
TCP_CLOSE(sock); #ifdef WITH_SSL
if (g_ssl)
{
if (!g_network_error)
(void) SSL_shutdown(g_ssl);
SSL_free(g_ssl);
g_ssl = NULL;
SSL_CTX_free(g_ssl_ctx);
g_ssl_ctx = NULL;
}
#endif /* WITH_SSL */
TCP_CLOSE(g_sock);
g_sock = -1;
} }
char * char *
@ -253,9 +536,9 @@ tcp_get_address()
static char ipaddr[32]; static char ipaddr[32];
struct sockaddr_in sockaddr; struct sockaddr_in sockaddr;
socklen_t len = sizeof(sockaddr); socklen_t len = sizeof(sockaddr);
if (getsockname(sock, (struct sockaddr *) &sockaddr, &len) == 0) if (getsockname(g_sock, (struct sockaddr *) &sockaddr, &len) == 0)
{ {
unsigned char *ip = (unsigned char *) &sockaddr.sin_addr; uint8 *ip = (uint8 *) & sockaddr.sin_addr;
sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
} }
else else
@ -263,36 +546,49 @@ tcp_get_address()
return ipaddr; return ipaddr;
} }
RD_BOOL
tcp_is_connected()
{
struct sockaddr_in sockaddr;
socklen_t len = sizeof(sockaddr);
if (getpeername(g_sock, (struct sockaddr *) &sockaddr, &len))
return True;
return False;
}
/* reset the state of the tcp layer */ /* reset the state of the tcp layer */
/* Support for Session Directory */ /* Support for Session Directory */
void void
tcp_reset_state(void) tcp_reset_state(void)
{ {
sock = -1; /* reset socket */ int i;
/* Clear the incoming stream */ /* Clear the incoming stream */
if (in.data != NULL) if (g_in.data != NULL)
xfree(in.data); xfree(g_in.data);
in.p = NULL; g_in.p = NULL;
in.end = NULL; g_in.end = NULL;
in.data = NULL; g_in.data = NULL;
in.size = 0; g_in.size = 0;
in.iso_hdr = NULL; g_in.iso_hdr = NULL;
in.mcs_hdr = NULL; g_in.mcs_hdr = NULL;
in.sec_hdr = NULL; g_in.sec_hdr = NULL;
in.rdp_hdr = NULL; g_in.rdp_hdr = NULL;
in.channel_hdr = NULL; g_in.channel_hdr = NULL;
/* Clear the outgoing stream */ /* Clear the outgoing stream(s) */
if (out.data != NULL) for (i = 0; i < STREAM_COUNT; i++)
xfree(out.data); {
out.p = NULL; if (g_out[i].data != NULL)
out.end = NULL; xfree(g_out[i].data);
out.data = NULL; g_out[i].p = NULL;
out.size = 0; g_out[i].end = NULL;
out.iso_hdr = NULL; g_out[i].data = NULL;
out.mcs_hdr = NULL; g_out[i].size = 0;
out.sec_hdr = NULL; g_out[i].iso_hdr = NULL;
out.rdp_hdr = NULL; g_out[i].mcs_hdr = NULL;
out.channel_hdr = NULL; g_out[i].sec_hdr = NULL;
g_out[i].rdp_hdr = NULL;
g_out[i].channel_hdr = NULL;
}
} }

View file

@ -1,11 +1,12 @@
/* /*
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Common data types Common data types
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman 1999-2008
Copyright 2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
This program is free software; you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@ -13,11 +14,12 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program. If not, see <http://www.gnu.org/licenses/>.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
typedef int RD_BOOL;
#ifndef True #ifndef True
#define True (1) #define True (1)
#define False (0) #define False (0)
@ -35,6 +37,15 @@ typedef void *RD_HGLYPH;
typedef void *RD_HCOLOURMAP; typedef void *RD_HCOLOURMAP;
typedef void *RD_HCURSOR; typedef void *RD_HCURSOR;
typedef enum _RDP_VERSION
{
RDP_V4 = 4,
RDP_V5 = 5,
RDP_V6 = 6
} RDP_VERSION;
typedef struct _RD_POINT typedef struct _RD_POINT
{ {
sint16 x, y; sint16 x, y;
@ -77,13 +88,22 @@ typedef struct _PEN
} }
PEN; PEN;
/* this is whats in the brush cache */
typedef struct _BRUSHDATA
{
uint32 colour_code;
uint32 data_size;
uint8 *data;
}
BRUSHDATA;
typedef struct _BRUSH typedef struct _BRUSH
{ {
uint8 xorigin; uint8 xorigin;
uint8 yorigin; uint8 yorigin;
uint8 style; uint8 style;
uint8 pattern[8]; uint8 pattern[8];
BRUSHDATA *bd;
} }
BRUSH; BRUSH;
@ -117,6 +137,16 @@ typedef struct _key_translation
} }
key_translation; key_translation;
typedef struct _key_translation_entry
{
key_translation *tr;
/* The full KeySym for this entry, not KEYMAP_MASKed */
uint32 keysym;
/* This will be non-NULL if there has been a hash collision */
struct _key_translation_entry *next;
}
key_translation_entry;
typedef struct _VCHANNEL typedef struct _VCHANNEL
{ {
uint16 mcs_id; uint16 mcs_id;
@ -143,7 +173,7 @@ CELLHEADER;
#define MAX_CBSIZE 256 #define MAX_CBSIZE 256
/* RDPSND */ /* RDPSND */
typedef struct typedef struct _RD_WAVEFORMATEX
{ {
uint16 wFormatTag; uint16 wFormatTag;
uint16 nChannels; uint16 nChannels;
@ -170,13 +200,13 @@ typedef uint32 RD_NTHANDLE;
typedef struct _DEVICE_FNS typedef struct _DEVICE_FNS
{ {
RD_NTSTATUS(*create) (uint32 device, uint32 desired_access, uint32 share_mode, RD_NTSTATUS(*create) (uint32 device, uint32 desired_access, uint32 share_mode,
uint32 create_disposition, uint32 flags_and_attributes, char *filename, uint32 create_disposition, uint32 flags_and_attributes,
RD_NTHANDLE * handle); char *filename, RD_NTHANDLE * handle);
RD_NTSTATUS(*close) (RD_NTHANDLE handle); RD_NTSTATUS(*close) (RD_NTHANDLE handle);
RD_NTSTATUS(*read) (RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, RD_NTSTATUS(*read) (RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset,
uint32 * result); uint32 * result);
RD_NTSTATUS(*write) (RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, RD_NTSTATUS(*write) (RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset,
uint32 * result); uint32 * result);
RD_NTSTATUS(*device_control) (RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out); RD_NTSTATUS(*device_control) (RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out);
} }
DEVICE_FNS; DEVICE_FNS;
@ -233,7 +263,7 @@ typedef struct rdpdr_printer_info
char *driver, *printer; char *driver, *printer;
uint32 bloblen; uint32 bloblen;
uint8 *blob; uint8 *blob;
BOOL default_printer; RD_BOOL default_printer;
} }
PRINTER; PRINTER;
@ -250,7 +280,6 @@ NOTIFY;
#define PATH_MAX 256 #define PATH_MAX 256
#endif #endif
#ifndef _WIN32
typedef struct fileinfo typedef struct fileinfo
{ {
uint32 device_id, flags_and_attributes, accessmask; uint32 device_id, flags_and_attributes, accessmask;
@ -258,11 +287,10 @@ typedef struct fileinfo
DIR *pdir; DIR *pdir;
struct dirent *pdirent; struct dirent *pdirent;
char pattern[PATH_MAX]; char pattern[PATH_MAX];
BOOL delete_on_close; RD_BOOL delete_on_close;
NOTIFY notify; NOTIFY notify;
uint32 info_class; uint32 info_class;
} }
FILEINFO; FILEINFO;
#endif
typedef BOOL(*str_handle_lines_t) (const char *line, void *data); typedef RD_BOOL(*str_handle_lines_t) (const char *line, void *data);

View file

@ -29,43 +29,63 @@ char g_password[256] = "";
char g_shell[256] = ""; char g_shell[256] = "";
char g_directory[256] = ""; char g_directory[256] = "";
char g_domain[256] = ""; char g_domain[256] = "";
BOOL g_desktop_save = False; /* desktop save order */ RD_BOOL g_desktop_save = False; /* desktop save order */
BOOL g_polygon_ellipse_orders = False; /* polygon / ellipse orders */ RD_BOOL g_polygon_ellipse_orders = False; /* polygon / ellipse orders */
BOOL g_bitmap_compression = True; RD_BOOL g_bitmap_compression = True;
uint32 g_rdp5_performanceflags = uint32 g_rdp5_performanceflags =
RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS; RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS | RDP5_NO_CURSOR_SHADOW;
BOOL g_bitmap_cache_persist_enable = False; RD_BOOL g_bitmap_cache_persist_enable = False;
BOOL g_bitmap_cache_precache = True; RD_BOOL g_bitmap_cache_precache = True;
BOOL g_bitmap_cache = True; RD_BOOL g_bitmap_cache = True;
BOOL g_encryption = True; RD_BOOL g_encryption = True;
int g_server_depth = 8; int g_server_depth = 8;
BOOL g_use_rdp5 = False; RD_BOOL g_use_rdp5 = False;
int g_width = 800; int g_width = 800;
int g_height = 600; int g_height = 600;
uint32 g_keylayout = 0x409; /* Defaults to US keyboard layout */ uint32 g_keylayout = 0x409; /* Defaults to US keyboard layout */
int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */ int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */
int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */ int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */
int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */ int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */
BOOL g_console_session = False; RD_BOOL g_console_session = False;
/* can't be static, hardware file or bsops need these */ /* can't be static, hardware file or bsops need these */
int g_tcp_sck = 0; int g_tcp_sck = 0;
int pal_entries[256]; int pal_entries[256];
/* Session Directory redirection */ /* Session Directory redirection */
BOOL g_redirect = False; RD_BOOL g_redirect = False;
char g_redirect_server[64]; char g_redirect_server[256];
char g_redirect_domain[16]; uint32 g_redirect_server_len;
char g_redirect_password[64]; char g_redirect_domain[256];
char g_redirect_username[64]; uint32 g_redirect_domain_len;
char g_redirect_cookie[128]; char g_redirect_username[256];
uint32 g_redirect_username_len;
uint8 g_redirect_lb_info[256];
uint32 g_redirect_lb_info_len;
uint8 g_redirect_cookie[256];
uint32 g_redirect_cookie_len;
uint32 g_redirect_flags = 0; uint32 g_redirect_flags = 0;
uint32 g_redirect_session_id = 0;
extern int g_tcp_port_rdp; extern int g_tcp_port_rdp;
static int g_deactivated = 0; static int g_deactivated = 0;
static uint32 g_ext_disc_reason = 0; static uint32 g_ext_disc_reason = 0;
RDP_VERSION g_rdp_version = RDP_V5; /* Default to version 5 */
RD_BOOL g_encryption_initial = True;
RD_BOOL g_user_quit = False;
RD_BOOL g_network_error = False;
uint8 g_client_random[SEC_RANDOM_SIZE];
RD_BOOL g_pending_resize = False;
RD_BOOL g_numlock_sync = False;
uint32 g_reconnect_logonid = 0;
char g_reconnect_random[16];
time_t g_reconnect_random_ts;
RD_BOOL g_has_reconnect_random = False;
RD_BOOL g_reconnect_loop = False;
struct bitmap struct bitmap
{ {
uint8 * data; uint8 * data;
@ -153,9 +173,9 @@ ui_select(int in)
/*****************************************************************************/ /*****************************************************************************/
void * void *
ui_create_cursor(uint32 x, uint32 y, ui_create_cursor(unsigned int x, unsigned int y,
int width, int height, int width, int height,
uint8 * andmask, uint8 * xormask) uint8 * andmask, uint8 * xormask, int xor_bpp)
{ {
int i; int i;
int j; int j;
@ -164,7 +184,11 @@ ui_create_cursor(uint32 x, uint32 y,
if (width != 32 || height != 32) if (width != 32 || height != 32)
{ {
return 0; return NULL;
}
if (xor_bpp==1)
{
return (void *) mi_create_cursor(x, y, width, height, (unsigned char *)andmask, (unsigned char *)xormask);
} }
memset(am, 0, 32 * 4); memset(am, 0, 32 * 4);
memset(xm, 0, 32 * 4); memset(xm, 0, 32 * 4);
@ -645,7 +669,7 @@ ui_end_update(void)
/*****************************************************************************/ /*****************************************************************************/
void void
ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints, ui_polygon(uint8 opcode, uint8 fillmode, RD_POINT * point, int npoints,
BRUSH * brush, int bgcolour, int fgcolour) BRUSH * brush, int bgcolour, int fgcolour)
{ {
/* not used */ /* not used */
@ -653,7 +677,7 @@ ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints,
/*****************************************************************************/ /*****************************************************************************/
void void
ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen) ui_polyline(uint8 opcode, RD_POINT * points, int npoints, PEN * pen)
{ {
int i, x, y, dx, dy; int i, x, y, dx, dy;
if (npoints > 0) if (npoints > 0)
@ -691,7 +715,7 @@ generate_random(uint8 * random)
rand(); rand();
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
{ {
random[i] = rand() >> 16; /* higher bits are more random */ random[i] = rand(); /* higher bits are more random */
} }
} }
@ -710,7 +734,7 @@ load_licence(uint8 ** data)
/*****************************************************************************/ /*****************************************************************************/
void * void *
xrealloc(void * in, int size) xrealloc(void * in, size_t size)
{ {
if (size < 1) if (size < 1)
{ {
@ -933,10 +957,10 @@ ui_main(void)
flags = RDP_LOGON_NORMAL; flags = RDP_LOGON_NORMAL;
if (g_password[0] != 0) if (g_password[0] != 0)
{ {
flags |= RDP_LOGON_AUTO; flags |= RDP_INFO_AUTOLOGON;
} }
if (!rdp_connect(g_servername, flags, g_domain, g_password, if (!rdp_connect(g_servername, flags, g_domain, g_password,
g_shell, g_directory)) g_shell, g_directory, FALSE))
{ {
return 0; return 0;
} }

View file

@ -1114,6 +1114,7 @@ wWinMain(HINSTANCE hInstance,
uni_to_str(szValue, GetStringFromSettings(pRdpSettings, L"username")); uni_to_str(szValue, GetStringFromSettings(pRdpSettings, L"username"));
SetDomainAndUsername(szValue); SetDomainAndUsername(szValue);
strcpy(g_password, ""); strcpy(g_password, "");
strcpy(g_hostname, tcp_get_address());
g_server_depth = GetIntegerFromSettings(pRdpSettings, L"session bpp"); g_server_depth = GetIntegerFromSettings(pRdpSettings, L"session bpp");
if (g_server_depth > 16) g_server_depth = 16; /* hack, we don't support 24bpp yet */ if (g_server_depth > 16) g_server_depth = 16; /* hack, we don't support 24bpp yet */
g_screen_width = GetSystemMetrics(SM_CXSCREEN); g_screen_width = GetSystemMetrics(SM_CXSCREEN);