parent
41df89c7f2
commit
992dbfa7b3
@ -0,0 +1,25 @@
|
||||
|
||||
LIBXRDPOBJ = libxrdp.o xrdp_tcp.o xrdp_iso.o xrdp_mcs.o \
|
||||
xrdp_sec.o xrdp_rdp.o xrdp_orders.o \
|
||||
xrdp_bitmap_compress.o \
|
||||
../common/os_calls.o \
|
||||
../common/ssl_calls.o
|
||||
|
||||
CFLAGS = -Wall -O2 -I../common -fPIC
|
||||
LDFLAGS = -shared
|
||||
LIBS = -ldl -lcrypto
|
||||
CC = gcc
|
||||
|
||||
all: libxrdp
|
||||
|
||||
static: $(LIBXRDPOBJ)
|
||||
$(AR) rvu libxrdp.a $(LIBXRDPOBJ)
|
||||
ranlib libxrdp.a
|
||||
|
||||
libxrdp: $(LIBXRDPOBJ)
|
||||
$(CC) $(LDFLAGS) -o libxrdp.so $(LIBXRDPOBJ) $(LIBS)
|
||||
strip libxrdp.so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBXRDPOBJ) libxrdp.a libxrdp.so
|
||||
|
@ -0,0 +1,530 @@
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2004-2005
|
||||
|
||||
this is the interface to libxrdp
|
||||
|
||||
*/
|
||||
|
||||
#include "libxrdp.h"
|
||||
|
||||
/******************************************************************************/
|
||||
struct xrdp_session* EXPORT_CC
|
||||
libxrdp_init(long id, int sck)
|
||||
{
|
||||
struct xrdp_session* session;
|
||||
|
||||
session = (struct xrdp_session*)g_malloc(sizeof(struct xrdp_session), 1);
|
||||
session->id = id;
|
||||
session->rdp = xrdp_rdp_create(session, sck);
|
||||
session->orders = xrdp_orders_create(session, (struct xrdp_rdp*)session->rdp);
|
||||
session->client_info = &(((struct xrdp_rdp*)session->rdp)->client_info);
|
||||
return session;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_exit(struct xrdp_session* session)
|
||||
{
|
||||
if (session == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
xrdp_orders_delete((struct xrdp_orders*)session->orders);
|
||||
xrdp_rdp_delete((struct xrdp_rdp*)session->rdp);
|
||||
g_free(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_disconnect(struct xrdp_session* session)
|
||||
{
|
||||
return xrdp_rdp_disconnect((struct xrdp_rdp*)session->rdp);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_process_incomming(struct xrdp_session* session)
|
||||
{
|
||||
return xrdp_rdp_incoming((struct xrdp_rdp*)session->rdp);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_process_data(struct xrdp_session* session)
|
||||
{
|
||||
struct stream* s;
|
||||
int cont;
|
||||
int rv;
|
||||
int code;
|
||||
|
||||
cont = 1;
|
||||
rv = 0;
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
while (cont && !session->term)
|
||||
{
|
||||
code = 0;
|
||||
if (xrdp_rdp_recv((struct xrdp_rdp*)session->rdp, s, &code) != 0)
|
||||
{
|
||||
rv = 1;
|
||||
break;
|
||||
}
|
||||
DEBUG(("libxrdp_process_data code %d\n\r", code));
|
||||
switch (code)
|
||||
{
|
||||
case -1:
|
||||
xrdp_rdp_send_demand_active((struct xrdp_rdp*)session->rdp);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
case RDP_PDU_CONFIRM_ACTIVE: /* 3 */
|
||||
xrdp_rdp_process_confirm_active((struct xrdp_rdp*)session->rdp, s);
|
||||
break;
|
||||
case RDP_PDU_DATA: /* 7 */
|
||||
if (xrdp_rdp_process_data((struct xrdp_rdp*)session->rdp, s) != 0)
|
||||
{
|
||||
DEBUG(("libxrdp_process_data returned non zero\n\r"));
|
||||
cont = 0;
|
||||
session->term = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_printf("unknown in libxrdp_process_data\n\r");
|
||||
break;
|
||||
}
|
||||
if (cont)
|
||||
{
|
||||
cont = s->next_packet < s->end;
|
||||
}
|
||||
}
|
||||
free_stream(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_send_palette(struct xrdp_session* session, int* palette)
|
||||
{
|
||||
int i;
|
||||
int color;
|
||||
struct stream* s;
|
||||
|
||||
if (session->client_info->bpp > 8)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* clear orders */
|
||||
libxrdp_orders_force_send(session);
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
|
||||
out_uint16_le(s, RDP_UPDATE_PALETTE);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 256); /* # of colors */
|
||||
out_uint16_le(s, 0);
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
color = palette[i];
|
||||
out_uint8(s, color >> 16);
|
||||
out_uint8(s, color >> 8);
|
||||
out_uint8(s, color);
|
||||
}
|
||||
s_mark_end(s);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s, RDP_DATA_PDU_UPDATE);
|
||||
free_stream(s);
|
||||
/* send the orders palette too */
|
||||
libxrdp_orders_init(session);
|
||||
libxrdp_orders_send_palette(session, palette, 0);
|
||||
libxrdp_orders_send(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_send_bitmap(struct xrdp_session* session, int width, int height,
|
||||
int bpp, char* data, int x, int y, int cx, int cy)
|
||||
{
|
||||
int data_size;
|
||||
int line_size;
|
||||
int i;
|
||||
int j;
|
||||
int total_lines;
|
||||
int lines_sending;
|
||||
int Bpp;
|
||||
int e;
|
||||
int bufsize;
|
||||
int total_bufsize;
|
||||
int num_updates;
|
||||
char* p_num_updates;
|
||||
char* p;
|
||||
char* q;
|
||||
struct stream* s;
|
||||
struct stream* temp_s;
|
||||
|
||||
Bpp = (bpp + 7) / 8;
|
||||
e = width % 4;
|
||||
if (e != 0)
|
||||
{
|
||||
e = 4 - e;
|
||||
}
|
||||
line_size = width * Bpp;
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (session->client_info->use_bitmap_comp)
|
||||
{
|
||||
make_stream(temp_s);
|
||||
init_stream(temp_s, 65536);
|
||||
i = 0;
|
||||
if (cy <= height)
|
||||
{
|
||||
i = cy;
|
||||
}
|
||||
while (i > 0)
|
||||
{
|
||||
total_bufsize = 0;
|
||||
num_updates = 0;
|
||||
xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
|
||||
out_uint16_le(s, RDP_UPDATE_BITMAP);
|
||||
p_num_updates = s->p;
|
||||
out_uint8s(s, 2); /* num_updates set later */
|
||||
do
|
||||
{
|
||||
if (session->client_info->op1)
|
||||
{
|
||||
s_push_layer(s, channel_hdr, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_push_layer(s, channel_hdr, 26);
|
||||
}
|
||||
p = s->p;
|
||||
lines_sending = xrdp_bitmap_compress(data, width, height,
|
||||
s, bpp,
|
||||
4096 - total_bufsize,
|
||||
i - 1, temp_s, e);
|
||||
if (lines_sending == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
num_updates++;
|
||||
bufsize = s->p - p;
|
||||
total_bufsize += bufsize;
|
||||
i = i - lines_sending;
|
||||
s_mark_end(s);
|
||||
s_pop_layer(s, channel_hdr);
|
||||
out_uint16_le(s, x); /* left */
|
||||
out_uint16_le(s, y + i); /* top */
|
||||
out_uint16_le(s, (x + cx) - 1); /* right */
|
||||
out_uint16_le(s, (y + i + lines_sending) - 1); /* bottom */
|
||||
out_uint16_le(s, width + e); /* width */
|
||||
out_uint16_le(s, lines_sending); /* height */
|
||||
out_uint16_le(s, bpp); /* bpp */
|
||||
if (session->client_info->op1)
|
||||
{
|
||||
out_uint16_le(s, 0x401); /* compress */
|
||||
out_uint16_le(s, bufsize); /* compressed size */
|
||||
j = (width + e) * Bpp;
|
||||
j = j * lines_sending;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint16_le(s, 0x1); /* compress */
|
||||
out_uint16_le(s, bufsize + 8);
|
||||
out_uint8s(s, 2); /* pad */
|
||||
out_uint16_le(s, bufsize); /* compressed size */
|
||||
j = (width + e) * Bpp;
|
||||
out_uint16_le(s, j); /* line size */
|
||||
j = j * lines_sending;
|
||||
out_uint16_le(s, j); /* final size */
|
||||
}
|
||||
if (j > 32768)
|
||||
{
|
||||
g_printf("error, decompressed size too big, its %d\n\r", j);
|
||||
}
|
||||
if (bufsize > 8192)
|
||||
{
|
||||
g_printf("error, compressed size too big, its %d\n\r", bufsize);
|
||||
}
|
||||
s->p = s->end;
|
||||
} while (total_bufsize < 4096 && i > 0);
|
||||
p_num_updates[0] = num_updates;
|
||||
p_num_updates[1] = num_updates >> 8;
|
||||
xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s,
|
||||
RDP_DATA_PDU_UPDATE);
|
||||
if (total_bufsize > 8192)
|
||||
{
|
||||
g_printf("error, total compressed size too big, its %d\n\r",
|
||||
total_bufsize);
|
||||
}
|
||||
}
|
||||
free_stream(temp_s);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines_sending = 0;
|
||||
data_size = width * height * Bpp;
|
||||
total_lines = height;
|
||||
i = 0;
|
||||
p = data;
|
||||
if (line_size > 0 && total_lines > 0)
|
||||
{
|
||||
while (i < total_lines)
|
||||
{
|
||||
lines_sending = 4096 / (line_size + e * Bpp);
|
||||
if (i + lines_sending > total_lines)
|
||||
{
|
||||
lines_sending = total_lines - i;
|
||||
}
|
||||
p = p + line_size * lines_sending;
|
||||
xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
|
||||
out_uint16_le(s, RDP_UPDATE_BITMAP);
|
||||
out_uint16_le(s, 1); /* num updates */
|
||||
out_uint16_le(s, x);
|
||||
out_uint16_le(s, y + i);
|
||||
out_uint16_le(s, (x + cx) - 1);
|
||||
out_uint16_le(s, (y + i + lines_sending) - 1);
|
||||
out_uint16_le(s, width + e);
|
||||
out_uint16_le(s, lines_sending);
|
||||
out_uint16_le(s, bpp); /* bpp */
|
||||
out_uint16_le(s, 0); /* compress */
|
||||
out_uint16_le(s, (line_size + e * Bpp) * lines_sending); /* bufsize */
|
||||
q = p;
|
||||
for (j = 0; j < lines_sending; j++)
|
||||
{
|
||||
q = q - line_size;
|
||||
out_uint8a(s, q, line_size)
|
||||
out_uint8s(s, e * Bpp);
|
||||
}
|
||||
s_mark_end(s);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s,
|
||||
RDP_DATA_PDU_UPDATE);
|
||||
i = i + lines_sending;
|
||||
}
|
||||
}
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_send_pointer(struct xrdp_session* session, int cache_idx,
|
||||
char* data, char* mask, int x, int y)
|
||||
{
|
||||
struct stream* s;
|
||||
char* p;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
|
||||
out_uint16_le(s, RDP_POINTER_COLOR);
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
out_uint16_le(s, cache_idx); /* cache_idx */
|
||||
out_uint16_le(s, x);
|
||||
out_uint16_le(s, y);
|
||||
out_uint16_le(s, 32);
|
||||
out_uint16_le(s, 32);
|
||||
out_uint16_le(s, 128);
|
||||
out_uint16_le(s, 3072);
|
||||
p = data;
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
for (j = 0; j < 32; j++)
|
||||
{
|
||||
out_uint8(s, *p);
|
||||
p++;
|
||||
out_uint8(s, *p);
|
||||
p++;
|
||||
out_uint8(s, *p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
out_uint8a(s, mask, 128); /* mask */
|
||||
s_mark_end(s);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s, RDP_DATA_PDU_POINTER);
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_set_pointer(struct xrdp_session* session, int cache_idx)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
|
||||
out_uint16_le(s, RDP_POINTER_CACHED);
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
out_uint16_le(s, cache_idx); /* cache_idx */
|
||||
s_mark_end(s);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s, RDP_DATA_PDU_POINTER);
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_init(struct xrdp_session* session)
|
||||
{
|
||||
return xrdp_orders_init((struct xrdp_orders*)session->orders);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_send(struct xrdp_session* session)
|
||||
{
|
||||
return xrdp_orders_send((struct xrdp_orders*)session->orders);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_force_send(struct xrdp_session* session)
|
||||
{
|
||||
return xrdp_orders_force_send((struct xrdp_orders*)session->orders);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_rect(struct xrdp_session* session, int x, int y,
|
||||
int cx, int cy, int color, struct xrdp_rect* rect)
|
||||
{
|
||||
return xrdp_orders_rect((struct xrdp_orders*)session->orders,
|
||||
x, y, cx, cy, color, rect);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_screen_blt(struct xrdp_session* session, int x, int y,
|
||||
int cx, int cy, int srcx, int srcy,
|
||||
int rop, struct xrdp_rect* rect)
|
||||
{
|
||||
return xrdp_orders_screen_blt((struct xrdp_orders*)session->orders,
|
||||
x, y, cx, cy, srcx, srcy, rop, rect);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_pat_blt(struct xrdp_session* session, int x, int y,
|
||||
int cx, int cy, int rop, int bg_color,
|
||||
int fg_color, struct xrdp_brush* brush,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
return xrdp_orders_pat_blt((struct xrdp_orders*)session->orders,
|
||||
x, y, cx, cy, rop, bg_color, fg_color,
|
||||
brush, rect);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_dest_blt(struct xrdp_session* session, int x, int y,
|
||||
int cx, int cy, int rop,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
return xrdp_orders_dest_blt((struct xrdp_orders*)session->orders,
|
||||
x, y, cx, cy, rop, rect);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_line(struct xrdp_session* session, int mix_mode,
|
||||
int startx, int starty,
|
||||
int endx, int endy, int rop, int bg_color,
|
||||
struct xrdp_pen* pen,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
return xrdp_orders_line((struct xrdp_orders*)session->orders,
|
||||
mix_mode, startx, starty, endx, endy,
|
||||
rop, bg_color, pen, rect);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_mem_blt(struct xrdp_session* session, int cache_id,
|
||||
int color_table, int x, int y, int cx, int cy,
|
||||
int rop, int srcx, int srcy,
|
||||
int cache_idx, struct xrdp_rect* rect)
|
||||
{
|
||||
return xrdp_orders_mem_blt((struct xrdp_orders*)session->orders,
|
||||
cache_id, color_table, x, y, cx, cy, rop,
|
||||
srcx, srcy, cache_idx, rect);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_text(struct xrdp_session* session,
|
||||
int font, int flags, int mixmode,
|
||||
int fg_color, int bg_color,
|
||||
int clip_left, int clip_top,
|
||||
int clip_right, int clip_bottom,
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char* data, int data_len,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
return xrdp_orders_text((struct xrdp_orders*)session->orders,
|
||||
font, flags, mixmode, fg_color, bg_color,
|
||||
clip_left, clip_top, clip_right, clip_bottom,
|
||||
box_left, box_top, box_right, box_bottom,
|
||||
x, y, data, data_len, rect);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_send_palette(struct xrdp_session* session, int* palette,
|
||||
int cache_id)
|
||||
{
|
||||
return xrdp_orders_send_palette((struct xrdp_orders*)session->orders,
|
||||
palette, cache_id);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_send_raw_bitmap(struct xrdp_session* session,
|
||||
int width, int height, int bpp, char* data,
|
||||
int cache_id, int cache_idx)
|
||||
{
|
||||
return xrdp_orders_send_raw_bitmap((struct xrdp_orders*)session->orders,
|
||||
width, height, bpp, data,
|
||||
cache_id, cache_idx);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_send_bitmap(struct xrdp_session* session,
|
||||
int width, int height, int bpp, char* data,
|
||||
int cache_id, int cache_idx)
|
||||
{
|
||||
return xrdp_orders_send_bitmap((struct xrdp_orders*)session->orders,
|
||||
width, height, bpp, data,
|
||||
cache_id, cache_idx);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_orders_send_font(struct xrdp_session* session,
|
||||
struct xrdp_font_char* font_char,
|
||||
int font_index, int char_index)
|
||||
{
|
||||
return xrdp_orders_send_font((struct xrdp_orders*)session->orders,
|
||||
font_char, font_index, char_index);
|
||||
}
|
@ -0,0 +1,342 @@
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2004-2005
|
||||
|
||||
libxrdp header
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(LIBXRDP_H)
|
||||
#define LIBXRDP_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "parse.h"
|
||||
#include "xrdp_constants.h"
|
||||
#include "defines.h"
|
||||
#include "os_calls.h"
|
||||
#include "ssl_calls.h"
|
||||
#include "list.h"
|
||||
#include "file.h"
|
||||
#include "libxrdpinc.h"
|
||||
|
||||
/* tcp */
|
||||
struct xrdp_tcp
|
||||
{
|
||||
int sck;
|
||||
int sck_closed;
|
||||
struct xrdp_iso* iso_layer; /* owner */
|
||||
};
|
||||
|
||||
/* iso */
|
||||
struct xrdp_iso
|
||||
{
|
||||
struct xrdp_mcs* mcs_layer; /* owner */
|
||||
struct xrdp_tcp* tcp_layer;
|
||||
};
|
||||
|
||||
/* mcs */
|
||||
struct xrdp_mcs
|
||||
{
|
||||
struct xrdp_sec* sec_layer; /* owner */
|
||||
struct xrdp_iso* iso_layer;
|
||||
int userid;
|
||||
int chanid;
|
||||
struct stream* client_mcs_data;
|
||||
struct stream* server_mcs_data;
|
||||
};
|
||||
|
||||
/* sec */
|
||||
struct xrdp_sec
|
||||
{
|
||||
struct xrdp_rdp* rdp_layer; /* owner */
|
||||
struct xrdp_mcs* mcs_layer;
|
||||
char server_random[32];
|
||||
char client_random[64];
|
||||
char client_crypt_random[72];
|
||||
struct stream client_mcs_data;
|
||||
struct stream server_mcs_data;
|
||||
int decrypt_use_count;
|
||||
int encrypt_use_count;
|
||||
char decrypt_key[16];
|
||||
char encrypt_key[16];
|
||||
char decrypt_update_key[16];
|
||||
char encrypt_update_key[16];
|
||||
int rc4_key_size;
|
||||
int rc4_key_len;
|
||||
char sign_key[16];
|
||||
void* decrypt_rc4_info;
|
||||
void* encrypt_rc4_info;
|
||||
};
|
||||
|
||||
/* rdp */
|
||||
struct xrdp_rdp
|
||||
{
|
||||
struct xrdp_session* session;
|
||||
struct xrdp_sec* sec_layer;
|
||||
int share_id;
|
||||
int mcs_channel;
|
||||
struct xrdp_client_info client_info;
|
||||
};
|
||||
|
||||
/* orders */
|
||||
struct xrdp_orders
|
||||
{
|
||||
struct stream* out_s;
|
||||
struct xrdp_rdp* rdp_layer;
|
||||
struct xrdp_session* session;
|
||||
struct xrdp_wm* wm;
|
||||
|
||||
char* order_count_ptr; /* pointer to count, set when sending */
|
||||
int order_count;
|
||||
int order_level; /* inc for every call to xrdp_orders_init */
|
||||
|
||||
int last_order; /* last order sent */
|
||||
|
||||
int clip_left; /* RDP_ORDER_BOUNDS, RDP_ORDER_LASTBOUNDS */
|
||||
int clip_top;
|
||||
int clip_right;
|
||||
int clip_bottom;
|
||||
|
||||
int rect_x; /* RDP_ORDER_RECT */
|
||||
int rect_y;
|
||||
int rect_cx;
|
||||
int rect_cy;
|
||||
int rect_color;
|
||||
|
||||
int scr_blt_x; /* RDP_ORDER_SCREENBLT */
|
||||
int scr_blt_y;
|
||||
int scr_blt_cx;
|
||||
int scr_blt_cy;
|
||||
int scr_blt_rop;
|
||||
int scr_blt_srcx;
|
||||
int scr_blt_srcy;
|
||||
|
||||
int pat_blt_x; /* RDP_ORDER_PATBLT */
|
||||
int pat_blt_y;
|
||||
int pat_blt_cx;
|
||||
int pat_blt_cy;
|
||||
int pat_blt_rop;
|
||||
int pat_blt_bg_color;
|
||||
int pat_blt_fg_color;
|
||||
struct xrdp_brush pat_blt_brush;
|
||||
|
||||
int dest_blt_x; /* RDP_ORDER_DESTBLT */
|
||||
int dest_blt_y;
|
||||
int dest_blt_cx;
|
||||
int dest_blt_cy;
|
||||
int dest_blt_rop;
|
||||
|
||||
int line_mix_mode; /* RDP_ORDER_LINE */
|
||||
int line_startx;
|
||||
int line_starty;
|
||||
int line_endx;
|
||||
int line_endy;
|
||||
int line_bg_color;
|
||||
int line_rop;
|
||||
struct xrdp_pen line_pen;
|
||||
|
||||
int mem_blt_color_table; /* RDP_ORDER_MEMBLT */
|
||||
int mem_blt_cache_id;
|
||||
int mem_blt_x;
|
||||
int mem_blt_y;
|
||||
int mem_blt_cx;
|
||||
int mem_blt_cy;
|
||||
int mem_blt_rop;
|
||||
int mem_blt_srcx;
|
||||
int mem_blt_srcy;
|
||||
int mem_blt_cache_idx;
|
||||
|
||||
int text_font; /* RDP_ORDER_TEXT2 */
|
||||
int text_flags;
|
||||
int text_unknown;
|
||||
int text_mixmode;
|
||||
int text_fg_color;
|
||||
int text_bg_color;
|
||||
int text_clip_left;
|
||||
int text_clip_top;
|
||||
int text_clip_right;
|
||||
int text_clip_bottom;
|
||||
int text_box_left;
|
||||
int text_box_top;
|
||||
int text_box_right;
|
||||
int text_box_bottom;
|
||||
int text_x;
|
||||
int text_y;
|
||||
int text_len;
|
||||
char* text_data;
|
||||
};
|
||||
|
||||
/* xrdp_tcp.c */
|
||||
struct xrdp_tcp* APP_CC
|
||||
xrdp_tcp_create(struct xrdp_iso* owner, int sck);
|
||||
void APP_CC
|
||||
xrdp_tcp_delete(struct xrdp_tcp* self);
|
||||
int APP_CC
|
||||
xrdp_tcp_init(struct xrdp_tcp* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_tcp_recv(struct xrdp_tcp* self, struct stream* s, int len);
|
||||
int APP_CC
|
||||
xrdp_tcp_send(struct xrdp_tcp* self, struct stream* s);
|
||||
|
||||
/* xrdp_iso.c */
|
||||
struct xrdp_iso* APP_CC
|
||||
xrdp_iso_create(struct xrdp_mcs* owner, int sck);
|
||||
void APP_CC
|
||||
xrdp_iso_delete(struct xrdp_iso* self);
|
||||
int APP_CC
|
||||
xrdp_iso_init(struct xrdp_iso* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_iso_recv(struct xrdp_iso* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_iso_send(struct xrdp_iso* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_iso_incoming(struct xrdp_iso* self);
|
||||
|
||||
/* xrdp_mcs.c */
|
||||
struct xrdp_mcs* APP_CC
|
||||
xrdp_mcs_create(struct xrdp_sec* owner, int sck,
|
||||
struct stream* client_mcs_data,
|
||||
struct stream* server_mcs_data);
|
||||
void APP_CC
|
||||
xrdp_mcs_delete(struct xrdp_mcs* self);
|
||||
int APP_CC
|
||||
xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan);
|
||||
int APP_CC
|
||||
xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_mcs_incoming(struct xrdp_mcs* self);
|
||||
int APP_CC
|
||||
xrdp_mcs_disconnect(struct xrdp_mcs* self);
|
||||
|
||||
/* xrdp_sec.c */
|
||||
struct xrdp_sec* APP_CC
|
||||
xrdp_sec_create(struct xrdp_rdp* owner, int sck);
|
||||
void APP_CC
|
||||
xrdp_sec_delete(struct xrdp_sec* self);
|
||||
int APP_CC
|
||||
xrdp_sec_init(struct xrdp_sec* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan);
|
||||
int APP_CC
|
||||
xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int flags);
|
||||
int APP_CC
|
||||
xrdp_sec_incoming(struct xrdp_sec* self);
|
||||
int APP_CC
|
||||
xrdp_sec_disconnect(struct xrdp_sec* self);
|
||||
|
||||
/* xrdp_rdp.c */
|
||||
struct xrdp_rdp* APP_CC
|
||||
xrdp_rdp_create(struct xrdp_session* session, int sck);
|
||||
void APP_CC
|
||||
xrdp_rdp_delete(struct xrdp_rdp* self);
|
||||
int APP_CC
|
||||
xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code);
|
||||
int APP_CC
|
||||
xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type);
|
||||
int APP_CC
|
||||
xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s,
|
||||
int data_pdu_type);
|
||||
int APP_CC
|
||||
xrdp_rdp_incoming(struct xrdp_rdp* self);
|
||||
int APP_CC
|
||||
xrdp_rdp_send_demand_active(struct xrdp_rdp* self);
|
||||
int APP_CC
|
||||
xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s);
|
||||
int APP_CC
|
||||
xrdp_rdp_disconnect(struct xrdp_rdp* self);
|
||||
|
||||
/* xrdp_orders.c */
|
||||
struct xrdp_orders* APP_CC
|
||||
xrdp_orders_create(struct xrdp_session* session,
|
||||
struct xrdp_rdp* rdp_layer);
|
||||
void APP_CC
|
||||
xrdp_orders_delete(struct xrdp_orders* self);
|
||||
int APP_CC
|
||||
xrdp_orders_init(struct xrdp_orders* self);
|
||||
int APP_CC
|
||||
xrdp_orders_send(struct xrdp_orders* self);
|
||||
int APP_CC
|
||||
xrdp_orders_force_send(struct xrdp_orders* self);
|
||||
int APP_CC
|
||||
xrdp_orders_rect(struct xrdp_orders* self, int x, int y, int cx, int cy,
|
||||
int color, struct xrdp_rect* rect);
|
||||
int APP_CC
|
||||
xrdp_orders_screen_blt(struct xrdp_orders* self, int x, int y,
|
||||
int cx, int cy, int srcx, int srcy,
|
||||
int rop, struct xrdp_rect* rect);
|
||||
int APP_CC
|
||||
xrdp_orders_pat_blt(struct xrdp_orders* self, int x, int y,
|
||||
int cx, int cy, int rop, int bg_color,
|
||||
int fg_color, struct xrdp_brush* brush,
|
||||
struct xrdp_rect* rect);
|
||||
int APP_CC
|
||||
xrdp_orders_dest_blt(struct xrdp_orders* self, int x, int y,
|
||||
int cx, int cy, int rop,
|
||||
struct xrdp_rect* rect);
|
||||
int APP_CC
|
||||
xrdp_orders_line(struct xrdp_orders* self, int mix_mode,
|
||||
int startx, int starty,
|
||||
int endx, int endy, int rop, int bg_color,
|
||||
struct xrdp_pen* pen,
|
||||
struct xrdp_rect* rect);
|
||||
int APP_CC
|
||||
xrdp_orders_mem_blt(struct xrdp_orders* self, int cache_id,
|
||||
int color_table, int x, int y, int cx, int cy,
|
||||
int rop, int srcx, int srcy,
|
||||
int cache_idx, struct xrdp_rect* rect);
|
||||
int APP_CC
|
||||
xrdp_orders_text(struct xrdp_orders* self,
|
||||
int font, int flags, int mixmode,
|
||||
int fg_color, int bg_color,
|
||||
int clip_left, int clip_top,
|
||||
int clip_right, int clip_bottom,
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char* data, int data_len,
|
||||
struct xrdp_rect* rect);
|
||||
int APP_CC
|
||||
xrdp_orders_send_palette(struct xrdp_orders* self, int* palette,
|
||||
int cache_id);
|
||||
int APP_CC
|
||||
xrdp_orders_send_raw_bitmap(struct xrdp_orders* self,
|
||||
int width, int height, int bpp, char* data,
|
||||
int cache_id, int cache_idx);
|
||||
int APP_CC
|
||||
xrdp_orders_send_bitmap(struct xrdp_orders* self,
|
||||
int width, int height, int bpp, char* data,
|
||||
int cache_id, int cache_idx);
|
||||
int APP_CC
|
||||
xrdp_orders_send_font(struct xrdp_orders* self,
|
||||
struct xrdp_font_char* font_char,
|
||||
int font_index, int char_index);
|
||||
|
||||
/* xrdp_bitmap_compress.c */
|
||||
int APP_CC
|
||||
xrdp_bitmap_compress(char* in_data, int width, int height,
|
||||
struct stream* s, int bpp, int byte_limit,
|
||||
int start_line, struct stream* temp,
|
||||
int e);
|
||||
|
||||
#endif
|
@ -0,0 +1,170 @@
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2004-2005
|
||||
|
||||
header file for use with libxrdp.so / xrdp.dll
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(LIBXRDPINC_H)
|
||||
#define LIBXRDPINC_H
|
||||
|
||||
struct xrdp_client_info
|
||||
{
|
||||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
int cache1_entries;
|
||||
int cache1_size;
|
||||
int cache2_entries;
|
||||
int cache2_size;
|
||||
int cache3_entries;
|
||||
int cache3_size;
|
||||
int pointer_cache_entries;
|
||||
int use_bitmap_comp;
|
||||
int use_bitmap_cache;
|
||||
int op1; /* use smaller bitmap header, todo */
|
||||
int desktop_cache;
|
||||
int use_compact_packets; /* rdp5 smaller packets */
|
||||
};
|
||||
|
||||
struct xrdp_brush
|
||||
{
|
||||
int x_orgin;
|
||||
int y_orgin;
|
||||
int style;
|
||||
char pattern[8];
|
||||
};
|
||||
|
||||
struct xrdp_pen
|
||||
{
|
||||
int style;
|
||||
int width;
|
||||
int color;
|
||||
};
|
||||
|
||||
struct xrdp_font_char
|
||||
{
|
||||
int offset;
|
||||
int baseline;
|
||||
int width;
|
||||
int height;
|
||||
int incby;
|
||||
char* data;
|
||||
};
|
||||
|
||||
struct xrdp_rect
|
||||
{
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
};
|
||||
|
||||
struct xrdp_session
|
||||
{
|
||||
long id;
|
||||
int sck;
|
||||
int term; /* do we need this */
|
||||
int (*callback)(long id, int msg, long param1, long param2, long param3,
|
||||
long param4);
|
||||
void* rdp;
|
||||
void* orders;
|
||||
struct xrdp_client_info* client_info;
|
||||
int up_and_running;
|
||||
};
|
||||
|
||||
struct xrdp_session*
|
||||
libxrdp_init(long id, int sck);
|
||||
int
|
||||
libxrdp_exit(struct xrdp_session* session);
|
||||
int
|
||||
libxrdp_disconnect(struct xrdp_session* session);
|
||||
int
|
||||
libxrdp_process_incomming(struct xrdp_session* session);
|
||||
int
|
||||
libxrdp_process_data(struct xrdp_session* session);
|
||||
int
|
||||
libxrdp_send_palette(struct xrdp_session* session, int* palette);
|
||||
int
|
||||
libxrdp_send_bitmap(struct xrdp_session* session, int width, int height,
|
||||
int bpp, char* data, int x, int y, int cx, int cy);
|
||||
int
|
||||
libxrdp_send_pointer(struct xrdp_session* session, int cache_idx,
|
||||
char* data, char* mask, int x, int y);
|
||||
int
|
||||
libxrdp_set_pointer(struct xrdp_session* session, int cache_idx);
|
||||
int
|
||||
libxrdp_orders_init(struct xrdp_session* session);
|
||||
int
|
||||
libxrdp_orders_send(struct xrdp_session* session);
|
||||
int
|
||||
libxrdp_orders_force_send(struct xrdp_session* session);
|
||||
int
|
||||
libxrdp_orders_rect(struct xrdp_session* session, int x, int y,
|
||||
int cx, int cy, int color, struct xrdp_rect* rect);
|
||||
int
|
||||
libxrdp_orders_screen_blt(struct xrdp_session* session, int x, int y,
|
||||
int cx, int cy, int srcx, int srcy,
|
||||
int rop, struct xrdp_rect* rect);
|
||||
int
|
||||
libxrdp_orders_pat_blt(struct xrdp_session* session, int x, int y,
|
||||
int cx, int cy, int rop, int bg_color,
|
||||
int fg_color, struct xrdp_brush* brush,
|
||||
struct xrdp_rect* rect);
|
||||
int
|
||||
libxrdp_orders_dest_blt(struct xrdp_session* session, int x, int y,
|
||||
int cx, int cy, int rop,
|
||||
struct xrdp_rect* rect);
|
||||
int
|
||||
libxrdp_orders_line(struct xrdp_session* session, int mix_mode,
|
||||
int startx, int starty,
|
||||
int endx, int endy, int rop, int bg_color,
|
||||
struct xrdp_pen* pen,
|
||||
struct xrdp_rect* rect);
|
||||
int
|
||||
libxrdp_orders_mem_blt(struct xrdp_session* session, int cache_id,
|
||||
int color_table, int x, int y, int cx, int cy,
|
||||
int rop, int srcx, int srcy,
|
||||
int cache_idx, struct xrdp_rect* rect);
|
||||
int
|
||||
libxrdp_orders_text(struct xrdp_session* session,
|
||||
int font, int flags, int mixmode,
|
||||
int fg_color, int bg_color,
|
||||
int clip_left, int clip_top,
|
||||
int clip_right, int clip_bottom,
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char* data, int data_len,
|
||||
struct xrdp_rect* rect);
|
||||
int
|
||||
libxrdp_orders_send_palette(struct xrdp_session* session, int* palette,
|
||||
int cache_id);
|
||||
int
|
||||
libxrdp_orders_send_raw_bitmap(struct xrdp_session* session,
|
||||
int width, int height, int bpp, char* data,
|
||||
int cache_id, int cache_idx);
|
||||
int
|
||||
libxrdp_orders_send_bitmap(struct xrdp_session* session,
|
||||
int width, int height, int bpp, char* data,
|
||||
int cache_id, int cache_idx);
|
||||
int
|
||||
libxrdp_orders_send_font(struct xrdp_session* session,
|
||||
struct xrdp_font_char* font_char,
|
||||
int font_index, int char_index);
|
||||
|
||||
#endif
|
@ -0,0 +1,42 @@
|
||||
# borland windows makefile
|
||||
#
|
||||
# this assumes openssl and borland free command line tools are installed
|
||||
# this assumes c:\windows is windows directory
|
||||
#
|
||||
# run 'set PATH=c:\borland\bcc55\bin' and run 'make -f makefile_win32 all'
|
||||
#
|
||||
|
||||
XRDPOBJ = libxrdp.obj xrdp_tcp.obj xrdp_iso.obj xrdp_mcs.obj \
|
||||
xrdp_sec.obj xrdp_rdp.obj xrdp_orders.obj \
|
||||
xrdp_bitmap_compress.obj \
|
||||
list.obj \
|
||||
file.obj \
|
||||
os_calls.obj \
|
||||
ssl_calls.obj
|
||||
|
||||
CFLAGS = -w- -O2 -I../common -Ic:/borland/bcc55/include -Ic:/openssl/include
|
||||
LDFLAGS = -Lc:/borland/bcc55/lib
|
||||
|
||||
xrdp: $(XRDPOBJ)
|
||||
$(CC) $(LDFLAGS) -WD -exrdp.dll libeay32.lib $(XRDPOBJ)
|
||||
|
||||
all: lib xrdp
|
||||
|
||||
clean:
|
||||
del $(XRDPOBJ) xrdp.dll
|
||||
|
||||
lib:
|
||||
implib -a -w libeay32.lib c:/windows/system32/libeay32.dll
|
||||
|
||||
list.obj:
|
||||
$(CC) $(CFLAGS) -c ../common/list.c
|
||||
|
||||
file.obj:
|
||||
$(CC) $(CFLAGS) -c ../common/file.c
|
||||
|
||||
os_calls.obj:
|
||||
$(CC) $(CFLAGS) -c ../common/os_calls.c
|
||||
|
||||
ssl_calls.obj:
|
||||
$(CC) $(CFLAGS) -c ../common/ssl_calls.c
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,195 @@
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2004-2005
|
||||
|
||||
iso layer
|
||||
|
||||
*/
|
||||
|
||||
#include "libxrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_iso* APP_CC
|
||||
xrdp_iso_create(struct xrdp_mcs* owner, int sck)
|
||||
{
|
||||
struct xrdp_iso* self;
|
||||
|
||||
self = (struct xrdp_iso*)g_malloc(sizeof(struct xrdp_iso), 1);
|
||||
self->mcs_layer = owner;
|
||||
self->tcp_layer = xrdp_tcp_create(self, sck);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
xrdp_iso_delete(struct xrdp_iso* self)
|
||||
{
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
xrdp_tcp_delete(self->tcp_layer);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_iso_recv_msg(struct xrdp_iso* self, struct stream* s, int* code)
|
||||
{
|
||||
int ver;
|
||||
int len;
|
||||
|
||||
*code = 0;
|
||||
if (xrdp_tcp_recv(self->tcp_layer, s, 4) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, ver);
|
||||
if (ver != 3)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 1);
|
||||
in_uint16_be(s, len);
|
||||
if (xrdp_tcp_recv(self->tcp_layer, s, len - 4) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 1);
|
||||
in_uint8(s, *code);
|
||||
if (*code == ISO_PDU_DT)
|
||||
{
|
||||
in_uint8s(s, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
in_uint8s(s, 5);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_iso_recv(struct xrdp_iso* self, struct stream* s)
|
||||
{
|
||||
int code;
|
||||
|
||||
DEBUG((" in xrdp_iso_recv\n\r"));
|
||||
if (xrdp_iso_recv_msg(self, s, &code) != 0)
|
||||
{
|
||||
DEBUG((" out xrdp_iso_recv xrdp_iso_recv_msg return non zero\n\r"));
|
||||
return 1;
|
||||
}
|
||||
if (code != ISO_PDU_DT)
|
||||
{
|
||||
DEBUG((" out xrdp_iso_recv code != ISO_PDU_DT\n\r"));
|
||||
return 1;
|
||||
}
|
||||
DEBUG((" out xrdp_iso_recv\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_iso_send_msg(struct xrdp_iso* self, struct stream* s, int code)
|
||||
{
|
||||
if (xrdp_tcp_init(self->tcp_layer, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
out_uint8(s, 3);
|
||||
out_uint8(s, 0);
|
||||
out_uint16_be(s, 11); /* length */
|
||||
out_uint8(s, 8);
|
||||
out_uint8(s, code);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint8(s, 0);
|
||||
s_mark_end(s);
|
||||
if (xrdp_tcp_send(self->tcp_layer, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_iso_incoming(struct xrdp_iso* self)
|
||||
{
|
||||
int code;
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
DEBUG((" in xrdp_iso_incoming\n\r"));
|
||||
if (xrdp_iso_recv_msg(self, s, &code) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
if (code != ISO_PDU_CR)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_iso_send_msg(self, s, ISO_PDU_CC) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
DEBUG((" out xrdp_iso_incoming\n\r"));
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_iso_init(struct xrdp_iso* self, struct stream* s)
|
||||
{
|
||||
xrdp_tcp_init(self->tcp_layer, s);
|
||||
s_push_layer(s, iso_hdr, 7);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_iso_send(struct xrdp_iso* self, struct stream* s)
|
||||
{
|
||||
int len;
|
||||
|
||||
DEBUG((" in xrdp_iso_send\n\r"));
|
||||
s_pop_layer(s, iso_hdr);
|
||||
len = s->end - s->p;
|
||||
out_uint8(s, 3);
|
||||
out_uint8(s, 0);
|
||||
out_uint16_be(s, len);
|
||||
out_uint8(s, 2);
|
||||
out_uint8(s, ISO_PDU_DT);
|
||||
out_uint8(s, 0x80);
|
||||
if (xrdp_tcp_send(self->tcp_layer, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG((" out xrdp_iso_send\n\r"));
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,629 @@
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2004-2005
|
||||
|
||||
mcs layer
|
||||
|
||||
*/
|
||||
|
||||
#include "libxrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_mcs* APP_CC
|
||||
xrdp_mcs_create(struct xrdp_sec* owner, int sck,
|
||||
struct stream* client_mcs_data,
|
||||
struct stream* server_mcs_data)
|
||||
{
|
||||
struct xrdp_mcs* self;
|
||||
|
||||
self = (struct xrdp_mcs*)g_malloc(sizeof(struct xrdp_mcs), 1);
|
||||
self->sec_layer = owner;
|
||||
self->userid = 1;
|
||||
self->chanid = 1001;
|
||||
self->client_mcs_data = client_mcs_data;
|
||||
self->server_mcs_data = server_mcs_data;
|
||||
self->iso_layer = xrdp_iso_create(self, sck);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
xrdp_mcs_delete(struct xrdp_mcs* self)
|
||||
{
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
xrdp_iso_delete(self->iso_layer);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int chanid)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_iso_init(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint8(s, (MCS_CJCF << 2) | 2);
|
||||
out_uint8(s, 0);
|
||||
out_uint16_be(s, self->userid);
|
||||
out_uint16_be(s, chanid);
|
||||
out_uint16_be(s, chanid);
|
||||
s_mark_end(s);
|
||||
if (xrdp_iso_send(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan)
|
||||
{
|
||||
int appid;
|
||||
int opcode;
|
||||
int len;
|
||||
|
||||
DEBUG((" in xrdp_mcs_recv\n\r"));
|
||||
while (1)
|
||||
{
|
||||
if (xrdp_iso_recv(self->iso_layer, s) != 0)
|
||||
{
|
||||
DEBUG((" out xrdp_mcs_recv xrdp_iso_recv returned non zero\n\r"));
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, opcode);
|
||||
appid = opcode >> 2;
|
||||
if (appid == MCS_DPUM)
|
||||
{
|
||||
DEBUG((" out xrdp_mcs_recv appid != MCS_DPUM\n\r"));
|
||||
return 1;
|
||||
}
|
||||
if (appid == MCS_CJRQ)
|
||||
{
|
||||
xrdp_mcs_send_cjcf(self, self->userid + MCS_USERCHANNEL_BASE);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (appid != MCS_SDRQ)
|
||||
{
|
||||
DEBUG((" out xrdp_mcs_recv err got 0x%x need MCS_SDRQ\n\r", appid));
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 2);
|
||||
in_uint16_be(s, *chan);
|
||||
in_uint8s(s, 1);
|
||||
in_uint8(s, len);
|
||||
if (len & 0x80)
|
||||
{
|
||||
in_uint8s(s, 1);
|
||||
}
|
||||
DEBUG((" out xrdp_mcs_recv\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_ber_parse_header(struct xrdp_mcs* self, struct stream* s,
|
||||
int tag_val, int* len)
|
||||
{
|
||||
int tag;
|
||||
int l;
|
||||
int i;
|
||||
|
||||
if (tag_val > 0xff)
|
||||
{
|
||||
in_uint16_be(s, tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
in_uint8(s, tag);
|
||||
}
|
||||
if (tag != tag_val)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, l);
|
||||
if (l & 0x80)
|
||||
{
|
||||
l = l & ~0x80;
|
||||
*len = 0;
|
||||
while (l > 0)
|
||||
{
|
||||
in_uint8(s, i);
|
||||
*len = (*len << 8) | i;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*len = l;
|
||||
}
|
||||
if (s_check(s))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_parse_domain_params(struct xrdp_mcs* self, struct stream* s)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (xrdp_mcs_ber_parse_header(self, s, MCS_TAG_DOMAIN_PARAMS, &len) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, len);
|
||||
if (s_check(s))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_recv_connect_initial(struct xrdp_mcs* self)
|
||||
{
|
||||
int len;
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_iso_recv(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_ber_parse_header(self, s, MCS_CONNECT_INITIAL, &len) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, len);
|
||||
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, len);
|
||||
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, len);
|
||||
if (xrdp_mcs_parse_domain_params(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_parse_domain_params(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_parse_domain_params(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
/* make a copy of client mcs data */
|
||||
init_stream(self->client_mcs_data, len);
|
||||
out_uint8a(self->client_mcs_data, s->p, len);
|
||||
in_uint8s(s, len);
|
||||
s_mark_end(self->client_mcs_data);
|
||||
if (s_check_end(s))
|
||||
{
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_recv_edrq(struct xrdp_mcs* self)
|
||||
{
|
||||
int opcode;
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_iso_recv(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, opcode);
|
||||
if ((opcode >> 2) != MCS_EDRQ)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 2);
|
||||
in_uint8s(s, 2);
|
||||
if (opcode & 2)
|
||||
{
|
||||
in_uint16_be(s, self->userid);
|
||||
}
|
||||
if (!(s_check_end(s)))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_recv_aurq(struct xrdp_mcs* self)
|
||||
{
|
||||
int opcode;
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_iso_recv(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, opcode);
|
||||
if ((opcode >> 2) != MCS_AURQ)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
if (opcode & 2)
|
||||
{
|
||||
in_uint16_be(s, self->userid);
|
||||
}
|
||||
if (!(s_check_end(s)))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_send_aucf(struct xrdp_mcs* self)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_iso_init(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint8(s, ((MCS_AUCF << 2) | 2));
|
||||
out_uint8s(s, 1);
|
||||
out_uint16_be(s, self->userid);
|
||||
s_mark_end(s);
|
||||
if (xrdp_iso_send(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_recv_cjrq(struct xrdp_mcs* self)
|
||||
{
|
||||
int opcode;
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_iso_recv(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, opcode);
|
||||
if ((opcode >> 2) != MCS_CJRQ)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 4);
|
||||
if (opcode & 2)
|
||||
{
|
||||
in_uint8s(s, 2);
|
||||
}
|
||||
if (!(s_check_end(s)))
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_ber_out_header(struct xrdp_mcs* self, struct stream* s,
|
||||
int tag_val, int len)
|
||||
{
|
||||
if (tag_val > 0xff)
|
||||
{
|
||||
out_uint16_be(s, tag_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint8(s, tag_val);
|
||||
}
|
||||
if (len >= 0x80)
|
||||
{
|
||||
out_uint8(s, 0x82);
|
||||
out_uint16_be(s, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint8(s, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_ber_out_int8(struct xrdp_mcs* self, struct stream* s, int value)
|
||||
{
|
||||
xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1);
|
||||
out_uint8(s, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0 /* not used */
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_ber_out_int16(struct xrdp_mcs* self, struct stream* s, int value)
|
||||
{
|
||||
xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 2);
|
||||
out_uint8(s, (value >> 8));
|
||||
out_uint8(s, value);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_ber_out_int24(struct xrdp_mcs* self, struct stream* s, int value)
|
||||
{
|
||||
xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 3);
|
||||
out_uint8(s, (value >> 16));
|
||||
out_uint8(s, (value >> 8));
|
||||
out_uint8(s, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_out_domain_params(struct xrdp_mcs* self, struct stream* s,
|
||||
int max_channels,
|
||||
int max_users, int max_tokens,
|
||||
int max_pdu_size)
|
||||
{
|
||||
xrdp_mcs_ber_out_header(self, s, MCS_TAG_DOMAIN_PARAMS, 26);
|
||||
xrdp_mcs_ber_out_int8(self, s, max_channels);
|
||||
xrdp_mcs_ber_out_int8(self, s, max_users);
|
||||
xrdp_mcs_ber_out_int8(self, s, max_tokens);
|
||||
xrdp_mcs_ber_out_int8(self, s, 1);
|
||||
xrdp_mcs_ber_out_int8(self, s, 0);
|
||||
xrdp_mcs_ber_out_int8(self, s, 1);
|
||||
xrdp_mcs_ber_out_int24(self, s, max_pdu_size);
|
||||
xrdp_mcs_ber_out_int8(self, s, 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_mcs_send_connect_response(struct xrdp_mcs* self)
|
||||
{
|
||||
int data_len;
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
data_len = self->server_mcs_data->end - self->server_mcs_data->data;
|
||||
xrdp_iso_init(self->iso_layer, s);
|
||||
xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, 313);
|
||||
xrdp_mcs_ber_out_header(self, s, BER_TAG_RESULT, 1);
|
||||
out_uint8(s, 0);
|
||||
xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1);
|
||||
out_uint8(s, 0);
|
||||
xrdp_mcs_out_domain_params(self, s, 2, 2, 0, 0xffff);
|
||||
xrdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, data_len);
|
||||
/* mcs data */
|
||||
out_uint8a(s, self->server_mcs_data->data, data_len);
|
||||
s_mark_end(s);
|
||||
if (xrdp_iso_send(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_mcs_incoming(struct xrdp_mcs* self)
|
||||
{
|
||||
DEBUG((" in xrdp_mcs_incoming\n\r"));
|
||||
if (xrdp_iso_incoming(self->iso_layer) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_recv_connect_initial(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_send_connect_response(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_recv_edrq(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_recv_aurq(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_send_aucf(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_recv_cjrq(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_send_cjcf(self, self->userid + MCS_USERCHANNEL_BASE) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_recv_cjrq(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_mcs_send_cjcf(self, MCS_GLOBAL_CHANNEL) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG((" out xrdp_mcs_incoming\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s)
|
||||
{
|
||||
xrdp_iso_init(self->iso_layer, s);
|
||||
s_push_layer(s, mcs_hdr, 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s)
|
||||
{
|
||||
int len;
|
||||
|
||||
DEBUG((" in xrdp_mcs_send\n\r"));
|
||||
s_pop_layer(s, mcs_hdr);
|
||||
len = (s->end - s->p) - 8;
|
||||
len = len | 0x8000;
|
||||
out_uint8(s, MCS_SDIN << 2);
|
||||
out_uint16_be(s, self->userid);
|
||||
out_uint16_be(s, MCS_GLOBAL_CHANNEL);
|
||||
out_uint8(s, 0x70);
|
||||
out_uint16_be(s, len);
|
||||
if (xrdp_iso_send(self->iso_layer, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG((" out xrdp_mcs_send\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_mcs_disconnect(struct xrdp_mcs* self)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_iso_init(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint8(s, (MCS_DPUM << 2) | 1);
|
||||
out_uint8(s, 0x80);
|
||||
s_mark_end(s);
|
||||
if (xrdp_iso_send(self->iso_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,847 @@
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2004-2005
|
||||
|
||||
rdp layer
|
||||
|
||||
*/
|
||||
|
||||
#include "libxrdp.h"
|
||||
|
||||
static char unknown1[172] =
|
||||
{ 0xff, 0x02, 0xb6, 0x00, 0x28, 0x00, 0x00, 0x00,
|
||||
0x27, 0x00, 0x27, 0x00, 0x03, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x26, 0x00, 0x01, 0x00, 0x1e, 0x00,
|
||||
0x02, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x1d, 0x00,
|
||||
0x04, 0x00, 0x27, 0x00, 0x05, 0x00, 0x0b, 0x00,
|
||||
0x06, 0x00, 0x28, 0x00, 0x08, 0x00, 0x21, 0x00,
|
||||
0x09, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x22, 0x00,
|
||||
0x0b, 0x00, 0x25, 0x00, 0x0c, 0x00, 0x24, 0x00,
|
||||
0x0d, 0x00, 0x23, 0x00, 0x0e, 0x00, 0x19, 0x00,
|
||||
0x0f, 0x00, 0x16, 0x00, 0x10, 0x00, 0x15, 0x00,
|
||||
0x11, 0x00, 0x1c, 0x00, 0x12, 0x00, 0x1b, 0x00,
|
||||
0x13, 0x00, 0x1a, 0x00, 0x14, 0x00, 0x17, 0x00,
|
||||
0x15, 0x00, 0x18, 0x00, 0x16, 0x00, 0x0e, 0x00,
|
||||
0x18, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00,
|
||||
0x1a, 0x00, 0x12, 0x00, 0x1b, 0x00, 0x14, 0x00,
|
||||
0x1f, 0x00, 0x13, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x21, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x06, 0x00,
|
||||
0x23, 0x00, 0x07, 0x00, 0x24, 0x00, 0x08, 0x00,
|
||||
0x25, 0x00, 0x09, 0x00, 0x26, 0x00, 0x04, 0x00,
|
||||
0x27, 0x00, 0x03, 0x00, 0x28, 0x00, 0x02, 0x00,
|
||||
0x29, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x05, 0x00,
|
||||
0x2b, 0x00, 0x2a, 0x00 };
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_read_config(struct xrdp_client_info* client_info)
|
||||
{
|
||||
int fd;
|
||||
int index;
|
||||
struct list* items;
|
||||
struct list* values;
|
||||
char* item;
|
||||
char* value;
|
||||
|
||||
fd = g_file_open("xrdp.ini");
|
||||
if (fd > 0)
|
||||
{
|
||||
items = list_create();
|
||||
items->auto_free = 1;
|
||||
values = list_create();
|
||||
values->auto_free = 1;
|
||||
file_read_section(fd, "globals", items, values);
|
||||
for (index = 0; index < items->count; index++)
|
||||
{
|
||||
item = (char*)list_get_item(items, index);
|
||||
value = (char*)list_get_item(values, index);
|
||||
if (g_strcmp(item, "bitmap_cache") == 0)
|
||||
{
|
||||
if (g_strcmp(value, "yes") == 0)
|
||||
{
|
||||
client_info->use_bitmap_cache = 1;
|
||||
}
|
||||
}
|
||||
else if (g_strcmp(item, "bitmap_compression") == 0)
|
||||
{
|
||||
if (g_strcmp(value, "yes") == 0)
|
||||
{
|
||||
client_info->use_bitmap_comp = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
list_delete(items);
|
||||
list_delete(values);
|
||||
g_file_close(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_rdp* APP_CC
|
||||
xrdp_rdp_create(struct xrdp_session* session, int sck)
|
||||
{
|
||||
struct xrdp_rdp* self;
|
||||
|
||||
self = (struct xrdp_rdp*)g_malloc(sizeof(struct xrdp_rdp), 1);
|
||||
self->session = session;
|
||||
self->share_id = 66538;
|
||||
self->sec_layer = xrdp_sec_create(self, sck);
|
||||
/* read ini settings */
|
||||
xrdp_rdp_read_config(&self->client_info);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
xrdp_rdp_delete(struct xrdp_rdp* self)
|
||||
{
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
xrdp_sec_delete(self->sec_layer);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
if (xrdp_sec_init(self->sec_layer, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
s_push_layer(s, rdp_hdr, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
if (xrdp_sec_init(self->sec_layer, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
s_push_layer(s, rdp_hdr, 18);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns erros */
|
||||
int APP_CC
|
||||
xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code)
|
||||
{
|
||||
int error;
|
||||
int len;
|
||||
int pdu_code;
|
||||
int chan;
|
||||
|
||||
DEBUG(("in xrdp_rdp_recv\n\r"));
|
||||
if (s->next_packet == 0 || s->next_packet >= s->end)
|
||||
{
|
||||
chan = 0;
|
||||
error = xrdp_sec_recv(self->sec_layer, s, &chan);
|
||||
if (error == -1) /* special code for send demand active */
|
||||
{
|
||||
s->next_packet = 0;
|
||||
*code = -1;
|
||||
DEBUG(("out xrdp_rdp_recv\n\r"));
|
||||
return 0;
|
||||
}
|
||||
if (error != 0)
|
||||
{
|
||||
DEBUG(("out xrdp_rdp_recv error\n\r"));
|
||||
return 1;
|
||||
}
|
||||
if (chan != MCS_GLOBAL_CHANNEL && chan > 0)
|
||||
{
|
||||
s->next_packet = 0;
|
||||
*code = 0;
|
||||
DEBUG(("out xrdp_rdp_recv\n\r"));
|
||||
return 0;
|
||||
}
|
||||
s->next_packet = s->p;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->p = s->next_packet;
|
||||
}
|
||||
in_uint16_le(s, len);
|
||||
if (len == 0x8000)
|
||||
{
|
||||
s->next_packet += 8;
|
||||
*code = 0;
|
||||
DEBUG(("out xrdp_rdp_recv\n\r"));
|
||||
return 0;
|
||||
}
|
||||
in_uint16_le(s, pdu_code);
|
||||
*code = pdu_code & 0xf;
|
||||
in_uint8s(s, 2); /* mcs user id */
|
||||
s->next_packet += len;
|
||||
DEBUG(("out xrdp_rdp_recv\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type)
|
||||
{
|
||||
int len;
|
||||
|
||||
DEBUG(("in xrdp_rdp_send\n\r"));
|
||||
s_pop_layer(s, rdp_hdr);
|
||||
len = s->end - s->p;
|
||||
out_uint16_le(s, len);
|
||||
out_uint16_le(s, 0x10 | pdu_type);
|
||||
out_uint16_le(s, self->mcs_channel);
|
||||
if (xrdp_sec_send(self->sec_layer, s, 0) != 0)
|
||||
{
|
||||
DEBUG(("out xrdp_rdp_send error\n\r"));
|
||||
return 1;
|
||||
}
|
||||
DEBUG(("out xrdp_rdp_send\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s,
|
||||
int data_pdu_type)
|
||||
{
|
||||
int len;
|
||||
|
||||
DEBUG(("in xrdp_rdp_send_data\n\r"));
|
||||
s_pop_layer(s, rdp_hdr);
|
||||
len = s->end - s->p;
|
||||
out_uint16_le(s, len);
|
||||
out_uint16_le(s, 0x10 | RDP_PDU_DATA);
|
||||
out_uint16_le(s, self->mcs_channel);
|
||||
out_uint32_le(s, self->share_id);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 1);
|
||||
out_uint16_le(s, len - 14);
|
||||
out_uint8(s, data_pdu_type);
|
||||
out_uint8(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
if (xrdp_sec_send(self->sec_layer, s, 0) != 0)
|
||||
{
|
||||
DEBUG(("out xrdp_rdp_send_data error\n\r"));
|
||||
return 1;
|
||||
}
|
||||
DEBUG(("out xrdp_rdp_send_data\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp* self)
|
||||
{
|
||||
struct stream* p;
|
||||
int i;
|
||||
|
||||
p = &self->sec_layer->client_mcs_data;
|
||||
p->p = p->data;
|
||||
in_uint8s(p, 31);
|
||||
in_uint16_le(p, self->client_info.width);
|
||||
in_uint16_le(p, self->client_info.height);
|
||||
in_uint8s(p, 120);
|
||||
self->client_info.bpp = 8;
|
||||
in_uint16_le(p, i);
|
||||
switch (i)
|
||||
{
|
||||
case 0xca01:
|
||||
in_uint8s(p, 6);
|
||||
in_uint8(p, i);
|
||||
if (i > 8)
|
||||
{
|
||||
self->client_info.bpp = i;
|
||||
}
|
||||
break;
|
||||
case 0xca02:
|
||||
self->client_info.bpp = 15;
|
||||
break;
|
||||
case 0xca03:
|
||||
self->client_info.bpp = 16;
|
||||
break;
|
||||
case 0xca04:
|
||||
self->client_info.bpp = 24;
|
||||
break;
|
||||
}
|
||||
p->p = p->data;
|
||||
DEBUG(("client width %d, client height %d bpp %d\n\r",
|
||||
self->client_info.width, self->client_info.height,
|
||||
self->client_info.bpp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_rdp_incoming(struct xrdp_rdp* self)
|
||||
{
|
||||
DEBUG(("in xrdp_rdp_incoming\n\r"));
|
||||
if (xrdp_sec_incoming(self->sec_layer) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
self->mcs_channel = self->sec_layer->mcs_layer->userid +
|
||||
MCS_USERCHANNEL_BASE;
|
||||
xrdp_rdp_parse_client_mcs_data(self);
|
||||
DEBUG(("out xrdp_rdp_incoming mcs channel %d\n\r", self->mcs_channel));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_rdp_send_demand_active(struct xrdp_rdp* self)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_rdp_init(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_uint32_le(s, self->share_id);
|
||||
out_uint32_be(s, 0x04000401);
|
||||
out_uint32_be(s, 0x524e5300);
|
||||
out_uint32_be(s, 0x08000000);
|
||||
out_uint32_be(s, 0x09000800);
|
||||
out_uint16_le(s, self->mcs_channel);
|
||||
out_uint16_be(s, 0xb5e2);
|
||||
|
||||
/* Output general capability set */
|
||||
out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */
|
||||
out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */
|
||||
out_uint16_le(s, 1); /* OS major type */
|
||||
out_uint16_le(s, 3); /* OS minor type */
|
||||
out_uint16_le(s, 0x200); /* Protocol version */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
out_uint16_le(s, 0); /* Compression types */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
out_uint16_le(s, 0); /* Update capability */
|
||||
out_uint16_le(s, 0); /* Remote unshare capability */
|
||||
out_uint16_le(s, 0); /* Compression level */
|
||||
out_uint16_le(s, 0); /* Pad */
|
||||
|
||||
/* Output bitmap capability set */
|
||||
out_uint16_le(s, RDP_CAPSET_BITMAP); /* 2 */
|
||||
out_uint16_le(s, RDP_CAPLEN_BITMAP); /* 28(0x1c) */
|
||||
out_uint16_le(s, self->client_info.bpp); /* Preferred BPP */
|
||||
out_uint16_le(s, 1); /* Receive 1 BPP */
|
||||
out_uint16_le(s, 1); /* Receive 4 BPP */
|
||||
out_uint16_le(s, 1); /* Receive 8 BPP */
|
||||
out_uint16_le(s, self->client_info.width); /* width */
|
||||
out_uint16_le(s, self->client_info.height); /* height */
|
||||
out_uint16_le(s, 0); /* Pad */
|
||||
out_uint16_le(s, 1); /* Allow resize */
|
||||
out_uint16_le(s, 1); /* bitmap compression */
|
||||
out_uint16_le(s, 0); /* unknown */
|
||||
out_uint16_le(s, 0); /* unknown */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
|
||||
/* Output ? */
|
||||
out_uint16_le(s, 14);
|
||||
out_uint16_le(s, 4);
|
||||
|
||||
/* Output order capability set */
|
||||
out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */
|
||||
out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */
|
||||
out_uint8s(s, 16);
|
||||
out_uint32_be(s, 0x40420f00);
|
||||
out_uint16_le(s, 1); /* Cache X granularity */
|
||||
out_uint16_le(s, 20); /* Cache Y granularity */
|
||||
out_uint16_le(s, 0); /* Pad */
|
||||
out_uint16_le(s, 1); /* Max order level */
|
||||
out_uint16_le(s, 0x2f); /* Number of fonts */
|
||||
out_uint16_le(s, 0x22); /* Capability flags */
|
||||
/* caps */
|
||||
out_uint8(s, 1); /* dest blt */
|
||||
out_uint8(s, 1); /* pat blt */
|
||||
out_uint8(s, 1); /* screen blt */
|
||||
out_uint8(s, 1); /* memblt */
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 1);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
out_uint16_le(s, 0x6a1);
|
||||
out_uint8s(s, 6); /* ? */
|
||||
out_uint32_le(s, 0x0f4240); /* desk save */
|
||||
out_uint32_le(s, 0); /* ? */
|
||||
out_uint32_le(s, 0); /* ? */
|
||||
|
||||
/* Output color cache capability set */
|
||||
out_uint16_le(s, RDP_CAPSET_COLCACHE);
|
||||
out_uint16_le(s, RDP_CAPLEN_COLCACHE);
|
||||
out_uint16_le(s, 6); /* cache size */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
|
||||
/* Output pointer capability set */
|
||||
out_uint16_le(s, RDP_CAPSET_POINTER);
|
||||
out_uint16_le(s, RDP_CAPLEN_POINTER);
|
||||
out_uint16_le(s, 1); /* Colour pointer */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
|
||||
/* Output ? */
|
||||
out_uint16_le(s, 0xd);
|
||||
out_uint16_le(s, 0x58); /* 88 */
|
||||
out_uint8(s, 1);
|
||||
out_uint8s(s, 83);
|
||||
|
||||
s_mark_end(s);
|
||||
|
||||
if (xrdp_rdp_send(self, s, RDP_PDU_DEMAND_ACTIVE) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_process_capset_general(struct xrdp_rdp* self, struct stream* s,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
in_uint8s(s, 10);
|
||||
in_uint16_le(s, i);
|
||||
self->client_info.use_compact_packets = (i != 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
in_uint8s(s, 72);
|
||||
in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */
|
||||
self->client_info.desktop_cache = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* get the bitmap cache size */
|
||||
static int APP_CC
|
||||
xrdp_process_capset_bmpcache(struct xrdp_rdp* self, struct stream* s,
|
||||
int len)
|
||||
{
|
||||
in_uint8s(s, 24);
|
||||
in_uint16_le(s, self->client_info.cache1_entries);
|
||||
in_uint16_le(s, self->client_info.cache1_size);
|
||||
in_uint16_le(s, self->client_info.cache2_entries);
|
||||
in_uint16_le(s, self->client_info.cache2_size);
|
||||
in_uint16_le(s, self->client_info.cache3_entries);
|
||||
in_uint16_le(s, self->client_info.cache3_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* get the number of client cursor cache */
|
||||
static int APP_CC
|
||||
xrdp_process_capset_pointercache(struct xrdp_rdp* self, struct stream* s,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
in_uint8s(s, 2); /* color pointer */
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, 32);
|
||||
self->client_info.pointer_cache_entries = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
int cap_len;
|
||||
int source_len;
|
||||
int num_caps;
|
||||
int index;
|
||||
int type;
|
||||
int len;
|
||||
char* p;
|
||||
|
||||
in_uint8s(s, 4); /* rdp_shareid */
|
||||
in_uint8s(s, 2); /* userid */
|
||||
in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */
|
||||
in_uint16_le(s, cap_len);
|
||||
in_uint8s(s, source_len);
|
||||
in_uint16_le(s, num_caps);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
for (index = 0; index < num_caps; index++)
|
||||
{
|
||||
p = s->p;
|
||||
in_uint16_le(s, type);
|
||||
in_uint16_le(s, len);
|
||||
switch (type)
|
||||
{
|
||||
case RDP_CAPSET_GENERAL: /* 1 */
|
||||
xrdp_process_capset_general(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_ORDER: /* 3 */
|
||||
xrdp_process_capset_order(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BMPCACHE: /* 4 */
|
||||
xrdp_process_capset_bmpcache(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_POINTER: /* 8 */
|
||||
xrdp_process_capset_pointercache(self, s, len);
|
||||
break;
|
||||
}
|
||||
s->p = p + len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_process_data_pointer(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* RDP_DATA_PDU_INPUT */
|
||||
static int APP_CC
|
||||
xrdp_rdp_process_data_input(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
int num_events;
|
||||
int index;
|
||||
int msg_type;
|
||||
int device_flags;
|
||||
int param1;
|
||||
int param2;
|
||||
int time;
|
||||
|
||||
in_uint16_le(s, num_events);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
DEBUG(("xrdp_rdp_process_data_input %d events\n\r", num_events));
|
||||
for (index = 0; index < num_events; index++)
|
||||
{
|
||||
in_uint32_le(s, time);
|
||||
in_uint16_le(s, msg_type);
|
||||
in_uint16_le(s, device_flags);
|
||||
in_sint16_le(s, param1);
|
||||
in_sint16_le(s, param2);
|
||||
DEBUG(("xrdp_rdp_process_data_input event %4.4x flags %4.4x param1 %d \
|
||||
param2 %d time %d\n\r", msg_type, device_flags, param1, param2, time));
|
||||
if (self->session->callback != 0)
|
||||
{
|
||||
/* msg_type can be
|
||||
RDP_INPUT_SYNCHRONIZE - 0
|
||||
RDP_INPUT_SCANCODE - 4
|
||||
RDP_INPUT_MOUSE - 0x8001 */
|
||||
self->session->callback(self->session->id, msg_type, param1, param2,
|
||||
device_flags, time);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_send_synchronise(struct xrdp_rdp* self)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_rdp_init_data(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint16_le(s, 1);
|
||||
out_uint16_le(s, 1002);
|
||||
s_mark_end(s);
|
||||
if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_SYNCHRONISE) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_send_control(struct xrdp_rdp* self, int action)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_rdp_init_data(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint16_le(s, action);
|
||||
out_uint16_le(s, 0); /* userid */
|
||||
out_uint32_le(s, 1002); /* control id */
|
||||
s_mark_end(s);
|
||||
if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_CONTROL) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_process_data_control(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
int action;
|
||||
|
||||
in_uint16_le(s, action);
|
||||
in_uint8s(s, 2); /* user id */
|
||||
in_uint8s(s, 4); /* control id */
|
||||
if (action == RDP_CTL_REQUEST_CONTROL)
|
||||
{
|
||||
xrdp_rdp_send_synchronise(self);
|
||||
xrdp_rdp_send_control(self, RDP_CTL_COOPERATE);
|
||||
xrdp_rdp_send_control(self, RDP_CTL_GRANT_CONTROL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_process_data_sync(struct xrdp_rdp* self)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_process_screen_update(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
int op;
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
int cx;
|
||||
int cy;
|
||||
|
||||
in_uint32_le(s, op);
|
||||
in_uint16_le(s, left);
|
||||
in_uint16_le(s, top);
|
||||
in_uint16_le(s, right);
|
||||
in_uint16_le(s, bottom);
|
||||
cx = (right - left) + 1;
|
||||
cy = (bottom - top) + 1;
|
||||
if (self->session->callback != 0)
|
||||
{
|
||||
self->session->callback(self->session->id, 0x4444, left, top, cx, cy);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_send_unknown1(struct xrdp_rdp* self)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_rdp_init_data(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(s, unknown1, 172);
|
||||
s_mark_end(s);
|
||||
if (xrdp_rdp_send_data(self, s, 0x28) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_rdp_process_data_font(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
int seq;
|
||||
|
||||
in_uint8s(s, 2); /* num of fonts */
|
||||
in_uint8s(s, 2); /* unknown */
|
||||
in_uint16_le(s, seq);
|
||||
/* 419 client sends Seq 1, then 2 */
|
||||
/* 2600 clients sends only Seq 3 */
|
||||
if (seq == 2 || seq == 3) /* after second font message, we are up and */
|
||||
{ /* running */
|
||||
xrdp_rdp_send_unknown1(self);
|
||||
self->session->up_and_running = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* sent 37 pdu */
|
||||
static int APP_CC
|
||||
xrdp_rdp_send_disconnect_query_response(struct xrdp_rdp* self)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_rdp_init_data(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
s_mark_end(s);
|
||||
if (xrdp_rdp_send_data(self, s, 37) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0 /* not used */
|
||||
/*****************************************************************************/
|
||||
/* sent RDP_DATA_PDU_DISCONNECT 47 pdu */
|
||||
static int APP_CC
|
||||
xrdp_rdp_send_disconnect_reason(struct xrdp_rdp* self, int reason)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_rdp_init_data(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint32_le(s, reason);
|
||||
s_mark_end(s);
|
||||
if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_DISCONNECT) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* RDP_PDU_DATA */
|
||||
int APP_CC
|
||||
xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s)
|
||||
{
|
||||
int len;
|
||||
int data_type;
|
||||
int ctype;
|
||||
int clen;
|
||||
|
||||
in_uint8s(s, 6);
|
||||
in_uint16_le(s, len);
|
||||
in_uint8(s, data_type);
|
||||
in_uint8(s, ctype);
|
||||
in_uint16_le(s, clen);
|
||||
DEBUG(("xrdp_rdp_process_data code %d\n\r", data_type));
|
||||
switch (data_type)
|
||||
{
|
||||
case RDP_DATA_PDU_POINTER: /* 27 */
|
||||
xrdp_rdp_process_data_pointer(self, s);
|
||||
break;
|
||||
case RDP_DATA_PDU_INPUT: /* 28 */
|
||||
xrdp_rdp_process_data_input(self, s);
|
||||
break;
|
||||
case RDP_DATA_PDU_CONTROL: /* 20 */
|
||||
xrdp_rdp_process_data_control(self, s);
|
||||
break;
|
||||
case RDP_DATA_PDU_SYNCHRONISE: /* 31 */
|
||||
xrdp_rdp_process_data_sync(self);
|
||||
break;
|
||||
case 33: /* 33 ?? Invalidate an area I think */
|
||||
xrdp_rdp_process_screen_update(self, s);
|
||||
break;
|
||||
case 35:
|
||||
/* 35 ?? this comes when minimuzing a full screen mstsc.exe 2600 */
|
||||
/* I think this is saying the client no longer wants screen */
|
||||
/* updates and it will issue a 33 above to catch up */
|
||||
/* so minimized apps don't take bandwidth */
|
||||
break;
|
||||
case 36: /* 36 ?? disconnect query? */
|
||||
/* when this message comes, send a 37 back so the client */
|
||||
/* is sure the connection is alive and it can ask if user */
|
||||
/* really wants to disconnect */
|
||||
xrdp_rdp_send_disconnect_query_response(self); /* send a 37 back */
|
||||
break;
|
||||
case RDP_DATA_PDU_FONT2: /* 39 */
|
||||
xrdp_rdp_process_data_font(self, s);
|
||||
break;
|
||||
default:
|
||||
g_printf("unknown in xrdp_rdp_process_data %d\n\r", data_type);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_rdp_disconnect(struct xrdp_rdp* self)
|
||||
{
|
||||
return xrdp_sec_disconnect(self->sec_layer);
|
||||
}
|
@ -0,0 +1,606 @@
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2004-2005
|
||||
|
||||
secure layer
|
||||
|
||||
*/
|
||||
|
||||
#include "libxrdp.h"
|
||||
|
||||
static char pad_54[40] =
|
||||
{ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
|
||||
54, 54, 54, 54, 54, 54, 54, 54 };
|
||||
|
||||
static char pad_92[48] =
|
||||
{ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
|
||||
92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
|
||||
92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92 };
|
||||
|
||||
static char pub_exp[4] = { 0x01, 0x00, 0x01, 0x00 };
|
||||
|
||||
static char pub_mod[64] =
|
||||
{ 0x67, 0xab, 0x0e, 0x6a, 0x9f, 0xd6, 0x2b, 0xa3,
|
||||
0x32, 0x2f, 0x41, 0xd1, 0xce, 0xee, 0x61, 0xc3,
|
||||
0x76, 0x0b, 0x26, 0x11, 0x70, 0x48, 0x8a, 0x8d,
|
||||
0x23, 0x81, 0x95, 0xa0, 0x39, 0xf7, 0x5b, 0xaa,
|
||||
0x3e, 0xf1, 0xed, 0xb8, 0xc4, 0xee, 0xce, 0x5f,
|
||||
0x6a, 0xf5, 0x43, 0xce, 0x5f, 0x60, 0xca, 0x6c,
|
||||
0x06, 0x75, 0xae, 0xc0, 0xd6, 0xa4, 0x0c, 0x92,
|
||||
0xa4, 0xc6, 0x75, 0xea, 0x64, 0xb2, 0x50, 0x5b };
|
||||
|
||||
static char pub_sig[64] =
|
||||
{ 0x6a, 0x41, 0xb1, 0x43, 0xcf, 0x47, 0x6f, 0xf1,
|
||||
0xe6, 0xcc, 0xa1, 0x72, 0x97, 0xd9, 0xe1, 0x85,
|
||||
0x15, 0xb3, 0xc2, 0x39, 0xa0, 0xa6, 0x26, 0x1a,
|
||||
0xb6, 0x49, 0x01, 0xfa, 0xa6, 0xda, 0x60, 0xd7,
|
||||
0x45, 0xf7, 0x2c, 0xee, 0xe4, 0x8e, 0x64, 0x2e,
|
||||
0x37, 0x49, 0xf0, 0x4c, 0x94, 0x6f, 0x08, 0xf5,
|
||||
0x63, 0x4c, 0x56, 0x29, 0x55, 0x5a, 0x63, 0x41,
|
||||
0x2c, 0x20, 0x65, 0x95, 0x99, 0xb1, 0x15, 0x7c };
|
||||
|
||||
static char pri_exp[64] =
|
||||
{ 0x41, 0x93, 0x05, 0xB1, 0xF4, 0x38, 0xFC, 0x47,
|
||||
0x88, 0xC4, 0x7F, 0x83, 0x8C, 0xEC, 0x90, 0xDA,
|
||||
0x0C, 0x8A, 0xB5, 0xAE, 0x61, 0x32, 0x72, 0xF5,
|
||||
0x2B, 0xD1, 0x7B, 0x5F, 0x44, 0xC0, 0x7C, 0xBD,
|
||||
0x8A, 0x35, 0xFA, 0xAE, 0x30, 0xF6, 0xC4, 0x6B,
|
||||
0x55, 0xA7, 0x65, 0xEF, 0xF4, 0xB2, 0xAB, 0x18,
|
||||
0x4E, 0xAA, 0xE6, 0xDC, 0x71, 0x17, 0x3B, 0x4C,
|
||||
0xC2, 0x15, 0x4C, 0xF7, 0x81, 0xBB, 0xF0, 0x03 };
|
||||
|
||||
static char lic1[322] =
|
||||
{ 0x80, 0x00, 0x3e, 0x01, 0x01, 0x02, 0x3e, 0x01,
|
||||
0x7b, 0x3c, 0x31, 0xa6, 0xae, 0xe8, 0x74, 0xf6,
|
||||
0xb4, 0xa5, 0x03, 0x90, 0xe7, 0xc2, 0xc7, 0x39,
|
||||
0xba, 0x53, 0x1c, 0x30, 0x54, 0x6e, 0x90, 0x05,
|
||||
0xd0, 0x05, 0xce, 0x44, 0x18, 0x91, 0x83, 0x81,
|
||||
0x00, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00,
|
||||
0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00,
|
||||
0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00,
|
||||
0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00,
|
||||
0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00,
|
||||
0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00,
|
||||
0x6e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x32, 0x00, 0x33, 0x00, 0x36, 0x00, 0x00, 0x00,
|
||||
0x0d, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0xb8, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x5c, 0x00, 0x52, 0x53, 0x41, 0x31,
|
||||
0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
|
||||
0x01, 0xc7, 0xc9, 0xf7, 0x8e, 0x5a, 0x38, 0xe4,
|
||||
0x29, 0xc3, 0x00, 0x95, 0x2d, 0xdd, 0x4c, 0x3e,
|
||||
0x50, 0x45, 0x0b, 0x0d, 0x9e, 0x2a, 0x5d, 0x18,
|
||||
0x63, 0x64, 0xc4, 0x2c, 0xf7, 0x8f, 0x29, 0xd5,
|
||||
0x3f, 0xc5, 0x35, 0x22, 0x34, 0xff, 0xad, 0x3a,
|
||||
0xe6, 0xe3, 0x95, 0x06, 0xae, 0x55, 0x82, 0xe3,
|
||||
0xc8, 0xc7, 0xb4, 0xa8, 0x47, 0xc8, 0x50, 0x71,
|
||||
0x74, 0x29, 0x53, 0x89, 0x6d, 0x9c, 0xed, 0x70,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x48, 0x00, 0xa8, 0xf4, 0x31, 0xb9,
|
||||
0xab, 0x4b, 0xe6, 0xb4, 0xf4, 0x39, 0x89, 0xd6,
|
||||
0xb1, 0xda, 0xf6, 0x1e, 0xec, 0xb1, 0xf0, 0x54,
|
||||
0x3b, 0x5e, 0x3e, 0x6a, 0x71, 0xb4, 0xf7, 0x75,
|
||||
0xc8, 0x16, 0x2f, 0x24, 0x00, 0xde, 0xe9, 0x82,
|
||||
0x99, 0x5f, 0x33, 0x0b, 0xa9, 0xa6, 0x94, 0xaf,
|
||||
0xcb, 0x11, 0xc3, 0xf2, 0xdb, 0x09, 0x42, 0x68,
|
||||
0x29, 0x56, 0x58, 0x01, 0x56, 0xdb, 0x59, 0x03,
|
||||
0x69, 0xdb, 0x7d, 0x37, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x0e, 0x00, 0x0e, 0x00, 0x6d, 0x69, 0x63, 0x72,
|
||||
0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x00 };
|
||||
|
||||
static char lic2[20] =
|
||||
{ 0x80, 0x00, 0x10, 0x00, 0xff, 0x02, 0x10, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x28, 0x14, 0x00, 0x00 };
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_sec* APP_CC
|
||||
xrdp_sec_create(struct xrdp_rdp* owner, int sck)
|
||||
{
|
||||
struct xrdp_sec* self;
|
||||
|
||||
self = (struct xrdp_sec*)g_malloc(sizeof(struct xrdp_sec), 1);
|
||||
self->rdp_layer = owner;
|
||||
self->rc4_key_size = 1;
|
||||
self->decrypt_rc4_info = g_rc4_info_create();
|
||||
self->encrypt_rc4_info = g_rc4_info_create();
|
||||
g_random(self->server_random, 32);
|
||||
self->mcs_layer = xrdp_mcs_create(self, sck, &self->client_mcs_data,
|
||||
&self->server_mcs_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
xrdp_sec_delete(struct xrdp_sec* self)
|
||||
{
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
xrdp_mcs_delete(self->mcs_layer);
|
||||
g_rc4_info_delete(self->decrypt_rc4_info);
|
||||
g_rc4_info_delete(self->encrypt_rc4_info);
|
||||
g_free(self->client_mcs_data.data);
|
||||
g_free(self->server_mcs_data.data);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_sec_init(struct xrdp_sec* self, struct stream* s)
|
||||
{
|
||||
if (xrdp_mcs_init(self->mcs_layer, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
s_push_layer(s, sec_hdr, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Reduce key entropy from 64 to 40 bits */
|
||||
static void APP_CC
|
||||
xrdp_sec_make_40bit(char* key)
|
||||
{
|
||||
key[0] = 0xd1;
|
||||
key[1] = 0x26;
|
||||
key[2] = 0x9e;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* update an encryption key */
|
||||
static int APP_CC
|
||||
xrdp_sec_update(char* key, char* update_key, int key_len)
|
||||
{
|
||||
char shasig[20];
|
||||
void* sha1_info;
|
||||
void* md5_info;
|
||||
void* rc4_info;
|
||||
|
||||
sha1_info = g_sha1_info_create();
|
||||
md5_info = g_md5_info_create();
|
||||
rc4_info = g_rc4_info_create();
|
||||
g_sha1_clear(sha1_info);
|
||||
g_sha1_transform(sha1_info, update_key, key_len);
|
||||
g_sha1_transform(sha1_info, pad_54, 40);
|
||||
g_sha1_transform(sha1_info, key, key_len);
|
||||
g_sha1_complete(sha1_info, shasig);
|
||||
g_md5_clear(md5_info);
|
||||
g_md5_transform(md5_info, update_key, key_len);
|
||||
g_md5_transform(md5_info, pad_92, 48);
|
||||
g_md5_transform(md5_info, shasig, 20);
|
||||
g_md5_complete(md5_info, key);
|
||||
g_rc4_set_key(rc4_info, key, key_len);
|
||||
g_rc4_crypt(rc4_info, key, key_len);
|
||||
if (key_len == 8)
|
||||
{
|
||||
xrdp_sec_make_40bit(key);
|
||||
}
|
||||
g_sha1_info_delete(sha1_info);
|
||||
g_md5_info_delete(md5_info);
|
||||
g_rc4_info_delete(rc4_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void APP_CC
|
||||
xrdp_sec_decrypt(struct xrdp_sec* self, char* data, int len)
|
||||
{
|
||||
if (self->decrypt_use_count == 4096)
|
||||
{
|
||||
xrdp_sec_update(self->decrypt_key, self->decrypt_update_key,
|
||||
self->rc4_key_len);
|
||||
g_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key,
|
||||
self->rc4_key_len);
|
||||
self->decrypt_use_count = 0;
|
||||
}
|
||||
g_rc4_crypt(self->decrypt_rc4_info, data, len);
|
||||
self->decrypt_use_count++;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_sec_process_logon_info(struct xrdp_sec* self, struct stream* s)
|
||||
{
|
||||
int flags;
|
||||
int len_domain;
|
||||
int len_user;
|
||||
int len_password;
|
||||
int len_program;
|
||||
int len_directory;
|
||||
|
||||
in_uint8s(s, 4);
|
||||
in_uint32_le(s, flags);
|
||||
DEBUG(("in xrdp_sec_process_logon_info flags $%x\n\r", flags));
|
||||
/* this is the first test that the decrypt is working */
|
||||
if ((flags & RDP_LOGON_NORMAL) != RDP_LOGON_NORMAL) /* 0x33 */
|
||||
{ /* must be or error */
|
||||
return 1;
|
||||
}
|
||||
if (flags & RDP_LOGON_AUTO)
|
||||
{
|
||||
}
|
||||
if (flags & RDP_COMPRESSION)
|
||||
{
|
||||
}
|
||||
in_uint16_le(s, len_domain);
|
||||
in_uint16_le(s, len_user);
|
||||
in_uint16_le(s, len_password);
|
||||
in_uint16_le(s, len_program);
|
||||
in_uint16_le(s, len_directory);
|
||||
in_uint8s(s, len_domain + 2);
|
||||
in_uint8s(s, len_user + 2);
|
||||
in_uint8s(s, len_password + 2);
|
||||
in_uint8s(s, len_program + 2);
|
||||
in_uint8s(s, len_directory + 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_sec_send_lic_initial(struct xrdp_sec* self)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_mcs_init(self->mcs_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(s, lic1, 322);
|
||||
s_mark_end(s);
|
||||
if (xrdp_mcs_send(self->mcs_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
static int APP_CC
|
||||
xrdp_sec_send_lic_response(struct xrdp_sec* self)
|
||||
{
|
||||
struct stream* s;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_mcs_init(self->mcs_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(s, lic2, 20);
|
||||
s_mark_end(s);
|
||||
if (xrdp_mcs_send(self->mcs_layer, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void APP_CC
|
||||
xrdp_sec_reverse(char* p, int len)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char temp;
|
||||
|
||||
i = 0;
|
||||
j = len - 1;
|
||||
while (i < j)
|
||||
{
|
||||
temp = p[i];
|
||||
p[i] = p[j];
|
||||
p[j] = temp;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void APP_CC
|
||||
xrdp_sec_rsa_op(char* out, char* in, char* mod, char* exp)
|
||||
{
|
||||
char lexp[64];
|
||||
char lmod[64];
|
||||
char lin[64];
|
||||
char lout[64];
|
||||
int len;
|
||||
|
||||
g_memcpy(lexp, exp, 64);
|
||||
g_memcpy(lmod, mod, 64);
|
||||
g_memcpy(lin, in, 64);
|
||||
xrdp_sec_reverse(lexp, 64);
|
||||
xrdp_sec_reverse(lmod, 64);
|
||||
xrdp_sec_reverse(lin, 64);
|
||||
g_memset(lout, 0, 64);
|
||||
len = g_mod_exp(lout, lin, lmod, lexp);
|
||||
xrdp_sec_reverse(lout, len);
|
||||
g_memcpy(out, lout, 64);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void APP_CC
|
||||
xrdp_sec_hash_48(char* out, char* in, char* salt1, char* salt2, int salt)
|
||||
{
|
||||
int i;
|
||||
void* sha1_info;
|
||||
void* md5_info;
|
||||
char pad[4];
|
||||
char sha1_sig[20];
|
||||
char md5_sig[16];
|
||||
|
||||
sha1_info = g_sha1_info_create();
|
||||
md5_info = g_md5_info_create();
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
g_memset(pad, salt + i, 4);
|
||||
g_sha1_clear(sha1_info);
|
||||
g_sha1_transform(sha1_info, pad, i + 1);
|
||||
g_sha1_transform(sha1_info, in, 48);
|
||||
g_sha1_transform(sha1_info, salt1, 32);
|
||||
g_sha1_transform(sha1_info, salt2, 32);
|
||||
g_sha1_complete(sha1_info, sha1_sig);
|
||||
g_md5_clear(md5_info);
|
||||
g_md5_transform(md5_info, in, 48);
|
||||
g_md5_transform(md5_info, sha1_sig, 20);
|
||||
g_md5_complete(md5_info, md5_sig);
|
||||
g_memcpy(out + i * 16, md5_sig, 16);
|
||||
}
|
||||
g_sha1_info_delete(sha1_info);
|
||||
g_md5_info_delete(md5_info);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void APP_CC
|
||||
xrdp_sec_hash_16(char* out, char* in, char* salt1, char* salt2)
|
||||
{
|
||||
void* md5_info;
|
||||
|
||||
md5_info = g_md5_info_create();
|
||||
g_md5_clear(md5_info);
|
||||
g_md5_transform(md5_info, in, 16);
|
||||
g_md5_transform(md5_info, salt1, 32);
|
||||
g_md5_transform(md5_info, salt2, 32);
|
||||
g_md5_complete(md5_info, out);
|
||||
g_md5_info_delete(md5_info);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void APP_CC
|
||||
xrdp_sec_establish_keys(struct xrdp_sec* self)
|
||||
{
|
||||
char session_key[48];
|
||||
char temp_hash[48];
|
||||
char input[48];
|
||||
|
||||
g_memcpy(input, self->client_random, 24);
|
||||
g_memcpy(input + 24, self->server_random, 24);
|
||||
xrdp_sec_hash_48(temp_hash, input, self->client_random,
|
||||
self->server_random, 65);
|
||||
xrdp_sec_hash_48(session_key, temp_hash, self->client_random,
|
||||
self->server_random, 88);
|
||||
g_memcpy(self->sign_key, session_key, 16);
|
||||
xrdp_sec_hash_16(self->encrypt_key, session_key + 16, self->client_random,
|
||||
self->server_random);
|
||||
xrdp_sec_hash_16(self->decrypt_key, session_key + 32, self->client_random,
|
||||
self->server_random);
|
||||
if (self->rc4_key_size == 1)
|
||||
{
|
||||
xrdp_sec_make_40bit(self->sign_key);
|
||||
xrdp_sec_make_40bit(self->encrypt_key);
|
||||
xrdp_sec_make_40bit(self->decrypt_key);
|
||||
self->rc4_key_len = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->rc4_key_len = 16;
|
||||
}
|
||||
g_memcpy(self->decrypt_update_key, self->decrypt_key, 16);
|
||||
g_memcpy(self->encrypt_update_key, self->encrypt_key, 16);
|
||||
g_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key, self->rc4_key_len);
|
||||
g_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key, self->rc4_key_len);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan)
|
||||
{
|
||||
int flags;
|
||||
int len;
|
||||
|
||||
DEBUG((" in xrdp_sec_recv\n\r"));
|
||||
if (xrdp_mcs_recv(self->mcs_layer, s, chan) != 0)
|
||||
{
|
||||
DEBUG((" out xrdp_sec_recv error\n\r"));
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, flags);
|
||||
DEBUG((" in xrdp_sec_recv flags $%x\n\r", flags));
|
||||
if (flags & SEC_ENCRYPT) /* 0x08 */
|
||||
{
|
||||
in_uint8s(s, 8); /* signature */
|
||||
xrdp_sec_decrypt(self, s->p, s->end - s->p);
|
||||
}
|
||||
if (flags & SEC_CLIENT_RANDOM) /* 0x01 */
|
||||
{
|
||||
in_uint32_le(s, len);
|
||||
in_uint8a(s, self->client_crypt_random, 64);
|
||||
xrdp_sec_rsa_op(self->client_random, self->client_crypt_random,
|
||||
pub_mod, pri_exp);
|
||||
xrdp_sec_establish_keys(self);
|
||||
*chan = 1; /* just set a non existing channel and exit */
|
||||
return 0;
|
||||
}
|
||||
if (flags & SEC_LOGON_INFO) /* 0x40 */
|
||||
{
|
||||
if (xrdp_sec_process_logon_info(self, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xrdp_sec_send_lic_initial(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
*chan = 1; /* just set a non existing channel and exit */
|
||||
return 0;
|
||||
}
|
||||
if (flags & SEC_LICENCE_NEG) /* 0x80 */
|
||||
{
|
||||
if (xrdp_sec_send_lic_response(self) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return -1; /* special error that means send demand active */
|
||||
}
|
||||
DEBUG((" out xrdp_sec_recv error\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* TODO needs outgoing encryption */
|
||||
int APP_CC
|
||||
xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int flags)
|
||||
{
|
||||
DEBUG((" in xrdp_sec_send\n\r"));
|
||||
s_pop_layer(s, sec_hdr);
|
||||
out_uint32_le(s, flags);
|
||||
if (xrdp_mcs_send(self->mcs_layer, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
DEBUG((" out xrdp_sec_send\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* prepare server mcs data to send in mcs layer */
|
||||
static void APP_CC
|
||||
xrdp_sec_out_mcs_data(struct xrdp_sec* self)
|
||||
{
|
||||
struct stream* p;
|
||||
|
||||
p = &self->server_mcs_data;
|
||||
init_stream(p, 512);
|
||||
out_uint16_be(p, 5);
|
||||
out_uint16_be(p, 0x14);
|
||||
out_uint8(p, 0x7c);
|
||||
out_uint16_be(p, 1);
|
||||
out_uint8(p, 0x2a);
|
||||
out_uint8(p, 0x14);
|
||||
out_uint8(p, 0x76);
|
||||
out_uint8(p, 0x0a);
|
||||
out_uint8(p, 1);
|
||||
out_uint8(p, 1);
|
||||
out_uint8(p, 0);
|
||||
out_uint16_le(p, 0xc001);
|
||||
out_uint8(p, 0);
|
||||
out_uint8(p, 0x4d); /* M */
|
||||
out_uint8(p, 0x63); /* c */
|
||||
out_uint8(p, 0x44); /* D */
|
||||
out_uint8(p, 0x6e); /* n */
|
||||
out_uint16_be(p, 0x80fc);
|
||||
out_uint16_le(p, SEC_TAG_SRV_INFO);
|
||||
out_uint16_le(p, 8); /* len */
|
||||
out_uint8(p, 4); /* 4 = rdp5 1 = rdp4 */
|
||||
out_uint8(p, 0);
|
||||
out_uint8(p, 8);
|
||||
out_uint8(p, 0);
|
||||
out_uint16_le(p, SEC_TAG_SRV_CHANNELS);
|
||||
out_uint16_le(p, 8); /* len */
|
||||
out_uint8(p, 0xeb);
|
||||
out_uint8(p, 3);
|
||||
out_uint8(p, 0);
|
||||
out_uint8(p, 0);
|
||||
out_uint16_le(p, SEC_TAG_SRV_CRYPT);
|
||||
out_uint16_le(p, 0x00ec); /* len is 236 */
|
||||
out_uint32_le(p, 1); /* key len 1 = 40 bit 2 = 128 bit */
|
||||
out_uint32_le(p, 1); /* crypt level 1 = low 2 = medium 3 = high */
|
||||
out_uint32_le(p, 32); /* 32 bytes random len */
|
||||
out_uint32_le(p, 0xb8); /* 184 bytes rsa info(certificate) len */
|
||||
out_uint8a(p, self->server_random, 32);
|
||||
/* here to end is certificate */
|
||||
/* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */
|
||||
/* TermService\Parameters\Certificate */
|
||||
out_uint32_le(p, 1);
|
||||
out_uint32_le(p, 1);
|
||||
out_uint32_le(p, 1);
|
||||
out_uint16_le(p, SEC_TAG_PUBKEY);
|
||||
out_uint16_le(p, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */
|
||||
out_uint32_le(p, SEC_RSA_MAGIC);
|
||||
out_uint32_le(p, 0x48); /* 72 bytes modulus len */
|
||||
out_uint32_be(p, 0x00020000);
|
||||
out_uint32_be(p, 0x3f000000);
|
||||
out_uint8a(p, pub_exp, 4); /* pub exp */
|
||||
out_uint8a(p, pub_mod, 64); /* pub mod */
|
||||
out_uint8s(p, 8); /* pad */
|
||||
out_uint16_le(p, SEC_TAG_KEYSIG);
|
||||
out_uint16_le(p, 72); /* len */
|
||||
out_uint8a(p, pub_sig, 64); /* pub sig */
|
||||
out_uint8s(p, 8); /* pad */
|
||||
/* end certificate */
|
||||
s_mark_end(p);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_sec_incoming(struct xrdp_sec* self)
|
||||
{
|
||||
DEBUG(("in xrdp_sec_incoming\n\r"));
|
||||
xrdp_sec_out_mcs_data(self);
|
||||
if (xrdp_mcs_incoming(self->mcs_layer) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#ifdef XRDP_DEBUG
|
||||
g_printf("client mcs data received\n\r");
|
||||
g_hexdump(self->client_mcs_data.data,
|
||||
self->client_mcs_data.end - self->client_mcs_data.data);
|
||||
g_printf("server mcs data sent\n\r");
|
||||
g_hexdump(self->server_mcs_data.data,
|
||||
self->server_mcs_data.end - self->server_mcs_data.data);
|
||||
#endif
|
||||
DEBUG(("out xrdp_sec_incoming\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_sec_disconnect(struct xrdp_sec* self)
|
||||
{
|
||||
return xrdp_mcs_disconnect(self->mcs_layer);
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2004-2005
|
||||
|
||||
tcp layer
|
||||
|
||||
*/
|
||||
|
||||
#include "libxrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_tcp* APP_CC
|
||||
xrdp_tcp_create(struct xrdp_iso* owner, int sck)
|
||||
{
|
||||
struct xrdp_tcp* self;
|
||||
|
||||
self = (struct xrdp_tcp*)g_malloc(sizeof(struct xrdp_tcp), 1);
|
||||
self->iso_layer = owner;
|
||||
self->sck = sck;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
xrdp_tcp_delete(struct xrdp_tcp* self)
|
||||
{
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* get out stream ready for data */
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_tcp_init(struct xrdp_tcp* self, struct stream* s)
|
||||
{
|
||||
init_stream(s, 8192);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_tcp_recv(struct xrdp_tcp* self, struct stream* s, int len)
|
||||
{
|
||||
int rcvd;
|
||||
|
||||
if (self->sck_closed)
|
||||
{
|
||||
DEBUG((" in xrdp_tcp_recv, sck closed\n\r"));
|
||||
return 1;
|
||||
}
|
||||
DEBUG((" in xrdp_tcp_recv, gota get %d bytes\n\r", len));
|
||||
init_stream(s, len);
|
||||
while (len > 0)
|
||||
{
|
||||
rcvd = g_tcp_recv(self->sck, s->end, len, 0);
|
||||
if (rcvd == -1)
|
||||
{
|
||||
if (g_tcp_last_error_would_block(self->sck))
|
||||
{
|
||||
g_sleep(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->sck_closed = 1;
|
||||
DEBUG((" error = -1 in xrdp_tcp_recv socket %d\n\r", self->sck));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (rcvd == 0)
|
||||
{
|
||||
self->sck_closed = 1;
|
||||
DEBUG((" error = 0 in xrdp_tcp_recv socket %d\n\r", self->sck));
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->end += rcvd;
|
||||
len -= rcvd;
|
||||
}
|
||||
}
|
||||
DEBUG((" out xrdp_tcp_recv\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int APP_CC
|
||||
xrdp_tcp_send(struct xrdp_tcp* self, struct stream* s)
|
||||
{
|
||||
int len;
|
||||
int total;
|
||||
int sent;
|
||||
|
||||
if (self->sck_closed)
|
||||
{
|
||||
DEBUG((" in xrdp_tcp_send, sck closed\n\r"));
|
||||
return 1;
|
||||
}
|
||||
len = s->end - s->data;
|
||||
DEBUG((" in xrdp_tcp_send, gota send %d bytes\n\r", len));
|
||||
total = 0;
|
||||
while (total < len)
|
||||
{
|
||||
sent = g_tcp_send(self->sck, s->data + total, len - total, 0);
|
||||
if (sent == -1)
|
||||
{
|
||||
if (g_tcp_last_error_would_block(self->sck))
|
||||
{
|
||||
g_sleep(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->sck_closed = 1;
|
||||
DEBUG((" error = -1 in xrdp_tcp_send socket %d\n\r", self->sck));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (sent == 0)
|
||||
{
|
||||
self->sck_closed = 1;
|
||||
DEBUG((" error = 0 in xrdp_tcp_send socket %d\n\r", self->sck));
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
total = total + sent;
|
||||
}
|
||||
}
|
||||
DEBUG((" out xrdp_tcp_send, sent %d bytes ok\n\r", len));
|
||||
return 0;
|
||||
}
|
Loading…
Reference in new issue